コード例 #1
0
const boost::shared_ptr<ribi::trim::Cell> ribi::trim::CellFactory::CreateTestPrism() const noexcept
{
    const std::vector<boost::shared_ptr<Face> > faces {
        FaceFactory().CreateTestPrism()
    };
    const boost::shared_ptr<Cell> prism {
        CellFactory().Create(faces)
    };
    assert(prism);
    return prism;
}
コード例 #2
0
boost::shared_ptr<ribi::trim::Template> ribi::trim::Template::CreateTest3x3() noexcept
{
  std::vector<boost::shared_ptr<Face>> faces;
  std::vector<std::vector<int>> face_point_indices;
  std::vector<boost::shared_ptr<Point>> points;
  const int width{3};
  const int height{3};
  const int n_points{width * height};
  const bool verbose{false};
  points.reserve(n_points);

  //Create points
  {
    for(int i=0; i!=n_points; ++i)
    {
      const double x{static_cast<double>(i % width)};
      const double y{static_cast<double>(i / width)};
      const std::string boundary_type = "three_times_three";
      const boost::shared_ptr<const ConstCoordinat2D> bottom{
        new ConstCoordinat2D(x,y)
      };
      const auto point = PointFactory().Create(bottom);
      points.push_back(point);
    }
  }
  #ifndef NDEBUG
  //Check that there is no coordinat present twice
  {
    for (int i=0; i!=n_points; ++i)
    {
      const boost::shared_ptr<const ConstCoordinat2D> a { points[i]->GetCoordinat() };
      for (int j=0; j!=n_points; ++j)
      {
        const boost::shared_ptr<const ConstCoordinat2D> b { points[j]->GetCoordinat() };
        if (a == b)
        {
          assert(boost::geometry::distance(*a,*b) < 0.001);
        }
        else
        {
          assert(boost::geometry::distance(*a,*b) > 0.001);
        }
      }
    }
  }
  #endif

  //Load and translate faces
  face_point_indices = {
    { 0,1,3 },
    { 1,2,4 },
    { 1,3,4 },
    { 2,4,5 },
    { 3,4,6 },
    { 4,5,7 },
    { 4,6,7 },
    { 5,7,8 }
  };

  const std::vector<std::pair<int,int>> edges {
    { 0,1 },
    { 0,3 },
    { 1,2 },
    { 1,3 },
    { 1,4 },
    { 2,4 },
    { 2,5 },
    { 3,4 },
    { 3,6 },
    { 4,5 },
    { 4,6 },
    { 4,7 },
    { 5,7 },
    { 5,8 },
    { 6,7 },
    { 7,8 }
  };

  {
    for(const auto v: face_point_indices)
    {
      assert(v.size() == 3);
      //I do not correct for one-base Triangle.exe output
      const int point1 = v[0];
      const int point2 = v[1];
      const int point3 = v[2];
      assert(point1 >= 0);
      assert(point2 >= 0);
      assert(point3 >= 0);
      const std::vector<int> face_point_indices {
        point1,
        point2,
        point3
      };
      std::vector<boost::shared_ptr<Point>> face_points {
        points[point1],
        points[point2],
        points[point3]
      };
      
      if (!Helper().IsClockwiseHorizontal(face_points))
      {
        std::reverse(face_points.begin(),face_points.end());
      }
      assert(Helper().IsClockwiseHorizontal(face_points));
      const boost::shared_ptr<Face> face {
        FaceFactory().Create(
          face_points,
          FaceOrientation::horizontal,
          verbose
        )
      };
      faces.push_back(face);
    }
  }

  #ifndef NDEBUG
  const int n_faces = static_cast<int>(faces.size());
  assert(faces.size() == face_point_indices.size());
  for (int i=0; i!=n_faces; ++i)
  {
    const auto face = faces[i];
    const auto indices = face_point_indices[i];
    assert(face->GetPoints().size() == indices.size());
    /*
    const int n_points = static_cast<int>(indices.size());
    for (int j=0; j!=n_points; ++j)
    {
      //Only true when points are not reversed
      assert(face->GetPoints()[j] == points[ indices[j] ]);
    }
    */
  }
  #endif

  assert(faces.size()  ==  8 && "2x2 adjacent squares consist of 8 triangles");
  assert(edges.size()  == 16 && "2x2 adjacent squares (with diagonals) have 16 edges");
  assert(points.size() ==  9 && "2x2 adjacent squares have 9 nodes");

  const boost::shared_ptr<Template> my_template {
    new Template(
      edges,
      faces,
      face_point_indices,
      points
    )
  };
  assert(my_template);
  return my_template;
}
コード例 #3
0
void ribi::trim::Template::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  PointFactory();
  FaceFactory();

  const TestTimer test_timer(__func__,__FILE__,1.0);
  const bool verbose{false};
  if (verbose) { TRACE("IsClockWise, confirmation"); }
  {
    /*

    Cartesian plane

          |
          |
          A = (0,1)
         /|\
        / | \
    ---+--+--+----
      /   |   \
     C----+----B
          |
          |


    */
    //12 o'clock
    const boost::shared_ptr<const ConstCoordinat2D> a {
      new ConstCoordinat2D(0.0,1.0)
    };
    //4 o'clock
    const boost::shared_ptr<const ConstCoordinat2D> b {
      new ConstCoordinat2D(0.83,-0.5)
    };
    //8 o'clock
    const boost::shared_ptr<const ConstCoordinat2D> c {
      new ConstCoordinat2D(-0.83,-0.5)
    };
    std::vector<boost::shared_ptr<Point>> points {
      PointFactory().Create(a),
      PointFactory().Create(b),
      PointFactory().Create(c)
    };
    points[0]->SetZ(1.0 * boost::units::si::meter);
    points[1]->SetZ(1.0 * boost::units::si::meter);
    points[2]->SetZ(1.0 * boost::units::si::meter);
    assert( Helper().IsClockwiseHorizontal(points));
    std::reverse(points.begin(),points.end());
    assert(!Helper().IsClockwiseHorizontal(points));
  }
  if (verbose) { TRACE("IsClockWise, rejection"); }
  {
    /*

    Cartesian plane

          |
          |
          A = (0,1)
         /|\
        / | \
    ---+--+--+----
      /   |   \
     B----+----C
          |
          |


    */
    //12 o'clock
    const boost::shared_ptr<const ConstCoordinat2D> a {
      new ConstCoordinat2D(0.0,1.0)
    };
    //8 o'clock
    const boost::shared_ptr<const ConstCoordinat2D> b {
      new ConstCoordinat2D(-0.83,-0.5)
    };
    //4 o'clock
    const boost::shared_ptr<const ConstCoordinat2D> c {
      new ConstCoordinat2D(0.83,-0.5)
    };
    std::vector<boost::shared_ptr<Point>> points {
      PointFactory().Create(a),
      PointFactory().Create(b),
      PointFactory().Create(c)
    };
    points[0]->SetZ(1.0 * boost::units::si::meter);
    points[1]->SetZ(1.0 * boost::units::si::meter);
    points[2]->SetZ(1.0 * boost::units::si::meter);
    assert(!Helper().IsClockwiseHorizontal(points));
    std::reverse(points.begin(),points.end());
    assert(Helper().IsClockwiseHorizontal(points));
  }
  for (int i=0; i!=4; ++i)
  {
    const boost::shared_ptr<Template> my_template {
      CreateTest(i)
    };
    assert(my_template);
    for (const auto& face: my_template->GetFaces())
    {
      if (!Helper().IsClockwiseHorizontal(face->GetPoints()))
      {
        TRACE("BREAK");
      }
      assert(Helper().IsClockwiseHorizontal(face->GetPoints()));
    }
  }
}
コード例 #4
0
boost::shared_ptr<ribi::trim::Template> ribi::trim::Template::CreateTestTriangle2x2() noexcept
{
  std::vector<boost::shared_ptr<Face>> faces;
  std::vector<std::vector<int>> face_point_indices;
  std::vector<boost::shared_ptr<Point>> points;
  const int width{2};
  //const int height = 2;
  const int n_points{3}; //Triangle
  const bool verbose{false};
  points.reserve(n_points);

  //Create points
  {
    for(int i=0; i!=n_points; ++i)
    {
      const double x = static_cast<double>(i % width);
      const double y = static_cast<double>(i / width);
      const std::string boundary_type{"two_times_two"};
      const boost::shared_ptr<const ConstCoordinat2D> bottom {
        new ConstCoordinat2D(x,y)
      };
      const boost::shared_ptr<Point> point {
        PointFactory().Create(bottom)
      };
      points.push_back(point);
    }
  }
  #ifndef NDEBUG
  //Check that there is no coordinat present twice
  {
    for (int i=0; i!=n_points; ++i)
    {
      const boost::shared_ptr<const ConstCoordinat2D> a { points[i]->GetCoordinat() };
      for (int j=0; j!=n_points; ++j)
      {
        const boost::shared_ptr<const ConstCoordinat2D> b { points[j]->GetCoordinat() };
        if (a == b)
        {
          assert(boost::geometry::distance(*a,*b) < 0.001);
        }
        else
        {
          assert(boost::geometry::distance(*a,*b) > 0.001);
        }
      }
    }
  }
  #endif

  //Load and translate faces
  face_point_indices = {
    { 0,1,2 }
  };

  const std::vector<std::pair<int,int>> edges {
    { 0,1 },
    { 0,2 },
    { 1,2 }
  };

  {
    for(const auto v: face_point_indices)
    {
      assert(v.size() == 3);
      //I do not correct for one-base Triangle.exe output
      assert(v[0] >= 0);
      assert(v[1] >= 0);
      assert(v[2] >= 0);
      std::vector<boost::shared_ptr<Point>> face_points {
        points[ v[0] ],
        points[ v[1] ],
        points[ v[2] ]
      };
      
      if (!Helper().IsClockwiseHorizontal(face_points))
      {
        std::reverse(face_points.begin(),face_points.end());
      }
      #ifndef NDEBUG
      if (!Helper().IsClockwiseHorizontal(face_points))
      {
        TRACE("ERROR");
        TRACE(*face_points[0]);
        TRACE(*face_points[1]);
        TRACE(*face_points[2]);
        TRACE("BREAK");
      }
      #endif
      assert(Helper().IsClockwiseHorizontal(face_points));
      const boost::shared_ptr<Face> face {
        FaceFactory().Create(
          face_points,
          FaceOrientation::horizontal,
          verbose
        )
      };
      faces.push_back(face);
    }
  }

  #ifndef NDEBUG
  const int n_faces = static_cast<int>(faces.size());
  assert(faces.size() == face_point_indices.size());
  for (int i=0; i!=n_faces; ++i)
  {
    const auto face = faces[i];
    const auto indices = face_point_indices[i];
    assert(face->GetPoints().size() == indices.size());
  }
  #endif

  assert(faces.size()  == 1 && "A triangle is only 1 triangle");
  assert(edges.size()  == 3 && "A triangle has 3 edges");
  assert(points.size() == 3 && "A triangle has 3 nodes");

  const boost::shared_ptr<Template> my_template {
    new Template(
      edges,
      faces,
      face_point_indices,
      points
    )
  };
  assert(my_template);
  return my_template;
}
コード例 #5
0
ribi::trim::Template::Template(
  const std::string& filename_node,
  const std::string& filename_ele,
  const bool verbose
)
  : m_edges{},
    m_faces{},
    m_face_point_indices{},
    m_points{}
{
  #ifndef NDEBUG
  Test();
  #endif

  if (verbose) { TRACE("Load the points and faces created by Triangle"); }
  {
    const std::vector<std::string> v {
      ribi::fileio::FileIo().FileToVector(
        filename_node
      )
    };
    const int sz = v.size();
    const int percent = sz / 100 ? sz / 100: 1;
    for(int n=0; n!=sz; ++n)
    {
      if (verbose) { if (n % percent == 0) std::clog << '%'; }
      const std::string line = v[n];
      if(n==0) continue; //No idea why this has to be skipped
      const std::vector<std::string> w { CleanAndSplitString(ConvertNumbersToEnglish(line)) };
      if (w.empty() || w[0].empty() ||  w[0] == "#")
      {
        //The final comment line
        continue;
      }
      assert(w.size() == 4);
      assert(CanLexicalCast<int>(w[0]));
      assert(CanLexicalCast<double>(w[1]));
      #ifndef NDEBUG
      if (!CanLexicalCast<double>(w[2]))
      {
        TRACE("ERROR");
        TRACE(line);
        TRACE(w[0]);
        TRACE(w[1]);
        TRACE(w[2]);
        TRACE(w[3]);
        TRACE("BREAK");
      }
      #endif
      assert(CanLexicalCast<double>(w[2]));
      assert(CanLexicalCast<int>(w[3]));
      const double x = boost::lexical_cast<double>(w[1]);
      const double y = boost::lexical_cast<double>(w[2]);
      const boost::shared_ptr<const ConstCoordinat2D> bottom(
        new ConstCoordinat2D(x,y)
      );

      const boost::shared_ptr<Point> node {
        PointFactory().Create(bottom)
      };
      m_points.push_back(node);
    }
  }

  if (verbose) { TRACE("Load and translate faces"); }
  {
    const std::vector<std::string> v
      = ribi::fileio::FileIo().FileToVector(filename_ele);
    const int sz = v.size();
    const int percent = sz / 100 ? sz / 100: 1;
    for(int n=0; n!=sz; ++n)
    {
      if (verbose)
      {
        if (n % percent == 0)
        {
          std::clog << '%';
        }
      }
      const std::string line = v[n];
      if(n==0) continue;
      const std::vector<std::string> w { CleanAndSplitString(line) };
      if (w.empty() || w[0].empty() ||  w[0] == "#")
      {
        //The final comment line
        continue;
      }
      assert(w.size() == 4);
      assert(CanLexicalCast<int>(w[0]));
      assert(CanLexicalCast<int>(w[1]));
      assert(CanLexicalCast<int>(w[2]));
      assert(CanLexicalCast<int>(w[3]));

      //I hope that I made the Triangle.exe output start at index 0..
      const int point1 = boost::lexical_cast<int>(w[1]);
      const int point2 = boost::lexical_cast<int>(w[2]);
      const int point3 = boost::lexical_cast<int>(w[3]);
      assert(point1 >= 0); //Start at index 0
      assert(point2 >= 0); //Start at index 0
      assert(point3 >= 0); //Start at index 0
      assert(point1 - 0 < static_cast<int>(m_points.size()));
      assert(point2 - 0 < static_cast<int>(m_points.size()));
      assert(point3 - 0 < static_cast<int>(m_points.size()));
      const std::vector<int> face_point_indices {
        point1-0, //Start at index 0
        point2-0, //Start at index 0
        point3-0  //Start at index 0
      };
      m_edges.push_back(std::make_pair(face_point_indices[0],face_point_indices[1]));
      m_edges.push_back(std::make_pair(face_point_indices[0],face_point_indices[2]));
      m_edges.push_back(std::make_pair(face_point_indices[1],face_point_indices[2]));

      std::vector<boost::shared_ptr<Point>> face_points {
        m_points[point1-0], //Start at index 0
        m_points[point2-0], //Start at index 0
        m_points[point3-0]  //Start at index 0
      };
      if (!Helper().IsClockwiseHorizontal(face_points))
      {
        std::reverse(face_points.begin(),face_points.end());
      }
      assert(Helper().IsClockwiseHorizontal(face_points));
      if (!Helper().IsConvex(face_points)) { Helper().MakeConvex(face_points); }
      assert(Helper().IsConvex(face_points) && "FaceFactory only accepts convex ordered points");

      const boost::shared_ptr<Face> face {
        FaceFactory().Create(
          face_points,
          FaceOrientation::horizontal,
          verbose
        )
      };
      m_faces.push_back(face);
      m_face_point_indices.push_back(face_point_indices);

      assert(std::unique(m_face_point_indices.begin(),m_face_point_indices.end())
        == m_face_point_indices.end()
        && "Every face should have unique point indices");
    }
  }

  #ifndef NDEBUG
  if (verbose) { TRACE("Checking the result"); }
  const int n_faces = static_cast<int>(m_faces.size());
  assert(m_faces.size() == m_face_point_indices.size());
  for (int i=0; i!=n_faces; ++i)
  {
    const auto face = m_faces[i];
    const auto indices = m_face_point_indices[i];
    assert(face->GetPoints().size() == indices.size());
  }
  #endif

  for (auto& p: m_edges)
  {
    if (p.first > p.second) std::swap(p.first,p.second);
    assert(p.first < p.second);
  }
  std::sort(m_edges.begin(),m_edges.end());

  auto new_end = std::unique(m_edges.begin(),m_edges.end());
  m_edges.erase(new_end,m_edges.end());

  if (verbose) { TRACE("Done checking the result"); }
}
コード例 #6
0
void ribi::trim::CellsCreator::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  CellFactory();
  FaceFactory();

  const TestTimer test_timer(__func__,__FILE__,1.0);
  const bool verbose{false};

  /*
  if (testing_depth > 1)
  {
    if (verbose) { TRACE("Trying out to build cells from the hardest testing templates"); }
    {
      //This is the longest test by far
      //const TestTimer test_timer(boost::lexical_cast<std::string>(__LINE__),__FILE__,1.0);
      for (CreateVerticalFacesStrategy strategy: CreateVerticalFacesStrategies().GetAll())
      {
        const boost::shared_ptr<Template> my_template {
          Template::CreateTest(3)
        };

        const int n_cell_layers = 2;
        const boost::shared_ptr<CellsCreator> cells_creator {
          CellsCreatorFactory().Create(
            my_template,
            n_cell_layers,
            1.0 * boost::units::si::meter,
            strategy,
            verbose
          )
        };
        const std::vector<boost::shared_ptr<Cell>> cells { cells_creator->GetCells() };
        assert(cells.size() > 0);
      }
    }
  }
  */
  if (verbose) { TRACE("Specific: check if a Face really loses its neighbour: remove a prism from a cube"); }
  {
    //const TestTimer test_timer(boost::lexical_cast<std::string>(__LINE__),__FILE__,1.0);
    for (CreateVerticalFacesStrategy strategy: CreateVerticalFacesStrategies().GetAll())
    {
      //Create a 2x1 cell block
      const boost::shared_ptr<Template> my_template {
        Template::CreateTest(1)
      };
      assert(my_template->CountFaces() == 2);
      const int n_cell_layers = 1;
      const boost::shared_ptr<CellsCreator> cells_creator {
        CellsCreatorFactory().Create(
          my_template,
          n_cell_layers,
          1.0 * boost::units::si::meter,
          strategy,
          verbose
        )
      };
      const std::vector<boost::shared_ptr<Cell>> cells { cells_creator->GetCells() };
      assert(cells.size() == 2);
      const std::vector<boost::shared_ptr<Face>> faces_1 { cells[0]->GetFaces() };
      const std::vector<boost::shared_ptr<Face>> faces_2 { cells[1]->GetFaces() };
      //Find the one/two Faces that have a neighbour
      {
        const int n_faces_with_neighbour {
          static_cast<int>(
            std::count_if(faces_1.begin(),faces_1.end(),
              [](const boost::shared_ptr<Face> face)
              {
                return face->GetNeighbour().get();
              }
            )
          )
        };
        assert(
             (strategy == CreateVerticalFacesStrategy::one_face_per_square
               && n_faces_with_neighbour == 1)
          || (strategy == CreateVerticalFacesStrategy::two_faces_per_square
               && n_faces_with_neighbour == 2)
        );
      }
      {
        const int n_faces_with_neighbour {
          static_cast<int>(
            std::count_if(faces_2.begin(),faces_2.end(),
              [](const boost::shared_ptr<Face> face)
              {
                return face->GetNeighbour().get();
              }
            )
          )
        };
        assert(
             (strategy == CreateVerticalFacesStrategy::one_face_per_square
               && n_faces_with_neighbour == 1)
          || (strategy == CreateVerticalFacesStrategy::two_faces_per_square
               && n_faces_with_neighbour == 2)
        );
      }
      if (verbose) { TRACE("Creating internal faces 1"); }

      Helper::FaceSet internal_faces_1 = Helper().CreateEmptyFaceSet();
      if (verbose) { TRACE("Creating internal faces 1, std::copy_if"); }
      std::copy_if(
        faces_1.begin(),faces_1.end(),
        std::inserter(internal_faces_1,internal_faces_1.begin()),
        [](const boost::shared_ptr<Face> face)
        {
          assert(face);
          const bool do_copy = face->GetNeighbour().get();
          return do_copy;
        }
      );

      if (verbose) { TRACE("Creating internal faces 2"); }
      Helper::FaceSet internal_faces_2 = Helper().CreateEmptyFaceSet();
      std::copy_if(faces_2.begin(),faces_2.end(),std::inserter(internal_faces_2,internal_faces_2.begin()),
        [](const boost::shared_ptr<Face> face)
        {
          return face->GetNeighbour().get();
        }
      );
      if (verbose) { TRACE("Creating internal faces 1"); }
      assert(
        std::equal(
          internal_faces_1.begin(),internal_faces_1.end(),
          internal_faces_2.begin(),
          [](boost::shared_ptr<Face> lhs, boost::shared_ptr<Face> rhs) { return *lhs == *rhs; }
        )
      );
    }
  }
  if (verbose) { TRACE("Create Face, from bug"); }
  {
    //const TestTimer test_timer(boost::lexical_cast<std::string>(__LINE__),__FILE__,1.0);
    /*
    (1.17557,2.35781,5.0)
    (2.35114,3.23607,5.0)
    (1.17557,2.35781,6.0)
    (2.35114,3.23607,6.0)
    */
    //Ordering cannot be known for sure to be convex from these indices
    typedef boost::geometry::model::d2::point_xy<double> Coordinat2D;
    std::vector<boost::shared_ptr<Point>> face_points {
      PointFactory().Create(boost::make_shared<Coordinat2D>(1.17557,2.35781)),
      PointFactory().Create(boost::make_shared<Coordinat2D>(2.35114,3.23607)),
      PointFactory().Create(boost::make_shared<Coordinat2D>(1.17557,2.35781)),
      PointFactory().Create(boost::make_shared<Coordinat2D>(2.35114,3.23607))
    };
    face_points[0]->SetZ(5.0 * boost::units::si::meter);
    face_points[1]->SetZ(5.0 * boost::units::si::meter);
    face_points[2]->SetZ(6.0 * boost::units::si::meter);
    face_points[3]->SetZ(6.0 * boost::units::si::meter);

    //Order face_points
    if (!Helper().IsConvex(face_points)) { Helper().MakeConvex(face_points); }

    #ifndef NDEBUG
    if (!Helper().IsConvex(face_points))
    {
      TRACE("ERROR");
      for (const auto& p: face_points) { TRACE(*p); }
      TRACE("BREAK");
    }
    #endif

    assert(Helper().IsConvex(face_points));

    //Cannot order face winding yet, need Cells for this
    const boost::shared_ptr<Face> face {
      FaceFactory().Create(
        face_points,
        FaceOrientation::vertical,
        verbose
      )
    };
  }

  //From bug
  {
    //const TestTimer test_timer(boost::lexical_cast<std::string>(__LINE__),__FILE__,1.0);
    typedef boost::geometry::model::d2::point_xy<double> Coordinat2D;
    const double x1 = 0.0004035051226622692510832834944523028752882964909076690673828125;
    const double y1 = 0.00023296416881187433805568132161312178141088224947452545166015625;
    const double z1 = 0; //left out the '.0' intentionally

    const double x2 = 0.000403505141811931846741734464245610070065595209598541259765625;
    const double y2 = 0.00023296414405748076185791173298156309101614169776439666748046875;
    const double z2 = 0; //left out the '.0' intentionally

    const double x3 = 0.0004035051226622692510832834944523028752882964909076690673828125;
    const double y3 = 0.00023296416881187433805568132161312178141088224947452545166015625;
    const double z3 = 0.00025000000000000000520417042793042128323577344417572021484375;

    const double x4 = 0.000403505141811931846741734464245610070065595209598541259765625;
    const double y4 = 0.00023296414405748076185791173298156309101614169776439666748046875;
    const double z4 = 0.00025000000000000000520417042793042128323577344417572021484375;
    const auto c1 = boost::make_shared<Coordinat2D>(x1,y1);
    const auto c2 = boost::make_shared<Coordinat2D>(x2,y2);
    const auto c3 = boost::make_shared<Coordinat2D>(x3,y3);
    const auto c4 = boost::make_shared<Coordinat2D>(x4,y4);
    const auto p1 = PointFactory().Create(c1);
    const auto p2 = PointFactory().Create(c2);
    const auto p3 = PointFactory().Create(c3);
    const auto p4 = PointFactory().Create(c4);
    p1->SetZ(z1 * boost::units::si::meter);
    p2->SetZ(z2 * boost::units::si::meter);
    p3->SetZ(z3 * boost::units::si::meter);
    p4->SetZ(z4 * boost::units::si::meter);
    std::vector<boost::shared_ptr<Point>> face_points;
    face_points.push_back(p1);
    face_points.push_back(p2);
    face_points.push_back(p3);
    face_points.push_back(p4);
    assert(IsPlane(face_points));
  }
}
コード例 #7
0
std::vector<boost::shared_ptr<ribi::trim::Face>> ribi::trim::CellsCreator::CreateVerticalFaces(
  const boost::shared_ptr<const Template> t,
  const std::vector<boost::shared_ptr<Point>>& all_points,
  const int n_face_layers,
  const boost::units::quantity<boost::units::si::length> layer_height,
  const CreateVerticalFacesStrategy strategy,
  const bool verbose
) noexcept
{
  assert(t);

  assert(n_face_layers > 0);
  if (n_face_layers < 2)
  {
    if (verbose)
    {
      std::clog << __FILE__ << "(" <<  (__LINE__) <<  ") : "
        << "Too few layers to create vertical faces" << std::endl
      ;
    }
    std::vector<boost::shared_ptr<ribi::trim::Face>> no_faces;
    return no_faces;
  }
  #ifndef NDEBUG
  const FaceFactory face_factory;

  if (verbose)
  {
    std::clog << __FILE__ << "(" <<  (__LINE__) <<  ") : "
      << "Checking points" << std::endl
    ;
  }

  for (const auto& point: all_points) { assert(point); }

  if (verbose)
  {
    std::clog << __FILE__ << "(" <<  (__LINE__) <<  ") : "
      << "Get edges" << std::endl
    ;
  }
  #endif
  const std::vector<std::pair<int,int>> edges = t->GetEdges();


  assert(!edges.empty());
  const int n_edges = static_cast<int>(edges.size());
  const int n_points_per_layer = static_cast<int>(t->GetPoints().size());
  assert(n_points_per_layer > 0);
  const int n_ver_faces
    = strategy == CreateVerticalFacesStrategy::one_face_per_square
    ? 1 * n_edges
    : 2 * n_edges //For every horizontal edge, two triangles are used instead
  ;

  std::vector<boost::shared_ptr<Face>> v;
  #ifndef NDEBUG
  const int n_reserve = n_ver_faces * (n_face_layers - 1);
  #endif
  assert(n_reserve > 0);
  assert(n_reserve < static_cast<int>(v.max_size()));
  v.reserve(n_ver_faces * (n_face_layers - 1));

  assert(n_face_layers > 0);
  if (n_face_layers == 1)
  {
    std::vector<boost::shared_ptr<ribi::trim::Face>> no_faces;
    return no_faces;
  }

  if (verbose)
  {
    std::clog << __FILE__ << "(" <<  (__LINE__) <<  ") : "
      << "Start building " << (n_face_layers-1) //Number of cell layers
      << " layers" << std::endl
    ;
  }

  for (int layer=0; layer!=n_face_layers-1; ++layer) //-1 because there are no points above the top layer
  {
    if (verbose)
    {
      std::clog << __FILE__ << "(" <<  (__LINE__) <<  ") : "
        << (layer+1) //Human-based
        << "/" << (n_face_layers-1) //Number of cell layers
        << std::endl
      ;
    }

    const int points_offset = n_points_per_layer * layer;
    assert(points_offset >= 0);
    const auto z_here  = static_cast<double>(layer + 0) * layer_height;
    const auto z_above = static_cast<double>(layer + 1) * layer_height;
    for (const std::pair<int,int>& edge: edges)
    {
      assert(edge.first < edge.second);

      assert(points_offset + edge.first  < static_cast<int>(all_points.size()));
      assert(points_offset + edge.second < static_cast<int>(all_points.size()));
      assert(points_offset + edge.first  + n_points_per_layer < static_cast<int>(all_points.size()));
      assert(points_offset + edge.second + n_points_per_layer < static_cast<int>(all_points.size()));
      if (strategy == CreateVerticalFacesStrategy::one_face_per_square)
      {
        //Ordering cannot be known for sure to be convex from these indices
        assert(all_points[points_offset + edge.first]);
        assert(all_points[points_offset + edge.second]);
        assert(all_points[points_offset + edge.first  + n_points_per_layer]);
        assert(all_points[points_offset + edge.second + n_points_per_layer]);
        std::vector<boost::shared_ptr<Point>> face_points;
        face_points.push_back(all_points[points_offset + edge.first]);
        face_points.push_back(all_points[points_offset + edge.second]);
        face_points.push_back(all_points[points_offset + edge.first  + n_points_per_layer]);
        face_points.push_back(all_points[points_offset + edge.second + n_points_per_layer]);
        assert(face_points.size() == 4);
        assert(face_points[0]);
        assert(face_points[1]);
        assert(face_points[2]);
        assert(face_points[3]);
        assert(face_points[0] != face_points[1]);
        assert(face_points[0] != face_points[2]);
        assert(face_points[0] != face_points[3]);
        assert(face_points[1] != face_points[2]);
        assert(face_points[1] != face_points[3]);
        assert(face_points[2] != face_points[3]);
        face_points[0]->SetZ(z_here);
        face_points[1]->SetZ(z_here);
        face_points[2]->SetZ(z_above);
        face_points[3]->SetZ(z_above);
        #ifndef NDEBUG
        if(!IsPlane(face_points))
        {
          TRACE("ERROR");
          std::stringstream s;
          s
            << face_points.size() << '\n'
            << std::setprecision(99)
          ;
          for (const auto& point: face_points) { s << (*point) << " "; }
          TRACE(s.str());
          TRACE("BREAK");
        }
        #endif
        assert(IsPlane(face_points));

        //Order face_points
        if (!Helper().IsConvex(face_points))
        {
          Helper().MakeConvex(face_points);
        }

        assert(Helper().IsConvex(face_points));

        //Cannot order face winding yet, need Cells for this
        const boost::shared_ptr<Face> face {
          FaceFactory().Create(
            face_points,
            FaceOrientation::vertical,
            verbose
          )
        };
        assert(face);
        v.push_back(face);
      }
      else
      {
        assert(all_points[points_offset + edge.first]);
        assert(all_points[points_offset + edge.second]);
        assert(all_points[points_offset + edge.first + n_points_per_layer]);
        const std::vector<boost::shared_ptr<Point>> face_points_1 {
          all_points[points_offset + edge.first],
          all_points[points_offset + edge.second],
          all_points[points_offset + edge.first + n_points_per_layer]
        };
        assert(face_points_1[0] != face_points_1[1]);
        assert(face_points_1[0] != face_points_1[2]);
        assert(face_points_1[1] != face_points_1[2]);

        face_points_1[0]->SetZ(z_here);
        face_points_1[1]->SetZ(z_here);
        face_points_1[2]->SetZ(z_above);

        assert(Helper().IsConvex(face_points_1)
          && "FaceFactory expects convex ordered points");

        //Cannot order face winding yet, need Cells for this
        const boost::shared_ptr<Face> face_1 {
          FaceFactory().Create(
            face_points_1,
            FaceOrientation::vertical,
            verbose
          )
        };
        assert(face_1);
        v.push_back(face_1);


        assert(all_points[points_offset + edge.second]);
        assert(all_points[points_offset + edge.second + n_points_per_layer]);
        assert(all_points[points_offset + edge.first  + n_points_per_layer]);
        std::vector<boost::shared_ptr<Point>> face_points_2 {
          all_points[points_offset + edge.second],
          all_points[points_offset + edge.second + n_points_per_layer],
          all_points[points_offset + edge.first  + n_points_per_layer]
        };
        assert(face_points_2[0] != face_points_2[1]);
        assert(face_points_2[0] != face_points_2[2]);
        assert(face_points_2[1] != face_points_2[2]);

        face_points_2[0]->SetZ(z_here );
        face_points_2[1]->SetZ(z_above);
        face_points_2[2]->SetZ(z_above);

        #ifndef NDEBUG
        if (!Helper().IsConvex(face_points_2))
        {
          TRACE("ERROR");

          for (const auto& point:face_points_2) { TRACE(Geometry().ToStr(point->GetCoordinat3D())); }
        }
        #endif

        assert(Helper().IsConvex(face_points_2)
          && "FaceFactory expects convex ordered points");

        const boost::shared_ptr<Face> face_2 {
          FaceFactory().Create(
            face_points_2,
            FaceOrientation::vertical,
            verbose
          )
        };
        assert(face_2);
        v.push_back(face_2);
      }
    }
  }

  assert(n_ver_faces * (n_face_layers - 1) == static_cast<int>(v.size()));

  if (verbose)
  {
    std::clog << __FILE__ << "(" <<  (__LINE__) <<  ") : "
      << "Done building " << (n_face_layers-1) //Number of cell layers
      << " layers" << std::endl
    ;
  }

  return v;
}
コード例 #8
0
std::vector<boost::shared_ptr<ribi::trim::Face>> ribi::trim::CellsCreator::CreateHorizontalFaces(
  const boost::shared_ptr<const Template> t,
  const std::vector<boost::shared_ptr<Point>>& all_points,
  const int n_face_layers
)
{
  const bool verbose{false};
  std::vector<boost::shared_ptr<Face>> v;
  assert(t);
  #ifndef NDEBUG
  if (all_points.empty())
  {
    TRACE("ERROR");
    TRACE("BREAK");
  }
  #endif
  assert(!all_points.empty());

  const int n_points_per_layer{static_cast<int>(t->GetPoints().size())};
  #ifndef NDEBUG
  const int n_faces_per_layer{static_cast<int>(t->GetFaces().size())};
  assert(n_face_layers > 0);
  #endif
  v.reserve(n_face_layers * n_points_per_layer);

  for (int layer=0; layer!=n_face_layers; ++layer)
  {
    const int point_offset{n_points_per_layer * layer};
    for (const std::vector<int>& face_point_indices: t->GetFacePointIndices())
    {
      #ifndef NDEBUG
      const int face_index{static_cast<int>(v.size())};
      assert(face_point_indices.size() == 3); //Triangulation
      #endif
      std::vector<boost::shared_ptr<Point>> face_points;
      for (int point_index: face_point_indices)
      {
        assert(point_index + point_offset < static_cast<int>(all_points.size()));
        face_points.push_back(all_points[point_index + point_offset]);
        #ifndef NDEBUG
        if (face_points.size() >= 2 && face_points[0]->CanGetZ())
        {
          assert(face_points.front()->GetZ() == face_points.back()->GetZ());
        }
        #endif
      }

      assert(layer == 0 || face_index - n_faces_per_layer >= 0);
      assert(layer == 0 || face_index - n_faces_per_layer < static_cast<int>(v.size()));
      if ( (layer % 2 == 0 && !Helper().IsClockwiseHorizontal(face_points))
        || (layer % 2 == 1 &&  Helper().IsClockwiseHorizontal(face_points))
      )
      {
        std::reverse(face_points.begin(),face_points.end());
      }

      if(!Helper().IsConvex(face_points)) { Helper().MakeConvex(face_points); }
      assert(Helper().IsConvex(face_points));
      //const FaceFactory face_factory;
      const boost::shared_ptr<Face> face {
        FaceFactory().Create(
          face_points,
          FaceOrientation::horizontal,
          verbose
        )
      };
      v.push_back(face);
    }
  }
  return v;
}