<commit_before>/*
 * Software License Agreement (BSD License)
 *
 * Point Cloud Library (PCL) - www.pointclouds.org
 * Copyright (c) 2012-, Open Perception, Inc.
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above
 *    copyright notice, this list of conditions and the following
 *    disclaimer in the documentation and/or other materials provided
 *    with the distribution.
 *  * Neither the name of the copyright holder(s) nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 */

#ifndef PCL_FILTERS_IMPL_NORMAL_SPACE_SAMPLE_H_
#define PCL_FILTERS_IMPL_NORMAL_SPACE_SAMPLE_H_

#include <pcl/filters/normal_space.h>
#include <pcl/common/io.h>

#include <vector>
#include <list>

///////////////////////////////////////////////////////////////////////////////
template<typename PointT, typename NormalT> bool
pcl::NormalSpaceSampling<PointT, NormalT>::initCompute ()
{
  if (!FilterIndices<PointT>::initCompute ())
    return false;

  // If sample size is 0 or if the sample size is greater then input cloud size then return entire copy of cloud
  if (sample_ >= input_->size ())
  {
    PCL_ERROR ("[NormalSpaceSampling::initCompute] Requested more samples than the input cloud size: %d vs %zu\n",
               sample_, input_->size ());
    return false;
  }

  boost::mt19937 *rng = new boost::mt19937 (static_cast<unsigned int> (seed_));
  boost::uniform_int<unsigned int> *uniform_distrib = new boost::uniform_int<unsigned int> (0, unsigned (input_->size ()));
  rng_uniform_distribution_ = new boost::variate_generator<boost::mt19937, boost::uniform_int<unsigned int> > (*rng, *uniform_distrib);

  return (true);
}

///////////////////////////////////////////////////////////////////////////////
template<typename PointT, typename NormalT> void
pcl::NormalSpaceSampling<PointT, NormalT>::applyFilter (PointCloud &output)
{
  std::vector<int> indices;
  if (keep_organized_)
  {
    bool temp = extract_removed_indices_;
    extract_removed_indices_ = true;
    applyFilter (indices);
    extract_removed_indices_ = temp;

    output = *input_;
    for (int rii = 0; rii < static_cast<int> (removed_indices_->size ()); ++rii)  // rii = removed indices iterator
      output.points[(*removed_indices_)[rii]].x = output.points[(*removed_indices_)[rii]].y = output.points[(*removed_indices_)[rii]].z = user_filter_value_;
    if (!pcl_isfinite (user_filter_value_))
      output.is_dense = false;
  }
  else
  {
    output.is_dense = true;
    applyFilter (indices);
    pcl::copyPointCloud (*input_, indices, output);
  }
}

///////////////////////////////////////////////////////////////////////////////
template<typename PointT, typename NormalT> bool
pcl::NormalSpaceSampling<PointT, NormalT>::isEntireBinSampled (boost::dynamic_bitset<> &array,
                                                               unsigned int start_index,
                                                               unsigned int length)
{
  bool status = true;
  for (unsigned int i = start_index; i < start_index + length; i++)
  {
    status = status & array.test (i);
  }
  return status;
}

///////////////////////////////////////////////////////////////////////////////
template<typename PointT, typename NormalT> unsigned int
pcl::NormalSpaceSampling<PointT, NormalT>::findBin (const float *normal, unsigned int)
{
  unsigned int bin_number = 0;
  // Holds the bin numbers for direction cosines in x,y,z directions
  unsigned int t[3] = {0,0,0};

  // dcos is the direction cosine.
  float dcos = 0.0;
  float bin_size = 0.0;
  // max_cos and min_cos are the maximum and minimum values of cos(theta) respectively
  float max_cos = 1.0;
  float min_cos = -1.0;

//  dcos = cosf (normal[0]);
  dcos = normal[0];
  bin_size = (max_cos - min_cos) / static_cast<float> (binsx_);

  // Finding bin number for direction cosine in x direction
  unsigned int k = 0;
  for (float i = min_cos; (i + bin_size) < (max_cos - bin_size); i += bin_size , k++)
  {
    if (dcos >= i && dcos <= (i+bin_size))
    {
      break;
    }
  }
  t[0] = k;

//  dcos = cosf (normal[1]);
  dcos = normal[1];
  bin_size = (max_cos - min_cos) / static_cast<float> (binsy_);

  // Finding bin number for direction cosine in y direction
  k = 0;
  for (float i = min_cos; (i + bin_size) < (max_cos - bin_size); i += bin_size , k++)
  {
    if (dcos >= i && dcos <= (i+bin_size))
    {
      break;
    }
  }
  t[1] = k;

//  dcos = cosf (normal[2]);
  dcos = normal[2];
  bin_size = (max_cos - min_cos) / static_cast<float> (binsz_);

  // Finding bin number for direction cosine in z direction
  k = 0;
  for (float i = min_cos; (i + bin_size) < (max_cos - bin_size); i += bin_size , k++)
  {
    if (dcos >= i && dcos <= (i+bin_size))
    {
      break;
    }
  }
  t[2] = k;

  bin_number = t[0] * (binsy_*binsz_) + t[1] * binsz_ + t[2];
  return bin_number;
}

///////////////////////////////////////////////////////////////////////////////
template<typename PointT, typename NormalT> void
pcl::NormalSpaceSampling<PointT, NormalT>::applyFilter (std::vector<int> &indices)
{
  if (!initCompute ())
  {
    indices = *indices_;
    return;
  }

  unsigned int max_values = (std::min) (sample_, static_cast<unsigned int> (input_normals_->size ()));
  // Resize output indices to sample size
  indices.resize (max_values);
  removed_indices_->resize (max_values);

  // Allocate memory for the histogram of normals. Normals will then be sampled from each bin.
  unsigned int n_bins = binsx_ * binsy_ * binsz_;
  // list<int> holds the indices of points in that bin. Using list to avoid repeated resizing of vectors.
  // Helps when the point cloud is large.
  std::vector<std::list <int> > normals_hg;
  normals_hg.reserve (n_bins);
  for (unsigned int i = 0; i < n_bins; i++)
    normals_hg.push_back (std::list<int> ());

  for (std::vector<int>::const_iterator it = indices_->begin (); it != indices_->end (); ++it)
  {
    unsigned int bin_number = findBin (input_normals_->points[*it].normal, n_bins);
    normals_hg[bin_number].push_back (*it);
  }

  // Setting up random access for the list created above. Maintaining the iterators to individual elements of the list
  // in a vector. Using vector now as the size of the list is known.
  std::vector<std::vector<std::list<int>::iterator> > random_access (normals_hg.size ());
  for (unsigned int i = 0; i < normals_hg.size (); i++)
  {
    random_access.push_back (std::vector<std::list<int>::iterator> ());
    random_access[i].resize (normals_hg[i].size ());

    unsigned int j = 0;
    for (std::list<int>::iterator itr = normals_hg[i].begin (); itr != normals_hg[i].end (); itr++, j++)
      random_access[i][j] = itr;
  }
  std::vector<unsigned int> start_index (normals_hg.size ());
  start_index[0] = 0;
  unsigned int prev_index = start_index[0];
  for (unsigned int i = 1; i < normals_hg.size (); i++)
  {
    start_index[i] = prev_index + static_cast<unsigned int> (normals_hg[i-1].size ());
    prev_index = start_index[i];
  }

  // Maintaining flags to check if a point is sampled
  boost::dynamic_bitset<> is_sampled_flag (input_normals_->points.size ());
  // Maintaining flags to check if all points in the bin are sampled
  boost::dynamic_bitset<> bin_empty_flag (normals_hg.size ());
  unsigned int i = 0;
  while (i < sample_)
  {
    // Iterating through every bin and picking one point at random, until the required number of points are sampled.
    for (unsigned int j = 0; j < normals_hg.size (); j++)
    {
      unsigned int M = static_cast<unsigned int> (normals_hg[j].size ());
      if (M == 0 || bin_empty_flag.test (j)) // bin_empty_flag(i) is set if all points in that bin are sampled..
        continue;

      unsigned int pos = 0;
      unsigned int random_index = 0;

      // Picking up a sample at random from jth bin
      do
      {
        random_index = static_cast<unsigned int> ((*rng_uniform_distribution_) () % M);
        pos = start_index[j] + random_index;
      } while (is_sampled_flag.test (pos));

      is_sampled_flag.flip (start_index[j] + random_index);

      // Checking if all points in bin j are sampled.
      if (isEntireBinSampled (is_sampled_flag, start_index[j], static_cast<unsigned int> (normals_hg[j].size ())))
        bin_empty_flag.flip (j);

      unsigned int index = *(random_access[j][random_index]);
      indices[i] = index;
      i++;
      if (i == sample_)
        break;
    }
  }

  // If we need to return the indices that we haven't sampled
  if (extract_removed_indices_)
  {
    std::vector<int> indices_temp = indices;
    std::sort (indices_temp.begin (), indices_temp.end ());

    std::vector<int> all_indices_temp = *indices_;
    std::sort (all_indices_temp.begin (), all_indices_temp.end ());
    set_difference (all_indices_temp.begin (), all_indices_temp.end (),
                    indices_temp.begin (), indices_temp.end (),
                    inserter (*removed_indices_, removed_indices_->begin ()));
  }
}

#define PCL_INSTANTIATE_NormalSpaceSampling(T,NT) template class PCL_EXPORTS pcl::NormalSpaceSampling<T,NT>;

#endif    // PCL_FILTERS_IMPL_NORMAL_SPACE_SAMPLE_H_
<commit_msg>* Fixed memory leak in @NormalSpaceSampling@ -- why were we using pointers?<commit_after>/*
 * Software License Agreement (BSD License)
 *
 * Point Cloud Library (PCL) - www.pointclouds.org
 * Copyright (c) 2012-, Open Perception, Inc.
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above
 *    copyright notice, this list of conditions and the following
 *    disclaimer in the documentation and/or other materials provided
 *    with the distribution.
 *  * Neither the name of the copyright holder(s) nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 */

#ifndef PCL_FILTERS_IMPL_NORMAL_SPACE_SAMPLE_H_
#define PCL_FILTERS_IMPL_NORMAL_SPACE_SAMPLE_H_

#include <pcl/filters/normal_space.h>
#include <pcl/common/io.h>

#include <vector>
#include <list>

///////////////////////////////////////////////////////////////////////////////
template<typename PointT, typename NormalT> bool
pcl::NormalSpaceSampling<PointT, NormalT>::initCompute ()
{
  if (!FilterIndices<PointT>::initCompute ())
    return false;

  // If sample size is 0 or if the sample size is greater then input cloud size then return entire copy of cloud
  if (sample_ >= input_->size ())
  {
    PCL_ERROR ("[NormalSpaceSampling::initCompute] Requested more samples than the input cloud size: %d vs %zu\n",
               sample_, input_->size ());
    return false;
  }

  boost::mt19937 rng (static_cast<unsigned int> (seed_));
  boost::uniform_int<unsigned int> uniform_distrib (0, unsigned (input_->size ()));
  if (rng_uniform_distribution_ != NULL)
    delete rng_uniform_distribution_;
  rng_uniform_distribution_ = new boost::variate_generator<boost::mt19937, boost::uniform_int<unsigned int> > (rng, uniform_distrib);

  return (true);
}

///////////////////////////////////////////////////////////////////////////////
template<typename PointT, typename NormalT> void
pcl::NormalSpaceSampling<PointT, NormalT>::applyFilter (PointCloud &output)
{
  std::vector<int> indices;
  if (keep_organized_)
  {
    bool temp = extract_removed_indices_;
    extract_removed_indices_ = true;
    applyFilter (indices);
    extract_removed_indices_ = temp;

    output = *input_;
    for (int rii = 0; rii < static_cast<int> (removed_indices_->size ()); ++rii)  // rii = removed indices iterator
      output.points[(*removed_indices_)[rii]].x = output.points[(*removed_indices_)[rii]].y = output.points[(*removed_indices_)[rii]].z = user_filter_value_;
    if (!pcl_isfinite (user_filter_value_))
      output.is_dense = false;
  }
  else
  {
    output.is_dense = true;
    applyFilter (indices);
    pcl::copyPointCloud (*input_, indices, output);
  }
}

///////////////////////////////////////////////////////////////////////////////
template<typename PointT, typename NormalT> bool
pcl::NormalSpaceSampling<PointT, NormalT>::isEntireBinSampled (boost::dynamic_bitset<> &array,
                                                               unsigned int start_index,
                                                               unsigned int length)
{
  bool status = true;
  for (unsigned int i = start_index; i < start_index + length; i++)
  {
    status = status & array.test (i);
  }
  return status;
}

///////////////////////////////////////////////////////////////////////////////
template<typename PointT, typename NormalT> unsigned int
pcl::NormalSpaceSampling<PointT, NormalT>::findBin (const float *normal, unsigned int)
{
  unsigned int bin_number = 0;
  // Holds the bin numbers for direction cosines in x,y,z directions
  unsigned int t[3] = {0,0,0};

  // dcos is the direction cosine.
  float dcos = 0.0;
  float bin_size = 0.0;
  // max_cos and min_cos are the maximum and minimum values of cos(theta) respectively
  float max_cos = 1.0;
  float min_cos = -1.0;

//  dcos = cosf (normal[0]);
  dcos = normal[0];
  bin_size = (max_cos - min_cos) / static_cast<float> (binsx_);

  // Finding bin number for direction cosine in x direction
  unsigned int k = 0;
  for (float i = min_cos; (i + bin_size) < (max_cos - bin_size); i += bin_size , k++)
  {
    if (dcos >= i && dcos <= (i+bin_size))
    {
      break;
    }
  }
  t[0] = k;

//  dcos = cosf (normal[1]);
  dcos = normal[1];
  bin_size = (max_cos - min_cos) / static_cast<float> (binsy_);

  // Finding bin number for direction cosine in y direction
  k = 0;
  for (float i = min_cos; (i + bin_size) < (max_cos - bin_size); i += bin_size , k++)
  {
    if (dcos >= i && dcos <= (i+bin_size))
    {
      break;
    }
  }
  t[1] = k;

//  dcos = cosf (normal[2]);
  dcos = normal[2];
  bin_size = (max_cos - min_cos) / static_cast<float> (binsz_);

  // Finding bin number for direction cosine in z direction
  k = 0;
  for (float i = min_cos; (i + bin_size) < (max_cos - bin_size); i += bin_size , k++)
  {
    if (dcos >= i && dcos <= (i+bin_size))
    {
      break;
    }
  }
  t[2] = k;

  bin_number = t[0] * (binsy_*binsz_) + t[1] * binsz_ + t[2];
  return bin_number;
}

///////////////////////////////////////////////////////////////////////////////
template<typename PointT, typename NormalT> void
pcl::NormalSpaceSampling<PointT, NormalT>::applyFilter (std::vector<int> &indices)
{
  if (!initCompute ())
  {
    indices = *indices_;
    return;
  }

  unsigned int max_values = (std::min) (sample_, static_cast<unsigned int> (input_normals_->size ()));
  // Resize output indices to sample size
  indices.resize (max_values);
  removed_indices_->resize (max_values);

  // Allocate memory for the histogram of normals. Normals will then be sampled from each bin.
  unsigned int n_bins = binsx_ * binsy_ * binsz_;
  // list<int> holds the indices of points in that bin. Using list to avoid repeated resizing of vectors.
  // Helps when the point cloud is large.
  std::vector<std::list <int> > normals_hg;
  normals_hg.reserve (n_bins);
  for (unsigned int i = 0; i < n_bins; i++)
    normals_hg.push_back (std::list<int> ());

  for (std::vector<int>::const_iterator it = indices_->begin (); it != indices_->end (); ++it)
  {
    unsigned int bin_number = findBin (input_normals_->points[*it].normal, n_bins);
    normals_hg[bin_number].push_back (*it);
  }

  // Setting up random access for the list created above. Maintaining the iterators to individual elements of the list
  // in a vector. Using vector now as the size of the list is known.
  std::vector<std::vector<std::list<int>::iterator> > random_access (normals_hg.size ());
  for (unsigned int i = 0; i < normals_hg.size (); i++)
  {
    random_access.push_back (std::vector<std::list<int>::iterator> ());
    random_access[i].resize (normals_hg[i].size ());

    unsigned int j = 0;
    for (std::list<int>::iterator itr = normals_hg[i].begin (); itr != normals_hg[i].end (); itr++, j++)
      random_access[i][j] = itr;
  }
  std::vector<unsigned int> start_index (normals_hg.size ());
  start_index[0] = 0;
  unsigned int prev_index = start_index[0];
  for (unsigned int i = 1; i < normals_hg.size (); i++)
  {
    start_index[i] = prev_index + static_cast<unsigned int> (normals_hg[i-1].size ());
    prev_index = start_index[i];
  }

  // Maintaining flags to check if a point is sampled
  boost::dynamic_bitset<> is_sampled_flag (input_normals_->points.size ());
  // Maintaining flags to check if all points in the bin are sampled
  boost::dynamic_bitset<> bin_empty_flag (normals_hg.size ());
  unsigned int i = 0;
  while (i < sample_)
  {
    // Iterating through every bin and picking one point at random, until the required number of points are sampled.
    for (unsigned int j = 0; j < normals_hg.size (); j++)
    {
      unsigned int M = static_cast<unsigned int> (normals_hg[j].size ());
      if (M == 0 || bin_empty_flag.test (j)) // bin_empty_flag(i) is set if all points in that bin are sampled..
        continue;

      unsigned int pos = 0;
      unsigned int random_index = 0;

      // Picking up a sample at random from jth bin
      do
      {
        random_index = static_cast<unsigned int> ((*rng_uniform_distribution_) () % M);
        pos = start_index[j] + random_index;
      } while (is_sampled_flag.test (pos));

      is_sampled_flag.flip (start_index[j] + random_index);

      // Checking if all points in bin j are sampled.
      if (isEntireBinSampled (is_sampled_flag, start_index[j], static_cast<unsigned int> (normals_hg[j].size ())))
        bin_empty_flag.flip (j);

      unsigned int index = *(random_access[j][random_index]);
      indices[i] = index;
      i++;
      if (i == sample_)
        break;
    }
  }

  // If we need to return the indices that we haven't sampled
  if (extract_removed_indices_)
  {
    std::vector<int> indices_temp = indices;
    std::sort (indices_temp.begin (), indices_temp.end ());

    std::vector<int> all_indices_temp = *indices_;
    std::sort (all_indices_temp.begin (), all_indices_temp.end ());
    set_difference (all_indices_temp.begin (), all_indices_temp.end (),
                    indices_temp.begin (), indices_temp.end (),
                    inserter (*removed_indices_, removed_indices_->begin ()));
  }
}

#define PCL_INSTANTIATE_NormalSpaceSampling(T,NT) template class PCL_EXPORTS pcl::NormalSpaceSampling<T,NT>;

#endif    // PCL_FILTERS_IMPL_NORMAL_SPACE_SAMPLE_H_
<|endoftext|>


<commit_before><commit_msg>Always play ChromeVox enabled/disabled sounds regardless of system sound enabled flag.<commit_after><|endoftext|>


<commit_before>#include "src/triangle.h"

#define VERTEX_SWAP(v1, v2) { gfx_Vertex s = v2; v2 = v1; v1 = s; }

// simplest case: will plot either a flat bottom or flat top triangles
enum TriangleType
{
    FLAT_BOTTOM,
    FLAT_TOP
};

// internal: perform triangle rendering based on its type
static void drawTriangleType(const gfx_Triangle *t, const gfx_Vertex *v0, const gfx_Vertex *v1, const gfx_Vertex *v2, unsigned char *buffer, enum TriangleType type, short colorKey);

/* ***** */
void gfx_drawTriangle(const gfx_Triangle *t, unsigned char *buffer)
{
    // draw triangle to screen buffer without any color keying
    gfx_drawTriangleColorKey(t, buffer, -1);
}

/* ***** */
void gfx_drawTriangleColorKey(const gfx_Triangle *t, unsigned char *buffer, short colorKey)
{
    gfx_Vertex v0, v1, v2;

    v0 = t->vertices[0];
    v1 = t->vertices[1];
    v2 = t->vertices[2];

    // sort vertices so that v0 is topmost, then v2, then v1
    if(v2.position.y > v1.position.y)
    {
        v2 = t->vertices[1];
        v1 = t->vertices[2];
    }

    if(v0.position.y > v1.position.y)
    {
        v0 = v1;
        v1 = t->vertices[0];
    }

    if(v0.position.y > v2.position.y)
        VERTEX_SWAP(v0, v2)

    // handle 2 basic cases of flat bottom and flat top triangles
    if(v1.position.y == v2.position.y)
        drawTriangleType(t, &v0, &v1, &v2, buffer, FLAT_BOTTOM, colorKey);
    else if(v0.position.y == v1.position.y)
        drawTriangleType(t, &v2, &v1, &v0, buffer, FLAT_TOP, colorKey);
    else
    {
        // "Non-trivial" triangles will be broken down into a composition of flat bottom and flat top triangles.
        // For this, we need to calculate a new vertex, v3 and interpolate its UV coordinates.
        gfx_Vertex v3;
        mth_Vector4 diff, diff2;
        double ratioU = 1, ratioV = 1;

        v3.position.x = v0.position.x + ((float)(v2.position.y - v0.position.y) / (float)(v1.position.y - v0.position.y)) * (v1.position.x - v0.position.x);
        v3.position.y = v2.position.y;
        // todo: interpolate z for proper perspective texture mapping!
        v3.position.z = v2.position.z;
        v3.position.w = v2.position.w;

        diff  = mth_vecSub(&v1.position, &v0.position);
        diff2 = mth_vecSub(&v3.position, &v0.position);

        if(diff.x != 0)
            ratioU = diff2.x / diff.x;

        if(diff.y != 0)
            ratioV = diff2.y / diff.y;

        // lerp the UV mapping for the triangle
        v3.uv.u = v1.uv.u * ratioU + v0.uv.u * (1.0 - ratioU);
        v3.uv.v = v1.uv.v * ratioV + v0.uv.v * (1.0 - ratioV);

        // this swap is done to maintain consistent renderer behavior
        if(v3.position.x < v2.position.x)
            VERTEX_SWAP(v3, v2)

        // draw the composition of both triangles to form the desired shape
        drawTriangleType(t, &v0, &v3, &v2, buffer, FLAT_BOTTOM, colorKey);
        drawTriangleType(t, &v1, &v3, &v2, buffer, FLAT_TOP, colorKey);
    }
}

/*
 * Depending on the triangle type, the order of processed vertices is as follows:
 *
 * v0         v0----v1
 * |\         |     /
 * | \        |    /
 * |  \       |   /
 * |   \      |  /
 * |    \     | /
 * |     \    |/
 * v2-----v1  v2
 */
static void drawTriangleType(const gfx_Triangle *t, const gfx_Vertex *v0, const gfx_Vertex *v1, const gfx_Vertex *v2, unsigned char *buffer, enum TriangleType type, const short colorKey)
{
    double invDy, dxLeft, dxRight, xLeft, xRight;
    double x, y, yDir = 1;
    int useColorKey = colorKey != -1 ? 1 : 0;

    if(type == FLAT_BOTTOM)
    {
        invDy  = 1.f / (v2->position.y - v0->position.y);
    }
    else
    {
        invDy  = 1.f / (v0->position.y - v2->position.y);
        yDir = -1;
    }
    dxLeft  = (v2->position.x - v0->position.x) * invDy;
    dxRight = (v1->position.x - v0->position.x) * invDy;
    xLeft  = v0->position.x;
    xRight = xLeft;

    if(!t->texture)
    {
        for(y = v0->position.y; ; y += yDir)
        {
            if(type == FLAT_TOP && y < v2->position.y)
            {
                break;
            }
            else if(type == FLAT_BOTTOM && y > v2->position.y)
            {
                // to avoid pixel wide gaps, render extra line at the junction between two final points
                gfx_drawLine(xLeft-dxLeft, y, xRight-dxRight, y, t->color, buffer);
                break;
            }

            gfx_drawLine(xLeft, y, xRight, y, t->color, buffer);
            xLeft  += dxLeft;
            xRight += dxRight;

        }
    }
    else
    {
        float texW = t->texture->width - 1;
        float texH = t->texture->height - 1;
        int   texArea = texW * texH;
        float duLeft  = texW * (v2->uv.u - v0->uv.u) * invDy;
        float dvLeft  = texH * (v2->uv.v - v0->uv.v) * invDy;
        float duRight = texW * (v1->uv.u - v0->uv.u) * invDy;
        float dvRight = texH * (v1->uv.v - v0->uv.v) * invDy;

        float startU = texW * v0->uv.u;
        float startV = texH * v0->uv.v;
        // With triangles the texture gradients (u,v slopes over the triangle surface)
        // are guaranteed to be constant, so we need to calculate du and dv only once.
        float invDx = 1.f / (dxRight - dxLeft);
        float du = (duRight - duLeft) * invDx;
        float dv = (dvRight - dvLeft) * invDx;
        float startX = xLeft;
        float endX   = xRight;

        gfx_setPalette(t->texture->palette);

        for(y = v0->position.y; ; y += yDir)
        {
            float u = startU;
            float v = startV;

            if(type == FLAT_BOTTOM && y > v2->position.y)
            {
                u -= du;
                v -= dv;
                for(x = startX-dxLeft; x <= endX-dxRight; ++x)
                {
                    unsigned char pixel = t->texture->data[(int)u + ((int)v * t->texture->height)];

                    if(!useColorKey || (useColorKey && pixel != (unsigned char)colorKey))
                        gfx_drawPixel(x, y, pixel, buffer);
                    u += du;
                    v += dv;
                }
                break;
            }
            else if ( type == FLAT_TOP && y < v2->position.y)
                break;

            for(x = startX; x <= endX; ++x)
            {
                // fetch texture data with a texArea modulus for proper effect in case u or v are > 1
                unsigned char pixel = t->texture->data[((int)u + ((int)v * t->texture->height)) % texArea];

                if(!useColorKey || (useColorKey && pixel != (unsigned char)colorKey))
                    gfx_drawPixel(x, y, pixel, buffer);
                u += du;
                v += dv;
            }

            startX += dxLeft;
            endX   += dxRight;
            startU += duLeft;
            startV += dvLeft;
        }
    }
}
<commit_msg>interpolate z coordinate for v3<commit_after>#include "src/triangle.h"

#define VERTEX_SWAP(v1, v2) { gfx_Vertex s = v2; v2 = v1; v1 = s; }

// simplest case: will plot either a flat bottom or flat top triangles
enum TriangleType
{
    FLAT_BOTTOM,
    FLAT_TOP
};

// internal: perform triangle rendering based on its type
static void drawTriangleType(const gfx_Triangle *t, const gfx_Vertex *v0, const gfx_Vertex *v1, const gfx_Vertex *v2, unsigned char *buffer, enum TriangleType type, short colorKey);

/* ***** */
void gfx_drawTriangle(const gfx_Triangle *t, unsigned char *buffer)
{
    // draw triangle to screen buffer without any color keying
    gfx_drawTriangleColorKey(t, buffer, -1);
}

/* ***** */
void gfx_drawTriangleColorKey(const gfx_Triangle *t, unsigned char *buffer, short colorKey)
{
    gfx_Vertex v0, v1, v2;

    v0 = t->vertices[0];
    v1 = t->vertices[1];
    v2 = t->vertices[2];

    // sort vertices so that v0 is topmost, then v2, then v1
    if(v2.position.y > v1.position.y)
    {
        v2 = t->vertices[1];
        v1 = t->vertices[2];
    }

    if(v0.position.y > v1.position.y)
    {
        v0 = v1;
        v1 = t->vertices[0];
    }

    if(v0.position.y > v2.position.y)
        VERTEX_SWAP(v0, v2)

    // handle 2 basic cases of flat bottom and flat top triangles
    if(v1.position.y == v2.position.y)
        drawTriangleType(t, &v0, &v1, &v2, buffer, FLAT_BOTTOM, colorKey);
    else if(v0.position.y == v1.position.y)
        drawTriangleType(t, &v2, &v1, &v0, buffer, FLAT_TOP, colorKey);
    else
    {
        // "Non-trivial" triangles will be broken down into a composition of flat bottom and flat top triangles.
        // For this, we need to calculate a new vertex, v3 and interpolate its UV coordinates.
        gfx_Vertex v3;
        mth_Vector4 diff, diff2;
        double ratioU = 1, ratioV = 1;

        v3.position.x = v0.position.x + ((float)(v2.position.y - v0.position.y) / (float)(v1.position.y - v0.position.y)) * (v1.position.x - v0.position.x);
        v3.position.y = v2.position.y;
        v3.position.z = v0.position.z + ((float)(v2.position.y - v0.position.y) / (float)(v1.position.y - v0.position.y)) * (v1.position.z - v0.position.z);
        v3.position.w = v2.position.w;

        diff  = mth_vecSub(&v1.position, &v0.position);
        diff2 = mth_vecSub(&v3.position, &v0.position);

        if(diff.x != 0)
            ratioU = diff2.x / diff.x;

        if(diff.y != 0)
            ratioV = diff2.y / diff.y;

        // lerp the UV mapping for the triangle
        v3.uv.u = v1.uv.u * ratioU + v0.uv.u * (1.0 - ratioU);
        v3.uv.v = v1.uv.v * ratioV + v0.uv.v * (1.0 - ratioV);

        // this swap is done to maintain consistent renderer behavior
        if(v3.position.x < v2.position.x)
            VERTEX_SWAP(v3, v2)

        // draw the composition of both triangles to form the desired shape
        drawTriangleType(t, &v0, &v3, &v2, buffer, FLAT_BOTTOM, colorKey);
        drawTriangleType(t, &v1, &v3, &v2, buffer, FLAT_TOP, colorKey);
    }
}

/*
 * Depending on the triangle type, the order of processed vertices is as follows:
 *
 * v0         v0----v1
 * |\         |     /
 * | \        |    /
 * |  \       |   /
 * |   \      |  /
 * |    \     | /
 * |     \    |/
 * v2-----v1  v2
 */
static void drawTriangleType(const gfx_Triangle *t, const gfx_Vertex *v0, const gfx_Vertex *v1, const gfx_Vertex *v2, unsigned char *buffer, enum TriangleType type, const short colorKey)
{
    double invDy, dxLeft, dxRight, xLeft, xRight;
    double x, y, yDir = 1;
    int useColorKey = colorKey != -1 ? 1 : 0;

    if(type == FLAT_BOTTOM)
    {
        invDy  = 1.f / (v2->position.y - v0->position.y);
    }
    else
    {
        invDy  = 1.f / (v0->position.y - v2->position.y);
        yDir = -1;
    }
    dxLeft  = (v2->position.x - v0->position.x) * invDy;
    dxRight = (v1->position.x - v0->position.x) * invDy;
    xLeft  = v0->position.x;
    xRight = xLeft;

    if(!t->texture)
    {
        for(y = v0->position.y; ; y += yDir)
        {
            if(type == FLAT_TOP && y < v2->position.y)
            {
                break;
            }
            else if(type == FLAT_BOTTOM && y > v2->position.y)
            {
                // to avoid pixel wide gaps, render extra line at the junction between two final points
                gfx_drawLine(xLeft-dxLeft, y, xRight-dxRight, y, t->color, buffer);
                break;
            }

            gfx_drawLine(xLeft, y, xRight, y, t->color, buffer);
            xLeft  += dxLeft;
            xRight += dxRight;

        }
    }
    else
    {
        float texW = t->texture->width - 1;
        float texH = t->texture->height - 1;
        int   texArea = texW * texH;
        float duLeft  = texW * (v2->uv.u - v0->uv.u) * invDy;
        float dvLeft  = texH * (v2->uv.v - v0->uv.v) * invDy;
        float duRight = texW * (v1->uv.u - v0->uv.u) * invDy;
        float dvRight = texH * (v1->uv.v - v0->uv.v) * invDy;

        float startU = texW * v0->uv.u;
        float startV = texH * v0->uv.v;
        // With triangles the texture gradients (u,v slopes over the triangle surface)
        // are guaranteed to be constant, so we need to calculate du and dv only once.
        float invDx = 1.f / (dxRight - dxLeft);
        float du = (duRight - duLeft) * invDx;
        float dv = (dvRight - dvLeft) * invDx;
        float startX = xLeft;
        float endX   = xRight;

        gfx_setPalette(t->texture->palette);

        for(y = v0->position.y; ; y += yDir)
        {
            float u = startU;
            float v = startV;

            if(type == FLAT_BOTTOM && y > v2->position.y)
            {
                u -= du;
                v -= dv;
                for(x = startX-dxLeft; x <= endX-dxRight; ++x)
                {
                    unsigned char pixel = t->texture->data[(int)u + ((int)v * t->texture->height)];

                    if(!useColorKey || (useColorKey && pixel != (unsigned char)colorKey))
                        gfx_drawPixel(x, y, pixel, buffer);
                    u += du;
                    v += dv;
                }
                break;
            }
            else if ( type == FLAT_TOP && y < v2->position.y)
                break;

            for(x = startX; x <= endX; ++x)
            {
                // fetch texture data with a texArea modulus for proper effect in case u or v are > 1
                unsigned char pixel = t->texture->data[((int)u + ((int)v * t->texture->height)) % texArea];

                if(!useColorKey || (useColorKey && pixel != (unsigned char)colorKey))
                    gfx_drawPixel(x, y, pixel, buffer);
                u += du;
                v += dv;
            }

            startX += dxLeft;
            endX   += dxRight;
            startU += duLeft;
            startV += dvLeft;
        }
    }
}
<|endoftext|>


<commit_before>// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -verify -fsyntax-only -std=c++11 -fms-extensions %s

#if !__has_feature(attribute_deprecated_with_replacement)
#error "Missing __has_feature"
#endif

int a1 [[deprecated("warning", "fixit")]]; // expected-error{{'deprecated' attribute takes no more than 1 argument}}
int a2 [[deprecated("warning", 1)]]; // expected-error{{'deprecated' attribute takes no more than 1 argument}}

int b1 [[gnu::deprecated("warning", "fixit")]]; // expected-error{{'deprecated' attribute takes no more than 1 argument}}
int b2 [[gnu::deprecated("warning", 1)]]; // expected-error{{'deprecated' attribute takes no more than 1 argument}}

__declspec(deprecated("warning", "fixit")) int c1; // expected-error{{'deprecated' attribute takes no more than 1 argument}}
__declspec(deprecated("warning", 1)) int c2; // expected-error{{'deprecated' attribute takes no more than 1 argument}}

int d1 __attribute__((deprecated("warning", "fixit")));
int d2 __attribute__((deprecated("warning", 1))); // expected-error{{'deprecated' attribute requires a string}}
<commit_msg>Update testing case on swift-3.0 branch.<commit_after>// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -verify -fsyntax-only -std=c++11 -fms-extensions %s

#if !__has_feature(attribute_deprecated_with_replacement)
#error "Missing __has_feature"
#endif

int a1 [[deprecated("warning", "fixit")]]; // expected-warning{{use of the 'deprecated' attribute is a C++14 extension}} expected-error{{'deprecated' attribute takes no more than 1 argument}}
int a2 [[deprecated("warning", 1)]]; // expected-warning{{use of the 'deprecated' attribute is a C++14 extension}} expected-error{{'deprecated' attribute takes no more than 1 argument}}

int b1 [[gnu::deprecated("warning", "fixit")]]; // expected-error{{'deprecated' attribute takes no more than 1 argument}}
int b2 [[gnu::deprecated("warning", 1)]]; // expected-error{{'deprecated' attribute takes no more than 1 argument}}

__declspec(deprecated("warning", "fixit")) int c1; // expected-error{{'deprecated' attribute takes no more than 1 argument}}
__declspec(deprecated("warning", 1)) int c2; // expected-error{{'deprecated' attribute takes no more than 1 argument}}

int d1 __attribute__((deprecated("warning", "fixit")));
int d2 __attribute__((deprecated("warning", 1))); // expected-error{{'deprecated' attribute requires a string}}
<|endoftext|>


<commit_before>#include "PNGRead.hpp"

#include <memory>

#include <cstdio>
#include <png.h>

namespace Slic3r { namespace png {

struct PNGDescr {
    png_struct *png = nullptr; png_info *info = nullptr;

    PNGDescr() = default;
    PNGDescr(const PNGDescr&) = delete;
    PNGDescr(PNGDescr&&) = delete;
    PNGDescr& operator=(const PNGDescr&) = delete;
    PNGDescr& operator=(PNGDescr&&) = delete;

    ~PNGDescr()
    {
        if (png && info) png_destroy_info_struct(png, &info);
        if (png) png_destroy_read_struct( &png, nullptr, nullptr);
    }
};

bool is_png(const ReadBuf &rb)
{
    static const constexpr int PNG_SIG_BYTES = 8;

    return rb.sz >= PNG_SIG_BYTES &&
           !png_sig_cmp(static_cast<png_const_bytep>(rb.buf), 0, PNG_SIG_BYTES);
}

bool decode_png(const ReadBuf &rb, ImageGreyscale &img)
{
    if (!is_png(rb)) return false;

    PNGDescr dsc;
    dsc.png = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);

    if(!dsc.png) return false;

    dsc.info = png_create_info_struct(dsc.png);
    if(!dsc.info) return {};

    FILE *io = ::fmemopen(const_cast<void *>(rb.buf), rb.sz, "rb");
    png_init_io(dsc.png, io);

    png_read_info(dsc.png, dsc.info);

    img.cols = png_get_image_width(dsc.png, dsc.info);
    img.rows = png_get_image_height(dsc.png, dsc.info);
    size_t color_type = png_get_color_type(dsc.png, dsc.info);
    size_t bit_depth  = png_get_bit_depth(dsc.png, dsc.info);

    if (color_type != PNG_COLOR_TYPE_GRAY || bit_depth != 8)
        return false;

    img.buf.resize(img.rows * img.cols);

    auto readbuf = static_cast<png_bytep>(img.buf.data());
    for (size_t r = 0; r < img.rows; ++r)
        png_read_row(dsc.png, readbuf + r * img.cols, nullptr);

    fclose(io);

    return true;
}

}}
<commit_msg>Don't use fmemopen, its not standard.<commit_after>#include "PNGRead.hpp"

#include <memory>

#include <cstdio>
#include <png.h>

namespace Slic3r { namespace png {

struct PNGDescr {
    png_struct *png = nullptr; png_info *info = nullptr;

    PNGDescr() = default;
    PNGDescr(const PNGDescr&) = delete;
    PNGDescr(PNGDescr&&) = delete;
    PNGDescr& operator=(const PNGDescr&) = delete;
    PNGDescr& operator=(PNGDescr&&) = delete;

    ~PNGDescr()
    {
        if (png && info) png_destroy_info_struct(png, &info);
        if (png) png_destroy_read_struct( &png, nullptr, nullptr);
    }
};

bool is_png(const ReadBuf &rb)
{
    static const constexpr int PNG_SIG_BYTES = 8;

    return rb.sz >= PNG_SIG_BYTES &&
           !png_sig_cmp(static_cast<png_const_bytep>(rb.buf), 0, PNG_SIG_BYTES);
}

// A wrapper around ReadBuf to be read repeatedly like a stream. libpng needs
// this form for its buffer read callback.
struct ReadBufReader {
    const ReadBuf &rdbuf; size_t pos;
    ReadBufReader(const ReadBuf &rd): rdbuf{rd}, pos{0} {}
};

// Buffer read callback for libpng. It provides an allocated output buffer and
// the amount of data it desires to read from the input.
void png_read_callback(png_struct *png_ptr,
                       png_bytep   outBytes,
                       png_size_t  byteCountToRead)
{
    // Retrieve our input buffer through the png_ptr
    auto reader = static_cast<ReadBufReader *>(png_get_io_ptr(png_ptr));

    if (!reader || byteCountToRead > reader->rdbuf.sz - reader->pos) return;

    auto   buf = static_cast<const png_byte *>(reader->rdbuf.buf);
    size_t pos = reader->pos;

    std::copy(buf + pos, buf + (pos + byteCountToRead), outBytes);
    reader->pos += byteCountToRead;
}

bool decode_png(const ReadBuf &rb, ImageGreyscale &img)
{
    if (!is_png(rb)) return false;

    PNGDescr dsc;
    dsc.png = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr,
                                     nullptr);

    if(!dsc.png) return false;

    dsc.info = png_create_info_struct(dsc.png);
    if(!dsc.info) return {};

    ReadBufReader reader {rb};
    png_set_read_fn(dsc.png, static_cast<void *>(&reader), png_read_callback);

    png_read_info(dsc.png, dsc.info);

    img.cols = png_get_image_width(dsc.png, dsc.info);
    img.rows = png_get_image_height(dsc.png, dsc.info);
    size_t color_type = png_get_color_type(dsc.png, dsc.info);
    size_t bit_depth  = png_get_bit_depth(dsc.png, dsc.info);

    if (color_type != PNG_COLOR_TYPE_GRAY || bit_depth != 8)
        return false;

    img.buf.resize(img.rows * img.cols);

    auto readbuf = static_cast<png_bytep>(img.buf.data());
    for (size_t r = 0; r < img.rows; ++r)
        png_read_row(dsc.png, readbuf + r * img.cols, nullptr);

    return true;
}

}} // namespace Slic3r::png
<|endoftext|>


<commit_before>#include <osg/MatrixTransform>
#include <osg/ClipNode>
#include <osg/Billboard>
#include <osg/Geode>
#include <osg/Group>
#include <osg/Notify>
#include <osg/Material>
#include <osg/PolygonOffset>
#include <osg/PolygonMode>
#include <osg/LineStipple>

#include <osgDB/Registry>
#include <osgDB/ReadFile>

#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgUtil/TransformCallback>

#include <osgProducer/Viewer>

#include <osgUtil/Optimizer>

void write_usage(std::ostream& out,const std::string& name)
{
    out << std::endl;
    out <<"usage:"<< std::endl;
    out <<"    "<<name<<" [options] infile1 [infile2 ...]"<< std::endl;
    out << std::endl;
    out <<"options:"<< std::endl;
    out <<"    -l libraryName      - load plugin of name libraryName"<< std::endl;
    out <<"                          i.e. -l osgdb_pfb"<< std::endl;
    out <<"                          Useful for loading reader/writers which can load"<< std::endl;
    out <<"                          other file formats in addition to its extension."<< std::endl;
    out <<"    -e extensionName    - load reader/wrter plugin for file extension"<< std::endl;
    out <<"                          i.e. -e pfb"<< std::endl;
    out <<"                          Useful short hand for specifying full library name as"<< std::endl;
    out <<"                          done with -l above, as it automatically expands to"<< std::endl;
    out <<"                          the full library name appropriate for each platform."<< std::endl;
    out <<std::endl;
    out <<"    -stereo             - switch on stereo rendering, using the default of,"<< std::endl;
    out <<"                          ANAGLYPHIC or the value set in the OSG_STEREO_MODE "<< std::endl;
    out <<"                          environmental variable. See doc/stereo.html for "<< std::endl;
    out <<"                          further details on setting up accurate stereo "<< std::endl;
    out <<"                          for your system. "<< std::endl;
    out <<"    -stereo ANAGLYPHIC  - switch on anaglyphic(red/cyan) stereo rendering."<< std::endl;
    out <<"    -stereo QUAD_BUFFER - switch on quad buffered stereo rendering."<< std::endl;
    out <<std::endl;
    out <<"    -stencil            - use a visual with stencil buffer enabled, this "<< std::endl;
    out <<"                          also allows the depth complexity statistics mode"<< std::endl;
    out <<"                          to be used (press 'p' three times to cycle to it)."<< std::endl;
    out << std::endl;
}

osg::Node* decorate_with_clip_node(osg::Node* subgraph)
{
    osg::Group* rootnode = new osg::Group;

    // create wireframe view of the model so the user can see
    // what parts are being culled away.
    osg::StateSet* stateset = new osg::StateSet;
    //osg::Material* material = new osg::Material;
    osg::PolygonMode* polymode = new osg::PolygonMode;
    polymode->setMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::LINE);
    stateset->setAttributeAndModes(polymode,osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON);

    osg::Group* wireframe_subgraph = new osg::Group;
    wireframe_subgraph->setStateSet(stateset);
    wireframe_subgraph->addChild(subgraph);
    rootnode->addChild(wireframe_subgraph);

/*
    // simple approach to adding a clipnode above a subrgaph.

    // create clipped part.
    osg::ClipNode* clipped_subgraph = new osg::ClipNode;

    osg::BoundingSphere bs = subgraph->getBound();
    bs.radius()*= 0.4f;

    osg::BoundingBox bb;
    bb.expandBy(bs);

    clipped_subgraph->createClipBox(bb);
    clipped_subgraph->addChild(subgraph);
    rootnode->addChild(clipped_subgraph);
*/

    // more complex approach to managing ClipNode, allowing
    // ClipNode node to be transformed independantly from the subgraph
    // that it is clipping.

    osg::MatrixTransform* transform= new osg::MatrixTransform;

    osg::NodeCallback* nc = new osgUtil::TransformCallback(subgraph->getBound().center(),osg::Vec3(0.0f,0.0f,1.0f),osg::inDegrees(45.0f));
    transform->setUpdateCallback(nc);

    osg::ClipNode* clipnode = new osg::ClipNode;
    osg::BoundingSphere bs = subgraph->getBound();
    bs.radius()*= 0.4f;

    osg::BoundingBox bb;
    bb.expandBy(bs);

    clipnode->createClipBox(bb);
    clipnode->setCullingActive(false);

    transform->addChild(clipnode);
    rootnode->addChild(transform);

    // create clipped part.
    osg::Group* clipped_subgraph = new osg::Group;

    clipped_subgraph->setStateSet(clipnode->getStateSet());
    clipped_subgraph->addChild(subgraph);
    rootnode->addChild(clipped_subgraph);

    return rootnode;
}

int main( int argc, char **argv )
{

    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);

    // set up the usage document, in case we need to print out how to use this program.
    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates use multi-pass and osg::ClipNode to clip parts of the scene away..");
    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");

    // initialize the viewer.
    osgProducer::Viewer viewer(arguments);

    // set up the value with sensible default event handlers.
    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);

    // get details on keyboard and mouse bindings used by the viewer.
    viewer.getUsage(*arguments.getApplicationUsage());

    // if user request help write it out to cout.
    if (arguments.read("-h") || arguments.read("--help"))
    {
        arguments.getApplicationUsage()->write(std::cout);
        return 1;
    }

    // any option left unread are converted into errors to write out later.
    arguments.reportRemainingOptionsAsUnrecognized();

    // report any errors if they have occured when parsing the program aguments.
    if (arguments.errors())
    {
        arguments.writeErrorMessages(std::cout);
        return 1;
    }

    if (arguments.argc()<=1)
    {
        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
        return 1;
    }

    // load the nodes from the commandline arguments.
    osg::Node* loadedModel = osgDB::readNodeFiles(arguments);
    if (!loadedModel)
    {
        write_usage(osg::notify(osg::NOTICE),argv[0]);
        return 1;
    }

    // decorate the scenegraph with a clip node.
    osg::Node* rootnode = decorate_with_clip_node(loadedModel);

    // run optimization over the scene graph
    osgUtil::Optimizer optimzer;
    optimzer.optimize(rootnode);

    // set the scene to render
    viewer.setSceneData(rootnode);

    // create the windows and run the threads.
    viewer.realize();

    while( !viewer.done() )
    {
        // wait for all cull and draw threads to complete.
        viewer.sync();

        // update the scene by traversing it with the the update visitor which will
        // call all node update callbacks and animations.
        viewer.update();

        // fire off the cull and draw traversals of the scene.
        viewer.frame();

    }

    // wait for all cull and draw threads to complete before exit.
    viewer.sync();

    return 0;
}
<commit_msg>Removed redundent write_usage function.<commit_after>#include <osg/MatrixTransform>
#include <osg/ClipNode>
#include <osg/Billboard>
#include <osg/Geode>
#include <osg/Group>
#include <osg/Notify>
#include <osg/Material>
#include <osg/PolygonOffset>
#include <osg/PolygonMode>
#include <osg/LineStipple>

#include <osgDB/Registry>
#include <osgDB/ReadFile>

#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgUtil/TransformCallback>

#include <osgProducer/Viewer>

#include <osgUtil/Optimizer>

osg::Node* decorate_with_clip_node(osg::Node* subgraph)
{
    osg::Group* rootnode = new osg::Group;

    // create wireframe view of the model so the user can see
    // what parts are being culled away.
    osg::StateSet* stateset = new osg::StateSet;
    //osg::Material* material = new osg::Material;
    osg::PolygonMode* polymode = new osg::PolygonMode;
    polymode->setMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::LINE);
    stateset->setAttributeAndModes(polymode,osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON);

    osg::Group* wireframe_subgraph = new osg::Group;
    wireframe_subgraph->setStateSet(stateset);
    wireframe_subgraph->addChild(subgraph);
    rootnode->addChild(wireframe_subgraph);

/*
    // simple approach to adding a clipnode above a subrgaph.

    // create clipped part.
    osg::ClipNode* clipped_subgraph = new osg::ClipNode;

    osg::BoundingSphere bs = subgraph->getBound();
    bs.radius()*= 0.4f;

    osg::BoundingBox bb;
    bb.expandBy(bs);

    clipped_subgraph->createClipBox(bb);
    clipped_subgraph->addChild(subgraph);
    rootnode->addChild(clipped_subgraph);
*/

    // more complex approach to managing ClipNode, allowing
    // ClipNode node to be transformed independantly from the subgraph
    // that it is clipping.

    osg::MatrixTransform* transform= new osg::MatrixTransform;

    osg::NodeCallback* nc = new osgUtil::TransformCallback(subgraph->getBound().center(),osg::Vec3(0.0f,0.0f,1.0f),osg::inDegrees(45.0f));
    transform->setUpdateCallback(nc);

    osg::ClipNode* clipnode = new osg::ClipNode;
    osg::BoundingSphere bs = subgraph->getBound();
    bs.radius()*= 0.4f;

    osg::BoundingBox bb;
    bb.expandBy(bs);

    clipnode->createClipBox(bb);
    clipnode->setCullingActive(false);

    transform->addChild(clipnode);
    rootnode->addChild(transform);

    // create clipped part.
    osg::Group* clipped_subgraph = new osg::Group;

    clipped_subgraph->setStateSet(clipnode->getStateSet());
    clipped_subgraph->addChild(subgraph);
    rootnode->addChild(clipped_subgraph);

    return rootnode;
}

int main( int argc, char **argv )
{

    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);

    // set up the usage document, in case we need to print out how to use this program.
    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates use multi-pass and osg::ClipNode to clip parts of the scene away..");
    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");

    // initialize the viewer.
    osgProducer::Viewer viewer(arguments);

    // set up the value with sensible default event handlers.
    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);

    // get details on keyboard and mouse bindings used by the viewer.
    viewer.getUsage(*arguments.getApplicationUsage());

    // if user request help write it out to cout.
    if (arguments.read("-h") || arguments.read("--help"))
    {
        arguments.getApplicationUsage()->write(std::cout);
        return 1;
    }

    // any option left unread are converted into errors to write out later.
    arguments.reportRemainingOptionsAsUnrecognized();

    // report any errors if they have occured when parsing the program aguments.
    if (arguments.errors())
    {
        arguments.writeErrorMessages(std::cout);
        return 1;
    }

    if (arguments.argc()<=1)
    {
        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
        return 1;
    }

    // load the nodes from the commandline arguments.
    osg::Node* loadedModel = osgDB::readNodeFiles(arguments);
    if (!loadedModel)
    {
        return 1;
    }

    // decorate the scenegraph with a clip node.
    osg::Node* rootnode = decorate_with_clip_node(loadedModel);

    // run optimization over the scene graph
    osgUtil::Optimizer optimzer;
    optimzer.optimize(rootnode);

    // set the scene to render
    viewer.setSceneData(rootnode);

    // create the windows and run the threads.
    viewer.realize();

    while( !viewer.done() )
    {
        // wait for all cull and draw threads to complete.
        viewer.sync();

        // update the scene by traversing it with the the update visitor which will
        // call all node update callbacks and animations.
        viewer.update();

        // fire off the cull and draw traversals of the scene.
        viewer.frame();

    }

    // wait for all cull and draw threads to complete before exit.
    viewer.sync();

    return 0;
}
<|endoftext|>


<commit_before>/*
  Library to control the 74HC595
  More info at http://bildr.org/?s=74hc595
*/

#include "Arduino.h"
#include "Shiftduino.h"

int _dataPin;				//pin 14 on the 75HC595
int _latchPin;				//pin 12 on the 75HC595
int _clockPin;				//pin 11 on the 75HC595

int _numOfRegisterPins;		//number of c.i. in cascade

#define maxRegisterPins 64

boolean _registers[maxRegisterPins];

Shiftduino::Shiftduino(uint8_t dataPin, uint8_t clockPin, uint8_t latchPin, uint8_t numOfRegisters){

	_dataPin = dataPin;
	pinMode(_dataPin, OUTPUT);

	_clockPin = clockPin;
	pinMode(_clockPin, OUTPUT);

	_latchPin = latchPin;
	pinMode(_latchPin, OUTPUT);

	_numOfRegisterPins = numOfRegisters * 8;

	//reset all register pins
	clear();
	writeValues();
}

//set all register pins to LOW
void Shiftduino::clear(){
  for(int i = _numOfRegisterPins - 1; i >=  0; i--){
     _registers[i] = LOW;
  }

  //set pins
  writeValues();
}

//set an individual pin HIGH or LOW
void Shiftduino::setPin(int index, int value){
  _registers[index] = value;

  //set pins
  writeValues();
}

//set an individual pin HIGH or LOW, specifiying the register number
void Shiftduino::setPin(int registerNum, int index, int value){
  finalIndex = (registerNum * _numOfRegisterPins) + index;
  _registers[finalIndex] = value;

  //set pins
  writeValues();
}

//set all pins HIGH or LOW
void Shiftduino::setPins(boolean values[]){
  for(int i = _numOfRegisterPins - 1; i >=  0; i--){
     _registers[i] = values[i];
  }

  //set pins
  writeValues();
}

//set all pins HIGH or LOW
void Shiftduino::setPins(uint64_t values){
  for(int i = 0; i < _numOfRegisterPins; i++){
    _registers[i] = values & 0x00000001;
	values >>= 1;
  }

  //set pins
  writeValues();
}

//Set and display registers
//Only call AFTER all values are set how you would like (slow otherwise)
void Shiftduino::writeValues(){

  digitalWrite(_latchPin, LOW);

  for(int i = _numOfRegisterPins - 1; i >=  0; i--){
    digitalWrite(_clockPin, LOW);

    int value = _registers[i];

    digitalWrite(_dataPin, value);
    digitalWrite(_clockPin, HIGH);

  }
  digitalWrite(_latchPin, HIGH);
}

<commit_msg>corrected minor bug<commit_after>/*
  Library to control the 74HC595
  More info at http://bildr.org/?s=74hc595
*/

#include "Arduino.h"
#include "Shiftduino.h"

int _dataPin;				//pin 14 on the 75HC595
int _latchPin;				//pin 12 on the 75HC595
int _clockPin;				//pin 11 on the 75HC595

int _numOfRegisterPins;		//number of c.i. in cascade

#define maxRegisterPins 64

boolean _registers[maxRegisterPins];

Shiftduino::Shiftduino(uint8_t dataPin, uint8_t clockPin, uint8_t latchPin, uint8_t numOfRegisters){

	_dataPin = dataPin;
	pinMode(_dataPin, OUTPUT);

	_clockPin = clockPin;
	pinMode(_clockPin, OUTPUT);

	_latchPin = latchPin;
	pinMode(_latchPin, OUTPUT);

	_numOfRegisterPins = numOfRegisters * 8;

	//reset all register pins
	clear();
	writeValues();
}

//set all register pins to LOW
void Shiftduino::clear(){
  for(int i = _numOfRegisterPins - 1; i >=  0; i--){
     _registers[i] = LOW;
  }

  //set pins
  writeValues();
}

//set an individual pin HIGH or LOW
void Shiftduino::setPin(int index, int value){
  _registers[index] = value;

  //set pins
  writeValues();
}

//set an individual pin HIGH or LOW, specifiying the register number
void Shiftduino::setPin(int registerNum, int index, int value){
  finalIndex = (registerNum * 8) + index;
  _registers[finalIndex] = value;

  //set pins
  writeValues();
}

//set all pins HIGH or LOW
void Shiftduino::setPins(boolean values[]){
  for(int i = _numOfRegisterPins - 1; i >=  0; i--){
     _registers[i] = values[i];
  }

  //set pins
  writeValues();
}

//set all pins HIGH or LOW
void Shiftduino::setPins(uint64_t values){
  for(int i = 0; i < _numOfRegisterPins; i++){
    _registers[i] = values & 0x00000001;
	values >>= 1;
  }

  //set pins
  writeValues();
}

//Set and display registers
//Only call AFTER all values are set how you would like (slow otherwise)
void Shiftduino::writeValues(){

  digitalWrite(_latchPin, LOW);

  for(int i = _numOfRegisterPins - 1; i >=  0; i--){
    digitalWrite(_clockPin, LOW);

    int value = _registers[i];

    digitalWrite(_dataPin, value);
    digitalWrite(_clockPin, HIGH);

  }
  digitalWrite(_latchPin, HIGH);
}

<|endoftext|>


<commit_before>// Copyright (C) 2012-2014 Leap Motion, Inc. All rights reserved.
#pragma once
#include TYPE_INDEX_HEADER
#include <string>

#if __GNUG__ // Mac and linux
#include <cxxabi.h>
#include <cstdlib>
#include MEMORY_HEADER
#endif

//
// Demangle type names on mac and linux.
// Just returns type_info.name() on windows
//
namespace autowiring {
#if __GNUG__ // Mac and linux

  std::string demangle(const std::type_info& ti) {
    int status;
    std::unique_ptr<char, void(*)(void*)> res{
      abi::__cxa_demangle(ti.name(), nullptr, nullptr, &status),
      std::free
    };
    return std::string(status == 0 ? res.get() : ti.name());
  }

#else // Windows

  std::string demangle(const std::type_info& ti) {
    return std::string(ti.name());
  }

#endif

  template<typename T>
  std::string demangle(T) {
    return demangle(typeid(T));
  }
}//namespace autowiring
<commit_msg>Make demangle static inline<commit_after>// Copyright (C) 2012-2014 Leap Motion, Inc. All rights reserved.
#pragma once
#include TYPE_INDEX_HEADER
#include <string>

#if __GNUG__ // Mac and linux
#include <cxxabi.h>
#include <cstdlib>
#include MEMORY_HEADER
#endif

//
// Demangle type names on mac and linux.
// Just returns type_info.name() on windows
//
namespace autowiring {
#if __GNUG__ // Mac and linux

  static inline std::string demangle(const std::type_info& ti) {
    int status;
    std::unique_ptr<char, void(*)(void*)> res{
      abi::__cxa_demangle(ti.name(), nullptr, nullptr, &status),
      std::free
    };
    return std::string(status == 0 ? res.get() : ti.name());
  }

#else // Windows

  static inline std::string demangle(const std::type_info& ti) {
    return std::string(ti.name());
  }

#endif

  template<typename T>
  static inline std::string demangle(T) {
    return demangle(typeid(T));
  }
}//namespace autowiring
<|endoftext|>


<commit_before>/*
 *            Copyright 2009-2019 The VOTCA Development Team
 *                       (http://www.votca.org)
 *
 *      Licensed under the Apache License, Version 2.0 (the "License")
 *
 * You may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *              http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <numeric>
#include <votca/xtp/checkpoint.h>
#include <votca/xtp/jobtopology.h>
#include <votca/xtp/polarregion.h>
#include <votca/xtp/qmregion.h>
#include <votca/xtp/segmentmapper.h>
#include <votca/xtp/staticregion.h>

namespace votca {
namespace xtp {

void JobTopology::SortRegionsDefbyId(
    std::vector<tools::Property*>& regions_def) const {
  std::sort(regions_def.begin(), regions_def.end(),
            [](const tools::Property* A, const tools::Property* B) {
              return (A->get("id").as<int>()) < (B->get("id").as<int>());
            });
}

void JobTopology::ModifyOptionsByJobFile(
    std::vector<tools::Property*>& regions_def) const {

  const tools::Property& jobinput = _job.getInput();
  std::vector<const tools::Property*> regions_def_job =
      jobinput.Select("regions.region");

  std::string tag = "jobfile";
  for (tools::Property* prop : regions_def) {
    int id = prop->get("id").as<int>();
    std::vector<std::string> paths = FindReplacePathsInOptions(*prop, tag);
    if (!paths.empty()) {
      XTP_LOG_SAVE(logINFO, _log) << " Region " << std::to_string(id)
                                  << " is modified by jobfile" << std::flush;
      XTP_LOG_SAVE(logINFO, _log)
          << " Replacing the following paths with jobfile entries"
          << std::flush;
      for (const std::string& path : paths) {
        XTP_LOG_SAVE(logINFO, _log) << " - " << path << std::flush;
      }

      bool found_region_in_jobfile = false;
      const tools::Property* job_prop = nullptr;
      for (const tools::Property* prop_job : regions_def_job) {
        int id2 = prop_job->get("id").as<int>();
        if (id2 == id) {
          job_prop = prop_job;
          found_region_in_jobfile = true;
        }
      }
      if (!found_region_in_jobfile) {
        throw std::runtime_error("Region " + std::to_string(id) +
                                 " was not found in jobfile.");
      }
      UpdateFromJobfile(*prop, *job_prop, paths);
    }
  }
}

void JobTopology::BuildRegions(const Topology& top, tools::Property options) {

  std::vector<tools::Property*> regions_def = options.Select("region");
  CheckEnumerationOfRegions(regions_def);
  SortRegionsDefbyId(regions_def);
  ModifyOptionsByJobFile(regions_def);

  std::vector<std::vector<SegId> > region_seg_ids =
      PartitionRegions(regions_def, top);

  // around this point the whole jobtopology will be centered
  CreateRegions(options, top, region_seg_ids);
  XTP_LOG_SAVE(logINFO, _log) << " Regions created" << std::flush;
  for (const auto& region : _regions) {
    XTP_LOG_SAVE(logINFO, _log) << *region << std::flush;
  }

  return;
}

std::vector<std::string> JobTopology::FindReplacePathsInOptions(
    const tools::Property& options, std::string tag) const {
  std::vector<std::string> result;
  std::string options_path = "options.qmmm.regions.region";
  for (const tools::Property& sub : options) {
    if (sub.HasChildren()) {
      std::vector<std::string> subresult = FindReplacePathsInOptions(sub, tag);
      result.insert(result.end(), subresult.begin(), subresult.end());
    } else if (sub.value() == tag) {
      std::string path = sub.path() + "." + sub.name();
      std::size_t pos = path.find(options_path);
      if (pos != std::string::npos) {
        path.replace(pos, options_path.size(), "");
      }
      result.push_back(path);
    }
  }
  return result;
}

void JobTopology::UpdateFromJobfile(
    tools::Property& options, const tools::Property& job_opt,
    const std::vector<std::string>& paths) const {
  for (const std::string& path : paths) {
    if (job_opt.exists(path)) {
      options.set(path, job_opt.get(path).value());
    } else {
      throw std::runtime_error("Jobfile does not contain options for " + path);
    }
  }
}

template <class T>
void JobTopology::ShiftPBC(const Topology& top, const Eigen::Vector3d& center,
                           T& mol) const {
  Eigen::Vector3d r_pbc = top.PbShortestConnect(center, mol.getPos());
  Eigen::Vector3d r = mol.getPos() - center;
  Eigen::Vector3d shift = r_pbc - r;
  std::cout << "mol.getPos().transpose()<<"
               "<<center"
            << std::endl;
  std::cout << mol.getPos().transpose() << " " << center.transpose()
            << std::endl;
  std::cout << r_pbc.transpose() << " " << r.transpose() << std::endl;
  if (shift.norm() > 1e-9) {
    mol.Translate(shift);
  }
}

void JobTopology::CreateRegions(
    const tools::Property& options, const Topology& top,
    const std::vector<std::vector<SegId> >& region_seg_ids) {
  std::string mapfile =
      options.ifExistsReturnElseThrowRuntimeError<std::string>("mapfile");
  std::vector<const tools::Property*> regions_def = options.Select("region");
  // around this point the whole jobtopology will be centered for removing pbc
  Eigen::Vector3d center = top.getSegment(region_seg_ids[0][0].Id()).getPos();

  for (const tools::Property* region_def : regions_def) {
    int id = region_def->ifExistsReturnElseThrowRuntimeError<int>("id");
    const std::vector<SegId>& seg_ids = region_seg_ids[id];
    std::string type =
        region_def->ifExistsReturnElseThrowRuntimeError<std::string>("type");
    std::unique_ptr<Region> region;
    QMRegion QMdummy(0, _log, "");
    StaticRegion Staticdummy(0, _log);
    PolarRegion Polardummy(0, _log);

    if (type == QMdummy.identify()) {
      std::unique_ptr<QMRegion> qmregion =
          std::unique_ptr<QMRegion>(new QMRegion(id, _log, _workdir));
      QMMapper qmmapper(_log);
      qmmapper.LoadMappingFile(mapfile);
      for (const SegId& seg_index : seg_ids) {
        const Segment& segment = top.getSegment(seg_index.Id());
        QMMolecule mol = qmmapper.map(segment, seg_index);
        mol.setName("qm" + std::to_string(id));
        ShiftPBC(top, center, mol);
        qmregion->push_back(mol);
      }
      region = std::move(qmregion);
    } else if (type == Polardummy.identify()) {
      std::unique_ptr<PolarRegion> polarregion =
          std::unique_ptr<PolarRegion>(new PolarRegion(id, _log));
      PolarMapper polmap(_log);
      polmap.LoadMappingFile(mapfile);
      for (const SegId& seg_index : seg_ids) {
        const Segment& segment = top.getSegment(seg_index.Id());

        PolarSegment mol = polmap.map(segment, seg_index);
        std::cout << "id" << seg_index.Id() << " " << segment.getId() << " "
                  << segment.getPos().transpose() << " "
                  << mol.getPos().transpose() << std::endl;
        ShiftPBC(top, center, mol);
        mol.setName("mm" + std::to_string(id));
        polarregion->push_back(mol);
      }
      region = std::move(polarregion);
    } else if (type == Staticdummy.identify()) {
      std::unique_ptr<StaticRegion> staticregion =
          std::unique_ptr<StaticRegion>(new StaticRegion(id, _log));
      StaticMapper staticmap(_log);
      staticmap.LoadMappingFile(mapfile);
      for (const SegId& seg_index : seg_ids) {
        const Segment& segment = top.getSegment(seg_index.Id());
        StaticSegment mol = staticmap.map(segment, seg_index);
        mol.setName("mm" + std::to_string(id));
        ShiftPBC(top, center, mol);
        staticregion->push_back(mol);
      }
      region = std::move(staticregion);

    } else {
      throw std::runtime_error("Region type not known!");
    }
    region->Initialize(*region_def);
    _regions.push_back(std::move(region));
  }
}

void JobTopology::WriteToPdb(std::string filename) const {

  csg::PDBWriter writer;
  writer.Open(filename, false);
  writer.WriteHeader("Job:" + std::to_string(this->_job.getId()));
  for (const std::unique_ptr<Region>& reg : _regions) {
    reg->WritePDB(writer);
  }
  writer.Close();
}

std::vector<std::vector<SegId> > JobTopology::PartitionRegions(
    const std::vector<tools::Property*>& regions_def,
    const Topology& top) const {

  std::vector<int> explicitly_named_segs_per_region;
  std::vector<std::vector<SegId> > segids_per_region;
  std::vector<bool> processed_segments =
      std::vector<bool>(top.Segments().size(), false);
  for (const tools::Property* region_def : regions_def) {

    if (!region_def->exists("segments") && !region_def->exists("cutoff")) {
      throw std::runtime_error(
          "Region definition needs either segments or a cutoff to find "
          "segments");
    }
    std::vector<SegId> seg_ids;
    if (region_def->exists("segments")) {
      std::string seg_ids_string =
          region_def->get("segments").as<std::string>();
      tools::Tokenizer tok(seg_ids_string, " \n\t");
      for (const std::string& seg_id_string : tok.ToVector()) {
        seg_ids.push_back(SegId(seg_id_string));
      }
      for (const SegId& seg_id : seg_ids) {
        if (seg_id.Id() > int(top.Segments().size() - 1)) {
          throw std::runtime_error("Segment id is not in topology");
        }
        processed_segments[seg_id.Id()] = true;
      }
    }
    explicitly_named_segs_per_region.push_back(seg_ids.size());

    if (region_def->exists("cutoff")) {
      double cutoff = tools::conv::nm2bohr *
                      region_def->ifExistsReturnElseThrowRuntimeError<double>(
                          "cutoff.radius");

      std::string seg_geometry =
          region_def->ifExistsReturnElseReturnDefault<std::string>(
              "cutoff.geometry", "n");
      double min = top.getBox().diagonal().minCoeff();
      if (cutoff > 0.5 * min) {
        throw std::runtime_error(
            (boost::format("Cutoff is larger than half the box size. Maximum "
                           "allowed cutoff is %1$1.1f") %
             (tools::conv::bohr2nm * 0.5 * min))
                .str());
      }
      std::vector<SegId> center = seg_ids;
      if (region_def->exists("cutoff.region")) {
        int id = region_def->get("cutoff.region").as<int>();
        bool only_explicit = region_def->ifExistsReturnElseReturnDefault<bool>(
            "cutoff.relative_to_explicit_segs", false);
        if (id < int(segids_per_region.size())) {
          center = segids_per_region[id];
          if (only_explicit) {
            int no_of_segs = explicitly_named_segs_per_region[id];
            if (no_of_segs == 0) {
              throw std::runtime_error("Region with id '" + std::to_string(id) +
                                       "' does not have");
            }
            center.resize(no_of_segs, SegId(0, "n"));
            // need the second argument because resize can also increase
            // capacity of vector and then needs a constructor,
            // here we shrink, so should not happen
          }
        } else {
          throw std::runtime_error("Region with id '" + std::to_string(id) +
                                   "' used for cutoff does not exist");
        }
      }
      if (center.empty()) {
        throw std::runtime_error(
            "Region needs either a segment or another region to which to apply "
            "the cutoff");
      }
      for (const SegId& segid : center) {
        const Segment& center_seg = top.getSegment(segid.Id());
        for (const Segment& otherseg : top.Segments()) {
          if (center_seg.getId() == otherseg.getId() ||
              processed_segments[otherseg.getId()]) {
            continue;
          }
          if (top.PbShortestConnect(center_seg.getPos(), otherseg.getPos())
                  .norm() < cutoff) {
            seg_ids.push_back(SegId(otherseg.getId(), seg_geometry));
            processed_segments[otherseg.getId()] = true;
          }
        }
      }
    }
    segids_per_region.push_back(seg_ids);
  }
  return segids_per_region;
}

void JobTopology::CheckEnumerationOfRegions(
    const std::vector<tools::Property*>& regions_def) const {
  std::vector<int> reg_ids;
  for (const tools::Property* region_def : regions_def) {
    reg_ids.push_back(
        region_def->ifExistsReturnElseThrowRuntimeError<int>("id"));
  }

  std::vector<int> v(reg_ids.size());
  std::iota(v.begin(), v.end(), 0);
  if (!std::is_permutation(reg_ids.begin(), reg_ids.end(), v.begin())) {
    throw std::runtime_error(
        "Region id definitions are not clear. You must start at id 0 and then "
        "ascending order. i.e. 0 1 2 3.");
  }
}

void JobTopology::WriteToHdf5(std::string filename) const {
  CheckpointFile cpf(filename, CheckpointAccessLevel::CREATE);
  CheckpointWriter a = cpf.getWriter();
  a(_job.getId(), "jobid");

  for (const auto& region : _regions) {
    CheckpointWriter w =
        cpf.getWriter("region_" + std::to_string(region->getId()));
    region->WriteToCpt(w);
  }
}

}  // namespace xtp
}  // namespace votca
<commit_msg>removed couts<commit_after>/*
 *            Copyright 2009-2019 The VOTCA Development Team
 *                       (http://www.votca.org)
 *
 *      Licensed under the Apache License, Version 2.0 (the "License")
 *
 * You may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *              http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <numeric>
#include <votca/xtp/checkpoint.h>
#include <votca/xtp/jobtopology.h>
#include <votca/xtp/polarregion.h>
#include <votca/xtp/qmregion.h>
#include <votca/xtp/segmentmapper.h>
#include <votca/xtp/staticregion.h>

namespace votca {
namespace xtp {

void JobTopology::SortRegionsDefbyId(
    std::vector<tools::Property*>& regions_def) const {
  std::sort(regions_def.begin(), regions_def.end(),
            [](const tools::Property* A, const tools::Property* B) {
              return (A->get("id").as<int>()) < (B->get("id").as<int>());
            });
}

void JobTopology::ModifyOptionsByJobFile(
    std::vector<tools::Property*>& regions_def) const {

  const tools::Property& jobinput = _job.getInput();
  std::vector<const tools::Property*> regions_def_job =
      jobinput.Select("regions.region");

  std::string tag = "jobfile";
  for (tools::Property* prop : regions_def) {
    int id = prop->get("id").as<int>();
    std::vector<std::string> paths = FindReplacePathsInOptions(*prop, tag);
    if (!paths.empty()) {
      XTP_LOG_SAVE(logINFO, _log) << " Region " << std::to_string(id)
                                  << " is modified by jobfile" << std::flush;
      XTP_LOG_SAVE(logINFO, _log)
          << " Replacing the following paths with jobfile entries"
          << std::flush;
      for (const std::string& path : paths) {
        XTP_LOG_SAVE(logINFO, _log) << " - " << path << std::flush;
      }

      bool found_region_in_jobfile = false;
      const tools::Property* job_prop = nullptr;
      for (const tools::Property* prop_job : regions_def_job) {
        int id2 = prop_job->get("id").as<int>();
        if (id2 == id) {
          job_prop = prop_job;
          found_region_in_jobfile = true;
        }
      }
      if (!found_region_in_jobfile) {
        throw std::runtime_error("Region " + std::to_string(id) +
                                 " was not found in jobfile.");
      }
      UpdateFromJobfile(*prop, *job_prop, paths);
    }
  }
}

void JobTopology::BuildRegions(const Topology& top, tools::Property options) {

  std::vector<tools::Property*> regions_def = options.Select("region");
  CheckEnumerationOfRegions(regions_def);
  SortRegionsDefbyId(regions_def);
  ModifyOptionsByJobFile(regions_def);

  std::vector<std::vector<SegId> > region_seg_ids =
      PartitionRegions(regions_def, top);

  // around this point the whole jobtopology will be centered
  CreateRegions(options, top, region_seg_ids);
  XTP_LOG_SAVE(logINFO, _log) << " Regions created" << std::flush;
  for (const auto& region : _regions) {
    XTP_LOG_SAVE(logINFO, _log) << *region << std::flush;
  }

  return;
}

std::vector<std::string> JobTopology::FindReplacePathsInOptions(
    const tools::Property& options, std::string tag) const {
  std::vector<std::string> result;
  std::string options_path = "options.qmmm.regions.region";
  for (const tools::Property& sub : options) {
    if (sub.HasChildren()) {
      std::vector<std::string> subresult = FindReplacePathsInOptions(sub, tag);
      result.insert(result.end(), subresult.begin(), subresult.end());
    } else if (sub.value() == tag) {
      std::string path = sub.path() + "." + sub.name();
      std::size_t pos = path.find(options_path);
      if (pos != std::string::npos) {
        path.replace(pos, options_path.size(), "");
      }
      result.push_back(path);
    }
  }
  return result;
}

void JobTopology::UpdateFromJobfile(
    tools::Property& options, const tools::Property& job_opt,
    const std::vector<std::string>& paths) const {
  for (const std::string& path : paths) {
    if (job_opt.exists(path)) {
      options.set(path, job_opt.get(path).value());
    } else {
      throw std::runtime_error("Jobfile does not contain options for " + path);
    }
  }
}

template <class T>
void JobTopology::ShiftPBC(const Topology& top, const Eigen::Vector3d& center,
                           T& mol) const {
  Eigen::Vector3d r_pbc = top.PbShortestConnect(center, mol.getPos());
  Eigen::Vector3d r = mol.getPos() - center;
  Eigen::Vector3d shift = r_pbc - r;
  if (shift.norm() > 1e-9) {
    mol.Translate(shift);
  }
}

void JobTopology::CreateRegions(
    const tools::Property& options, const Topology& top,
    const std::vector<std::vector<SegId> >& region_seg_ids) {
  std::string mapfile =
      options.ifExistsReturnElseThrowRuntimeError<std::string>("mapfile");
  std::vector<const tools::Property*> regions_def = options.Select("region");
  // around this point the whole jobtopology will be centered for removing pbc
  Eigen::Vector3d center = top.getSegment(region_seg_ids[0][0].Id()).getPos();

  for (const tools::Property* region_def : regions_def) {
    int id = region_def->ifExistsReturnElseThrowRuntimeError<int>("id");
    const std::vector<SegId>& seg_ids = region_seg_ids[id];
    std::string type =
        region_def->ifExistsReturnElseThrowRuntimeError<std::string>("type");
    std::unique_ptr<Region> region;
    QMRegion QMdummy(0, _log, "");
    StaticRegion Staticdummy(0, _log);
    PolarRegion Polardummy(0, _log);

    if (type == QMdummy.identify()) {
      std::unique_ptr<QMRegion> qmregion =
          std::unique_ptr<QMRegion>(new QMRegion(id, _log, _workdir));
      QMMapper qmmapper(_log);
      qmmapper.LoadMappingFile(mapfile);
      for (const SegId& seg_index : seg_ids) {
        const Segment& segment = top.getSegment(seg_index.Id());
        QMMolecule mol = qmmapper.map(segment, seg_index);
        mol.setName("qm" + std::to_string(id));
        ShiftPBC(top, center, mol);
        qmregion->push_back(mol);
      }
      region = std::move(qmregion);
    } else if (type == Polardummy.identify()) {
      std::unique_ptr<PolarRegion> polarregion =
          std::unique_ptr<PolarRegion>(new PolarRegion(id, _log));
      PolarMapper polmap(_log);
      polmap.LoadMappingFile(mapfile);
      for (const SegId& seg_index : seg_ids) {
        const Segment& segment = top.getSegment(seg_index.Id());

        PolarSegment mol = polmap.map(segment, seg_index);

        ShiftPBC(top, center, mol);
        mol.setName("mm" + std::to_string(id));
        polarregion->push_back(mol);
      }
      region = std::move(polarregion);
    } else if (type == Staticdummy.identify()) {
      std::unique_ptr<StaticRegion> staticregion =
          std::unique_ptr<StaticRegion>(new StaticRegion(id, _log));
      StaticMapper staticmap(_log);
      staticmap.LoadMappingFile(mapfile);
      for (const SegId& seg_index : seg_ids) {
        const Segment& segment = top.getSegment(seg_index.Id());
        StaticSegment mol = staticmap.map(segment, seg_index);
        mol.setName("mm" + std::to_string(id));
        ShiftPBC(top, center, mol);
        staticregion->push_back(mol);
      }
      region = std::move(staticregion);

    } else {
      throw std::runtime_error("Region type not known!");
    }
    region->Initialize(*region_def);
    _regions.push_back(std::move(region));
  }
}

void JobTopology::WriteToPdb(std::string filename) const {

  csg::PDBWriter writer;
  writer.Open(filename, false);
  writer.WriteHeader("Job:" + std::to_string(this->_job.getId()));
  for (const std::unique_ptr<Region>& reg : _regions) {
    reg->WritePDB(writer);
  }
  writer.Close();
}

std::vector<std::vector<SegId> > JobTopology::PartitionRegions(
    const std::vector<tools::Property*>& regions_def,
    const Topology& top) const {

  std::vector<int> explicitly_named_segs_per_region;
  std::vector<std::vector<SegId> > segids_per_region;
  std::vector<bool> processed_segments =
      std::vector<bool>(top.Segments().size(), false);
  for (const tools::Property* region_def : regions_def) {

    if (!region_def->exists("segments") && !region_def->exists("cutoff")) {
      throw std::runtime_error(
          "Region definition needs either segments or a cutoff to find "
          "segments");
    }
    std::vector<SegId> seg_ids;
    if (region_def->exists("segments")) {
      std::string seg_ids_string =
          region_def->get("segments").as<std::string>();
      tools::Tokenizer tok(seg_ids_string, " \n\t");
      for (const std::string& seg_id_string : tok.ToVector()) {
        seg_ids.push_back(SegId(seg_id_string));
      }
      for (const SegId& seg_id : seg_ids) {
        if (seg_id.Id() > int(top.Segments().size() - 1)) {
          throw std::runtime_error("Segment id is not in topology");
        }
        processed_segments[seg_id.Id()] = true;
      }
    }
    explicitly_named_segs_per_region.push_back(seg_ids.size());

    if (region_def->exists("cutoff")) {
      double cutoff = tools::conv::nm2bohr *
                      region_def->ifExistsReturnElseThrowRuntimeError<double>(
                          "cutoff.radius");

      std::string seg_geometry =
          region_def->ifExistsReturnElseReturnDefault<std::string>(
              "cutoff.geometry", "n");
      double min = top.getBox().diagonal().minCoeff();
      if (cutoff > 0.5 * min) {
        throw std::runtime_error(
            (boost::format("Cutoff is larger than half the box size. Maximum "
                           "allowed cutoff is %1$1.1f") %
             (tools::conv::bohr2nm * 0.5 * min))
                .str());
      }
      std::vector<SegId> center = seg_ids;
      if (region_def->exists("cutoff.region")) {
        int id = region_def->get("cutoff.region").as<int>();
        bool only_explicit = region_def->ifExistsReturnElseReturnDefault<bool>(
            "cutoff.relative_to_explicit_segs", false);
        if (id < int(segids_per_region.size())) {
          center = segids_per_region[id];
          if (only_explicit) {
            int no_of_segs = explicitly_named_segs_per_region[id];
            if (no_of_segs == 0) {
              throw std::runtime_error("Region with id '" + std::to_string(id) +
                                       "' does not have");
            }
            center.resize(no_of_segs, SegId(0, "n"));
            // need the second argument because resize can also increase
            // capacity of vector and then needs a constructor,
            // here we shrink, so should not happen
          }
        } else {
          throw std::runtime_error("Region with id '" + std::to_string(id) +
                                   "' used for cutoff does not exist");
        }
      }
      if (center.empty()) {
        throw std::runtime_error(
            "Region needs either a segment or another region to which to apply "
            "the cutoff");
      }
      for (const SegId& segid : center) {
        const Segment& center_seg = top.getSegment(segid.Id());
        for (const Segment& otherseg : top.Segments()) {
          if (center_seg.getId() == otherseg.getId() ||
              processed_segments[otherseg.getId()]) {
            continue;
          }
          if (top.PbShortestConnect(center_seg.getPos(), otherseg.getPos())
                  .norm() < cutoff) {
            seg_ids.push_back(SegId(otherseg.getId(), seg_geometry));
            processed_segments[otherseg.getId()] = true;
          }
        }
      }
    }
    segids_per_region.push_back(seg_ids);
  }
  return segids_per_region;
}

void JobTopology::CheckEnumerationOfRegions(
    const std::vector<tools::Property*>& regions_def) const {
  std::vector<int> reg_ids;
  for (const tools::Property* region_def : regions_def) {
    reg_ids.push_back(
        region_def->ifExistsReturnElseThrowRuntimeError<int>("id"));
  }

  std::vector<int> v(reg_ids.size());
  std::iota(v.begin(), v.end(), 0);
  if (!std::is_permutation(reg_ids.begin(), reg_ids.end(), v.begin())) {
    throw std::runtime_error(
        "Region id definitions are not clear. You must start at id 0 and then "
        "ascending order. i.e. 0 1 2 3.");
  }
}

void JobTopology::WriteToHdf5(std::string filename) const {
  CheckpointFile cpf(filename, CheckpointAccessLevel::CREATE);
  CheckpointWriter a = cpf.getWriter();
  a(_job.getId(), "jobid");

  for (const auto& region : _regions) {
    CheckpointWriter w =
        cpf.getWriter("region_" + std::to_string(region->getId()));
    region->WriteToCpt(w);
  }
}

}  // namespace xtp
}  // namespace votca
<|endoftext|>