Mosfet80 updatedpoli2tri (#5682)

* updated poli2tri library to last version
pull/5432/head^2
Kim Kulling 2024-07-23 10:41:43 +02:00 committed by GitHub
parent db19f62a0c
commit 571ba09dc7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 456 additions and 257 deletions

View File

@ -1,7 +1,6 @@
Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors Copyright (c) 2009-2018, Poly2Tri Contributors
http://code.google.com/p/poly2tri/
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met: are permitted provided that the following conditions are met:

View File

@ -1,51 +0,0 @@
==================
INSTALLATION GUIDE
==================
------------
Dependencies
------------
Core poly2tri lib:
- Standard Template Library (STL)
Testbed:
- gcc
- OpenGL
- GLFW (http://glfw.sf.net)
- Python
Waf (http://code.google.com/p/waf/) is used to compile the testbed.
A waf script (86kb) is included in the repositoty.
----------------------------------------------
Building the Testbed
----------------------------------------------
Posix/MSYS environment:
./waf configure
./waf build
Windows command line:
python waf configure
python waf build
----------------------------------------------
Running the Examples
----------------------------------------------
Load data points from a file:
p2t <filename> <center_x> <center_y> <zoom>
Random distribution of points inside a consrained box:
p2t random <num_points> <box_radius> <zoom>
Examples:
./p2t dude.dat 300 500 2
./p2t nazca_monkey.dat 0 0 9
./p2t random 10 100 5.0
./p2t random 1000 20000 0.025

View File

@ -0,0 +1,101 @@
Since there are no Input validation of the data given for triangulation you need
to think about this. Poly2Tri does not support repeat points within epsilon.
* If you have a cyclic function that generates random points make sure you don't
add the same coordinate twice.
* If you are given input and aren't sure same point exist twice you need to
check for this yourself.
* Only simple polygons are supported. You may add holes or interior Steiner points
* Interior holes must not touch other holes, nor touch the polyline boundary
* Use the library in this order:
1. Initialize CDT with a simple polyline (this defines the constrained edges)
2. Add holes if necessary (also simple polylines)
3. Add Steiner points
4. Triangulate
Make sure you understand the preceding notice before posting an issue. If you have
an issue not covered by the above, include your data-set with the problem.
The only easy day was yesterday; have a nice day. <Mason Green>
TESTBED INSTALLATION GUIDE
==========================
Dependencies
------------
Core poly2tri lib:
* Standard Template Library (STL)
Unit tests:
* Boost (filesystem, test framework)
Testbed:
* OpenGL
* [GLFW](http://glfw.sf.net)
Build the library
-----------------
With the ninja build system installed:
```
mkdir build && cd build
cmake -GNinja ..
cmake --build .
```
Build and run with unit tests
----------------------------
With the ninja build system:
```
mkdir build && cd build
cmake -GNinja -DP2T_BUILD_TESTS=ON ..
cmake --build .
ctest --output-on-failure
```
Build with the testbed
-----------------
```
mkdir build && cd build
cmake -GNinja -DP2T_BUILD_TESTBED=ON ..
cmake --build .
```
Running the Examples
--------------------
Load data points from a file:
```
build/testbed/p2t <filename> <center_x> <center_y> <zoom>
```
Load data points from a file and automatically fit the geometry to the window:
```
build/testbed/p2t <filename>
```
Random distribution of points inside a constrained box:
```
build/testbed/p2t random <num_points> <box_radius> <zoom>
```
Examples:
```
build/testbed/p2t testbed/data/dude.dat 350 500 3
build/testbed/p2t testbed/data/nazca_monkey.dat
build/testbed/p2t random 10 100 5.0
build/testbed/p2t random 1000 20000 0.025
```
References
==========
- Domiter V. and Zalik B. (2008) Sweepline algorithm for constrained Delaunay triangulation
- FlipScan by library author Thomas Åhlén
![FlipScan](doc/FlipScan.png)

View File

@ -0,0 +1,59 @@
/*
* Poly2Tri Copyright (c) 2009-2022, Poly2Tri Contributors
* https://github.com/jhasse/poly2tri
*
* 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 Poly2Tri 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.
*/
#pragma once
#if defined(_WIN32)
# pragma warning( disable: 4273)
# define P2T_COMPILER_DLLEXPORT __declspec(dllexport)
# define P2T_COMPILER_DLLIMPORT __declspec(dllimport)
#elif defined(__GNUC__)
# define P2T_COMPILER_DLLEXPORT __attribute__ ((visibility ("default")))
# define P2T_COMPILER_DLLIMPORT __attribute__ ((visibility ("default")))
#else
# define P2T_COMPILER_DLLEXPORT
# define P2T_COMPILER_DLLIMPORT
#endif
// We need to enable shard linkage explicitely
#ifdef ASSIMP_BUILD_DLL_EXPORT
# define P2T_SHARED_EXPORTS 1
#endif
#ifndef P2T_DLL_SYMBOL
# if defined(P2T_STATIC_EXPORTS)
# define P2T_DLL_SYMBOL
# elif defined(P2T_SHARED_EXPORTS)
# define P2T_DLL_SYMBOL P2T_COMPILER_DLLEXPORT
# else
# define P2T_DLL_SYMBOL P2T_COMPILER_DLLIMPORT
# endif
#endif

View File

@ -1,6 +1,6 @@
/* /*
* Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/ * https://github.com/jhasse/poly2tri
* *
* All rights reserved. * All rights reserved.
* *
@ -29,14 +29,24 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "shapes.h" #include "shapes.h"
#include <cassert>
#include <iostream> #include <iostream>
namespace p2t { namespace p2t {
Point::Point(double x, double y) : x(x), y(y)
{
}
std::ostream& operator<<(std::ostream& out, const Point& point) {
return out << point.x << "," << point.y;
}
Triangle::Triangle(Point& a, Point& b, Point& c) Triangle::Triangle(Point& a, Point& b, Point& c)
{ {
points_[0] = &a; points_[1] = &b; points_[2] = &c; points_[0] = &a; points_[1] = &b; points_[2] = &c;
neighbors_[0] = NULL; neighbors_[1] = NULL; neighbors_[2] = NULL; neighbors_[0] = nullptr; neighbors_[1] = nullptr; neighbors_[2] = nullptr;
constrained_edge[0] = constrained_edge[1] = constrained_edge[2] = false; constrained_edge[0] = constrained_edge[1] = constrained_edge[2] = false;
delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false; delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false;
interior_ = false; interior_ = false;
@ -76,39 +86,37 @@ void Triangle::MarkNeighbor(Triangle& t)
void Triangle::Clear() void Triangle::Clear()
{ {
Triangle *t; Triangle *t;
for( int i=0; i<3; i++ ) for (auto& neighbor : neighbors_) {
{ t = neighbor;
t = neighbors_[i]; if (t != nullptr) {
if( t != NULL ) t->ClearNeighbor(this);
{
t->ClearNeighbor( this );
} }
} }
ClearNeighbors(); ClearNeighbors();
points_[0]=points_[1]=points_[2] = NULL; points_[0]=points_[1]=points_[2] = nullptr;
} }
void Triangle::ClearNeighbor(const Triangle *triangle ) void Triangle::ClearNeighbor(const Triangle *triangle )
{ {
if( neighbors_[0] == triangle ) if( neighbors_[0] == triangle )
{ {
neighbors_[0] = NULL; neighbors_[0] = nullptr;
} }
else if( neighbors_[1] == triangle ) else if( neighbors_[1] == triangle )
{ {
neighbors_[1] = NULL; neighbors_[1] = nullptr;
} }
else else
{ {
neighbors_[2] = NULL; neighbors_[2] = nullptr;
} }
} }
void Triangle::ClearNeighbors() void Triangle::ClearNeighbors()
{ {
neighbors_[0] = NULL; neighbors_[0] = nullptr;
neighbors_[1] = NULL; neighbors_[1] = nullptr;
neighbors_[2] = NULL; neighbors_[2] = nullptr;
} }
void Triangle::ClearDelunayEdges() void Triangle::ClearDelunayEdges()
@ -220,7 +228,7 @@ Point* Triangle::PointCW(const Point& point)
return points_[1]; return points_[1];
} }
assert(0); assert(0);
return NULL; return nullptr;
} }
// The point counter-clockwise to given point // The point counter-clockwise to given point
@ -234,7 +242,18 @@ Point* Triangle::PointCCW(const Point& point)
return points_[0]; return points_[0];
} }
assert(0); assert(0);
return NULL; return nullptr;
}
// The neighbor across to given point
Triangle* Triangle::NeighborAcross(const Point& point)
{
if (&point == points_[0]) {
return neighbors_[0];
} else if (&point == points_[1]) {
return neighbors_[1];
}
return neighbors_[2];
} }
// The neighbor clockwise to given point // The neighbor clockwise to given point
@ -343,23 +362,50 @@ void Triangle::SetDelunayEdgeCW(const Point& p, bool e)
} }
} }
// The neighbor across to given point
Triangle& Triangle::NeighborAcross(const Point& opoint)
{
if (&opoint == points_[0]) {
return *neighbors_[0];
} else if (&opoint == points_[1]) {
return *neighbors_[1];
}
return *neighbors_[2];
}
void Triangle::DebugPrint() void Triangle::DebugPrint()
{ {
using namespace std; std::cout << *points_[0] << " " << *points_[1] << " " << *points_[2] << std::endl;
cout << points_[0]->x << "," << points_[0]->y << " ";
cout << points_[1]->x << "," << points_[1]->y << " ";
cout << points_[2]->x << "," << points_[2]->y << endl;
} }
bool Triangle::CircumcicleContains(const Point& point) const
{
assert(IsCounterClockwise());
const double dx = points_[0]->x - point.x;
const double dy = points_[0]->y - point.y;
const double ex = points_[1]->x - point.x;
const double ey = points_[1]->y - point.y;
const double fx = points_[2]->x - point.x;
const double fy = points_[2]->y - point.y;
const double ap = dx * dx + dy * dy;
const double bp = ex * ex + ey * ey;
const double cp = fx * fx + fy * fy;
return (dx * (fy * bp - cp * ey) - dy * (fx * bp - cp * ex) + ap * (fx * ey - fy * ex)) < 0;
} }
bool Triangle::IsCounterClockwise() const
{
return (points_[1]->x - points_[0]->x) * (points_[2]->y - points_[0]->y) -
(points_[2]->x - points_[0]->x) * (points_[1]->y - points_[0]->y) >
0;
}
bool IsDelaunay(const std::vector<p2t::Triangle*>& triangles)
{
for (const auto triangle : triangles) {
for (const auto other : triangles) {
if (triangle == other) {
continue;
}
for (int i = 0; i < 3; ++i) {
if (triangle->CircumcicleContains(*other->GetPoint(i))) {
return false;
}
}
}
}
return true;
}
} // namespace p2t

View File

@ -1,6 +1,6 @@
/* /*
* Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/ * https://github.com/jhasse/poly2tri
* *
* All rights reserved. * All rights reserved.
* *
@ -29,22 +29,24 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
// Include guard #pragma once
#ifndef SHAPES_H
#define SHAPES_H
#include <vector> #include "dll_symbol.h"
#include <cmath>
#include <cstddef> #include <cstddef>
#include <stdexcept> #include <stdexcept>
#include <assert.h> #include <vector>
#include <cmath>
#include <string>
#if defined(_WIN32)
# pragma warning( disable: 4251)
#endif
namespace p2t { namespace p2t {
struct Edge; struct Edge;
struct Point { struct P2T_DLL_SYMBOL Point {
double x, y; double x, y;
@ -59,7 +61,7 @@ struct Point {
std::vector<Edge*> edge_list; std::vector<Edge*> edge_list;
/// Construct using coordinates. /// Construct using coordinates.
Point(double x, double y) : x(x), y(y) {} Point(double x, double y);
/// Set this point to all zeros. /// Set this point to all zeros.
void set_zero() void set_zero()
@ -121,8 +123,10 @@ struct Point {
}; };
P2T_DLL_SYMBOL std::ostream& operator<<(std::ostream&, const Point&);
// Represents a simple polygon's edge // Represents a simple polygon's edge
struct Edge { struct P2T_DLL_SYMBOL Edge {
Point* p, *q; Point* p, *q;
@ -138,9 +142,7 @@ struct Edge {
p = &p2; p = &p2;
} else if (p1.x == p2.x) { } else if (p1.x == p2.x) {
// Repeat points // Repeat points
// ASSIMP_CHANGE (aramis_acg) throw std::runtime_error("Edge::Edge: p1 == p2");
throw std::runtime_error(std::string("repeat points"));
//assert(false);
} }
} }
@ -151,7 +153,7 @@ struct Edge {
// Triangle-based data structures are know to have better performance than quad-edge structures // Triangle-based data structures are know to have better performance than quad-edge structures
// See: J. Shewchuk, "Triangle: Engineering a 2D Quality Mesh Generator and Delaunay Triangulator" // See: J. Shewchuk, "Triangle: Engineering a 2D Quality Mesh Generator and Delaunay Triangulator"
// "Triangulations in CGAL" // "Triangulations in CGAL"
class Triangle { class P2T_DLL_SYMBOL Triangle {
public: public:
/// Constructor /// Constructor
@ -178,6 +180,7 @@ void MarkConstrainedEdge(Point* p, Point* q);
int Index(const Point* p); int Index(const Point* p);
int EdgeIndex(const Point* p1, const Point* p2); int EdgeIndex(const Point* p1, const Point* p2);
Triangle* NeighborAcross(const Point& point);
Triangle* NeighborCW(const Point& point); Triangle* NeighborCW(const Point& point);
Triangle* NeighborCCW(const Point& point); Triangle* NeighborCCW(const Point& point);
bool GetConstrainedEdgeCCW(const Point& p); bool GetConstrainedEdgeCCW(const Point& p);
@ -205,12 +208,14 @@ void ClearDelunayEdges();
inline bool IsInterior(); inline bool IsInterior();
inline void IsInterior(bool b); inline void IsInterior(bool b);
Triangle& NeighborAcross(const Point& opoint);
void DebugPrint(); void DebugPrint();
bool CircumcicleContains(const Point&) const;
private: private:
bool IsCounterClockwise() const;
/// Triangle points /// Triangle points
Point* points_[3]; Point* points_[3];
/// Neighbor list /// Neighbor list
@ -258,7 +263,7 @@ inline bool operator ==(const Point& a, const Point& b)
inline bool operator !=(const Point& a, const Point& b) inline bool operator !=(const Point& a, const Point& b)
{ {
return !(a.x == b.x) && !(a.y == b.y); return !(a.x == b.x) || !(a.y == b.y);
} }
/// Peform the dot product on two vectors. /// Peform the dot product on two vectors.
@ -322,6 +327,7 @@ inline void Triangle::IsInterior(bool b)
interior_ = b; interior_ = b;
} }
} /// Is this set a valid delaunay triangulation?
P2T_DLL_SYMBOL bool IsDelaunay(const std::vector<p2t::Triangle*>&);
#endif }

View File

@ -1,6 +1,6 @@
/* /*
* Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/ * https://github.com/jhasse/poly2tri
* *
* All rights reserved. * All rights reserved.
* *
@ -29,14 +29,15 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef UTILS_H #pragma once
#define UTILS_H
// Otherwise #defines like M_PI are undeclared under Visual Studio // Otherwise #defines like M_PI are undeclared under Visual Studio
#define _USE_MATH_DEFINES #define _USE_MATH_DEFINES
#include "shapes.h"
#include <cmath>
#include <exception> #include <exception>
#include <math.h>
// C99 removes M_PI from math.h // C99 removes M_PI from math.h
#ifndef M_PI #ifndef M_PI
@ -66,7 +67,11 @@ Orientation Orient2d(const Point& pa, const Point& pb, const Point& pc)
double detleft = (pa.x - pc.x) * (pb.y - pc.y); double detleft = (pa.x - pc.x) * (pb.y - pc.y);
double detright = (pa.y - pc.y) * (pb.x - pc.x); double detright = (pa.y - pc.y) * (pb.x - pc.x);
double val = detleft - detright; double val = detleft - detright;
if (val > -EPSILON && val < EPSILON) {
// Using a tolerance here fails on concave-by-subepsilon boundaries
// if (val > -EPSILON && val < EPSILON) {
// Using == on double makes -Wfloat-equal warnings yell at us
if (std::fpclassify(val) == FP_ZERO) {
return COLLINEAR; return COLLINEAR;
} else if (val > 0) { } else if (val > 0) {
return CCW; return CCW;
@ -123,5 +128,3 @@ bool InScanArea(const Point& pa, const Point& pb, const Point& pc, const Point&
} }
} }
#endif

View File

@ -1,6 +1,6 @@
/* /*
* Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/ * https://github.com/jhasse/poly2tri
* *
* All rights reserved. * All rights reserved.
* *
@ -29,10 +29,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef POLY2TRI_H #pragma once
#define POLY2TRI_H
#include "common/shapes.h" #include "common/shapes.h"
#include "sweep/cdt.h" #include "sweep/cdt.h"
#endif

View File

@ -1,6 +1,6 @@
/* /*
* Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/ * https://github.com/jhasse/poly2tri
* *
* All rights reserved. * All rights reserved.
* *
@ -30,6 +30,8 @@
*/ */
#include "advancing_front.h" #include "advancing_front.h"
#include <cassert>
namespace p2t { namespace p2t {
AdvancingFront::AdvancingFront(Node& head, Node& tail) AdvancingFront::AdvancingFront(Node& head, Node& tail)
@ -44,21 +46,21 @@ Node* AdvancingFront::LocateNode(double x)
Node* node = search_node_; Node* node = search_node_;
if (x < node->value) { if (x < node->value) {
while ((node = node->prev) != NULL) { while ((node = node->prev) != nullptr) {
if (x >= node->value) { if (x >= node->value) {
search_node_ = node; search_node_ = node;
return node; return node;
} }
} }
} else { } else {
while ((node = node->next) != NULL) { while ((node = node->next) != nullptr) {
if (x < node->value) { if (x < node->value) {
search_node_ = node->prev; search_node_ = node->prev;
return node->prev; return node->prev;
} }
} }
} }
return NULL; return nullptr;
} }
Node* AdvancingFront::FindSearchNode(double x) Node* AdvancingFront::FindSearchNode(double x)
@ -86,13 +88,13 @@ Node* AdvancingFront::LocatePoint(const Point* point)
} }
} }
} else if (px < nx) { } else if (px < nx) {
while ((node = node->prev) != NULL) { while ((node = node->prev) != nullptr) {
if (point == node->point) { if (point == node->point) {
break; break;
} }
} }
} else { } else {
while ((node = node->next) != NULL) { while ((node = node->next) != nullptr) {
if (point == node->point) if (point == node->point)
break; break;
} }
@ -105,4 +107,4 @@ AdvancingFront::~AdvancingFront()
{ {
} }
} } // namespace p2t

View File

@ -1,6 +1,6 @@
/* /*
* Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/ * https://github.com/jhasse/poly2tri
* *
* All rights reserved. * All rights reserved.
* *
@ -29,8 +29,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef ADVANCED_FRONT_H #pragma once
#define ADVANCED_FRONT_H
#include "../common/shapes.h" #include "../common/shapes.h"
@ -114,5 +113,3 @@ inline void AdvancingFront::set_search(Node* node)
} }
} }
#endif

View File

@ -1,6 +1,6 @@
/* /*
* Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2021, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/ * https://github.com/jhasse/poly2tri
* *
* All rights reserved. * All rights reserved.
* *
@ -68,4 +68,4 @@ CDT::~CDT()
delete sweep_; delete sweep_;
} }
} } // namespace p2t

View File

@ -1,6 +1,6 @@
/* /*
* Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/ * https://github.com/jhasse/poly2tri
* *
* All rights reserved. * All rights reserved.
* *
@ -29,13 +29,14 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef CDT_H #pragma once
#define CDT_H
#include "advancing_front.h" #include "advancing_front.h"
#include "sweep_context.h" #include "sweep_context.h"
#include "sweep.h" #include "sweep.h"
#include "../common/dll_symbol.h"
/** /**
* *
* @author Mason Green <mason.green@gmail.com> * @author Mason Green <mason.green@gmail.com>
@ -44,7 +45,7 @@
namespace p2t { namespace p2t {
class CDT class P2T_DLL_SYMBOL CDT
{ {
public: public:
@ -101,5 +102,3 @@ public:
}; };
} }
#endif

View File

@ -1,6 +1,6 @@
/* /*
* Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/ * https://github.com/jhasse/poly2tri
* *
* All rights reserved. * All rights reserved.
* *
@ -28,24 +28,21 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <stdexcept>
#include "sweep.h" #include "sweep.h"
#include "sweep_context.h" #include "sweep_context.h"
#include "advancing_front.h" #include "advancing_front.h"
#include "../common/utils.h" #include "../common/utils.h"
namespace p2t { #include <cassert>
#include <stdexcept>
#ifdef _MSC_VER namespace p2t {
# pragma warning(push)
# pragma warning( disable : 4702 )
#endif // _MSC_VER
// Triangulate simple polygon with holes // Triangulate simple polygon with holes
void Sweep::Triangulate(SweepContext& tcx) void Sweep::Triangulate(SweepContext& tcx)
{ {
tcx.InitTriangulation(); tcx.InitTriangulation();
tcx.CreateAdvancingFront(nodes_); tcx.CreateAdvancingFront();
// Sweep points; build mesh // Sweep points; build mesh
SweepPoints(tcx); SweepPoints(tcx);
// Clean up // Clean up
@ -57,8 +54,8 @@ void Sweep::SweepPoints(SweepContext& tcx)
for (size_t i = 1; i < tcx.point_count(); i++) { for (size_t i = 1; i < tcx.point_count(); i++) {
Point& point = *tcx.GetPoint(i); Point& point = *tcx.GetPoint(i);
Node* node = &PointEvent(tcx, point); Node* node = &PointEvent(tcx, point);
for (unsigned int ii = 0; ii < point.edge_list.size(); ii++) { for (auto& j : point.edge_list) {
EdgeEvent(tcx, point.edge_list[ii], node); EdgeEvent(tcx, j, node);
} }
} }
} }
@ -68,17 +65,25 @@ void Sweep::FinalizationPolygon(SweepContext& tcx)
// Get an Internal triangle to start with // Get an Internal triangle to start with
Triangle* t = tcx.front()->head()->next->triangle; Triangle* t = tcx.front()->head()->next->triangle;
Point* p = tcx.front()->head()->next->point; Point* p = tcx.front()->head()->next->point;
while (!t->GetConstrainedEdgeCW(*p)) { while (t && !t->GetConstrainedEdgeCW(*p)) {
t = t->NeighborCCW(*p); t = t->NeighborCCW(*p);
} }
// Collect interior triangles constrained by edges // Collect interior triangles constrained by edges
if (t) {
tcx.MeshClean(*t); tcx.MeshClean(*t);
}
} }
Node& Sweep::PointEvent(SweepContext& tcx, Point& point) Node& Sweep::PointEvent(SweepContext& tcx, Point& point)
{ {
Node& node = tcx.LocateNode(point); Node* node_ptr = tcx.LocateNode(point);
if (!node_ptr || !node_ptr->point || !node_ptr->next || !node_ptr->next->point)
{
throw std::runtime_error("PointEvent - null node");
}
Node& node = *node_ptr;
Node& new_node = NewFrontTriangle(tcx, point, node); Node& new_node = NewFrontTriangle(tcx, point, node);
// Only need to check +epsilon since point never have smaller // Only need to check +epsilon since point never have smaller
@ -111,9 +116,9 @@ void Sweep::EdgeEvent(SweepContext& tcx, Edge* edge, Node* node)
void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangle, Point& point) void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangle, Point& point)
{ {
if (triangle == nullptr) if (triangle == nullptr) {
return; throw std::runtime_error("EdgeEvent - null triangle");
}
if (IsEdgeSideOfTriangle(*triangle, ep, eq)) { if (IsEdgeSideOfTriangle(*triangle, ep, eq)) {
return; return;
} }
@ -121,17 +126,14 @@ void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangl
Point* p1 = triangle->PointCCW(point); Point* p1 = triangle->PointCCW(point);
Orientation o1 = Orient2d(eq, *p1, ep); Orientation o1 = Orient2d(eq, *p1, ep);
if (o1 == COLLINEAR) { if (o1 == COLLINEAR) {
if (triangle->Contains(&eq, p1)) {
triangle->MarkConstrainedEdge(&eq, p1);
if( triangle->Contains(&eq, p1)) {
triangle->MarkConstrainedEdge(&eq, p1 );
// We are modifying the constraint maybe it would be better to // We are modifying the constraint maybe it would be better to
// not change the given constraint and just keep a variable for the new constraint // not change the given constraint and just keep a variable for the new constraint
tcx.edge_event.constrained_edge->q = p1; tcx.edge_event.constrained_edge->q = p1;
triangle = &triangle->NeighborAcross(point); triangle = triangle->NeighborAcross(point);
EdgeEvent( tcx, ep, *p1, triangle, *p1 ); EdgeEvent(tcx, ep, *p1, triangle, *p1);
} else { } else {
// ASSIMP_CHANGE (aramis_acg)
throw std::runtime_error("EdgeEvent - collinear points not supported"); throw std::runtime_error("EdgeEvent - collinear points not supported");
} }
return; return;
@ -140,18 +142,14 @@ void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangl
Point* p2 = triangle->PointCW(point); Point* p2 = triangle->PointCW(point);
Orientation o2 = Orient2d(eq, *p2, ep); Orientation o2 = Orient2d(eq, *p2, ep);
if (o2 == COLLINEAR) { if (o2 == COLLINEAR) {
if (triangle->Contains(&eq, p2)) {
triangle->MarkConstrainedEdge(&eq, p2);
if( triangle->Contains(&eq, p2)) {
triangle->MarkConstrainedEdge(&eq, p2 );
// We are modifying the constraint maybe it would be better to // We are modifying the constraint maybe it would be better to
// not change the given constraint and just keep a variable for the new constraint // not change the given constraint and just keep a variable for the new constraint
tcx.edge_event.constrained_edge->q = p2; tcx.edge_event.constrained_edge->q = p2;
triangle = &triangle->NeighborAcross(point); triangle = triangle->NeighborAcross(point);
EdgeEvent( tcx, ep, *p2, triangle, *p2 ); EdgeEvent(tcx, ep, *p2, triangle, *p2);
} else { } else {
// ASSIMP_CHANGE (aramis_acg)
throw std::runtime_error("EdgeEvent - collinear points not supported"); throw std::runtime_error("EdgeEvent - collinear points not supported");
} }
return; return;
@ -162,12 +160,13 @@ void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangl
// that will cross edge // that will cross edge
if (o1 == CW) { if (o1 == CW) {
triangle = triangle->NeighborCCW(point); triangle = triangle->NeighborCCW(point);
} else{ } else {
triangle = triangle->NeighborCW(point); triangle = triangle->NeighborCW(point);
} }
EdgeEvent(tcx, ep, eq, triangle, point); EdgeEvent(tcx, ep, eq, triangle, point);
} else { } else {
// This triangle crosses constraint so lets flippin start! // This triangle crosses constraint so lets flippin start!
assert(triangle);
FlipEdgeEvent(tcx, ep, eq, triangle, point); FlipEdgeEvent(tcx, ep, eq, triangle, point);
} }
} }
@ -228,7 +227,6 @@ void Sweep::Fill(SweepContext& tcx, Node& node)
if (!Legalize(tcx, *triangle)) { if (!Legalize(tcx, *triangle)) {
tcx.MapTriangleToNodes(*triangle); tcx.MapTriangleToNodes(*triangle);
} }
} }
void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n) void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n)
@ -237,7 +235,7 @@ void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n)
// Fill right holes // Fill right holes
Node* node = n.next; Node* node = n.next;
while (node->next) { while (node && node->next) {
// if HoleAngle exceeds 90 degrees then break. // if HoleAngle exceeds 90 degrees then break.
if (LargeHole_DontFill(node)) break; if (LargeHole_DontFill(node)) break;
Fill(tcx, *node); Fill(tcx, *node);
@ -247,7 +245,7 @@ void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n)
// Fill left holes // Fill left holes
node = n.prev; node = n.prev;
while (node->prev) { while (node && node->prev) {
// if HoleAngle exceeds 90 degrees then break. // if HoleAngle exceeds 90 degrees then break.
if (LargeHole_DontFill(node)) break; if (LargeHole_DontFill(node)) break;
Fill(tcx, *node); Fill(tcx, *node);
@ -264,6 +262,35 @@ void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n)
} }
// True if HoleAngle exceeds 90 degrees. // True if HoleAngle exceeds 90 degrees.
// LargeHole_DontFill checks if the advancing front has a large hole.
// A "Large hole" is a triangle formed by a sequence of points in the advancing
// front where three neighbor points form a triangle.
// And angle between left-top, bottom, and right-top points is more than 90 degrees.
// The first part of the algorithm reviews only three neighbor points, e.g. named A, B, C.
// Additional part of this logic reviews a sequence of 5 points -
// additionally reviews one point before and one after the sequence of three (A, B, C),
// e.g. named X and Y.
// In this case, angles are XBC and ABY and this if angles are negative or more
// than 90 degrees LargeHole_DontFill returns true.
// But there is a configuration when ABC has a negative angle but XBC or ABY is less
// than 90 degrees and positive.
// Then function LargeHole_DontFill return false and initiates filling.
// This filling creates a triangle ABC and adds it to the advancing front.
// But in the case when angle ABC is negative this triangle goes inside the advancing front
// and can intersect previously created triangles.
// This triangle leads to making wrong advancing front and problems in triangulation in the future.
// Looks like such a triangle should not be created.
// The simplest way to check and fix it is to check an angle ABC.
// If it is negative LargeHole_DontFill should return true and
// not initiate creating the ABC triangle in the advancing front.
// X______A Y
// \ /
// \ /
// \ B /
// | /
// | /
// |/
// C
bool Sweep::LargeHole_DontFill(const Node* node) const { bool Sweep::LargeHole_DontFill(const Node* node) const {
const Node* nextNode = node->next; const Node* nextNode = node->next;
@ -271,20 +298,28 @@ bool Sweep::LargeHole_DontFill(const Node* node) const {
if (!AngleExceeds90Degrees(node->point, nextNode->point, prevNode->point)) if (!AngleExceeds90Degrees(node->point, nextNode->point, prevNode->point))
return false; return false;
if (AngleIsNegative(node->point, nextNode->point, prevNode->point))
return true;
// Check additional points on front. // Check additional points on front.
const Node* next2Node = nextNode->next; const Node* next2Node = nextNode->next;
// "..Plus.." because only want angles on same side as point being added. // "..Plus.." because only want angles on same side as point being added.
if ((next2Node != NULL) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, next2Node->point, prevNode->point)) if ((next2Node != nullptr) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, next2Node->point, prevNode->point))
return false; return false;
const Node* prev2Node = prevNode->prev; const Node* prev2Node = prevNode->prev;
// "..Plus.." because only want angles on same side as point being added. // "..Plus.." because only want angles on same side as point being added.
if ((prev2Node != NULL) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, nextNode->point, prev2Node->point)) if ((prev2Node != nullptr) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, nextNode->point, prev2Node->point))
return false; return false;
return true; return true;
} }
bool Sweep::AngleIsNegative(const Point* origin, const Point* pa, const Point* pb) const {
const double angle = Angle(origin, pa, pb);
return angle < 0;
}
bool Sweep::AngleExceeds90Degrees(const Point* origin, const Point* pa, const Point* pb) const { bool Sweep::AngleExceeds90Degrees(const Point* origin, const Point* pa, const Point* pb) const {
const double angle = Angle(origin, pa, pb); const double angle = Angle(origin, pa, pb);
return ((angle > PI_div2) || (angle < -PI_div2)); return ((angle > PI_div2) || (angle < -PI_div2));
@ -306,7 +341,7 @@ double Sweep::Angle(const Point* origin, const Point* pa, const Point* pb) const
*/ */
const double px = origin->x; const double px = origin->x;
const double py = origin->y; const double py = origin->y;
const double ax = pa->x- px; const double ax = pa->x - px;
const double ay = pa->y - py; const double ay = pa->y - py;
const double bx = pb->x - px; const double bx = pb->x - px;
const double by = pb->y - py; const double by = pb->y - py;
@ -599,7 +634,7 @@ void Sweep::FillRightBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)
if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) { if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) {
// Concave // Concave
FillRightConcaveEdgeEvent(tcx, edge, node); FillRightConcaveEdgeEvent(tcx, edge, node);
} else{ } else {
// Convex // Convex
FillRightConvexEdgeEvent(tcx, edge, node); FillRightConvexEdgeEvent(tcx, edge, node);
// Retry this one // Retry this one
@ -623,7 +658,6 @@ void Sweep::FillRightConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)
} }
} }
} }
} }
void Sweep::FillRightConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) void Sweep::FillRightConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)
@ -632,13 +666,13 @@ void Sweep::FillRightConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)
if (Orient2d(*node.next->point, *node.next->next->point, *node.next->next->next->point) == CCW) { if (Orient2d(*node.next->point, *node.next->next->point, *node.next->next->next->point) == CCW) {
// Concave // Concave
FillRightConcaveEdgeEvent(tcx, edge, *node.next); FillRightConcaveEdgeEvent(tcx, edge, *node.next);
} else{ } else {
// Convex // Convex
// Next above or below edge? // Next above or below edge?
if (Orient2d(*edge->q, *node.next->next->point, *edge->p) == CCW) { if (Orient2d(*edge->q, *node.next->next->point, *edge->p) == CCW) {
// Below // Below
FillRightConvexEdgeEvent(tcx, edge, *node.next); FillRightConvexEdgeEvent(tcx, edge, *node.next);
} else{ } else {
// Above // Above
} }
} }
@ -677,13 +711,13 @@ void Sweep::FillLeftConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)
if (Orient2d(*node.prev->point, *node.prev->prev->point, *node.prev->prev->prev->point) == CW) { if (Orient2d(*node.prev->point, *node.prev->prev->point, *node.prev->prev->prev->point) == CW) {
// Concave // Concave
FillLeftConcaveEdgeEvent(tcx, edge, *node.prev); FillLeftConcaveEdgeEvent(tcx, edge, *node.prev);
} else{ } else {
// Convex // Convex
// Next above or below edge? // Next above or below edge?
if (Orient2d(*edge->q, *node.prev->prev->point, *edge->p) == CW) { if (Orient2d(*edge->q, *node.prev->prev->point, *edge->p) == CW) {
// Below // Below
FillLeftConvexEdgeEvent(tcx, edge, *node.prev); FillLeftConvexEdgeEvent(tcx, edge, *node.prev);
} else{ } else {
// Above // Above
} }
} }
@ -699,17 +733,22 @@ void Sweep::FillLeftConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)
if (Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW) { if (Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW) {
// Next is concave // Next is concave
FillLeftConcaveEdgeEvent(tcx, edge, node); FillLeftConcaveEdgeEvent(tcx, edge, node);
} else{ } else {
// Next is convex // Next is convex
} }
} }
} }
} }
void Sweep::FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* t, Point& p) void Sweep::FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* t, Point& p)
{ {
Triangle& ot = t->NeighborAcross(p); assert(t);
Triangle* ot_ptr = t->NeighborAcross(p);
if (ot_ptr == nullptr)
{
throw std::runtime_error("FlipEdgeEvent - null neighbor across");
}
Triangle& ot = *ot_ptr;
Point& op = *ot.OppositePoint(*t, p); Point& op = *ot.OppositePoint(*t, p);
if (InScanArea(p, *t->PointCCW(p), *t->PointCW(p), op)) { if (InScanArea(p, *t->PointCCW(p), *t->PointCW(p), op)) {
@ -775,10 +814,26 @@ Point& Sweep::NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op)
void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle, void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle,
Triangle& t, Point& p) Triangle& t, Point& p)
{ {
Triangle& ot = t.NeighborAcross(p); Triangle* ot_ptr = t.NeighborAcross(p);
Point& op = *ot.OppositePoint(t, p); if (ot_ptr == nullptr) {
throw std::runtime_error("FlipScanEdgeEvent - null neighbor across");
}
if (InScanArea(eq, *flip_triangle.PointCCW(eq), *flip_triangle.PointCW(eq), op)) { Point* op_ptr = ot_ptr->OppositePoint(t, p);
if (op_ptr == nullptr) {
throw std::runtime_error("FlipScanEdgeEvent - null opposing point");
}
Point* p1 = flip_triangle.PointCCW(eq);
Point* p2 = flip_triangle.PointCW(eq);
if (p1 == nullptr || p2 == nullptr) {
throw std::runtime_error("FlipScanEdgeEvent - null on either of points");
}
Triangle& ot = *ot_ptr;
Point& op = *op_ptr;
if (InScanArea(eq, *p1, *p2, op)) {
// flip with new edge op->eq // flip with new edge op->eq
FlipEdgeEvent(tcx, eq, op, &ot, op); FlipEdgeEvent(tcx, eq, op, &ot, op);
// TODO: Actually I just figured out that it should be possible to // TODO: Actually I just figured out that it should be possible to
@ -788,7 +843,7 @@ void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle&
// also need to set a new flip_triangle first // also need to set a new flip_triangle first
// Turns out at first glance that this is somewhat complicated // Turns out at first glance that this is somewhat complicated
// so it will have to wait. // so it will have to wait.
} else{ } else {
Point& newP = NextFlipPoint(ep, eq, ot, op); Point& newP = NextFlipPoint(ep, eq, ot, op);
FlipScanEdgeEvent(tcx, ep, eq, flip_triangle, ot, newP); FlipScanEdgeEvent(tcx, ep, eq, flip_triangle, ot, newP);
} }
@ -797,14 +852,9 @@ void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle&
Sweep::~Sweep() { Sweep::~Sweep() {
// Clean up memory // Clean up memory
for(size_t i = 0; i < nodes_.size(); i++) { for (auto& node : nodes_) {
delete nodes_[i]; delete node;
} }
} }
#ifdef _MSC_VER } // namespace p2t
# pragma warning( pop )
#endif // _MSC_VER
}

View File

@ -1,6 +1,6 @@
/* /*
* Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/ * https://github.com/jhasse/poly2tri
* *
* All rights reserved. * All rights reserved.
* *
@ -33,11 +33,10 @@
* Zalik, B.(2008)'Sweep-line algorithm for constrained Delaunay triangulation', * Zalik, B.(2008)'Sweep-line algorithm for constrained Delaunay triangulation',
* International Journal of Geographical Information Science * International Journal of Geographical Information Science
* *
* "FlipScan" Constrained Edge Algorithm invented by Thomas ?hl?n, thahlen@gmail.com * "FlipScan" Constrained Edge Algorithm invented by Thomas Åhlén, thahlen@gmail.com
*/ */
#ifndef SWEEP_H #pragma once
#define SWEEP_H
#include <vector> #include <vector>
@ -172,6 +171,7 @@ private:
// Decision-making about when to Fill hole. // Decision-making about when to Fill hole.
// Contributed by ToolmakerSteve2 // Contributed by ToolmakerSteve2
bool LargeHole_DontFill(const Node* node) const; bool LargeHole_DontFill(const Node* node) const;
bool AngleIsNegative(const Point* origin, const Point* pa, const Point* pb) const;
bool AngleExceeds90Degrees(const Point* origin, const Point* pa, const Point* pb) const; bool AngleExceeds90Degrees(const Point* origin, const Point* pa, const Point* pb) const;
bool AngleExceedsPlus90DegreesOrIsNegative(const Point* origin, const Point* pa, const Point* pb) const; bool AngleExceedsPlus90DegreesOrIsNegative(const Point* origin, const Point* pa, const Point* pb) const;
double Angle(const Point* origin, const Point* pa, const Point* pb) const; double Angle(const Point* origin, const Point* pa, const Point* pb) const;
@ -281,5 +281,3 @@ private:
}; };
} }
#endif

View File

@ -1,6 +1,6 @@
/* /*
* Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2022, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/ * https://github.com/jhasse/poly2tri
* *
* All rights reserved. * All rights reserved.
* *
@ -34,13 +34,13 @@
namespace p2t { namespace p2t {
SweepContext::SweepContext(const std::vector<Point*>& polyline) : points_(polyline), SweepContext::SweepContext(std::vector<Point*> polyline) : points_(std::move(polyline)),
front_(0), front_(nullptr),
head_(0), head_(nullptr),
tail_(0), tail_(nullptr),
af_head_(0), af_head_(nullptr),
af_middle_(0), af_middle_(nullptr),
af_tail_(0) af_tail_(nullptr)
{ {
InitEdges(points_); InitEdges(points_);
} }
@ -48,8 +48,8 @@ SweepContext::SweepContext(const std::vector<Point*>& polyline) : points_(polyli
void SweepContext::AddHole(const std::vector<Point*>& polyline) void SweepContext::AddHole(const std::vector<Point*>& polyline)
{ {
InitEdges(polyline); InitEdges(polyline);
for(unsigned int i = 0; i < polyline.size(); i++) { for (auto i : polyline) {
points_.push_back(polyline[i]); points_.push_back(i);
} }
} }
@ -73,8 +73,8 @@ void SweepContext::InitTriangulation()
double ymax(points_[0]->y), ymin(points_[0]->y); double ymax(points_[0]->y), ymin(points_[0]->y);
// Calculate bounds. // Calculate bounds.
for (unsigned int i = 0; i < points_.size(); i++) { for (auto& point : points_) {
Point& p = *points_[i]; Point& p = *point;
if (p.x > xmax) if (p.x > xmax)
xmax = p.x; xmax = p.x;
if (p.x < xmin) if (p.x < xmin)
@ -87,8 +87,8 @@ void SweepContext::InitTriangulation()
double dx = kAlpha * (xmax - xmin); double dx = kAlpha * (xmax - xmin);
double dy = kAlpha * (ymax - ymin); double dy = kAlpha * (ymax - ymin);
head_ = new Point(xmax + dx, ymin - dy); head_ = new Point(xmin - dx, ymin - dy);
tail_ = new Point(xmin - dx, ymin - dy); tail_ = new Point(xmax + dx, ymin - dy);
// Sort points along y-axis // Sort points along y-axis
std::sort(points_.begin(), points_.end(), cmp); std::sort(points_.begin(), points_.end(), cmp);
@ -114,18 +114,17 @@ void SweepContext::AddToMap(Triangle* triangle)
map_.push_back(triangle); map_.push_back(triangle);
} }
Node& SweepContext::LocateNode(const Point& point) Node* SweepContext::LocateNode(const Point& point)
{ {
// TODO implement search tree // TODO implement search tree
return *front_->LocateNode(point.x); return front_->LocateNode(point.x);
} }
void SweepContext::CreateAdvancingFront(const std::vector<Node*>& nodes) void SweepContext::CreateAdvancingFront()
{ {
(void) nodes;
// Initial triangle // Initial triangle
Triangle* triangle = new Triangle(*points_[0], *tail_, *head_); Triangle* triangle = new Triangle(*points_[0], *head_, *tail_);
map_.push_back(triangle); map_.push_back(triangle);
@ -172,7 +171,7 @@ void SweepContext::MeshClean(Triangle& triangle)
Triangle *t = triangles.back(); Triangle *t = triangles.back();
triangles.pop_back(); triangles.pop_back();
if (t != NULL && !t->IsInterior()) { if (t != nullptr && !t->IsInterior()) {
t->IsInterior(true); t->IsInterior(true);
triangles_.push_back(t); triangles_.push_back(t);
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
@ -195,17 +194,13 @@ SweepContext::~SweepContext()
delete af_middle_; delete af_middle_;
delete af_tail_; delete af_tail_;
typedef std::list<Triangle*> type_list; for (auto ptr : map_) {
for(type_list::iterator iter = map_.begin(); iter != map_.end(); ++iter) {
Triangle* ptr = *iter;
delete ptr; delete ptr;
} }
for(unsigned int i = 0; i < edge_list.size(); i++) { for (auto& i : edge_list) {
delete edge_list[i]; delete i;
} }
} }
} } // namespace p2t

View File

@ -1,6 +1,6 @@
/* /*
* Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2022, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/ * https://github.com/jhasse/poly2tri
* *
* All rights reserved. * All rights reserved.
* *
@ -29,8 +29,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef SWEEP_CONTEXT_H #pragma once
#define SWEEP_CONTEXT_H
#include <list> #include <list>
#include <vector> #include <vector>
@ -52,7 +51,7 @@ class SweepContext {
public: public:
/// Constructor /// Constructor
SweepContext(const std::vector<Point*>& polyline); explicit SweepContext(std::vector<Point*> polyline);
/// Destructor /// Destructor
~SweepContext(); ~SweepContext();
@ -66,11 +65,11 @@ Point* tail() const;
size_t point_count() const; size_t point_count() const;
Node& LocateNode(const Point& point); Node* LocateNode(const Point& point);
void RemoveNode(Node* node); void RemoveNode(Node* node);
void CreateAdvancingFront(const std::vector<Node*>& nodes); void CreateAdvancingFront();
/// Try to map a node to all sides of this triangle that don't have a neighbor /// Try to map a node to all sides of this triangle that don't have a neighbor
void MapTriangleToNodes(Triangle& t); void MapTriangleToNodes(Triangle& t);
@ -103,15 +102,16 @@ struct Basin {
double width; double width;
bool left_highest; bool left_highest;
Basin() : left_node(NULL), bottom_node(NULL), right_node(NULL), width(0.0), left_highest(false) Basin()
: left_node(nullptr), bottom_node(nullptr), right_node(nullptr), width(0.0), left_highest(false)
{ {
} }
void Clear() void Clear()
{ {
left_node = NULL; left_node = nullptr;
bottom_node = NULL; bottom_node = nullptr;
right_node = NULL; right_node = nullptr;
width = 0.0; width = 0.0;
left_highest = false; left_highest = false;
} }
@ -182,5 +182,3 @@ inline Point* SweepContext::tail() const
} }
} }
#endif