<commit_before>/**
 * @file sgbm.cpp
 * @brief wrapper OpenCV's implementation of the SGBM stereo algorithm (Hirschmuller'08)
 * @author Gabriele Facciolo <facciolo@cmla.ens-cachan.fr>
 *
 * Copyright (c) 2012-2013, Gabriele Facciolo
 * All rights reserved.
 *
 * This program is free software: you can use, modify and/or redistribute it
 * under the terms of the simplified BSD License. You should have received a
 * copy of this license along this program. If not, see
 * <http://www.opensource.org/licenses/bsd-license.html>.
 */

#include <opencv2/calib3d/calib3d.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <cstdio>
extern "C" {
#include "iio.h"
}

using namespace cv;

void paste(Mat &dest, Mat &overlay, int px, int py)
{
    overlay.copyTo(dest(Range(py, py + overlay.rows),
        Range(px, px + overlay.cols)));
}

// FROM OPENCV's DOCUMENTATION
//
//
// The class implements the modified H. Hirschmuller algorithm [HH08] that
// differs from the original one as follows:
//
// By default, the algorithm is single-pass, which means that you consider only
// 5 directions instead of 8. Set fullDP=true to run the full variant of the
// algorithm but beware that it may consume a lot of memory.  The algorithm
// matches blocks, not individual pixels. Though, setting SADWindowSize=1
// reduces the blocks to single pixels.  Mutual information cost function is
// not implemented. Instead, a simpler Birchfield-Tomasi sub-pixel metric from
// [BT98] is used. Though, the color images are supported as well. Some pre-
// and post- processing steps from K. Konolige algorithm StereoBM::operator()
// are included, for example: pre-filtering (CV_STEREO_BM_XSOBEL type) and
// post-filtering (uniqueness check, quadratic interpolation and speckle
// filtering).
//
// PARAMETERS :
//
// minDisparity – Minimum possible disparity value. Normally, it is zero but
// sometimes rectification algorithms can shift images, so this parameter needs
// to be adjusted accordingly.
// numDisparities – Maximum disparity minus minimum disparity. The value is
// always greater than zero. In the current implementation, this parameter must
// be divisible by 16.
// SADWindowSize – Matched block size. It must be an odd number >=1 .
// Normally, it should be somewhere in the 3..11 range.
// P1 – The first parameter controlling the disparity smoothness. See below.
// P2 – The second parameter controlling the disparity smoothness.  The larger
// the values are, the smoother the disparity is. P1 is the penalty on the
// disparity change by plus or minus 1 between neighbor pixels. P2 is the
// penalty on the disparity change by more than 1 between neighbor pixels. The
// algorithm requires P2 > P1 . See stereo_match.cpp sample where some
// reasonably good P1 and P2 values are shown (like
// 8*number_of_image_channels*SADWindowSize*SADWindowSize and
// 32*number_of_image_channels*SADWindowSize*SADWindowSize , respectively).
// disp12MaxDiff – Maximum allowed difference (in integer pixel units) in the
// left-right disparity check. Set it to a non-positive value to disable the
// check.
// preFilterCap – Truncation value for the prefiltered image pixels.  The
// algorithm first computes x-derivative at each pixel and clips its value by
// [-preFilterCap, preFilterCap] interval. The result values are passed to the
// Birchfield-Tomasi pixel cost function.
// uniquenessRatio – Margin in percentage by which the best (minimum) computed
// cost function value should “win” the second best value to consider the found
// match correct. Normally, a value within the 5-15 range is good enough.
// speckleWindowSize – Maximum size of smooth disparity regions to consider
// their noise speckles and invalidate. Set it to 0 to disable speckle
// filtering. Otherwise, set it somewhere in the 50-200 range.
// speckleRange – Maximum disparity variation within each connected component.
// If you do speckle filtering, set the parameter to a positive value, it will
// be implicitly multiplied by 16. Normally, 1 or 2 is good enough.  fullDP –
// Set it to true to run the full-scale two-pass dynamic programming algorithm.
// It will consume O(W*H*numDisparities) bytes, which is large for 640x480
// stereo and huge for HD-size pictures. By default, it is set to false .

int main(int c, char** v)
{
    if (c < 4) {
        fprintf(stderr, "\tusage: %s im1 im2 out [mindisp(0) maxdisp(64)"
            "SADwindow(1) P1(0) P2(0) LRdiff(1)]\n", v[0]);
        exit(1);
    }
    Mat u1 = imread(v[1], 0);
    Mat u2 = imread(v[2], 0);
    int nch = u1.channels();

    int i = 4;
    int maxdisp = - ( (c>i) ? atoi(v[i]) : 0);   i++;
    int mindisp = - ( (c>i) ? atoi(v[i]) : 64);  i++;
    int SADwin  = (c>i) ? atoi(v[i]) : 1;  i++;
    int P1      = (c>i) ? atoi(v[i]) :  8*nch*SADwin*SADwin; i++;
    int P2      = (c>i) ? atoi(v[i]) : 32*nch*SADwin*SADwin; i++;
    int LRdiff  = (c>i) ? atoi(v[i]) : 1;  i++;

    // prepare the StereoSGBM object
    // the number of disparities has to be a multiple of 16
    StereoSGBM sgbm;
    sgbm.numberOfDisparities = (int) 16 * ceil((maxdisp - mindisp) / 16.0);
    sgbm.minDisparity = mindisp;
    sgbm.SADWindowSize = SADwin;
    sgbm.P1 = P1;
    sgbm.P2 = P2;
    sgbm.disp12MaxDiff = LRdiff;

    sgbm.fullDP = 0; // to run the full-scale two-pass dynamic programming algorithm
    sgbm.preFilterCap = 63;
    sgbm.uniquenessRatio = 10;
    sgbm.speckleWindowSize = 50;
    sgbm.speckleRange = 1;

    fprintf (stderr, "mind:%d maxd:%d win:%d P1:%d P2:%d LR:%d\n", mindisp,
        mindisp + sgbm.numberOfDisparities, SADwin, P1, P2, LRdiff);
    fprintf (stderr, "fullDP:%d preFilterCap:%d uniquenessRatio:%d"
        "speckleWin:%d SpeckleRange:%d\n", sgbm.fullDP, sgbm.preFilterCap,
        sgbm.uniquenessRatio, sgbm.speckleWindowSize, sgbm.speckleRange);

    // CROP TRICK
    // To avoid losing two vertical bands on the left and right sides of the
    // reference image
    // the stereo matching is done by the sgbm() operator
    Mat uu1(u1.rows, (int) (u1.cols + max(-mindisp, 0) + max(maxdisp, 0)), u1.type());
    Mat uu2(u2.rows, (int) (u2.cols + max(-mindisp, 0) + max(maxdisp, 0)), u2.type());
    paste(uu1, u1, max(maxdisp, 0), 0);
    paste(uu2, u2, max(maxdisp, 0), 0);
    Mat disp, ddisp;
    sgbm(uu1, uu2, ddisp);
    disp = ddisp(Range::all(), Range(max(maxdisp, 0), max(maxdisp, 0) + u1.cols));

//    // WITHOUT CROP TRICK
//    Mat disp, disp_8u;
//    sgbm(u1, u2, disp);
//    disp.convertTo(disp_8u, CV_8U);

    // convert back the disparities to our convention before saving
    float *odisp = (float*) malloc(disp.rows*disp.cols*sizeof(float));
    for (int y=0; y<disp.rows; y++)
        for (int x=0; x<disp.cols; x++)
            if (disp.at<int16_t>(y, x) == -((-mindisp+1)*16))
                odisp[x+y*disp.cols] = NAN;
            else
                odisp[x+y*disp.cols] = -((float) disp.at<int16_t>(y, x)) / 16.0;
                // sgbm output disparity map is a 16-bit signed single-channel
                // image of the same size as the input image. It contains
                // disparity values scaled by 16. So, to get the floating-point
                // disparity map, you need to divide each disp element by 16.

    iio_save_image_float(v[3], odisp, disp.cols, disp.rows);
    free(odisp);
    return 0;
}
<commit_msg>comment<commit_after>/**
 * @file sgbm.cpp
 * @brief wrapper OpenCV's implementation of the SGBM stereo algorithm (Hirschmuller'08)
 * @author Gabriele Facciolo <facciolo@cmla.ens-cachan.fr>
 *
 * Copyright (c) 2012-2013, Gabriele Facciolo
 * All rights reserved.
 *
 * This program is free software: you can use, modify and/or redistribute it
 * under the terms of the simplified BSD License. You should have received a
 * copy of this license along this program. If not, see
 * <http://www.opensource.org/licenses/bsd-license.html>.
 */

#include <opencv2/calib3d/calib3d.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <cstdio>
extern "C" {
#include "iio.h"
}

using namespace cv;

void paste(Mat &dest, Mat &overlay, int px, int py)
{
    overlay.copyTo(dest(Range(py, py + overlay.rows),
        Range(px, px + overlay.cols)));
}

// FROM OPENCV's DOCUMENTATION
//
//
// The class implements the modified H. Hirschmuller algorithm [HH08] that
// differs from the original one as follows:
//
// By default, the algorithm is single-pass, which means that you consider only
// 5 directions instead of 8. Set fullDP=true to run the full variant of the
// algorithm but beware that it may consume a lot of memory.  The algorithm
// matches blocks, not individual pixels. Though, setting SADWindowSize=1
// reduces the blocks to single pixels.  Mutual information cost function is
// not implemented. Instead, a simpler Birchfield-Tomasi sub-pixel metric from
// [BT98] is used. Though, the color images are supported as well. Some pre-
// and post- processing steps from K. Konolige algorithm StereoBM::operator()
// are included, for example: pre-filtering (CV_STEREO_BM_XSOBEL type) and
// post-filtering (uniqueness check, quadratic interpolation and speckle
// filtering).
//
// PARAMETERS :
//
// minDisparity – Minimum possible disparity value. Normally, it is zero but
// sometimes rectification algorithms can shift images, so this parameter needs
// to be adjusted accordingly.
// numDisparities – Maximum disparity minus minimum disparity. The value is
// always greater than zero. In the current implementation, this parameter must
// be divisible by 16.
// SADWindowSize – Matched block size. It must be an odd number >=1 .
// Normally, it should be somewhere in the 3..11 range.
// P1 – The first parameter controlling the disparity smoothness. See below.
// P2 – The second parameter controlling the disparity smoothness.  The larger
// the values are, the smoother the disparity is. P1 is the penalty on the
// disparity change by plus or minus 1 between neighbor pixels. P2 is the
// penalty on the disparity change by more than 1 between neighbor pixels. The
// algorithm requires P2 > P1 . See stereo_match.cpp sample where some
// reasonably good P1 and P2 values are shown (like
// 8*number_of_image_channels*SADWindowSize*SADWindowSize and
// 32*number_of_image_channels*SADWindowSize*SADWindowSize , respectively).
// disp12MaxDiff – Maximum allowed difference (in integer pixel units) in the
// left-right disparity check. Set it to a non-positive value to disable the
// check.
// preFilterCap – Truncation value for the prefiltered image pixels.  The
// algorithm first computes x-derivative at each pixel and clips its value by
// [-preFilterCap, preFilterCap] interval. The result values are passed to the
// Birchfield-Tomasi pixel cost function.
// uniquenessRatio – Margin in percentage by which the best (minimum) computed
// cost function value should “win” the second best value to consider the found
// match correct. Normally, a value within the 5-15 range is good enough.
// speckleWindowSize – Maximum size of smooth disparity regions to consider
// their noise speckles and invalidate. Set it to 0 to disable speckle
// filtering. Otherwise, set it somewhere in the 50-200 range.
// speckleRange – Maximum disparity variation within each connected component.
// If you do speckle filtering, set the parameter to a positive value, it will
// be implicitly multiplied by 16. Normally, 1 or 2 is good enough.  fullDP –
// Set it to true to run the full-scale two-pass dynamic programming algorithm.
// It will consume O(W*H*numDisparities) bytes, which is large for 640x480
// stereo and huge for HD-size pictures. By default, it is set to false .

int main(int c, char** v)
{
    if (c < 4) {
        fprintf(stderr, "\tusage: %s im1 im2 out [mindisp(0) maxdisp(64)"
            "SADwindow(1) P1(0) P2(0) LRdiff(1)]\n", v[0]);
        exit(1);
    }
    Mat u1 = imread(v[1], 0);
    Mat u2 = imread(v[2], 0);
    int nch = u1.channels();

    int i = 4;
    // Warning: here we convert between openCV (and Hirschmuller, and
    // Middlebury) disparity convention and ours. What we call disparity is the
    // opposite of what they call disparity.
    // the min and max disparities given as inputs of this binary follow our
    // convention, while in the code the disparities follow openCV convention.
    int maxdisp = - ( (c>i) ? atoi(v[i]) : 0);   i++;
    int mindisp = - ( (c>i) ? atoi(v[i]) : 64);  i++;
    int SADwin  = (c>i) ? atoi(v[i]) : 1;  i++;
    int P1      = (c>i) ? atoi(v[i]) :  8*nch*SADwin*SADwin; i++;
    int P2      = (c>i) ? atoi(v[i]) : 32*nch*SADwin*SADwin; i++;
    int LRdiff  = (c>i) ? atoi(v[i]) : 1;  i++;

    // prepare the StereoSGBM object
    // the number of disparities has to be a multiple of 16
    StereoSGBM sgbm;
    sgbm.numberOfDisparities = (int) 16 * ceil((maxdisp - mindisp) / 16.0);
    sgbm.minDisparity = mindisp;
    sgbm.SADWindowSize = SADwin;
    sgbm.P1 = P1;
    sgbm.P2 = P2;
    sgbm.disp12MaxDiff = LRdiff;

    sgbm.fullDP = 0; // to run the full-scale two-pass dynamic programming algorithm
    sgbm.preFilterCap = 63;
    sgbm.uniquenessRatio = 10;
    sgbm.speckleWindowSize = 50;
    sgbm.speckleRange = 1;

    fprintf (stderr, "mind:%d maxd:%d win:%d P1:%d P2:%d LR:%d\n", mindisp,
        mindisp + sgbm.numberOfDisparities, SADwin, P1, P2, LRdiff);
    fprintf (stderr, "fullDP:%d preFilterCap:%d uniquenessRatio:%d"
        "speckleWin:%d SpeckleRange:%d\n", sgbm.fullDP, sgbm.preFilterCap,
        sgbm.uniquenessRatio, sgbm.speckleWindowSize, sgbm.speckleRange);

    // CROP TRICK
    // To avoid losing two vertical bands on the left and right sides of the
    // reference image
    // the stereo matching is done by the sgbm() operator
    Mat uu1(u1.rows, (int) (u1.cols + max(-mindisp, 0) + max(maxdisp, 0)), u1.type());
    Mat uu2(u2.rows, (int) (u2.cols + max(-mindisp, 0) + max(maxdisp, 0)), u2.type());
    paste(uu1, u1, max(maxdisp, 0), 0);
    paste(uu2, u2, max(maxdisp, 0), 0);
    Mat disp, ddisp;
    sgbm(uu1, uu2, ddisp);
    disp = ddisp(Range::all(), Range(max(maxdisp, 0), max(maxdisp, 0) + u1.cols));

//    // WITHOUT CROP TRICK
//    Mat disp, disp_8u;
//    sgbm(u1, u2, disp);
//    disp.convertTo(disp_8u, CV_8U);

    // convert back the disparities to our convention before saving
    float *odisp = (float*) malloc(disp.rows*disp.cols*sizeof(float));
    for (int y=0; y<disp.rows; y++)
        for (int x=0; x<disp.cols; x++)
            if (disp.at<int16_t>(y, x) == -((-mindisp+1)*16))
                odisp[x+y*disp.cols] = NAN;
            else
                odisp[x+y*disp.cols] = -((float) disp.at<int16_t>(y, x)) / 16.0;
                // sgbm output disparity map is a 16-bit signed single-channel
                // image of the same size as the input image. It contains
                // disparity values scaled by 16. So, to get the floating-point
                // disparity map, you need to divide each disp element by 16.

    iio_save_image_float(v[3], odisp, disp.cols, disp.rows);
    free(odisp);
    return 0;
}
<|endoftext|>


<commit_before>#include <malloc_count/malloc_count.hpp>

namespace malloc_count {
    #define PHASE_STACK_SIZE 16

    #define MEMBLOCK_MAGIC 0xFEDCBA9876543210
    struct block_header_t {
        size_t magic;
        size_t size;
    };

    size_t next_phase_id = 1;

    phase_t pstack[PHASE_STACK_SIZE];
    int pcur = -1;

    bool paused = false;

    void begin_phase() {
        pcur++;
        if(pcur >= PHASE_STACK_SIZE) throw "phase stack overflow";

        pstack[pcur].id = next_phase_id++;
        pstack[pcur].mem_off = (pcur > 0) ? pstack[pcur - 1].mem_current : 0;
        pstack[pcur].mem_peak = 0;
        pstack[pcur].mem_current = 0;
        pstack[pcur].time_start = current_time_millis();
    }

    phase_t end_phase() {
        if(pcur < 0) throw "ending a phase that never began";

        pstack[pcur].time_end = current_time_millis();
        pstack[pcur].id = SIZE_MAX; //invalidate

        return pstack[pcur--];
    }

    void pause_phase() {
        paused = true;
    }

    void resume_phase() {
        paused = false;
    }

    inline bool is_managed(block_header_t* block) {
        return (block->magic == MEMBLOCK_MAGIC);
    }

    inline void count_malloc(size_t size) {
        if(!paused && pcur >= 0) {
            for(int i = 0; i <= pcur; i++) {
                pstack[i].mem_current += size;
                if(pstack[i].mem_current > pstack[i].mem_peak) {
                    pstack[i].mem_peak = pstack[i].mem_current;
                }
            }
        }
    }

    inline void count_free(size_t size) {
        if(!paused && pcur >= 0) {
            for(int i = 0; i <= pcur; i++) {
                pstack[i].mem_current -= size;
            }
        }
    }
}

#ifdef __CYGWIN__

#pragma message("malloc overrides are not supported on Cygwin.")

#elif !defined(STATS_DISABLED)

void* malloc(size_t size) {
    using namespace malloc_count;

    if(!size) return NULL;

    void *ptr = __libc_malloc(size + sizeof(block_header_t));

    auto block = (block_header_t*)ptr;
    block->magic = MEMBLOCK_MAGIC;
    block->size = size;

    count_malloc(size);

    return (char*)ptr + sizeof(block_header_t);
}

void free(void* ptr) {
    using namespace malloc_count;

    if(!ptr) return;

    auto block = (block_header_t*)((char*)ptr - sizeof(block_header_t));
    if(is_managed(block)) {
        count_free(block->size);
        __libc_free(block);
    } else {
        __libc_free(ptr);
    }
}

void* realloc(void* ptr, size_t size) {
    using namespace malloc_count;

    if(!size) {
        free(ptr);
        return NULL;
    } else if(!ptr) {
        return malloc(size);
    } else {
        auto block = (block_header_t*)((char*)ptr - sizeof(block_header_t));
        if(is_managed(block)) {
            void *new_ptr = __libc_realloc(block, size + sizeof(block_header_t));

            auto new_block = (block_header_t*)new_ptr;
            new_block->magic = MEMBLOCK_MAGIC; // just making sure
            new_block->size = size;

            count_free(block->size);
            count_malloc(size);

            return (char*)new_ptr + sizeof(block_header_t);
        } else {
            return __libc_realloc(ptr, size);
        }
    }
}

void* calloc(size_t num, size_t size) {
    size *= num;
    if(!size) return NULL;

    void* ptr = malloc(size);
    memset(ptr, 0, size);
    return ptr;
}

#endif
<commit_msg>Fixes #18823<commit_after>#include <malloc_count/malloc_count.hpp>

namespace malloc_count {
    #define PHASE_STACK_SIZE 16

    #define MEMBLOCK_MAGIC 0xFEDCBA9876543210
    struct block_header_t {
        size_t magic;
        size_t size;
    };

    size_t next_phase_id = 1;

    phase_t pstack[PHASE_STACK_SIZE];
    int pcur = -1;

    bool paused = false;

    void begin_phase() {
        pcur++;
        if(pcur >= PHASE_STACK_SIZE) throw "phase stack overflow";

        pstack[pcur].id = next_phase_id++;
        pstack[pcur].mem_off = (pcur > 0) ? pstack[pcur - 1].mem_current : 0;
        pstack[pcur].mem_peak = 0;
        pstack[pcur].mem_current = 0;
        pstack[pcur].time_start = current_time_millis();
    }

    phase_t end_phase() {
        if(pcur < 0) throw "ending a phase that never began";

        pstack[pcur].time_end = current_time_millis();
        pstack[pcur].id = SIZE_MAX; //invalidate

        return pstack[pcur--];
    }

    void pause_phase() {
        paused = true;
    }

    void resume_phase() {
        paused = false;
    }

    inline bool is_managed(block_header_t* block) {
        return (block->magic == MEMBLOCK_MAGIC);
    }

    inline void count_malloc(size_t size) {
        if(!paused && pcur >= 0) {
            for(int i = 0; i <= pcur; i++) {
                pstack[i].mem_current += size;
                if(pstack[i].mem_current > pstack[i].mem_peak) {
                    pstack[i].mem_peak = pstack[i].mem_current;
                }
            }
        }
    }

    inline void count_free(size_t size) {
        if(!paused && pcur >= 0) {
            for(int i = 0; i <= pcur; i++) {
                pstack[i].mem_current -= size;
            }
        }
    }
}

#ifdef __CYGWIN__

#pragma message("malloc overrides are not supported on Cygwin.")

#elif !defined(STATS_DISABLED)

void* malloc(size_t size) {
    using namespace malloc_count;

    if(!size) return NULL;

    void *ptr = __libc_malloc(size + sizeof(block_header_t));

    auto block = (block_header_t*)ptr;
    block->magic = MEMBLOCK_MAGIC;
    block->size = size;

    count_malloc(size);

    return (char*)ptr + sizeof(block_header_t);
}

void free(void* ptr) {
    using namespace malloc_count;

    if(!ptr) return;

    auto block = (block_header_t*)((char*)ptr - sizeof(block_header_t));
    if(is_managed(block)) {
        count_free(block->size);
        __libc_free(block);
    } else {
        __libc_free(ptr);
    }
}

void* realloc(void* ptr, size_t size) {
    using namespace malloc_count;

    if(!size) {
        free(ptr);
        return NULL;
    } else if(!ptr) {
        return malloc(size);
    } else {
        auto block = (block_header_t*)((char*)ptr - sizeof(block_header_t));
        if(is_managed(block)) {
            size_t old_size = block->size;
            void *new_ptr = __libc_realloc(block, size + sizeof(block_header_t));

            auto new_block = (block_header_t*)new_ptr;
            new_block->magic = MEMBLOCK_MAGIC; // just making sure
            new_block->size = size;

            count_free(old_size);
            count_malloc(size);

            return (char*)new_ptr + sizeof(block_header_t);
        } else {
            return __libc_realloc(ptr, size);
        }
    }
}

void* calloc(size_t num, size_t size) {
    size *= num;
    if(!size) return NULL;

    void* ptr = malloc(size);
    memset(ptr, 0, size);
    return ptr;
}

#endif
<|endoftext|>


<commit_before>// $Id: mesh_base_modification.C,v 1.2 2003-08-08 09:13:24 ddreyer Exp $

// The Next Great Finite Element Library.
// Copyright (C) 2002  Benjamin S. Kirk, John W. Peterson

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ includes
#include <map>

// Local includes
#include "mesh_base.h"
#include "libmesh.h"
#include "elem.h"
#include "mesh_logging.h"

// ------------------------------------------------------------
// Mesh class member functions for mesh modification
void MeshBase::all_second_order ()
{
  /*
   * when the mesh is not prepared,
   * at least renumber the nodes and
   * elements, so that the node ids
   * are correct
   */
  if (!this->_is_prepared)
      renumber_nodes_and_elements ();

  // does this work also in parallel?
  assert (this->n_processors() == 1);

  START_LOG("all_second_order()", "MeshBase");

  /*
   * the vector holding the new second-order
   * replacement elements
   */
  std::vector<Elem*> new_elements;
  new_elements.reserve(this->n_elem());

  /*
   * this map helps in identifying second order
   * nodes.  Namely, a second-order node:
   * - edge node
   * - face node
   * - bubble node
   * is uniquely defined through a set of adjacent
   * vertices.  This set of adjacent vertices is
   * used to identify already added higher-order
   * nodes.  We are safe to use node id's since we
   * make sure that these are correctly numbered.
   */
  std::map<std::vector<unsigned int>, Node*> adj_vertices_to_so_nodes;

  /*
   * for speed-up of the \p add_point() method, we
   * can reserve memory.  Guess the number of additional
   * nodes for different dimensions
   */
  switch (this->mesh_dimension())
  {
    case 1:
      /*
       * in 1D, there can only be order-increase from Edge2
       * to Edge3.  Something like 1/2 of n_nodes() have
       * to be added
       */
      this->_nodes.reserve(static_cast<unsigned int>(1.5*this->_nodes.size()));
      break;

    case 2:
      /*
       * in 2D, either refine from Tri3 to Tri6 (double the nodes)
       * or from Quad4 to Quad8 (again, double) or Quad9 (2.25 that much)
       */
      this->_nodes.reserve(static_cast<unsigned int>(2*this->_nodes.size()));
      break;

    case 3:
      /*
       * in 3D, either refine from Tet4 to Tet10 (factor = 2.5) up to
       * Hex8 to Hex27 (something  > 3).  Since in 3D there _are_ already
       * quite some nodes, and since we do not want to overburden the memory by
       * a too conservative guess, use the lower bound
       */
      this->_nodes.reserve(static_cast<unsigned int>(2.5*this->_nodes.size()));
      break;

    default:
	  // Hm?
	  error();
  }

  /*
   * iterate over all elements contained in the
   * mesh
   */
  elem_iterator       old_elements_it  (this->elements_begin());
  const elem_iterator old_elements_end (this->elements_end());

  for (; old_elements_it != old_elements_end; ++old_elements_it)
    {
      // the linear-order element
      Elem* lo_elem = *old_elements_it;

      // make sure it is linear order
      if (lo_elem->default_order() != FIRST)
        {
	  std::cerr << "ERROR: This is not a linear element: type="
		    << lo_elem->type() << std::endl;
	  error();
	}

      // this does _not_ work for refined elements
      assert (lo_elem->level () == 0);

      /*
       * build the second-order equivalent, add to
       * the new_elements list
       */
      Elem* so_elem = Elem::build (lo_elem->second_order_equivalent_type());
      assert (lo_elem->n_vertices() == so_elem->n_vertices());

      /*
       * By definition the vertices of the linear and
       * second order element are identically numbered.
       * transfer these.
       */
      for (unsigned int v=0; v < lo_elem->n_vertices(); v++)
	  so_elem->set_node(v) = lo_elem->get_node(v);

      /*
       * Now handle the additional mid-side nodes.  This
       * is simply handled through a map that remembers
       * the already-added nodes.  This map maps the global
       * ids of the vertices (that uniquely define this
       * higher-order node) to the new node.
       * Notation: son = second-order node
       */
      const unsigned int son_begin = so_elem->n_vertices();
      const unsigned int son_end   = so_elem->n_nodes();

      for (unsigned int son=son_begin; son<son_end; son++)
        {
	  const unsigned int n_adjacent_vertices = so_elem->n_second_order_adjacent_vertices(son);

	  /*
	   * form a vector that will hold the node id's of
	   * the vertices that are adjacent to the son-th
	   * second-order node
	   */
	  std::vector<unsigned int> adjacent_vertices_ids;
	  adjacent_vertices_ids.resize(n_adjacent_vertices);
	  for (unsigned int v=0; v<n_adjacent_vertices; v++)
	      adjacent_vertices_ids[v] = so_elem->node( so_elem->second_order_adjacent_vertex(son,v) );

	  /*
	   * \p adjacent_vertices_ids is now in order of the current
	   * side.  sort it, so that comparisons  with the
	   * \p adjacent_vertices_ids created through other elements'
	   * sides can match
	   */
	  std::sort(adjacent_vertices_ids.begin(), adjacent_vertices_ids.end());

	  // does this set of vertices already has a mid-node added?
	  std::map<std::vector<unsigned int>, Node*>::const_iterator pos =
	      adj_vertices_to_so_nodes.find(adjacent_vertices_ids);

	  if (pos == adj_vertices_to_so_nodes.end())
	    {
	      /*
	       * for this set of vertices, there is no
	       * second_order node yet.  Add it.
	       *
	       * compute the location of the new node as
	       * the average over the adjacent vertices.
	       */
	      Point new_location = this->point(adjacent_vertices_ids[0]);
	      for (unsigned int v=1; v<n_adjacent_vertices; v++)
		  new_location += this->point(adjacent_vertices_ids[v]);

	      new_location /= static_cast<Real>(n_adjacent_vertices);

	      // add the new point to the mesh
	      Node* so_node = this->add_point (new_location);

	      /*
	       * insert the new node with its defining vertex
	       * set into the map, and relocate pos to this
	       * new entry, so that the so_elem can use
	       * \p pos for inserting the node
	       */
	      adj_vertices_to_so_nodes.insert(std::make_pair(adjacent_vertices_ids, so_node));

	      so_elem->set_node(son) = so_node;
	    }
	  else
	      so_elem->set_node(son) = pos->second;

	}

      /*
       * The new second-order element is ready.
       * Add it to the new_elements vector
       */
      new_elements.push_back(so_elem);

    }

  // we can clear the map
  adj_vertices_to_so_nodes.clear();

  /*
   * the \p _elements vector has to be replaced
   * by the \p new_elements vector.  Delete the
   * old element, then put the new element in place.
   */
  {
    for (unsigned int e=0; e<_elements.size(); e++)
      {
	assert (_elements[e] != NULL);
	delete _elements[e];
	_elements[e] = new_elements[e];
      }

    // now we can safely clear our local \p new_elements vector
    new_elements.clear();
  }

  STOP_LOG("all_second_order()", "MeshBase");

  // renumber nodes, elements etc
  this->prepare_for_use();
}

<commit_msg>added #include <algorithm> for std::sort<commit_after>// $Id: mesh_base_modification.C,v 1.3 2003-08-15 19:14:13 benkirk Exp $

// The Next Great Finite Element Library.
// Copyright (C) 2002  Benjamin S. Kirk, John W. Peterson

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ includes
#include <algorithm>
#include <map>

// Local includes
#include "mesh_base.h"
#include "libmesh.h"
#include "elem.h"
#include "mesh_logging.h"

// ------------------------------------------------------------
// Mesh class member functions for mesh modification
void MeshBase::all_second_order ()
{
  /*
   * when the mesh is not prepared,
   * at least renumber the nodes and
   * elements, so that the node ids
   * are correct
   */
  if (!this->_is_prepared)
      renumber_nodes_and_elements ();

  // does this work also in parallel?
  assert (this->n_processors() == 1);

  START_LOG("all_second_order()", "MeshBase");

  /*
   * the vector holding the new second-order
   * replacement elements
   */
  std::vector<Elem*> new_elements;
  new_elements.reserve(this->n_elem());

  /*
   * this map helps in identifying second order
   * nodes.  Namely, a second-order node:
   * - edge node
   * - face node
   * - bubble node
   * is uniquely defined through a set of adjacent
   * vertices.  This set of adjacent vertices is
   * used to identify already added higher-order
   * nodes.  We are safe to use node id's since we
   * make sure that these are correctly numbered.
   */
  std::map<std::vector<unsigned int>, Node*> adj_vertices_to_so_nodes;

  /*
   * for speed-up of the \p add_point() method, we
   * can reserve memory.  Guess the number of additional
   * nodes for different dimensions
   */
  switch (this->mesh_dimension())
  {
    case 1:
      /*
       * in 1D, there can only be order-increase from Edge2
       * to Edge3.  Something like 1/2 of n_nodes() have
       * to be added
       */
      this->_nodes.reserve(static_cast<unsigned int>(1.5*this->_nodes.size()));
      break;

    case 2:
      /*
       * in 2D, either refine from Tri3 to Tri6 (double the nodes)
       * or from Quad4 to Quad8 (again, double) or Quad9 (2.25 that much)
       */
      this->_nodes.reserve(static_cast<unsigned int>(2*this->_nodes.size()));
      break;

    case 3:
      /*
       * in 3D, either refine from Tet4 to Tet10 (factor = 2.5) up to
       * Hex8 to Hex27 (something  > 3).  Since in 3D there _are_ already
       * quite some nodes, and since we do not want to overburden the memory by
       * a too conservative guess, use the lower bound
       */
      this->_nodes.reserve(static_cast<unsigned int>(2.5*this->_nodes.size()));
      break;

    default:
	  // Hm?
	  error();
  }

  /*
   * iterate over all elements contained in the
   * mesh
   */
  elem_iterator       old_elements_it  (this->elements_begin());
  const elem_iterator old_elements_end (this->elements_end());

  for (; old_elements_it != old_elements_end; ++old_elements_it)
    {
      // the linear-order element
      Elem* lo_elem = *old_elements_it;

      // make sure it is linear order
      if (lo_elem->default_order() != FIRST)
        {
	  std::cerr << "ERROR: This is not a linear element: type="
		    << lo_elem->type() << std::endl;
	  error();
	}

      // this does _not_ work for refined elements
      assert (lo_elem->level () == 0);

      /*
       * build the second-order equivalent, add to
       * the new_elements list
       */
      Elem* so_elem = Elem::build (lo_elem->second_order_equivalent_type());
      assert (lo_elem->n_vertices() == so_elem->n_vertices());

      /*
       * By definition the vertices of the linear and
       * second order element are identically numbered.
       * transfer these.
       */
      for (unsigned int v=0; v < lo_elem->n_vertices(); v++)
	  so_elem->set_node(v) = lo_elem->get_node(v);

      /*
       * Now handle the additional mid-side nodes.  This
       * is simply handled through a map that remembers
       * the already-added nodes.  This map maps the global
       * ids of the vertices (that uniquely define this
       * higher-order node) to the new node.
       * Notation: son = second-order node
       */
      const unsigned int son_begin = so_elem->n_vertices();
      const unsigned int son_end   = so_elem->n_nodes();

      for (unsigned int son=son_begin; son<son_end; son++)
        {
	  const unsigned int n_adjacent_vertices = so_elem->n_second_order_adjacent_vertices(son);

	  /*
	   * form a vector that will hold the node id's of
	   * the vertices that are adjacent to the son-th
	   * second-order node
	   */
	  std::vector<unsigned int> adjacent_vertices_ids;
	  adjacent_vertices_ids.resize(n_adjacent_vertices);
	  for (unsigned int v=0; v<n_adjacent_vertices; v++)
	      adjacent_vertices_ids[v] = so_elem->node( so_elem->second_order_adjacent_vertex(son,v) );

	  /*
	   * \p adjacent_vertices_ids is now in order of the current
	   * side.  sort it, so that comparisons  with the
	   * \p adjacent_vertices_ids created through other elements'
	   * sides can match
	   */
	  std::sort(adjacent_vertices_ids.begin(), adjacent_vertices_ids.end());

	  // does this set of vertices already has a mid-node added?
	  std::map<std::vector<unsigned int>, Node*>::const_iterator pos =
	      adj_vertices_to_so_nodes.find(adjacent_vertices_ids);

	  if (pos == adj_vertices_to_so_nodes.end())
	    {
	      /*
	       * for this set of vertices, there is no
	       * second_order node yet.  Add it.
	       *
	       * compute the location of the new node as
	       * the average over the adjacent vertices.
	       */
	      Point new_location = this->point(adjacent_vertices_ids[0]);
	      for (unsigned int v=1; v<n_adjacent_vertices; v++)
		  new_location += this->point(adjacent_vertices_ids[v]);

	      new_location /= static_cast<Real>(n_adjacent_vertices);

	      // add the new point to the mesh
	      Node* so_node = this->add_point (new_location);

	      /*
	       * insert the new node with its defining vertex
	       * set into the map, and relocate pos to this
	       * new entry, so that the so_elem can use
	       * \p pos for inserting the node
	       */
	      adj_vertices_to_so_nodes.insert(std::make_pair(adjacent_vertices_ids, so_node));

	      so_elem->set_node(son) = so_node;
	    }
	  else
	      so_elem->set_node(son) = pos->second;

	}

      /*
       * The new second-order element is ready.
       * Add it to the new_elements vector
       */
      new_elements.push_back(so_elem);

    }

  // we can clear the map
  adj_vertices_to_so_nodes.clear();

  /*
   * the \p _elements vector has to be replaced
   * by the \p new_elements vector.  Delete the
   * old element, then put the new element in place.
   */
  {
    for (unsigned int e=0; e<_elements.size(); e++)
      {
	assert (_elements[e] != NULL);
	delete _elements[e];
	_elements[e] = new_elements[e];
      }

    // now we can safely clear our local \p new_elements vector
    new_elements.clear();
  }

  STOP_LOG("all_second_order()", "MeshBase");

  // renumber nodes, elements etc
  this->prepare_for_use();
}

<|endoftext|>


<commit_before><commit_msg>Linux: when reading html from clipboard, interpret BOM to mean that the encoding is UTF-16. Otherwise, continue assuming it's utf-8.<commit_after><|endoftext|>


<commit_before><commit_msg>more stable ragdolls<commit_after><|endoftext|>


<commit_before>#include <plasp/sas/Description.h>

#include <iostream>

#include <boost/filesystem.hpp>

#include <plasp/sas/ParserException.h>

namespace plasp
{
namespace sas
{

////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Description
//
////////////////////////////////////////////////////////////////////////////////////////////////////

Description::Description()
:	m_usesActionCosts{false}
{
}

////////////////////////////////////////////////////////////////////////////////////////////////////

Description Description::fromFile(const boost::filesystem::path &path)
{
	Description description;

	setlocale(LC_NUMERIC, "C");

	if (!boost::filesystem::is_regular_file(path))
	{
		std::cerr << "Error: File does not exist: " << path.string() << std::endl;
		return description;
	}

	std::ifstream fileStream(path.string(), std::ios::in);
	fileStream.exceptions(std::ifstream::failbit | std::ifstream::badbit);

	description.parseVersionSection(fileStream);
	description.parseMetricSection(fileStream);
	description.parseVariablesSection(fileStream);
	description.parseMutexSection(fileStream);
	description.parseInitialStateSection(fileStream);
	description.parseGoalSection(fileStream);
	description.parseOperatorSection(fileStream);
	description.parseAxiomSection(fileStream);

	return description;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Description::print(std::ostream &ostream) const
{
	// Metric section
	ostream << "uses action costs: " << (m_usesActionCosts ? "yes" : "no") << std::endl;

	// Variable section
	ostream << "variables: " << m_variables.size() << std::endl;

	std::for_each(m_variables.cbegin(), m_variables.cend(),
		[&](const auto &variable)
		{
			ostream << "\t" << variable.name << std::endl;
			ostream << "\t\tvalues: " << variable.values.size() << std::endl;

			std::for_each(variable.values.cbegin(), variable.values.cend(),
				[&](const auto &value)
			    {
					ostream << "\t\t\t" << value.name << std::endl;
				});

			ostream << "\t\taxiom layer: " << variable.axiomLayer << std::endl;
		});

	// Mutex section
	ostream << "mutex groups: " << m_mutexGroups.size() << std::endl;

	std::for_each(m_mutexGroups.cbegin(), m_mutexGroups.cend(),
		[&](const auto &mutexGroup)
		{
			ostream << "\tmutex group:" << std::endl;

			std::for_each(mutexGroup.facts.cbegin(), mutexGroup.facts.cend(),
				[&](const auto &fact)
				{
					ostream << "\t\t" << fact.variable.name << " = " << fact.value.name << std::endl;
				});
		});

	// Initial state section
	ostream << "initial state:" << std::endl;

	std::for_each(m_initialStateFacts.cbegin(), m_initialStateFacts.cend(),
		[&](const auto &initialStateFact)
		{
			ostream << "\t" << initialStateFact.variable.name << " = " << initialStateFact.value.name << std::endl;
		});

	// Goal section
	ostream << "goal:" << std::endl;

	std::for_each(m_goalFacts.cbegin(), m_goalFacts.cend(),
		[&](const auto &goalFact)
		{
			ostream << "\t" << goalFact.variable.name << " = " << goalFact.value.name << std::endl;
		});

	// Operator section
	ostream << "operators: " << m_operators.size() << std::endl;

	std::for_each(m_operators.cbegin(), m_operators.cend(),
		[&](const auto &operator_)
		{
			ostream << "\t" << operator_.name << std::endl;
			ostream << "\t\tpreconditions: " << operator_.preconditions.size() << std::endl;

			std::for_each(operator_.preconditions.cbegin(), operator_.preconditions.cend(),
				[&](const auto &precondition)
				{
					std::cout << "\t\t\t" << precondition.variable.name << " = " << precondition.value.name << std::endl;
				});

			ostream << "\t\teffects: " << operator_.effects.size() << std::endl;

			std::for_each(operator_.effects.cbegin(), operator_.effects.cend(),
				[&](const auto &effect)
				{
					ostream << "\t\t\teffect:" << std::endl;
					ostream << "\t\t\t\tconditions: " << effect.conditions.size() << std::endl;

					std::for_each(effect.conditions.cbegin(), effect.conditions.cend(),
						[&](const auto &condition)
						{
							ostream << "\t\t\t\t\t" << condition.variable.name << " = " << condition.value.name << std::endl;
						});

					ostream << "\t\t\t\tpostcondition:" << std::endl;
					ostream << "\t\t\t\t\t" << effect.postcondition.variable.name << " = " << effect.postcondition.value.name << std::endl;
				});

			ostream << "\t\tcosts: " << operator_.costs << std::endl;
		});

	// Axiom section
	ostream << "axiom rules: " << m_axiomRules.size() << std::endl;

	std::for_each(m_axiomRules.cbegin(), m_axiomRules.cend(),
		[&](const auto &axiomRule)
		{
			ostream << "\taxiom rule:" << std::endl;
			ostream << "\t\tconditions: " << axiomRule.conditions.size() << std::endl;

			std::for_each(axiomRule.conditions.cbegin(), axiomRule.conditions.cend(),
				[&](const auto &condition)
				{
					ostream << "\t\t\t" << condition.variable.name << " = " << condition.value.name << std::endl;
				});

			ostream << "\t\tpostcondition:" << std::endl;
			ostream << "\t\t\t" << axiomRule.postcondition.variable.name << " = " << axiomRule.postcondition.value.name << std::endl;
		});
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Description::parseSectionIdentifier(std::istream &istream, const std::string &expectedSectionIdentifier) const
{
	const auto sectionIdentifier = parse<std::string>(istream);

	if (sectionIdentifier != expectedSectionIdentifier)
		throw ParserException("Invalid format, expected " + expectedSectionIdentifier + ", got " + sectionIdentifier);
}

////////////////////////////////////////////////////////////////////////////////////////////////////

template<class T>
T Description::parse(std::istream &istream) const
{
	T value;

	try
	{
		istream >> value;
	}
	catch (const std::exception &e)
	{
		throw ParserException(std::string("Could not parse value of type ") + typeid(T).name() + " (" + e.what() + ")");
	}

	return value;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

const Variable &Description::parseVariable(std::istream &istream) const
{
	const auto variableID = parse<size_t>(istream);

	if (variableID >= m_variables.size())
		throw ParserException("Variable index out of range (index " + std::to_string(variableID) + ")");

	return m_variables[variableID];
}

////////////////////////////////////////////////////////////////////////////////////////////////////

const Value &Description::parseValue(std::istream &istream, const Variable &variable) const
{
	const auto valueID = parse<int>(istream);

	if (valueID == -1)
		return Value::Any;

	if (valueID < 0 || static_cast<size_t>(valueID) >= variable.values.size())
		throw ParserException("Value index out of range (variable " + variable.name + ", index " + std::to_string(valueID) + ")");

	return variable.values[valueID];
}

////////////////////////////////////////////////////////////////////////////////////////////////////

AssignedVariable Description::parseAssignedVariable(std::istream &istream) const
{
	const auto &variable = parseVariable(istream);
	const auto &value = parseValue(istream, variable);

	return {variable, value};
}

////////////////////////////////////////////////////////////////////////////////////////////////////

VariableTransition Description::parseVariableTransition(std::istream &istream) const
{
	const auto &variable = parseVariable(istream);
	const auto &valueBefore = parseValue(istream, variable);
	const auto &valueAfter = parseValue(istream, variable);

	return {variable, valueBefore, valueAfter};
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Description::parseVersionSection(std::istream &istream) const
{
	// Version section
	parseSectionIdentifier(istream, "begin_version");

	const auto formatVersion = parse<size_t>(istream);

	if (formatVersion != 3)
		throw ParserException("Unsupported SAS format version (" + std::to_string(formatVersion) + ")");

	std::cout << "SAS format version: " << formatVersion << std::endl;

	parseSectionIdentifier(istream, "end_version");
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Description::parseMetricSection(std::istream &istream)
{
	parseSectionIdentifier(istream, "begin_metric");

	istream >> m_usesActionCosts;

	parseSectionIdentifier(istream, "end_metric");
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Description::parseVariablesSection(std::istream &istream)
{
	const auto numberOfVariables = parse<size_t>(istream);
	m_variables.resize(numberOfVariables);

	for (size_t i = 0; i < numberOfVariables; i++)
	{
		auto &variable = m_variables[i];

		parseSectionIdentifier(istream, "begin_variable");

		variable.name = parse<std::string>(istream);
		variable.axiomLayer = parse<int>(istream);

		const auto numberOfValues = parse<size_t>(istream);
		variable.values.resize(numberOfValues);

		istream.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

		for (size_t j = 0; j < numberOfValues; j++)
		{
			auto &value = variable.values[j];
			std::getline(istream, value.name);
		}

		parseSectionIdentifier(istream, "end_variable");
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Description::parseMutexSection(std::istream &istream)
{
	const auto numberOfMutexGroups = parse<size_t>(istream);
	m_mutexGroups.resize(numberOfMutexGroups);

	for (size_t i = 0; i < numberOfMutexGroups; i++)
	{
		parseSectionIdentifier(istream, "begin_mutex_group");

		auto &mutexGroup = m_mutexGroups[i];

		const auto numberOfFacts = parse<size_t>(istream);
		mutexGroup.facts.reserve(numberOfFacts);

		for (size_t j = 0; j < numberOfFacts; j++)
		{
			const auto fact = parseAssignedVariable(istream);
			mutexGroup.facts.push_back(std::move(fact));
		}

		parseSectionIdentifier(istream, "end_mutex_group");
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Description::parseInitialStateSection(std::istream &istream)
{
	parseSectionIdentifier(istream, "begin_state");

	m_initialStateFacts.reserve(m_variables.size());

	for (size_t i = 0; i < m_variables.size(); i++)
	{
		const auto &variable = m_variables[i];
		const auto &value = parseValue(istream, variable);

		m_initialStateFacts.push_back({variable, value});
	}

	parseSectionIdentifier(istream, "end_state");
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Description::parseGoalSection(std::istream &istream)
{
	parseSectionIdentifier(istream, "begin_goal");

	const auto numberOfGoalFacts = parse<size_t>(istream);
	m_goalFacts.reserve(numberOfGoalFacts);

	for (size_t i = 0; i < numberOfGoalFacts; i++)
	{
		const auto goalFact = parseAssignedVariable(istream);
		m_goalFacts.push_back(std::move(goalFact));
	}

	parseSectionIdentifier(istream, "end_goal");
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Description::parseOperatorSection(std::istream &istream)
{
	const auto numberOfOperators = parse<size_t>(istream);
	m_operators.resize(numberOfOperators);

	for (size_t i = 0; i < numberOfOperators; i++)
	{
		parseSectionIdentifier(istream, "begin_operator");

		istream.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

		auto &operator_ = m_operators[i];
		std::getline(istream, operator_.name);

		const auto numberOfPrevailConditions = parse<size_t>(istream);
		operator_.preconditions.reserve(numberOfPrevailConditions);

		for (size_t j = 0; j < numberOfPrevailConditions; j++)
		{
			const auto precondition = parseAssignedVariable(istream);
			operator_.preconditions.push_back(std::move(precondition));
		}

		const auto numberOfEffects = parse<size_t>(istream);
		operator_.effects.reserve(numberOfEffects);

		for (size_t j = 0; j < numberOfEffects; j++)
		{
			Effect::Conditions conditions;

			const auto numberOfEffectConditions = parse<size_t>(istream);
			conditions.reserve(numberOfEffectConditions);

			for (size_t k = 0; k < numberOfEffectConditions; k++)
			{
				const auto condition = parseAssignedVariable(istream);
				conditions.push_back(std::move(condition));
			}

			const auto variableTransition = parseVariableTransition(istream);

			if (&variableTransition.valueBefore != &Value::Any)
				operator_.preconditions.push_back({variableTransition.variable, variableTransition.valueBefore});

			const Effect::Condition postcondition = {variableTransition.variable, variableTransition.valueAfter};
			const Effect effect = {std::move(conditions), std::move(postcondition)};
			operator_.effects.push_back(std::move(effect));
		}

		operator_.costs = parse<size_t>(istream);

		parseSectionIdentifier(istream, "end_operator");
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Description::parseAxiomSection(std::istream &istream)
{
	const auto numberOfAxiomRules = parse<size_t>(istream);
	m_axiomRules.reserve(numberOfAxiomRules);

	std::cout << "Axiom rules: " << numberOfAxiomRules << std::endl;

	for (size_t i = 0; i < numberOfAxiomRules; i++)
	{
		parseSectionIdentifier(istream, "begin_rule");

		const auto numberOfConditions = parse<size_t>(istream);

		AxiomRule::Conditions conditions;
		conditions.reserve(numberOfConditions);

		for (size_t j = 0; j < numberOfConditions; j++)
		{
			const auto condition = parseAssignedVariable(istream);
			conditions.push_back(std::move(condition));
		}

		const auto variableTransition = parseVariableTransition(istream);

		if (&variableTransition.valueBefore != &Value::Any)
			conditions.push_back({variableTransition.variable, variableTransition.valueBefore});

		const AxiomRule::Condition postcondition = {variableTransition.variable, variableTransition.valueAfter};
		const AxiomRule axiomRule = {std::move(conditions), std::move(postcondition)};
		m_axiomRules.push_back(std::move(axiomRule));

		parseSectionIdentifier(istream, "end_rule");
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////

}
}
<commit_msg>Unified parsing of Boolean variable.<commit_after>#include <plasp/sas/Description.h>

#include <iostream>

#include <boost/filesystem.hpp>

#include <plasp/sas/ParserException.h>

namespace plasp
{
namespace sas
{

////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Description
//
////////////////////////////////////////////////////////////////////////////////////////////////////

Description::Description()
:	m_usesActionCosts{false}
{
}

////////////////////////////////////////////////////////////////////////////////////////////////////

Description Description::fromFile(const boost::filesystem::path &path)
{
	Description description;

	setlocale(LC_NUMERIC, "C");

	if (!boost::filesystem::is_regular_file(path))
	{
		std::cerr << "Error: File does not exist: " << path.string() << std::endl;
		return description;
	}

	std::ifstream fileStream(path.string(), std::ios::in);
	fileStream.exceptions(std::ifstream::failbit | std::ifstream::badbit);

	description.parseVersionSection(fileStream);
	description.parseMetricSection(fileStream);
	description.parseVariablesSection(fileStream);
	description.parseMutexSection(fileStream);
	description.parseInitialStateSection(fileStream);
	description.parseGoalSection(fileStream);
	description.parseOperatorSection(fileStream);
	description.parseAxiomSection(fileStream);

	return description;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Description::print(std::ostream &ostream) const
{
	// Metric section
	ostream << "uses action costs: " << (m_usesActionCosts ? "yes" : "no") << std::endl;

	// Variable section
	ostream << "variables: " << m_variables.size() << std::endl;

	std::for_each(m_variables.cbegin(), m_variables.cend(),
		[&](const auto &variable)
		{
			ostream << "\t" << variable.name << std::endl;
			ostream << "\t\tvalues: " << variable.values.size() << std::endl;

			std::for_each(variable.values.cbegin(), variable.values.cend(),
				[&](const auto &value)
			    {
					ostream << "\t\t\t" << value.name << std::endl;
				});

			ostream << "\t\taxiom layer: " << variable.axiomLayer << std::endl;
		});

	// Mutex section
	ostream << "mutex groups: " << m_mutexGroups.size() << std::endl;

	std::for_each(m_mutexGroups.cbegin(), m_mutexGroups.cend(),
		[&](const auto &mutexGroup)
		{
			ostream << "\tmutex group:" << std::endl;

			std::for_each(mutexGroup.facts.cbegin(), mutexGroup.facts.cend(),
				[&](const auto &fact)
				{
					ostream << "\t\t" << fact.variable.name << " = " << fact.value.name << std::endl;
				});
		});

	// Initial state section
	ostream << "initial state:" << std::endl;

	std::for_each(m_initialStateFacts.cbegin(), m_initialStateFacts.cend(),
		[&](const auto &initialStateFact)
		{
			ostream << "\t" << initialStateFact.variable.name << " = " << initialStateFact.value.name << std::endl;
		});

	// Goal section
	ostream << "goal:" << std::endl;

	std::for_each(m_goalFacts.cbegin(), m_goalFacts.cend(),
		[&](const auto &goalFact)
		{
			ostream << "\t" << goalFact.variable.name << " = " << goalFact.value.name << std::endl;
		});

	// Operator section
	ostream << "operators: " << m_operators.size() << std::endl;

	std::for_each(m_operators.cbegin(), m_operators.cend(),
		[&](const auto &operator_)
		{
			ostream << "\t" << operator_.name << std::endl;
			ostream << "\t\tpreconditions: " << operator_.preconditions.size() << std::endl;

			std::for_each(operator_.preconditions.cbegin(), operator_.preconditions.cend(),
				[&](const auto &precondition)
				{
					std::cout << "\t\t\t" << precondition.variable.name << " = " << precondition.value.name << std::endl;
				});

			ostream << "\t\teffects: " << operator_.effects.size() << std::endl;

			std::for_each(operator_.effects.cbegin(), operator_.effects.cend(),
				[&](const auto &effect)
				{
					ostream << "\t\t\teffect:" << std::endl;
					ostream << "\t\t\t\tconditions: " << effect.conditions.size() << std::endl;

					std::for_each(effect.conditions.cbegin(), effect.conditions.cend(),
						[&](const auto &condition)
						{
							ostream << "\t\t\t\t\t" << condition.variable.name << " = " << condition.value.name << std::endl;
						});

					ostream << "\t\t\t\tpostcondition:" << std::endl;
					ostream << "\t\t\t\t\t" << effect.postcondition.variable.name << " = " << effect.postcondition.value.name << std::endl;
				});

			ostream << "\t\tcosts: " << operator_.costs << std::endl;
		});

	// Axiom section
	ostream << "axiom rules: " << m_axiomRules.size() << std::endl;

	std::for_each(m_axiomRules.cbegin(), m_axiomRules.cend(),
		[&](const auto &axiomRule)
		{
			ostream << "\taxiom rule:" << std::endl;
			ostream << "\t\tconditions: " << axiomRule.conditions.size() << std::endl;

			std::for_each(axiomRule.conditions.cbegin(), axiomRule.conditions.cend(),
				[&](const auto &condition)
				{
					ostream << "\t\t\t" << condition.variable.name << " = " << condition.value.name << std::endl;
				});

			ostream << "\t\tpostcondition:" << std::endl;
			ostream << "\t\t\t" << axiomRule.postcondition.variable.name << " = " << axiomRule.postcondition.value.name << std::endl;
		});
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Description::parseSectionIdentifier(std::istream &istream, const std::string &expectedSectionIdentifier) const
{
	const auto sectionIdentifier = parse<std::string>(istream);

	if (sectionIdentifier != expectedSectionIdentifier)
		throw ParserException("Invalid format, expected " + expectedSectionIdentifier + ", got " + sectionIdentifier);
}

////////////////////////////////////////////////////////////////////////////////////////////////////

template<class T>
T Description::parse(std::istream &istream) const
{
	T value;

	try
	{
		istream >> value;
	}
	catch (const std::exception &e)
	{
		throw ParserException(std::string("Could not parse value of type ") + typeid(T).name() + " (" + e.what() + ")");
	}

	return value;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

const Variable &Description::parseVariable(std::istream &istream) const
{
	const auto variableID = parse<size_t>(istream);

	if (variableID >= m_variables.size())
		throw ParserException("Variable index out of range (index " + std::to_string(variableID) + ")");

	return m_variables[variableID];
}

////////////////////////////////////////////////////////////////////////////////////////////////////

const Value &Description::parseValue(std::istream &istream, const Variable &variable) const
{
	const auto valueID = parse<int>(istream);

	if (valueID == -1)
		return Value::Any;

	if (valueID < 0 || static_cast<size_t>(valueID) >= variable.values.size())
		throw ParserException("Value index out of range (variable " + variable.name + ", index " + std::to_string(valueID) + ")");

	return variable.values[valueID];
}

////////////////////////////////////////////////////////////////////////////////////////////////////

AssignedVariable Description::parseAssignedVariable(std::istream &istream) const
{
	const auto &variable = parseVariable(istream);
	const auto &value = parseValue(istream, variable);

	return {variable, value};
}

////////////////////////////////////////////////////////////////////////////////////////////////////

VariableTransition Description::parseVariableTransition(std::istream &istream) const
{
	const auto &variable = parseVariable(istream);
	const auto &valueBefore = parseValue(istream, variable);
	const auto &valueAfter = parseValue(istream, variable);

	return {variable, valueBefore, valueAfter};
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Description::parseVersionSection(std::istream &istream) const
{
	// Version section
	parseSectionIdentifier(istream, "begin_version");

	const auto formatVersion = parse<size_t>(istream);

	if (formatVersion != 3)
		throw ParserException("Unsupported SAS format version (" + std::to_string(formatVersion) + ")");

	std::cout << "SAS format version: " << formatVersion << std::endl;

	parseSectionIdentifier(istream, "end_version");
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Description::parseMetricSection(std::istream &istream)
{
	parseSectionIdentifier(istream, "begin_metric");

	m_usesActionCosts = parse<bool>(istream);

	parseSectionIdentifier(istream, "end_metric");
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Description::parseVariablesSection(std::istream &istream)
{
	const auto numberOfVariables = parse<size_t>(istream);
	m_variables.resize(numberOfVariables);

	for (size_t i = 0; i < numberOfVariables; i++)
	{
		auto &variable = m_variables[i];

		parseSectionIdentifier(istream, "begin_variable");

		variable.name = parse<std::string>(istream);
		variable.axiomLayer = parse<int>(istream);

		const auto numberOfValues = parse<size_t>(istream);
		variable.values.resize(numberOfValues);

		istream.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

		for (size_t j = 0; j < numberOfValues; j++)
		{
			auto &value = variable.values[j];
			std::getline(istream, value.name);
		}

		parseSectionIdentifier(istream, "end_variable");
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Description::parseMutexSection(std::istream &istream)
{
	const auto numberOfMutexGroups = parse<size_t>(istream);
	m_mutexGroups.resize(numberOfMutexGroups);

	for (size_t i = 0; i < numberOfMutexGroups; i++)
	{
		parseSectionIdentifier(istream, "begin_mutex_group");

		auto &mutexGroup = m_mutexGroups[i];

		const auto numberOfFacts = parse<size_t>(istream);
		mutexGroup.facts.reserve(numberOfFacts);

		for (size_t j = 0; j < numberOfFacts; j++)
		{
			const auto fact = parseAssignedVariable(istream);
			mutexGroup.facts.push_back(std::move(fact));
		}

		parseSectionIdentifier(istream, "end_mutex_group");
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Description::parseInitialStateSection(std::istream &istream)
{
	parseSectionIdentifier(istream, "begin_state");

	m_initialStateFacts.reserve(m_variables.size());

	for (size_t i = 0; i < m_variables.size(); i++)
	{
		const auto &variable = m_variables[i];
		const auto &value = parseValue(istream, variable);

		m_initialStateFacts.push_back({variable, value});
	}

	parseSectionIdentifier(istream, "end_state");
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Description::parseGoalSection(std::istream &istream)
{
	parseSectionIdentifier(istream, "begin_goal");

	const auto numberOfGoalFacts = parse<size_t>(istream);
	m_goalFacts.reserve(numberOfGoalFacts);

	for (size_t i = 0; i < numberOfGoalFacts; i++)
	{
		const auto goalFact = parseAssignedVariable(istream);
		m_goalFacts.push_back(std::move(goalFact));
	}

	parseSectionIdentifier(istream, "end_goal");
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Description::parseOperatorSection(std::istream &istream)
{
	const auto numberOfOperators = parse<size_t>(istream);
	m_operators.resize(numberOfOperators);

	for (size_t i = 0; i < numberOfOperators; i++)
	{
		parseSectionIdentifier(istream, "begin_operator");

		istream.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

		auto &operator_ = m_operators[i];
		std::getline(istream, operator_.name);

		const auto numberOfPrevailConditions = parse<size_t>(istream);
		operator_.preconditions.reserve(numberOfPrevailConditions);

		for (size_t j = 0; j < numberOfPrevailConditions; j++)
		{
			const auto precondition = parseAssignedVariable(istream);
			operator_.preconditions.push_back(std::move(precondition));
		}

		const auto numberOfEffects = parse<size_t>(istream);
		operator_.effects.reserve(numberOfEffects);

		for (size_t j = 0; j < numberOfEffects; j++)
		{
			Effect::Conditions conditions;

			const auto numberOfEffectConditions = parse<size_t>(istream);
			conditions.reserve(numberOfEffectConditions);

			for (size_t k = 0; k < numberOfEffectConditions; k++)
			{
				const auto condition = parseAssignedVariable(istream);
				conditions.push_back(std::move(condition));
			}

			const auto variableTransition = parseVariableTransition(istream);

			if (&variableTransition.valueBefore != &Value::Any)
				operator_.preconditions.push_back({variableTransition.variable, variableTransition.valueBefore});

			const Effect::Condition postcondition = {variableTransition.variable, variableTransition.valueAfter};
			const Effect effect = {std::move(conditions), std::move(postcondition)};
			operator_.effects.push_back(std::move(effect));
		}

		operator_.costs = parse<size_t>(istream);

		parseSectionIdentifier(istream, "end_operator");
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Description::parseAxiomSection(std::istream &istream)
{
	const auto numberOfAxiomRules = parse<size_t>(istream);
	m_axiomRules.reserve(numberOfAxiomRules);

	std::cout << "Axiom rules: " << numberOfAxiomRules << std::endl;

	for (size_t i = 0; i < numberOfAxiomRules; i++)
	{
		parseSectionIdentifier(istream, "begin_rule");

		const auto numberOfConditions = parse<size_t>(istream);

		AxiomRule::Conditions conditions;
		conditions.reserve(numberOfConditions);

		for (size_t j = 0; j < numberOfConditions; j++)
		{
			const auto condition = parseAssignedVariable(istream);
			conditions.push_back(std::move(condition));
		}

		const auto variableTransition = parseVariableTransition(istream);

		if (&variableTransition.valueBefore != &Value::Any)
			conditions.push_back({variableTransition.variable, variableTransition.valueBefore});

		const AxiomRule::Condition postcondition = {variableTransition.variable, variableTransition.valueAfter};
		const AxiomRule axiomRule = {std::move(conditions), std::move(postcondition)};
		m_axiomRules.push_back(std::move(axiomRule));

		parseSectionIdentifier(istream, "end_rule");
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////

}
}
<|endoftext|>


<commit_before>/* Copyright (c) 2013-2014 Jeffrey Pfau
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "KeyEditor.h"

#include "GamepadAxisEvent.h"
#include "GamepadButtonEvent.h"
#include "ShortcutController.h"

#include <QKeyEvent>

using namespace QGBA;

KeyEditor::KeyEditor(QWidget* parent)
	: QLineEdit(parent)
	, m_direction(GamepadAxisEvent::NEUTRAL)
	, m_key(-1)
	, m_axis(-1)
	, m_button(false)
{
	setAlignment(Qt::AlignCenter);
	setFocusPolicy(Qt::ClickFocus);
	m_lastKey.setSingleShot(true);
}

void KeyEditor::setValue(int key) {
	m_key = key;
	if (m_button) {
		updateButtonText();
	} else {
		if (key < 0) {
			setText(tr("---"));
		} else {
			setText(QKeySequence(key).toString(QKeySequence::NativeText));
		}
	}
	emit valueChanged(key);
}

void KeyEditor::setValueKey(int key) {
	m_button = false;
	setValue(key);
}

void KeyEditor::setValueButton(int button) {
	m_button = true;
	setValue(button);
}

void KeyEditor::setValueAxis(int axis, int32_t value) {
	m_button = true;
	m_axis = axis;
	m_direction = value < 0 ? GamepadAxisEvent::NEGATIVE : GamepadAxisEvent::POSITIVE;
	updateButtonText();
	emit axisChanged(axis, m_direction);
}

void KeyEditor::clearButton() {
	m_button = true;
	setValue(-1);
}

void KeyEditor::clearAxis() {
	m_button = true;
	m_axis = -1;
	m_direction = GamepadAxisEvent::NEUTRAL;
	updateButtonText();
	emit axisChanged(m_axis, m_direction);
}

QSize KeyEditor::sizeHint() const {
	QSize hint = QLineEdit::sizeHint();
	hint.setWidth(50);
	return hint;
}

void KeyEditor::keyPressEvent(QKeyEvent* event) {
	if (!m_button) {
		if (m_key < 0 || !m_lastKey.isActive()) {
			m_key = 0;
		}
		m_lastKey.start(KEY_TIME);
		if (m_key) {
			if (ShortcutController::isModifierKey(m_key)) {
				switch (event->key()) {
				case Qt::Key_Shift:
					setValue(Qt::ShiftModifier);
					break;
				case Qt::Key_Control:
					setValue(Qt::ControlModifier);
					break;
				case Qt::Key_Alt:
					setValue(Qt::AltModifier);
					break;
				case Qt::Key_Meta:
					setValue(Qt::MetaModifier);
					break;
				}
			}
			if (ShortcutController::isModifierKey(event->key())) {
				switch (event->key()) {
				case Qt::Key_Shift:
					setValue(m_key | Qt::ShiftModifier);
					break;
				case Qt::Key_Control:
					setValue(m_key | Qt::ControlModifier);
					break;
				case Qt::Key_Alt:
					setValue(m_key | Qt::AltModifier);
					break;
				case Qt::Key_Meta:
					setValue(m_key | Qt::MetaModifier);
					break;
				}
			} else {
				setValue(event->key() | (m_key & (Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier)));
			}
		} else {
			setValue(event->key());
		}
	}
	event->accept();
}

bool KeyEditor::event(QEvent* event) {
	if (!m_button) {
		if (event->type() == QEvent::KeyPress) {
			QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
			if (keyEvent->key() != Qt::Key_Tab && keyEvent->key() != Qt::Key_Backtab) {
				return QWidget::event(event);
			}
			if (!(keyEvent->modifiers() & ~Qt::ShiftModifier)) {
				keyPressEvent(keyEvent);
				keyEvent->accept();
				return true;
			}
		}
	} else {
		if (event->type() == GamepadButtonEvent::Down()) {
			setValueButton(static_cast<GamepadButtonEvent*>(event)->value());
			event->accept();
			return true;
		}
		if (event->type() == GamepadAxisEvent::Type()) {
			GamepadAxisEvent* gae = static_cast<GamepadAxisEvent*>(event);
			if (gae->isNew()) {
				setValueAxis(gae->axis(), gae->direction());
			}
			event->accept();
			return true;
		}
	}
	return QWidget::event(event);
}

void KeyEditor::updateButtonText() {
	QStringList text;
	if (m_key >= 0) {
		text.append(QString::number(m_key));
	}
	if (m_direction != GamepadAxisEvent::NEUTRAL) {
		text.append((m_direction == GamepadAxisEvent::NEGATIVE ? "-" : "+") + QString::number(m_axis));
	}
	if (text.isEmpty()) {
		setText(tr("---"));
	} else {
		setText(text.join("/"));
	}
}
<commit_msg>Qt: Make key binding fields have a width relative to its height<commit_after>/* Copyright (c) 2013-2014 Jeffrey Pfau
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "KeyEditor.h"

#include "GamepadAxisEvent.h"
#include "GamepadButtonEvent.h"
#include "ShortcutController.h"

#include <QFontMetrics>
#include <QKeyEvent>

using namespace QGBA;

KeyEditor::KeyEditor(QWidget* parent)
	: QLineEdit(parent)
	, m_direction(GamepadAxisEvent::NEUTRAL)
	, m_key(-1)
	, m_axis(-1)
	, m_button(false)
{
	setAlignment(Qt::AlignCenter);
	setFocusPolicy(Qt::ClickFocus);
	m_lastKey.setSingleShot(true);
}

void KeyEditor::setValue(int key) {
	m_key = key;
	if (m_button) {
		updateButtonText();
	} else {
		if (key < 0) {
			setText(tr("---"));
		} else {
			setText(QKeySequence(key).toString(QKeySequence::NativeText));
		}
	}
	emit valueChanged(key);
}

void KeyEditor::setValueKey(int key) {
	m_button = false;
	setValue(key);
}

void KeyEditor::setValueButton(int button) {
	m_button = true;
	setValue(button);
}

void KeyEditor::setValueAxis(int axis, int32_t value) {
	m_button = true;
	m_axis = axis;
	m_direction = value < 0 ? GamepadAxisEvent::NEGATIVE : GamepadAxisEvent::POSITIVE;
	updateButtonText();
	emit axisChanged(axis, m_direction);
}

void KeyEditor::clearButton() {
	m_button = true;
	setValue(-1);
}

void KeyEditor::clearAxis() {
	m_button = true;
	m_axis = -1;
	m_direction = GamepadAxisEvent::NEUTRAL;
	updateButtonText();
	emit axisChanged(m_axis, m_direction);
}

QSize KeyEditor::sizeHint() const {
	QSize hint = QLineEdit::sizeHint();
	QFontMetrics fm(font());
	hint.setWidth(fm.height() * 3);
	return hint;
}

void KeyEditor::keyPressEvent(QKeyEvent* event) {
	if (!m_button) {
		if (m_key < 0 || !m_lastKey.isActive()) {
			m_key = 0;
		}
		m_lastKey.start(KEY_TIME);
		if (m_key) {
			if (ShortcutController::isModifierKey(m_key)) {
				switch (event->key()) {
				case Qt::Key_Shift:
					setValue(Qt::ShiftModifier);
					break;
				case Qt::Key_Control:
					setValue(Qt::ControlModifier);
					break;
				case Qt::Key_Alt:
					setValue(Qt::AltModifier);
					break;
				case Qt::Key_Meta:
					setValue(Qt::MetaModifier);
					break;
				}
			}
			if (ShortcutController::isModifierKey(event->key())) {
				switch (event->key()) {
				case Qt::Key_Shift:
					setValue(m_key | Qt::ShiftModifier);
					break;
				case Qt::Key_Control:
					setValue(m_key | Qt::ControlModifier);
					break;
				case Qt::Key_Alt:
					setValue(m_key | Qt::AltModifier);
					break;
				case Qt::Key_Meta:
					setValue(m_key | Qt::MetaModifier);
					break;
				}
			} else {
				setValue(event->key() | (m_key & (Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier)));
			}
		} else {
			setValue(event->key());
		}
	}
	event->accept();
}

bool KeyEditor::event(QEvent* event) {
	if (!m_button) {
		if (event->type() == QEvent::KeyPress) {
			QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
			if (keyEvent->key() != Qt::Key_Tab && keyEvent->key() != Qt::Key_Backtab) {
				return QWidget::event(event);
			}
			if (!(keyEvent->modifiers() & ~Qt::ShiftModifier)) {
				keyPressEvent(keyEvent);
				keyEvent->accept();
				return true;
			}
		}
	} else {
		if (event->type() == GamepadButtonEvent::Down()) {
			setValueButton(static_cast<GamepadButtonEvent*>(event)->value());
			event->accept();
			return true;
		}
		if (event->type() == GamepadAxisEvent::Type()) {
			GamepadAxisEvent* gae = static_cast<GamepadAxisEvent*>(event);
			if (gae->isNew()) {
				setValueAxis(gae->axis(), gae->direction());
			}
			event->accept();
			return true;
		}
	}
	return QWidget::event(event);
}

void KeyEditor::updateButtonText() {
	QStringList text;
	if (m_key >= 0) {
		text.append(QString::number(m_key));
	}
	if (m_direction != GamepadAxisEvent::NEUTRAL) {
		text.append((m_direction == GamepadAxisEvent::NEGATIVE ? "-" : "+") + QString::number(m_axis));
	}
	if (text.isEmpty()) {
		setText(tr("---"));
	} else {
		setText(text.join("/"));
	}
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "iosplugin.h"

#include "iosconstants.h"
#include "iosconfigurations.h"
#include "iosdevicefactory.h"
#include "iossimulator.h"
#include "iossimulatorfactory.h"
#include "iosconfigurations.h"
#include "iosmanager.h"
#include "iosrunfactories.h"
#include "iossettingspage.h"
#include "iostoolhandler.h"
#include "iosqtversionfactory.h"
#include "iosbuildstep.h"
#include "iosdeploystepfactory.h"
#include "iosdeployconfiguration.h"
#include <projectexplorer/kitmanager.h>
#include <qtsupport/qtversionmanager.h>

#include <QtPlugin>

#include <projectexplorer/devicesupport/devicemanager.h>

namespace Ios {

IosPlugin::IosPlugin()
{
    qRegisterMetaType<Ios::IosToolHandler::Dict>("Ios::IosToolHandler::Dict");
}

bool IosPlugin::initialize(const QStringList &arguments, QString *errorMessage)
{
    Q_UNUSED(arguments);
    Q_UNUSED(errorMessage);

    Internal::IosConfigurations::instance();

    addAutoReleasedObject(new Internal::IosRunControlFactory);
    addAutoReleasedObject(new Internal::IosRunConfigurationFactory);
    addAutoReleasedObject(new Internal::IosSettingsPage);
    addAutoReleasedObject(new Internal::IosQtVersionFactory);
    addAutoReleasedObject(new Internal::IosDeviceFactory);
    addAutoReleasedObject(new Internal::IosSimulatorFactory);
    addAutoReleasedObject(new Internal::IosBuildStepFactory);
    addAutoReleasedObject(new Internal::IosDeployStepFactory);
    addAutoReleasedObject(new Internal::IosDeployConfigurationFactory);
    //ProjectExplorer::KitManager::instance()->registerKitInformation(new Internal::IosGdbServerKitInformation);
    return true;
}

void IosPlugin::extensionsInitialized()
{
    connect(ProjectExplorer::KitManager::instance(), SIGNAL(kitsLoaded()),
            this, SLOT(kitsRestored()));
}

void IosPlugin::kitsRestored()
{
    disconnect(ProjectExplorer::KitManager::instance(), SIGNAL(kitsLoaded()),
               this, SLOT(kitsRestored()));
    Internal::IosConfigurations::updateAutomaticKitList();
    connect(QtSupport::QtVersionManager::instance(),
            SIGNAL(qtVersionsChanged(QList<int>,QList<int>,QList<int>)),
            Internal::IosConfigurations::instance(),
            SLOT(updateAutomaticKitList()));
}

} // namespace Ios

Q_EXPORT_PLUGIN(Ios::IosPlugin)
<commit_msg>ios: fix missinig initialize after cleanup<commit_after>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "iosplugin.h"

#include "iosconstants.h"
#include "iosconfigurations.h"
#include "iosdevicefactory.h"
#include "iossimulator.h"
#include "iossimulatorfactory.h"
#include "iosconfigurations.h"
#include "iosmanager.h"
#include "iosrunfactories.h"
#include "iossettingspage.h"
#include "iostoolhandler.h"
#include "iosqtversionfactory.h"
#include "iosbuildstep.h"
#include "iosdeploystepfactory.h"
#include "iosdeployconfiguration.h"
#include <projectexplorer/kitmanager.h>
#include <qtsupport/qtversionmanager.h>

#include <QtPlugin>

#include <projectexplorer/devicesupport/devicemanager.h>

namespace Ios {

IosPlugin::IosPlugin()
{
    qRegisterMetaType<Ios::IosToolHandler::Dict>("Ios::IosToolHandler::Dict");
}

bool IosPlugin::initialize(const QStringList &arguments, QString *errorMessage)
{
    Q_UNUSED(arguments);
    Q_UNUSED(errorMessage);

    Internal::IosConfigurations::initialize();

    addAutoReleasedObject(new Internal::IosRunControlFactory);
    addAutoReleasedObject(new Internal::IosRunConfigurationFactory);
    addAutoReleasedObject(new Internal::IosSettingsPage);
    addAutoReleasedObject(new Internal::IosQtVersionFactory);
    addAutoReleasedObject(new Internal::IosDeviceFactory);
    addAutoReleasedObject(new Internal::IosSimulatorFactory);
    addAutoReleasedObject(new Internal::IosBuildStepFactory);
    addAutoReleasedObject(new Internal::IosDeployStepFactory);
    addAutoReleasedObject(new Internal::IosDeployConfigurationFactory);
    //ProjectExplorer::KitManager::instance()->registerKitInformation(new Internal::IosGdbServerKitInformation);
    return true;
}

void IosPlugin::extensionsInitialized()
{
    connect(ProjectExplorer::KitManager::instance(), SIGNAL(kitsLoaded()),
            this, SLOT(kitsRestored()));
}

void IosPlugin::kitsRestored()
{
    disconnect(ProjectExplorer::KitManager::instance(), SIGNAL(kitsLoaded()),
               this, SLOT(kitsRestored()));
    Internal::IosConfigurations::updateAutomaticKitList();
    connect(QtSupport::QtVersionManager::instance(),
            SIGNAL(qtVersionsChanged(QList<int>,QList<int>,QList<int>)),
            Internal::IosConfigurations::instance(),
            SLOT(updateAutomaticKitList()));
}

} // namespace Ios

Q_EXPORT_PLUGIN(Ios::IosPlugin)
<|endoftext|>