diff --git a/GeoLib/Surface.cpp b/GeoLib/Surface.cpp index 3b8b55fad2946baf4e0e27a80d20ebe157245ffb..2f2be4148d08df5efcec3dce6b5a0165f74eb72b 100644 --- a/GeoLib/Surface.cpp +++ b/GeoLib/Surface.cpp @@ -1,8 +1,4 @@ /** - * \file - * \author Thomas Fischer - * \date 2010-04-22 - * \brief Implementation of the Surface class. * * \copyright * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org) @@ -15,7 +11,7 @@ #include <list> // ThirdParty/logog -#include "logog/include/logog.hpp" +#include <logog/include/logog.hpp> #include "Surface.h" @@ -31,20 +27,38 @@ namespace GeoLib { -Surface::Surface (const std::vector<Point*> &pnt_vec) : - GeoObject(), _sfc_pnts(pnt_vec), _bounding_volume(nullptr), - _surface_grid(nullptr) -{} +Surface::Surface(const std::vector<Point*>& pnt_vec) + : GeoObject(), + _sfc_pnts(pnt_vec), + _bounding_volume(nullptr), + _surface_grid(nullptr) +{ +} + +Surface::Surface(Surface const& src) + : _sfc_pnts(src._sfc_pnts), + _bounding_volume(new AABB(*(src._bounding_volume))), + _surface_grid(nullptr) +{ + _sfc_triangles.reserve(src._sfc_triangles.size()); + std::transform(src._sfc_triangles.cbegin(), + src._sfc_triangles.cend(), + std::back_inserter(_sfc_triangles), + [](Triangle* t) { return new Triangle(*t); }); +} -Surface::~Surface () +Surface::~Surface() { for (std::size_t k(0); k < _sfc_triangles.size(); k++) delete _sfc_triangles[k]; } -void Surface::addTriangle(std::size_t pnt_a, std::size_t pnt_b, std::size_t pnt_c) +void Surface::addTriangle(std::size_t pnt_a, + std::size_t pnt_b, + std::size_t pnt_c) { - assert (pnt_a < _sfc_pnts.size() && pnt_b < _sfc_pnts.size() && pnt_c < _sfc_pnts.size()); + assert(pnt_a < _sfc_pnts.size() && pnt_b < _sfc_pnts.size() && + pnt_c < _sfc_pnts.size()); // Check if two points of the triangle have identical IDs if (pnt_a == pnt_b || pnt_a == pnt_c || pnt_b == pnt_c) @@ -54,92 +68,108 @@ void Surface::addTriangle(std::size_t pnt_a, std::size_t pnt_b, std::size_t pnt_ _surface_grid.reset(); _sfc_triangles.push_back(new Triangle(_sfc_pnts, pnt_a, pnt_b, pnt_c)); - if (!_bounding_volume) { + if (!_bounding_volume) + { std::vector<std::size_t> ids(3); ids[0] = pnt_a; ids[1] = pnt_b; ids[2] = pnt_c; _bounding_volume.reset(new AABB(_sfc_pnts, ids)); - } else { + } + else + { _bounding_volume->update(*_sfc_pnts[pnt_a]); _bounding_volume->update(*_sfc_pnts[pnt_b]); _bounding_volume->update(*_sfc_pnts[pnt_c]); } } -Surface* Surface::createSurface(const Polyline &ply) +Surface* Surface::createSurface(const Polyline& ply) { - if (!ply.isClosed()) { + if (!ply.isClosed()) + { WARN("Error in Surface::createSurface() - Polyline is not closed."); return nullptr; } - if (ply.getNumberOfPoints() > 2) { - // create empty surface - Surface *sfc(new Surface(ply.getPointsVec())); - - Polygon* polygon (new Polygon (ply)); - polygon->computeListOfSimplePolygons (); - - // create surfaces from simple polygons - const std::list<GeoLib::Polygon*>& list_of_simple_polygons (polygon->getListOfSimplePolygons()); - for (std::list<GeoLib::Polygon*>::const_iterator simple_polygon_it (list_of_simple_polygons.begin()); - simple_polygon_it != list_of_simple_polygons.end(); ++simple_polygon_it) { - - std::list<GeoLib::Triangle> triangles; - GeoLib::EarClippingTriangulation(*simple_polygon_it, triangles); + if (ply.getNumberOfPoints() <= 2) + { + WARN( + "Error in Surface::createSurface() - Polyline consists of less " + "than three points and therefore cannot be triangulated."); + return nullptr; + } - // add Triangles to Surface - std::list<GeoLib::Triangle>::const_iterator it (triangles.begin()); - while (it != triangles.end()) { - sfc->addTriangle ((*it)[0], (*it)[1], (*it)[2]); - ++it; - } - } - delete polygon; - if (sfc->getNTriangles() == 0) { - WARN("Surface::createSurface(): Triangulation does not contain any triangle."); - delete sfc; - return nullptr; + // create empty surface + Surface* sfc(new Surface(ply.getPointsVec())); + + Polygon* polygon(new Polygon(ply)); + polygon->computeListOfSimplePolygons(); + + // create surfaces from simple polygons + const std::list<GeoLib::Polygon*>& list_of_simple_polygons( + polygon->getListOfSimplePolygons()); + for (std::list<GeoLib::Polygon*>::const_iterator simple_polygon_it( + list_of_simple_polygons.begin()); + simple_polygon_it != list_of_simple_polygons.end(); + ++simple_polygon_it) + { + std::list<GeoLib::Triangle> triangles; + GeoLib::EarClippingTriangulation(*simple_polygon_it, triangles); + + // add Triangles to Surface + std::list<GeoLib::Triangle>::const_iterator it(triangles.begin()); + while (it != triangles.end()) + { + sfc->addTriangle((*it)[0], (*it)[1], (*it)[2]); + ++it; } - return sfc; - } else { - WARN("Error in Surface::createSurface() - Polyline consists of less than three points and therefore cannot be triangulated."); + } + delete polygon; + if (sfc->getNTriangles() == 0) + { + WARN( + "Surface::createSurface(): Triangulation does not contain any " + "triangle."); + delete sfc; return nullptr; } - + return sfc; } -std::size_t Surface::getNTriangles () const +std::size_t Surface::getNTriangles() const { return _sfc_triangles.size(); } -const Triangle* Surface::operator[] (std::size_t i) const +const Triangle* Surface::operator[](std::size_t i) const { - assert (i < _sfc_triangles.size()); + assert(i < _sfc_triangles.size()); return _sfc_triangles[i]; } bool Surface::isPntInBoundingVolume(MathLib::Point3d const& pnt) const { - return _bounding_volume->containsPoint (pnt); + return _bounding_volume->containsPoint(pnt); } bool Surface::isPntInSfc(MathLib::Point3d const& pnt) const { // Mutable _surface_grid is constructed if method is called the first time. - if (_surface_grid == nullptr) { + if (_surface_grid == nullptr) + { _surface_grid.reset(new SurfaceGrid(this)); } return _surface_grid->isPointInSurface( pnt, std::numeric_limits<double>::epsilon()); } -const Triangle* Surface::findTriangle (MathLib::Point3d const& pnt) const +const Triangle* Surface::findTriangle(MathLib::Point3d const& pnt) const { - for (std::size_t k(0); k<_sfc_triangles.size(); k++) { - if (_sfc_triangles[k]->containsPoint (pnt)) { + for (std::size_t k(0); k < _sfc_triangles.size(); k++) + { + if (_sfc_triangles[k]->containsPoint(pnt)) + { return _sfc_triangles[k]; } } diff --git a/GeoLib/Surface.h b/GeoLib/Surface.h index 28c96d077caa394e02e58e4bce333a325206ed6d..e94fe2eca155c5c026002f9b9d35ecad4b140296 100644 --- a/GeoLib/Surface.h +++ b/GeoLib/Surface.h @@ -1,8 +1,4 @@ /** - * \file - * \author Thomas Fischer - * \date 2010-01-22 - * \brief Definition of the Surface class. * * \copyright * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org) @@ -36,31 +32,36 @@ class SurfaceGrid; * to a vector of (pointers to) points (_sfc_pnts) and a vector that stores * the Triangles consisting of points from _sfc_pnts. * */ -class Surface : public GeoObject +class Surface final : public GeoObject { public: - Surface(const std::vector<Point*> &pnt_vec); - virtual ~Surface (); + explicit Surface(const std::vector<Point*>& pnt_vec); + Surface(Surface const& src); + ~Surface(); - /// return a geometry type - virtual GEOTYPE getGeoType() const {return GEOTYPE::SURFACE;} + Surface(Surface && src) = delete; + Surface& operator=(Surface const& src) = delete; + Surface& operator=(Surface && src) = delete; + /// return a geometry type + GEOTYPE getGeoType() const override { return GEOTYPE::SURFACE; } /** * adds three indices describing a triangle and updates the bounding box * */ - void addTriangle (std::size_t pnt_a, std::size_t pnt_b, std::size_t pnt_c); + void addTriangle(std::size_t pnt_a, std::size_t pnt_b, std::size_t pnt_c); /// Triangulates a new surface based on closed polyline. - static Surface* createSurface(const Polyline &ply); + static Surface* createSurface(const Polyline& ply); /** * returns the number of triangles describing the Surface * */ - std::size_t getNTriangles () const; + std::size_t getNTriangles() const; - /** \brief const access operator for the access to the i-th Triangle of the surface. + /** \brief const access operator for the access to the i-th Triangle of the + * surface. */ - const Triangle* operator[] (std::size_t i) const; + const Triangle* operator[](std::size_t i) const; /** * is the given point in the bounding volume of the surface @@ -82,17 +83,15 @@ public: */ const Triangle* findTriangle(MathLib::Point3d const& pnt) const; - const std::vector<Point*> *getPointVec() const { return &_sfc_pnts; } - + const std::vector<Point*>* getPointVec() const { return &_sfc_pnts; } /** * method allows access to the internal axis aligned bounding box * @return axis aligned bounding box */ - AABB const& getAABB () const { return *_bounding_volume; } - + AABB const& getAABB() const { return *_bounding_volume; } protected: /** a vector of pointers to Points */ - const std::vector<Point*> &_sfc_pnts; + const std::vector<Point*>& _sfc_pnts; /** position of pointers to the geometric points */ std::vector<Triangle*> _sfc_triangles; /** bounding volume is an axis aligned bounding box */ @@ -103,7 +102,6 @@ protected: /// called and a valid surface grid is not existing. mutable std::unique_ptr<SurfaceGrid> _surface_grid; }; - } #endif /* SURFACE_H_ */ diff --git a/GeoLib/Triangle.cpp b/GeoLib/Triangle.cpp index 02d4be34bd6fa6fa651f17bc0b0344e58f668579..5480a9c28499593c3bfcf3ebc23b75826d885c3f 100644 --- a/GeoLib/Triangle.cpp +++ b/GeoLib/Triangle.cpp @@ -1,8 +1,4 @@ /** - * \file - * \author Thomas Fischer - * \date 2010-06-06 - * \brief Implementation of the Triangle class. * * \copyright * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org) @@ -21,29 +17,12 @@ namespace GeoLib { -Triangle::Triangle (std::vector<Point *> const &pnt_vec) : - _pnts(pnt_vec), _initialized (false), _longest_edge (0.0) -{ - assert(!_pnts.empty()); - _pnt_ids[0] = std::numeric_limits<std::size_t>::max(); - _pnt_ids[1] = std::numeric_limits<std::size_t>::max(); - _pnt_ids[2] = std::numeric_limits<std::size_t>::max(); -} - Triangle::Triangle (std::vector<Point *> const &pnt_vec, std::size_t pnt_a, std::size_t pnt_b, std::size_t pnt_c) : - _pnts(pnt_vec), _initialized (true), _longest_edge (0.0) + _pnts(pnt_vec), _pnt_ids( {{pnt_a, pnt_b, pnt_c}} ) { assert(!_pnts.empty()); - _pnt_ids[0] = pnt_a; - _pnt_ids[1] = pnt_b; - _pnt_ids[2] = pnt_c; - _longest_edge = MathLib::sqrDist (*_pnts[_pnt_ids[0]], *_pnts[_pnt_ids[1]]); - double tmp (MathLib::sqrDist (*_pnts[_pnt_ids[1]], *_pnts[_pnt_ids[2]])); - if (tmp > _longest_edge) _longest_edge = tmp; - tmp = MathLib::sqrDist (*_pnts[_pnt_ids[0]], *_pnts[_pnt_ids[2]]); - if (tmp > _longest_edge) _longest_edge = tmp; - _longest_edge = sqrt (_longest_edge); + assert (pnt_a < _pnts.size() && pnt_b < _pnts.size() && pnt_c < _pnts.size()); } void Triangle::setTriangle (std::size_t pnt_a, std::size_t pnt_b, std::size_t pnt_c) @@ -52,13 +31,6 @@ void Triangle::setTriangle (std::size_t pnt_a, std::size_t pnt_b, std::size_t pn _pnt_ids[0] = pnt_a; _pnt_ids[1] = pnt_b; _pnt_ids[2] = pnt_c; - - _longest_edge = MathLib::sqrDist (*_pnts[_pnt_ids[0]], *_pnts[_pnt_ids[1]]); - double tmp (MathLib::sqrDist (*_pnts[_pnt_ids[1]], *_pnts[_pnt_ids[2]])); - if (tmp > _longest_edge) _longest_edge = tmp; - tmp = MathLib::sqrDist (*_pnts[_pnt_ids[0]], *_pnts[_pnt_ids[2]]); - if (tmp > _longest_edge) _longest_edge = tmp; - _longest_edge = sqrt (_longest_edge); } bool Triangle::containsPoint(MathLib::Point3d const& q, double eps) const @@ -90,7 +62,9 @@ bool Triangle::containsPoint2D (Point const& pnt) const const double upper (1+delta); // check if u0 and u1 fulfills the condition (with some delta) - if (-delta <= y[0] && y[0] <= upper && -delta <= y[1] && y[1] <= upper && y[0] + y[1] <= upper) { + if (-delta <= y[0] && y[0] <= upper && -delta <= y[1] && y[1] <= upper && + y[0] + y[1] <= upper) + { return true; } return false; diff --git a/GeoLib/Triangle.h b/GeoLib/Triangle.h index 0f88e4515a00a70fa1acbe92618cd965c58e47b6..75f82cb3fdd89d75c6dc36a6d6fe5eac4d219d9d 100644 --- a/GeoLib/Triangle.h +++ b/GeoLib/Triangle.h @@ -1,8 +1,4 @@ /** - * \file - * \author Thomas Fischer - * \date 2010-03-23 - * \brief Definition of the Triangle class. * * \copyright * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org) @@ -26,21 +22,19 @@ class Point; /** \brief Class Triangle consists of a reference to a point vector and * a vector that stores the indices in the point vector. * A surface is composed by triangles. The class Surface stores the position - * of pointers to the points of triangles in the m_sfc_pnt_ids vector. + * of pointers to the points of triangles in the _pnt_ids vector. * */ -class Triangle +class Triangle final { public: - /** - * construction of object, initialization of reference to point vector - */ - Triangle (std::vector<Point *> const &pnt_vec); - /** * construction of object, initialization of reference to point vector, * saves the three indices describing a triangle */ - Triangle (std::vector<Point *> const &pnt_vec, std::size_t pnt_a, std::size_t pnt_b, std::size_t pnt_c); + Triangle(std::vector<Point*> const& pnt_vec, + std::size_t pnt_a, + std::size_t pnt_b, + std::size_t pnt_c); /** * saves three indices describing a triangle @@ -50,7 +44,8 @@ public: /** \brief const access operator to access the index * of the i-th triangle point */ - const std::size_t& operator[] (std::size_t i) const { + const std::size_t& operator[](std::size_t i) const + { assert (i < 3); return _pnt_ids[i]; } @@ -58,7 +53,8 @@ public: /** * \brief const access operator to access the i-th triangle Point */ - const Point* getPoint (std::size_t i) const { + const Point* getPoint(std::size_t i) const + { assert (i < 3); return _pnts[_pnt_ids[i]]; } @@ -69,7 +65,9 @@ public: * @param eps Checks the 'epsilon'-neighbourhood * @return true, if point is in triangle, else false */ - bool containsPoint(MathLib::Point3d const& q, double eps = std::numeric_limits<float>::epsilon()) const; + bool containsPoint( + MathLib::Point3d const& q, + double eps = std::numeric_limits<float>::epsilon()) const; /** * projects the triangle points to the x-y-plane and @@ -77,15 +75,13 @@ public: * @param pnt the point to test for * @return true, if the point is into the projected triangle */ - bool containsPoint2D (Point const& pnt) const; + bool containsPoint2D(Point const& pnt) const; -protected: - /** a vector of pointers to points */ - const std::vector<Point*> &_pnts; - /** position of pointers to the geometric points */ - std::size_t _pnt_ids[3]; - bool _initialized; - double _longest_edge; +private: + /// a vector of pointers to points the triangle is based on + std::vector<Point*> const& _pnts; + /// position of pointers to the geometric points + std::array<std::size_t, 3> _pnt_ids; }; void getPlaneCoefficients(Triangle const& tri, double c[3]);