mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-11-02 20:51:23 -07:00 
			
		
		
		
	Merge branch 'master' of https://github.com/prusa3d/Slic3r into objects_centering
This commit is contained in:
		
						commit
						16bd7325c1
					
				
					 25 changed files with 964 additions and 660 deletions
				
			
		| 
						 | 
				
			
			@ -50,7 +50,6 @@ if (SLIC3R_GUI)
 | 
			
		|||
    if(WIN32)
 | 
			
		||||
        message(STATUS "WXWIN environment set to: $ENV{WXWIN}")
 | 
			
		||||
    elseif(UNIX)
 | 
			
		||||
        message(STATUS "wx-config path: ${wxWidgets_CONFIG_EXECUTABLE}")
 | 
			
		||||
        set(wxWidgets_USE_UNICODE ON)
 | 
			
		||||
        if(SLIC3R_STATIC)
 | 
			
		||||
            set(wxWidgets_USE_STATIC ON)
 | 
			
		||||
| 
						 | 
				
			
			@ -72,6 +71,10 @@ if (SLIC3R_GUI)
 | 
			
		|||
        find_package(wxWidgets 3.1 REQUIRED COMPONENTS base core adv html gl)
 | 
			
		||||
    endif ()
 | 
			
		||||
 | 
			
		||||
    if(UNIX)
 | 
			
		||||
        message(STATUS "wx-config path: ${wxWidgets_CONFIG_EXECUTABLE}")
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    include(${wxWidgets_USE_FILE})
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -310,16 +310,15 @@ ExPolygon::medial_axis(double max_width, double min_width, Polylines* polylines)
 | 
			
		|||
    polylines->insert(polylines->end(), tp.begin(), tp.end());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
ExPolygon::get_trapezoids(Polygons* polygons) const
 | 
			
		||||
/*
 | 
			
		||||
void ExPolygon::get_trapezoids(Polygons* polygons) const
 | 
			
		||||
{
 | 
			
		||||
    ExPolygons expp;
 | 
			
		||||
    expp.push_back(*this);
 | 
			
		||||
    boost::polygon::get_trapezoids(*polygons, expp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
ExPolygon::get_trapezoids(Polygons* polygons, double angle) const
 | 
			
		||||
void ExPolygon::get_trapezoids(Polygons* polygons, double angle) const
 | 
			
		||||
{
 | 
			
		||||
    ExPolygon clone = *this;
 | 
			
		||||
    clone.rotate(PI/2 - angle, Point(0,0));
 | 
			
		||||
| 
						 | 
				
			
			@ -327,12 +326,12 @@ ExPolygon::get_trapezoids(Polygons* polygons, double angle) const
 | 
			
		|||
    for (Polygons::iterator polygon = polygons->begin(); polygon != polygons->end(); ++polygon)
 | 
			
		||||
        polygon->rotate(-(PI/2 - angle), Point(0,0));
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
// This algorithm may return more trapezoids than necessary
 | 
			
		||||
// (i.e. it may break a single trapezoid in several because
 | 
			
		||||
// other parts of the object have x coordinates in the middle)
 | 
			
		||||
void
 | 
			
		||||
ExPolygon::get_trapezoids2(Polygons* polygons) const
 | 
			
		||||
void ExPolygon::get_trapezoids2(Polygons* polygons) const
 | 
			
		||||
{
 | 
			
		||||
    // get all points of this ExPolygon
 | 
			
		||||
    Points pp = *this;
 | 
			
		||||
| 
						 | 
				
			
			@ -370,8 +369,7 @@ ExPolygon::get_trapezoids2(Polygons* polygons) const
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
ExPolygon::get_trapezoids2(Polygons* polygons, double angle) const
 | 
			
		||||
void ExPolygon::get_trapezoids2(Polygons* polygons, double angle) const
 | 
			
		||||
{
 | 
			
		||||
    ExPolygon clone = *this;
 | 
			
		||||
    clone.rotate(PI/2 - angle, Point(0,0));
 | 
			
		||||
| 
						 | 
				
			
			@ -382,8 +380,7 @@ ExPolygon::get_trapezoids2(Polygons* polygons, double angle) const
 | 
			
		|||
 | 
			
		||||
// While this triangulates successfully, it's NOT a constrained triangulation
 | 
			
		||||
// as it will create more vertices on the boundaries than the ones supplied.
 | 
			
		||||
void
 | 
			
		||||
ExPolygon::triangulate(Polygons* polygons) const
 | 
			
		||||
void ExPolygon::triangulate(Polygons* polygons) const
 | 
			
		||||
{
 | 
			
		||||
    // first make trapezoids
 | 
			
		||||
    Polygons trapezoids;
 | 
			
		||||
| 
						 | 
				
			
			@ -394,8 +391,8 @@ ExPolygon::triangulate(Polygons* polygons) const
 | 
			
		|||
        polygon->triangulate_convex(polygons);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
ExPolygon::triangulate_pp(Polygons* polygons) const
 | 
			
		||||
/*
 | 
			
		||||
void ExPolygon::triangulate_pp(Polygons* polygons) const
 | 
			
		||||
{
 | 
			
		||||
    // convert polygons
 | 
			
		||||
    std::list<TPPLPoly> input;
 | 
			
		||||
| 
						 | 
				
			
			@ -452,9 +449,113 @@ ExPolygon::triangulate_pp(Polygons* polygons) const
 | 
			
		|||
        polygons->push_back(p);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
ExPolygon::triangulate_p2t(Polygons* polygons) const
 | 
			
		||||
std::list<TPPLPoly> expoly_to_polypartition_input(const ExPolygon &ex)
 | 
			
		||||
{
 | 
			
		||||
	std::list<TPPLPoly> input;
 | 
			
		||||
	// contour
 | 
			
		||||
	{
 | 
			
		||||
		input.emplace_back();
 | 
			
		||||
		TPPLPoly &p = input.back();
 | 
			
		||||
		p.Init(int(ex.contour.points.size()));
 | 
			
		||||
		for (const Point &point : ex.contour.points) {
 | 
			
		||||
			size_t i = &point - &ex.contour.points.front();
 | 
			
		||||
			p[i].x = point(0);
 | 
			
		||||
			p[i].y = point(1);
 | 
			
		||||
		}
 | 
			
		||||
		p.SetHole(false);
 | 
			
		||||
	}
 | 
			
		||||
	// holes
 | 
			
		||||
	for (const Polygon &hole : ex.holes) {
 | 
			
		||||
		input.emplace_back();
 | 
			
		||||
		TPPLPoly &p = input.back();
 | 
			
		||||
		p.Init(hole.points.size());
 | 
			
		||||
		for (const Point &point : hole.points) {
 | 
			
		||||
			size_t i = &point - &hole.points.front();
 | 
			
		||||
			p[i].x = point(0);
 | 
			
		||||
			p[i].y = point(1);
 | 
			
		||||
		}
 | 
			
		||||
		p.SetHole(true);
 | 
			
		||||
	}
 | 
			
		||||
	return input;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::list<TPPLPoly> expoly_to_polypartition_input(const ExPolygons &expps)
 | 
			
		||||
{
 | 
			
		||||
    std::list<TPPLPoly> input;
 | 
			
		||||
	for (const ExPolygon &ex : expps) {
 | 
			
		||||
        // contour
 | 
			
		||||
        {
 | 
			
		||||
            input.emplace_back();
 | 
			
		||||
            TPPLPoly &p = input.back();
 | 
			
		||||
            p.Init(int(ex.contour.points.size()));
 | 
			
		||||
            for (const Point &point : ex.contour.points) {
 | 
			
		||||
                size_t i = &point - &ex.contour.points.front();
 | 
			
		||||
                p[i].x = point(0);
 | 
			
		||||
                p[i].y = point(1);
 | 
			
		||||
            }
 | 
			
		||||
            p.SetHole(false);
 | 
			
		||||
        }
 | 
			
		||||
        // holes
 | 
			
		||||
        for (const Polygon &hole : ex.holes) {
 | 
			
		||||
            input.emplace_back();
 | 
			
		||||
            TPPLPoly &p = input.back();
 | 
			
		||||
            p.Init(hole.points.size());
 | 
			
		||||
            for (const Point &point : hole.points) {
 | 
			
		||||
                size_t i = &point - &hole.points.front();
 | 
			
		||||
                p[i].x = point(0);
 | 
			
		||||
                p[i].y = point(1);
 | 
			
		||||
            }
 | 
			
		||||
            p.SetHole(true);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return input;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::vector<Point> polypartition_output_to_triangles(const std::list<TPPLPoly> &output)
 | 
			
		||||
{
 | 
			
		||||
    size_t num_triangles = 0;
 | 
			
		||||
    for (const TPPLPoly &poly : output)
 | 
			
		||||
        if (poly.GetNumPoints() >= 3)
 | 
			
		||||
            num_triangles += (size_t)poly.GetNumPoints() - 2;
 | 
			
		||||
    std::vector<Point> triangles;
 | 
			
		||||
    triangles.reserve(triangles.size() + num_triangles * 3);
 | 
			
		||||
    for (const TPPLPoly &poly : output) {
 | 
			
		||||
        long num_points = poly.GetNumPoints();
 | 
			
		||||
        if (num_points >= 3) {
 | 
			
		||||
            const TPPLPoint *pt0 = &poly[0];
 | 
			
		||||
            const TPPLPoint *pt1 = nullptr;
 | 
			
		||||
            const TPPLPoint *pt2 = &poly[1];
 | 
			
		||||
            for (long i = 2; i < num_points; ++ i) {
 | 
			
		||||
                pt1 = pt2;
 | 
			
		||||
                pt2 = &poly[i];
 | 
			
		||||
                triangles.emplace_back(coord_t(pt0->x), coord_t(pt0->y));
 | 
			
		||||
                triangles.emplace_back(coord_t(pt1->x), coord_t(pt1->y));
 | 
			
		||||
                triangles.emplace_back(coord_t(pt2->x), coord_t(pt2->y));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return triangles;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ExPolygon::triangulate_pp(Points *triangles) const
 | 
			
		||||
{
 | 
			
		||||
    ExPolygons expp = union_ex(simplify_polygons(to_polygons(*this), true));
 | 
			
		||||
    std::list<TPPLPoly> input = expoly_to_polypartition_input(expp);
 | 
			
		||||
    // perform triangulation
 | 
			
		||||
    std::list<TPPLPoly> output;
 | 
			
		||||
    int res = TPPLPartition().Triangulate_MONO(&input, &output);
 | 
			
		||||
// int TPPLPartition::Triangulate_EC(TPPLPolyList *inpolys, TPPLPolyList *triangles) {
 | 
			
		||||
    if (res != 1)
 | 
			
		||||
        throw std::runtime_error("Triangulation failed");
 | 
			
		||||
    *triangles = polypartition_output_to_triangles(output);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Uses the Poly2tri library maintained by Jan Niklas Hasse @jhasse // https://github.com/jhasse/poly2tri
 | 
			
		||||
// See https://github.com/jhasse/poly2tri/blob/master/README.md for the limitations of the library!
 | 
			
		||||
// No duplicate points are allowed, no very close points, holes must not touch outer contour etc.
 | 
			
		||||
void ExPolygon::triangulate_p2t(Polygons* polygons) const
 | 
			
		||||
{
 | 
			
		||||
    ExPolygons expp = simplify_polygons_ex(*this, true);
 | 
			
		||||
    
 | 
			
		||||
| 
						 | 
				
			
			@ -478,16 +579,21 @@ ExPolygon::triangulate_p2t(Polygons* polygons) const
 | 
			
		|||
        }
 | 
			
		||||
        
 | 
			
		||||
        // perform triangulation
 | 
			
		||||
        cdt.Triangulate();
 | 
			
		||||
        std::vector<p2t::Triangle*> triangles = cdt.GetTriangles();
 | 
			
		||||
        
 | 
			
		||||
        for (std::vector<p2t::Triangle*>::const_iterator triangle = triangles.begin(); triangle != triangles.end(); ++triangle) {
 | 
			
		||||
            Polygon p;
 | 
			
		||||
            for (int i = 0; i <= 2; ++i) {
 | 
			
		||||
                p2t::Point* point = (*triangle)->GetPoint(i);
 | 
			
		||||
                p.points.push_back(Point(point->x, point->y));
 | 
			
		||||
        try {
 | 
			
		||||
            cdt.Triangulate();
 | 
			
		||||
            std::vector<p2t::Triangle*> triangles = cdt.GetTriangles();
 | 
			
		||||
            
 | 
			
		||||
            for (std::vector<p2t::Triangle*>::const_iterator triangle = triangles.begin(); triangle != triangles.end(); ++triangle) {
 | 
			
		||||
                Polygon p;
 | 
			
		||||
                for (int i = 0; i <= 2; ++i) {
 | 
			
		||||
                    p2t::Point* point = (*triangle)->GetPoint(i);
 | 
			
		||||
                    p.points.push_back(Point(point->x, point->y));
 | 
			
		||||
                }
 | 
			
		||||
                polygons->push_back(p);
 | 
			
		||||
            }
 | 
			
		||||
            polygons->push_back(p);
 | 
			
		||||
        } catch (const std::runtime_error & /* err */) {
 | 
			
		||||
            assert(false);
 | 
			
		||||
            // just ignore, don't triangulate
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (p2t::Point *ptr : ContourPoints)
 | 
			
		||||
| 
						 | 
				
			
			@ -495,8 +601,7 @@ ExPolygon::triangulate_p2t(Polygons* polygons) const
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Lines
 | 
			
		||||
ExPolygon::lines() const
 | 
			
		||||
Lines ExPolygon::lines() const
 | 
			
		||||
{
 | 
			
		||||
    Lines lines = this->contour.lines();
 | 
			
		||||
    for (Polygons::const_iterator h = this->holes.begin(); h != this->holes.end(); ++h) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,9 @@
 | 
			
		|||
#include "Polyline.hpp"
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
// polygon class of the polypartition library
 | 
			
		||||
class TPPLPoly;
 | 
			
		||||
 | 
			
		||||
namespace Slic3r {
 | 
			
		||||
 | 
			
		||||
class ExPolygon;
 | 
			
		||||
| 
						 | 
				
			
			@ -55,12 +58,13 @@ public:
 | 
			
		|||
    void simplify(double tolerance, ExPolygons* expolygons) const;
 | 
			
		||||
    void medial_axis(double max_width, double min_width, ThickPolylines* polylines) const;
 | 
			
		||||
    void medial_axis(double max_width, double min_width, Polylines* polylines) const;
 | 
			
		||||
    void get_trapezoids(Polygons* polygons) const;
 | 
			
		||||
    void get_trapezoids(Polygons* polygons, double angle) const;
 | 
			
		||||
//    void get_trapezoids(Polygons* polygons) const;
 | 
			
		||||
//    void get_trapezoids(Polygons* polygons, double angle) const;
 | 
			
		||||
    void get_trapezoids2(Polygons* polygons) const;
 | 
			
		||||
    void get_trapezoids2(Polygons* polygons, double angle) const;
 | 
			
		||||
    void triangulate(Polygons* polygons) const;
 | 
			
		||||
    void triangulate_pp(Polygons* polygons) const;
 | 
			
		||||
    // Triangulate into triples of points.
 | 
			
		||||
    void triangulate_pp(Points *triangles) const;
 | 
			
		||||
    void triangulate_p2t(Polygons* polygons) const;
 | 
			
		||||
    Lines lines() const;
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -297,6 +301,10 @@ extern std::vector<BoundingBox> get_extents_vector(const ExPolygons &polygons);
 | 
			
		|||
 | 
			
		||||
extern bool        remove_sticks(ExPolygon &poly);
 | 
			
		||||
 | 
			
		||||
extern std::list<TPPLPoly> expoly_to_polypartition_input(const ExPolygons &expp);
 | 
			
		||||
extern std::list<TPPLPoly> expoly_to_polypartition_input(const ExPolygon &ex);
 | 
			
		||||
extern std::vector<Point> polypartition_output_to_triangles(const std::list<TPPLPoly> &output);
 | 
			
		||||
 | 
			
		||||
} // namespace Slic3r
 | 
			
		||||
 | 
			
		||||
// start Boost
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,7 +41,7 @@
 | 
			
		|||
 | 
			
		||||
namespace Slic3r {
 | 
			
		||||
 | 
			
		||||
TriangleMesh::TriangleMesh(const Pointf3s &points, const std::vector<Vec3crd>& facets )
 | 
			
		||||
TriangleMesh::TriangleMesh(const Pointf3s &points, const std::vector<Vec3crd>& facets)
 | 
			
		||||
    : repaired(false)
 | 
			
		||||
{
 | 
			
		||||
    stl_initialize(&this->stl);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
 | 
			
		||||
 * http://code.google.com/p/poly2tri/
 | 
			
		||||
 * Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors
 | 
			
		||||
 * https://github.com/jhasse/poly2tri
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -29,10 +29,16 @@
 | 
			
		|||
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
#include "shapes.h"
 | 
			
		||||
 | 
			
		||||
#include <cassert>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
 | 
			
		||||
namespace p2t {
 | 
			
		||||
 | 
			
		||||
std::ostream& operator<<(std::ostream& out, const Point& point) {
 | 
			
		||||
  return out << point.x << "," << point.y;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Triangle::Triangle(Point& a, Point& b, Point& c)
 | 
			
		||||
{
 | 
			
		||||
  points_[0] = &a; points_[1] = &b; points_[2] = &c;
 | 
			
		||||
| 
						 | 
				
			
			@ -150,7 +156,7 @@ void Triangle::Legalize(Point& opoint, Point& npoint)
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Triangle::Index(const Point* p) const
 | 
			
		||||
int Triangle::Index(const Point* p)
 | 
			
		||||
{
 | 
			
		||||
  if (p == points_[0]) {
 | 
			
		||||
    return 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -163,7 +169,7 @@ int Triangle::Index(const Point* p) const
 | 
			
		|||
  return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Triangle::EdgeIndex(const Point* p1, const Point* p2) const
 | 
			
		||||
int Triangle::EdgeIndex(const Point* p1, const Point* p2)
 | 
			
		||||
{
 | 
			
		||||
  if (points_[0] == p1) {
 | 
			
		||||
    if (points_[1] == p2) {
 | 
			
		||||
| 
						 | 
				
			
			@ -259,7 +265,7 @@ Triangle* Triangle::NeighborCCW(const Point& point)
 | 
			
		|||
  return neighbors_[1];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Triangle::GetConstrainedEdgeCCW(const Point& p) const
 | 
			
		||||
bool Triangle::GetConstrainedEdgeCCW(const Point& p)
 | 
			
		||||
{
 | 
			
		||||
  if (&p == points_[0]) {
 | 
			
		||||
    return constrained_edge[2];
 | 
			
		||||
| 
						 | 
				
			
			@ -269,7 +275,7 @@ bool Triangle::GetConstrainedEdgeCCW(const Point& p) const
 | 
			
		|||
  return constrained_edge[1];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Triangle::GetConstrainedEdgeCW(const Point& p) const
 | 
			
		||||
bool Triangle::GetConstrainedEdgeCW(const Point& p)
 | 
			
		||||
{
 | 
			
		||||
  if (&p == points_[0]) {
 | 
			
		||||
    return constrained_edge[1];
 | 
			
		||||
| 
						 | 
				
			
			@ -301,7 +307,7 @@ void Triangle::SetConstrainedEdgeCW(const Point& p, bool ce)
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Triangle::GetDelunayEdgeCCW(const Point& p) const
 | 
			
		||||
bool Triangle::GetDelunayEdgeCCW(const Point& p)
 | 
			
		||||
{
 | 
			
		||||
  if (&p == points_[0]) {
 | 
			
		||||
    return delaunay_edge[2];
 | 
			
		||||
| 
						 | 
				
			
			@ -311,7 +317,7 @@ bool Triangle::GetDelunayEdgeCCW(const Point& p) const
 | 
			
		|||
  return delaunay_edge[1];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Triangle::GetDelunayEdgeCW(const Point& p) const
 | 
			
		||||
bool Triangle::GetDelunayEdgeCW(const Point& p)
 | 
			
		||||
{
 | 
			
		||||
  if (&p == points_[0]) {
 | 
			
		||||
    return delaunay_edge[1];
 | 
			
		||||
| 
						 | 
				
			
			@ -356,10 +362,7 @@ Triangle& Triangle::NeighborAcross(const Point& opoint)
 | 
			
		|||
 | 
			
		||||
void Triangle::DebugPrint()
 | 
			
		||||
{
 | 
			
		||||
  using namespace std;
 | 
			
		||||
  cout << points_[0]->x << "," << points_[0]->y << " ";
 | 
			
		||||
  cout << points_[1]->x << "," << points_[1]->y << " ";
 | 
			
		||||
  cout << points_[2]->x << "," << points_[2]->y << endl;
 | 
			
		||||
  std::cout << *points_[0] << " " << *points_[1] << " " << *points_[2] << std::endl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
 | 
			
		||||
 * http://code.google.com/p/poly2tri/
 | 
			
		||||
 * Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors
 | 
			
		||||
 * https://github.com/jhasse/poly2tri
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -33,10 +33,10 @@
 | 
			
		|||
#ifndef SHAPES_H
 | 
			
		||||
#define SHAPES_H
 | 
			
		||||
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <cmath>
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
namespace p2t {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -119,6 +119,8 @@ struct Point {
 | 
			
		|||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::ostream& operator<<(std::ostream&, const Point&);
 | 
			
		||||
 | 
			
		||||
// Represents a simple polygon's edge
 | 
			
		||||
struct Edge {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -130,13 +132,13 @@ struct Edge {
 | 
			
		|||
    if (p1.y > p2.y) {
 | 
			
		||||
      q = &p1;
 | 
			
		||||
      p = &p2;
 | 
			
		||||
    } else if (p1.y == p2.y) {
 | 
			
		||||
    } else if (std::abs(p1.y - p2.y) < 1e-10) {
 | 
			
		||||
      if (p1.x > p2.x) {
 | 
			
		||||
        q = &p1;
 | 
			
		||||
        p = &p2;
 | 
			
		||||
      } else if (p1.x == p2.x) {
 | 
			
		||||
      } else if (std::abs(p1.x - p2.x) < 1e-10) {
 | 
			
		||||
        // Repeat points
 | 
			
		||||
        assert(false);
 | 
			
		||||
        throw std::runtime_error("Edge::Edge: p1 == p2");
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -171,23 +173,23 @@ void MarkConstrainedEdge(int index);
 | 
			
		|||
void MarkConstrainedEdge(Edge& edge);
 | 
			
		||||
void MarkConstrainedEdge(Point* p, Point* q);
 | 
			
		||||
 | 
			
		||||
int Index(const Point* p) const;
 | 
			
		||||
int EdgeIndex(const Point* p1, const Point* p2) const;
 | 
			
		||||
int Index(const Point* p);
 | 
			
		||||
int EdgeIndex(const Point* p1, const Point* p2);
 | 
			
		||||
 | 
			
		||||
Triangle* NeighborCW(const Point& point);
 | 
			
		||||
Triangle* NeighborCCW(const Point& point);
 | 
			
		||||
bool GetConstrainedEdgeCCW(const Point& p) const;
 | 
			
		||||
bool GetConstrainedEdgeCW(const Point& p) const;
 | 
			
		||||
bool GetConstrainedEdgeCCW(const Point& p);
 | 
			
		||||
bool GetConstrainedEdgeCW(const Point& p);
 | 
			
		||||
void SetConstrainedEdgeCCW(const Point& p, bool ce);
 | 
			
		||||
void SetConstrainedEdgeCW(const Point& p, bool ce);
 | 
			
		||||
bool GetDelunayEdgeCCW(const Point& p) const;
 | 
			
		||||
bool GetDelunayEdgeCW(const Point& p) const;
 | 
			
		||||
bool GetDelunayEdgeCCW(const Point& p);
 | 
			
		||||
bool GetDelunayEdgeCW(const Point& p);
 | 
			
		||||
void SetDelunayEdgeCCW(const Point& p, bool e);
 | 
			
		||||
void SetDelunayEdgeCW(const Point& p, bool e);
 | 
			
		||||
 | 
			
		||||
bool Contains(const Point* p) const;
 | 
			
		||||
bool Contains(const Edge& e) const;
 | 
			
		||||
bool Contains(const Point* p, const Point* q) const;
 | 
			
		||||
bool Contains(const Point* p);
 | 
			
		||||
bool Contains(const Edge& e);
 | 
			
		||||
bool Contains(const Point* p, const Point* q);
 | 
			
		||||
void Legalize(Point& point);
 | 
			
		||||
void Legalize(Point& opoint, Point& npoint);
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -198,7 +200,7 @@ void ClearNeighbor(const Triangle *triangle);
 | 
			
		|||
void ClearNeighbors();
 | 
			
		||||
void ClearDelunayEdges();
 | 
			
		||||
 | 
			
		||||
inline bool IsInterior() const;
 | 
			
		||||
inline bool IsInterior();
 | 
			
		||||
inline void IsInterior(bool b);
 | 
			
		||||
 | 
			
		||||
Triangle& NeighborAcross(const Point& opoint);
 | 
			
		||||
| 
						 | 
				
			
			@ -293,22 +295,22 @@ inline Triangle* Triangle::GetNeighbor(int index)
 | 
			
		|||
  return neighbors_[index];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline bool Triangle::Contains(const Point* p) const
 | 
			
		||||
inline bool Triangle::Contains(const Point* p)
 | 
			
		||||
{
 | 
			
		||||
  return p == points_[0] || p == points_[1] || p == points_[2];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline bool Triangle::Contains(const Edge& e) const
 | 
			
		||||
inline bool Triangle::Contains(const Edge& e)
 | 
			
		||||
{
 | 
			
		||||
  return Contains(e.p) && Contains(e.q);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline bool Triangle::Contains(const Point* p, const Point* q) const
 | 
			
		||||
inline bool Triangle::Contains(const Point* p, const Point* q)
 | 
			
		||||
{
 | 
			
		||||
  return Contains(p) && Contains(q);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline bool Triangle::IsInterior() const
 | 
			
		||||
inline bool Triangle::IsInterior()
 | 
			
		||||
{
 | 
			
		||||
  return interior_;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -320,4 +322,4 @@ inline void Triangle::IsInterior(bool b)
 | 
			
		|||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
 | 
			
		||||
 * http://code.google.com/p/poly2tri/
 | 
			
		||||
 * Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors
 | 
			
		||||
 * https://github.com/jhasse/poly2tri
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -34,11 +34,18 @@
 | 
			
		|||
 | 
			
		||||
// Otherwise #defines like M_PI are undeclared under Visual Studio
 | 
			
		||||
#ifndef _USE_MATH_DEFINES
 | 
			
		||||
  #define _USE_MATH_DEFINES
 | 
			
		||||
	#define _USE_MATH_DEFINES
 | 
			
		||||
#endif /* _USE_MATH_DEFINES */
 | 
			
		||||
 | 
			
		||||
#include "shapes.h"
 | 
			
		||||
 | 
			
		||||
#include <cmath>
 | 
			
		||||
#include <exception>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
 | 
			
		||||
// C99 removes M_PI from math.h
 | 
			
		||||
#ifndef M_PI
 | 
			
		||||
#define M_PI 3.14159265358979323846264338327
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace p2t {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -121,4 +128,4 @@ bool InScanArea(const Point& pa, const Point& pb, const Point& pc, const Point&
 | 
			
		|||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
 | 
			
		||||
 * http://code.google.com/p/poly2tri/
 | 
			
		||||
 * Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors
 | 
			
		||||
 * https://github.com/jhasse/poly2tri
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -35,4 +35,4 @@
 | 
			
		|||
#include "common/shapes.h"
 | 
			
		||||
#include "sweep/cdt.h"
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
 | 
			
		||||
 * http://code.google.com/p/poly2tri/
 | 
			
		||||
 * Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors
 | 
			
		||||
 * https://github.com/jhasse/poly2tri
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -30,6 +30,8 @@
 | 
			
		|||
 */
 | 
			
		||||
#include "advancing_front.h"
 | 
			
		||||
 | 
			
		||||
#include <cassert>
 | 
			
		||||
 | 
			
		||||
namespace p2t {
 | 
			
		||||
 | 
			
		||||
AdvancingFront::AdvancingFront(Node& head, Node& tail)
 | 
			
		||||
| 
						 | 
				
			
			@ -105,4 +107,4 @@ AdvancingFront::~AdvancingFront()
 | 
			
		|||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
 | 
			
		||||
 * http://code.google.com/p/poly2tri/
 | 
			
		||||
 * Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors
 | 
			
		||||
 * https://github.com/jhasse/poly2tri
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -115,4 +115,4 @@ inline void AdvancingFront::set_search(Node* node)
 | 
			
		|||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
 | 
			
		||||
 * http://code.google.com/p/poly2tri/
 | 
			
		||||
 * Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors
 | 
			
		||||
 * https://github.com/jhasse/poly2tri
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -68,4 +68,4 @@ CDT::~CDT()
 | 
			
		|||
  delete sweep_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
 | 
			
		||||
 * http://code.google.com/p/poly2tri/
 | 
			
		||||
 * Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors
 | 
			
		||||
 * https://github.com/jhasse/poly2tri
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -102,4 +102,4 @@ public:
 | 
			
		|||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
 | 
			
		||||
 * http://code.google.com/p/poly2tri/
 | 
			
		||||
 * Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors
 | 
			
		||||
 * https://github.com/jhasse/poly2tri
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -28,19 +28,21 @@
 | 
			
		|||
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
			
		||||
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
#include "sweep.h"
 | 
			
		||||
#include "sweep_context.h"
 | 
			
		||||
#include "advancing_front.h"
 | 
			
		||||
#include "../common/utils.h"
 | 
			
		||||
 | 
			
		||||
#include <cassert>
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
 | 
			
		||||
namespace p2t {
 | 
			
		||||
 | 
			
		||||
// Triangulate simple polygon with holes
 | 
			
		||||
void Sweep::Triangulate(SweepContext& tcx)
 | 
			
		||||
{
 | 
			
		||||
  tcx.InitTriangulation();
 | 
			
		||||
  tcx.CreateAdvancingFront(nodes_);
 | 
			
		||||
  tcx.CreateAdvancingFront();
 | 
			
		||||
  // Sweep points; build mesh
 | 
			
		||||
  SweepPoints(tcx);
 | 
			
		||||
  // Clean up
 | 
			
		||||
| 
						 | 
				
			
			@ -699,13 +701,6 @@ void Sweep::FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* t,
 | 
			
		|||
  Triangle& ot = t->NeighborAcross(p);
 | 
			
		||||
  Point& op = *ot.OppositePoint(*t, p);
 | 
			
		||||
 | 
			
		||||
  if (&ot == NULL) {
 | 
			
		||||
    // If we want to integrate the fillEdgeEvent do it here
 | 
			
		||||
    // With current implementation we should never get here
 | 
			
		||||
    //throw new RuntimeException( "[BUG:FIXME] FLIP failed due to missing triangle");
 | 
			
		||||
    assert(0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (InScanArea(p, *t->PointCCW(p), *t->PointCW(p), op)) {
 | 
			
		||||
    // Lets rotate shared edge one vertex CW
 | 
			
		||||
    RotateTrianglePair(*t, p, ot, op);
 | 
			
		||||
| 
						 | 
				
			
			@ -772,13 +767,6 @@ void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle&
 | 
			
		|||
  Triangle& ot = t.NeighborAcross(p);
 | 
			
		||||
  Point& op = *ot.OppositePoint(t, p);
 | 
			
		||||
 | 
			
		||||
  if (&t.NeighborAcross(p) == NULL) {
 | 
			
		||||
    // If we want to integrate the fillEdgeEvent do it here
 | 
			
		||||
    // With current implementation we should never get here
 | 
			
		||||
    //throw new RuntimeException( "[BUG:FIXME] FLIP failed due to missing triangle");
 | 
			
		||||
    assert(0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (InScanArea(eq, *flip_triangle.PointCCW(eq), *flip_triangle.PointCW(eq), op)) {
 | 
			
		||||
    // flip with new edge op->eq
 | 
			
		||||
    FlipEdgeEvent(tcx, eq, op, &ot, op);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
 | 
			
		||||
 * http://code.google.com/p/poly2tri/
 | 
			
		||||
 * Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors
 | 
			
		||||
 * https://github.com/jhasse/poly2tri
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -282,4 +282,4 @@ private:
 | 
			
		|||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
 | 
			
		||||
 * http://code.google.com/p/poly2tri/
 | 
			
		||||
 * Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors
 | 
			
		||||
 * https://github.com/jhasse/poly2tri
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -120,10 +120,9 @@ Node& SweepContext::LocateNode(const Point& point)
 | 
			
		|||
  return *front_->LocateNode(point.x);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SweepContext::CreateAdvancingFront(const std::vector<Node*>& nodes)
 | 
			
		||||
void SweepContext::CreateAdvancingFront()
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
  (void) nodes;
 | 
			
		||||
  // Initial triangle
 | 
			
		||||
  Triangle* triangle = new Triangle(*points_[0], *tail_, *head_);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -169,8 +168,8 @@ void SweepContext::MeshClean(Triangle& triangle)
 | 
			
		|||
  triangles.push_back(&triangle);
 | 
			
		||||
 | 
			
		||||
  while(!triangles.empty()){
 | 
			
		||||
	Triangle *t = triangles.back();
 | 
			
		||||
	triangles.pop_back();
 | 
			
		||||
  Triangle *t = triangles.back();
 | 
			
		||||
  triangles.pop_back();
 | 
			
		||||
 | 
			
		||||
    if (t != NULL && !t->IsInterior()) {
 | 
			
		||||
      t->IsInterior(true);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
 | 
			
		||||
 * http://code.google.com/p/poly2tri/
 | 
			
		||||
 * Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors
 | 
			
		||||
 * https://github.com/jhasse/poly2tri
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -70,7 +70,7 @@ Node& LocateNode(const Point& point);
 | 
			
		|||
 | 
			
		||||
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
 | 
			
		||||
void MapTriangleToNodes(Triangle& t);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,6 +25,8 @@
 | 
			
		|||
#include <list>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <set>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
 | 
			
		||||
using namespace std;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -66,21 +68,26 @@ void TPPLPoly::Triangle(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3) {
 | 
			
		|||
	points[2] = p3;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TPPLPoly::TPPLPoly(const TPPLPoly &src) {
 | 
			
		||||
TPPLPoly::TPPLPoly(const TPPLPoly &src) : TPPLPoly() {
 | 
			
		||||
	hole = src.hole;
 | 
			
		||||
	numpoints = src.numpoints;
 | 
			
		||||
	points = new TPPLPoint[numpoints];
 | 
			
		||||
	memcpy(points, src.points, numpoints*sizeof(TPPLPoint));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TPPLPoly& TPPLPoly::operator=(const TPPLPoly &src) {
 | 
			
		||||
	if(&src != this) {
 | 
			
		||||
		Clear();
 | 
			
		||||
		hole = src.hole;
 | 
			
		||||
		numpoints = src.numpoints;
 | 
			
		||||
	if(numpoints > 0) {
 | 
			
		||||
		points = new TPPLPoint[numpoints];
 | 
			
		||||
		memcpy(points, src.points, numpoints*sizeof(TPPLPoint));
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TPPLPoly& TPPLPoly::operator=(const TPPLPoly &src) {
 | 
			
		||||
	Clear();
 | 
			
		||||
	hole = src.hole;
 | 
			
		||||
	numpoints = src.numpoints;
 | 
			
		||||
	
 | 
			
		||||
	if(numpoints > 0) {
 | 
			
		||||
		points = new TPPLPoint[numpoints];
 | 
			
		||||
		memcpy(points, src.points, numpoints*sizeof(TPPLPoint));
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	return *this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -105,16 +112,11 @@ void TPPLPoly::SetOrientation(int orientation) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void TPPLPoly::Invert() {
 | 
			
		||||
	long i;
 | 
			
		||||
	TPPLPoint *invpoints;
 | 
			
		||||
	std::reverse(points, points + numpoints);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	invpoints = new TPPLPoint[numpoints];
 | 
			
		||||
	for(i=0;i<numpoints;i++) {
 | 
			
		||||
		invpoints[i] = points[numpoints-i-1];
 | 
			
		||||
	}
 | 
			
		||||
TPPLPartition::PartitionVertex::PartitionVertex() : previous(NULL), next(NULL) {
 | 
			
		||||
 | 
			
		||||
	delete [] points;
 | 
			
		||||
	points = invpoints;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TPPLPoint TPPLPartition::Normalize(const TPPLPoint &p) {
 | 
			
		||||
| 
						 | 
				
			
			@ -169,10 +171,10 @@ int TPPLPartition::Intersects(TPPLPoint &p11, TPPLPoint &p12, TPPLPoint &p21, TP
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
//removes holes from inpolys by merging them with non-holes
 | 
			
		||||
int TPPLPartition::RemoveHoles(list<TPPLPoly> *inpolys, list<TPPLPoly> *outpolys) {
 | 
			
		||||
	list<TPPLPoly> polys;
 | 
			
		||||
	list<TPPLPoly>::iterator holeiter,polyiter,iter,iter2;
 | 
			
		||||
	long i,i2,holepointindex,polypointindex = 0;
 | 
			
		||||
int TPPLPartition::RemoveHoles(TPPLPolyList *inpolys, TPPLPolyList *outpolys) {
 | 
			
		||||
	TPPLPolyList polys;
 | 
			
		||||
	TPPLPolyList::iterator holeiter,polyiter,iter,iter2;
 | 
			
		||||
	long i,i2,holepointindex,polypointindex;
 | 
			
		||||
	TPPLPoint holepoint,polypoint,bestpolypoint;
 | 
			
		||||
	TPPLPoint linep1,linep2;
 | 
			
		||||
	TPPLPoint v1,v2;
 | 
			
		||||
| 
						 | 
				
			
			@ -183,14 +185,14 @@ int TPPLPartition::RemoveHoles(list<TPPLPoly> *inpolys, list<TPPLPoly> *outpolys
 | 
			
		|||
	
 | 
			
		||||
	//check for trivial case (no holes)
 | 
			
		||||
	hasholes = false;
 | 
			
		||||
	for(iter = inpolys->begin(); iter!=inpolys->end(); ++iter) {
 | 
			
		||||
	for(iter = inpolys->begin(); iter!=inpolys->end(); iter++) {
 | 
			
		||||
		if(iter->IsHole()) {
 | 
			
		||||
			hasholes = true;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if(!hasholes) {
 | 
			
		||||
		for(iter = inpolys->begin(); iter!=inpolys->end(); ++iter) {
 | 
			
		||||
		for(iter = inpolys->begin(); iter!=inpolys->end(); iter++) {
 | 
			
		||||
			outpolys->push_back(*iter);
 | 
			
		||||
		}
 | 
			
		||||
		return 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -201,7 +203,7 @@ int TPPLPartition::RemoveHoles(list<TPPLPoly> *inpolys, list<TPPLPoly> *outpolys
 | 
			
		|||
	while(1) {
 | 
			
		||||
		//find the hole point with the largest x
 | 
			
		||||
		hasholes = false;
 | 
			
		||||
		for(iter = polys.begin(); iter!=polys.end(); ++iter) {
 | 
			
		||||
		for(iter = polys.begin(); iter!=polys.end(); iter++) {
 | 
			
		||||
			if(!iter->IsHole()) continue;
 | 
			
		||||
 | 
			
		||||
			if(!hasholes) {
 | 
			
		||||
| 
						 | 
				
			
			@ -221,7 +223,7 @@ int TPPLPartition::RemoveHoles(list<TPPLPoly> *inpolys, list<TPPLPoly> *outpolys
 | 
			
		|||
		holepoint = holeiter->GetPoint(holepointindex);
 | 
			
		||||
		
 | 
			
		||||
		pointfound = false;
 | 
			
		||||
		for(iter = polys.begin(); iter!=polys.end(); ++iter) {
 | 
			
		||||
		for(iter = polys.begin(); iter!=polys.end(); iter++) {
 | 
			
		||||
			if(iter->IsHole()) continue;
 | 
			
		||||
			for(i=0; i < iter->GetNumPoints(); i++) {
 | 
			
		||||
				if(iter->GetPoint(i).x <= holepoint.x) continue;
 | 
			
		||||
| 
						 | 
				
			
			@ -237,7 +239,7 @@ int TPPLPartition::RemoveHoles(list<TPPLPoly> *inpolys, list<TPPLPoly> *outpolys
 | 
			
		|||
					if(v2.x > v1.x) continue;				
 | 
			
		||||
				}
 | 
			
		||||
				pointvisible = true;
 | 
			
		||||
				for(iter2 = polys.begin(); iter2!=polys.end(); ++iter2) {
 | 
			
		||||
				for(iter2 = polys.begin(); iter2!=polys.end(); iter2++) {
 | 
			
		||||
					if(iter2->IsHole()) continue;
 | 
			
		||||
					for(i2=0; i2 < iter2->GetNumPoints(); i2++) {
 | 
			
		||||
						linep1 = iter2->GetPoint(i2);
 | 
			
		||||
| 
						 | 
				
			
			@ -280,7 +282,7 @@ int TPPLPartition::RemoveHoles(list<TPPLPoly> *inpolys, list<TPPLPoly> *outpolys
 | 
			
		|||
		polys.push_back(newpoly);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for(iter = polys.begin(); iter!=polys.end(); ++iter) {
 | 
			
		||||
	for(iter = polys.begin(); iter!=polys.end(); iter++) {
 | 
			
		||||
		outpolys->push_back(*iter);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
| 
						 | 
				
			
			@ -335,7 +337,7 @@ bool TPPLPartition::InCone(PartitionVertex *v, TPPLPoint &p) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void TPPLPartition::UpdateVertexReflexity(PartitionVertex *v) {
 | 
			
		||||
	PartitionVertex *v1,*v3;
 | 
			
		||||
	PartitionVertex *v1 = NULL,*v3 = NULL;
 | 
			
		||||
	v1 = v->previous;
 | 
			
		||||
	v3 = v->next;
 | 
			
		||||
	v->isConvex = !IsReflex(v1->p,v->p,v3->p);	
 | 
			
		||||
| 
						 | 
				
			
			@ -343,7 +345,7 @@ void TPPLPartition::UpdateVertexReflexity(PartitionVertex *v) {
 | 
			
		|||
 | 
			
		||||
void TPPLPartition::UpdateVertex(PartitionVertex *v, PartitionVertex *vertices, long numvertices) {
 | 
			
		||||
	long i;
 | 
			
		||||
	PartitionVertex *v1,*v3;
 | 
			
		||||
	PartitionVertex *v1 = NULL,*v3 = NULL;
 | 
			
		||||
	TPPLPoint vec1,vec3;
 | 
			
		||||
 | 
			
		||||
	v1 = v->previous;
 | 
			
		||||
| 
						 | 
				
			
			@ -372,10 +374,12 @@ void TPPLPartition::UpdateVertex(PartitionVertex *v, PartitionVertex *vertices,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
//triangulation by ear removal
 | 
			
		||||
int TPPLPartition::Triangulate_EC(TPPLPoly *poly, list<TPPLPoly> *triangles) {
 | 
			
		||||
int TPPLPartition::Triangulate_EC(TPPLPoly *poly, TPPLPolyList *triangles) {
 | 
			
		||||
	if(!poly->Valid()) return 0;
 | 
			
		||||
 | 
			
		||||
	long numvertices;
 | 
			
		||||
	PartitionVertex *vertices;
 | 
			
		||||
	PartitionVertex *ear;
 | 
			
		||||
	PartitionVertex *vertices = NULL;
 | 
			
		||||
	PartitionVertex *ear = NULL;
 | 
			
		||||
	TPPLPoly triangle;
 | 
			
		||||
	long i,j;
 | 
			
		||||
	bool earfound;
 | 
			
		||||
| 
						 | 
				
			
			@ -446,21 +450,23 @@ int TPPLPartition::Triangulate_EC(TPPLPoly *poly, list<TPPLPoly> *triangles) {
 | 
			
		|||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int TPPLPartition::Triangulate_EC(list<TPPLPoly> *inpolys, list<TPPLPoly> *triangles) {
 | 
			
		||||
	list<TPPLPoly> outpolys;
 | 
			
		||||
	list<TPPLPoly>::iterator iter;
 | 
			
		||||
int TPPLPartition::Triangulate_EC(TPPLPolyList *inpolys, TPPLPolyList *triangles) {
 | 
			
		||||
	TPPLPolyList outpolys;
 | 
			
		||||
	TPPLPolyList::iterator iter;
 | 
			
		||||
	
 | 
			
		||||
	if(!RemoveHoles(inpolys,&outpolys)) return 0;
 | 
			
		||||
	for(iter=outpolys.begin();iter!=outpolys.end();++iter) {
 | 
			
		||||
	for(iter=outpolys.begin();iter!=outpolys.end();iter++) {
 | 
			
		||||
		if(!Triangulate_EC(&(*iter),triangles)) return 0;
 | 
			
		||||
	}
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int TPPLPartition::ConvexPartition_HM(TPPLPoly *poly, list<TPPLPoly> *parts) {
 | 
			
		||||
	list<TPPLPoly> triangles;
 | 
			
		||||
	list<TPPLPoly>::iterator iter1,iter2;
 | 
			
		||||
	TPPLPoly *poly1,*poly2;
 | 
			
		||||
int TPPLPartition::ConvexPartition_HM(TPPLPoly *poly, TPPLPolyList *parts) {
 | 
			
		||||
	if(!poly->Valid()) return 0;
 | 
			
		||||
	
 | 
			
		||||
	TPPLPolyList triangles;
 | 
			
		||||
	TPPLPolyList::iterator iter1,iter2;
 | 
			
		||||
	TPPLPoly *poly1 = NULL,*poly2 = NULL;
 | 
			
		||||
	TPPLPoly newpoly;
 | 
			
		||||
	TPPLPoint d1,d2,p1,p2,p3;
 | 
			
		||||
	long i11,i12,i21,i22,i13,i23,j,k;
 | 
			
		||||
| 
						 | 
				
			
			@ -486,7 +492,7 @@ int TPPLPartition::ConvexPartition_HM(TPPLPoly *poly, list<TPPLPoly> *parts) {
 | 
			
		|||
 | 
			
		||||
	if(!Triangulate_EC(poly,&triangles)) return 0;
 | 
			
		||||
 | 
			
		||||
	for(iter1 = triangles.begin(); iter1 != triangles.end(); ++iter1) {
 | 
			
		||||
	for(iter1 = triangles.begin(); iter1 != triangles.end(); iter1++) {
 | 
			
		||||
		poly1 = &(*iter1);
 | 
			
		||||
		for(i11=0;i11<poly1->GetNumPoints();i11++) {
 | 
			
		||||
			d1 = poly1->GetPoint(i11);
 | 
			
		||||
| 
						 | 
				
			
			@ -494,7 +500,7 @@ int TPPLPartition::ConvexPartition_HM(TPPLPoly *poly, list<TPPLPoly> *parts) {
 | 
			
		|||
			d2 = poly1->GetPoint(i12);
 | 
			
		||||
 | 
			
		||||
			isdiagonal = false;
 | 
			
		||||
			for(iter2 = iter1; iter2 != triangles.end(); ++iter2) {
 | 
			
		||||
			for(iter2 = iter1; iter2 != triangles.end(); iter2++) {
 | 
			
		||||
				if(iter1 == iter2) continue;
 | 
			
		||||
				poly2 = &(*iter2);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -550,19 +556,19 @@ int TPPLPartition::ConvexPartition_HM(TPPLPoly *poly, list<TPPLPoly> *parts) {
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for(iter1 = triangles.begin(); iter1 != triangles.end(); ++iter1) {
 | 
			
		||||
	for(iter1 = triangles.begin(); iter1 != triangles.end(); iter1++) {
 | 
			
		||||
		parts->push_back(*iter1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int TPPLPartition::ConvexPartition_HM(list<TPPLPoly> *inpolys, list<TPPLPoly> *parts) {
 | 
			
		||||
	list<TPPLPoly> outpolys;
 | 
			
		||||
	list<TPPLPoly>::iterator iter;
 | 
			
		||||
int TPPLPartition::ConvexPartition_HM(TPPLPolyList *inpolys, TPPLPolyList *parts) {
 | 
			
		||||
	TPPLPolyList outpolys;
 | 
			
		||||
	TPPLPolyList::iterator iter;
 | 
			
		||||
	
 | 
			
		||||
	if(!RemoveHoles(inpolys,&outpolys)) return 0;
 | 
			
		||||
	for(iter=outpolys.begin();iter!=outpolys.end();++iter) {
 | 
			
		||||
	for(iter=outpolys.begin();iter!=outpolys.end();iter++) {
 | 
			
		||||
		if(!ConvexPartition_HM(&(*iter),parts)) return 0;
 | 
			
		||||
	}
 | 
			
		||||
	return 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -571,14 +577,16 @@ int TPPLPartition::ConvexPartition_HM(list<TPPLPoly> *inpolys, list<TPPLPoly> *p
 | 
			
		|||
//minimum-weight polygon triangulation by dynamic programming
 | 
			
		||||
//O(n^3) time complexity
 | 
			
		||||
//O(n^2) space complexity
 | 
			
		||||
int TPPLPartition::Triangulate_OPT(TPPLPoly *poly, list<TPPLPoly> *triangles) {
 | 
			
		||||
int TPPLPartition::Triangulate_OPT(TPPLPoly *poly, TPPLPolyList *triangles) {
 | 
			
		||||
	if(!poly->Valid()) return 0;
 | 
			
		||||
 | 
			
		||||
	long i,j,k,gap,n;
 | 
			
		||||
	DPState **dpstates;
 | 
			
		||||
	DPState **dpstates = NULL;
 | 
			
		||||
	TPPLPoint p1,p2,p3,p4;
 | 
			
		||||
	long bestvertex;
 | 
			
		||||
	tppl_float weight,minweight,d1,d2;
 | 
			
		||||
	Diagonal diagonal,newdiagonal;
 | 
			
		||||
	list<Diagonal> diagonals;
 | 
			
		||||
	DiagonalList diagonals;
 | 
			
		||||
	TPPLPoly triangle;
 | 
			
		||||
	int ret = 1;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -703,7 +711,7 @@ int TPPLPartition::Triangulate_OPT(TPPLPoly *poly, list<TPPLPoly> *triangles) {
 | 
			
		|||
 | 
			
		||||
void TPPLPartition::UpdateState(long a, long b, long w, long i, long j, DPState2 **dpstates) {
 | 
			
		||||
	Diagonal newdiagonal;
 | 
			
		||||
	list<Diagonal> *pairs;
 | 
			
		||||
	DiagonalList *pairs = NULL;
 | 
			
		||||
	long w2;
 | 
			
		||||
 | 
			
		||||
	w2 = dpstates[a][b].weight;
 | 
			
		||||
| 
						 | 
				
			
			@ -725,8 +733,8 @@ void TPPLPartition::UpdateState(long a, long b, long w, long i, long j, DPState2
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void TPPLPartition::TypeA(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates) {
 | 
			
		||||
	list<Diagonal> *pairs;
 | 
			
		||||
	list<Diagonal>::iterator iter,lastiter;
 | 
			
		||||
	DiagonalList *pairs = NULL;
 | 
			
		||||
	DiagonalList::iterator iter,lastiter;
 | 
			
		||||
	long top;
 | 
			
		||||
	long w;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -742,7 +750,7 @@ void TPPLPartition::TypeA(long i, long j, long k, PartitionVertex *vertices, DPS
 | 
			
		|||
		iter = pairs->end();
 | 
			
		||||
		lastiter = pairs->end();
 | 
			
		||||
		while(iter!=pairs->begin()) {
 | 
			
		||||
			--iter;
 | 
			
		||||
			iter--;
 | 
			
		||||
			if(!IsReflex(vertices[iter->index2].p,vertices[j].p,vertices[k].p)) lastiter = iter;
 | 
			
		||||
			else break;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -756,8 +764,8 @@ void TPPLPartition::TypeA(long i, long j, long k, PartitionVertex *vertices, DPS
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void TPPLPartition::TypeB(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates) {
 | 
			
		||||
	list<Diagonal> *pairs;
 | 
			
		||||
	list<Diagonal>::iterator iter,lastiter;
 | 
			
		||||
	DiagonalList *pairs = NULL;
 | 
			
		||||
	DiagonalList::iterator iter,lastiter;
 | 
			
		||||
	long top;
 | 
			
		||||
	long w;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -778,7 +786,7 @@ void TPPLPartition::TypeB(long i, long j, long k, PartitionVertex *vertices, DPS
 | 
			
		|||
			while(iter!=pairs->end()) {
 | 
			
		||||
				if(!IsReflex(vertices[i].p,vertices[j].p,vertices[iter->index1].p)) {
 | 
			
		||||
					lastiter = iter;
 | 
			
		||||
					++iter;
 | 
			
		||||
					iter++;
 | 
			
		||||
				}
 | 
			
		||||
				else break;
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -789,19 +797,21 @@ void TPPLPartition::TypeB(long i, long j, long k, PartitionVertex *vertices, DPS
 | 
			
		|||
	UpdateState(i,k,w,j,top,dpstates);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int TPPLPartition::ConvexPartition_OPT(TPPLPoly *poly, list<TPPLPoly> *parts) {
 | 
			
		||||
int TPPLPartition::ConvexPartition_OPT(TPPLPoly *poly, TPPLPolyList *parts) {
 | 
			
		||||
	if(!poly->Valid()) return 0;
 | 
			
		||||
 | 
			
		||||
	TPPLPoint p1,p2,p3,p4;
 | 
			
		||||
	PartitionVertex *vertices;
 | 
			
		||||
	DPState2 **dpstates;
 | 
			
		||||
	PartitionVertex *vertices = NULL;
 | 
			
		||||
	DPState2 **dpstates = NULL;
 | 
			
		||||
	long i,j,k,n,gap;
 | 
			
		||||
	list<Diagonal> diagonals,diagonals2;
 | 
			
		||||
	DiagonalList diagonals,diagonals2;
 | 
			
		||||
	Diagonal diagonal,newdiagonal;
 | 
			
		||||
	list<Diagonal> *pairs,*pairs2;
 | 
			
		||||
	list<Diagonal>::iterator iter,iter2;
 | 
			
		||||
	DiagonalList *pairs = NULL,*pairs2 = NULL;
 | 
			
		||||
	DiagonalList::iterator iter,iter2;
 | 
			
		||||
	int ret;
 | 
			
		||||
	TPPLPoly newpoly;
 | 
			
		||||
	list<long> indices;
 | 
			
		||||
	list<long>::iterator iiter;
 | 
			
		||||
	vector<long> indices;
 | 
			
		||||
	vector<long>::iterator iiter;
 | 
			
		||||
	bool ijreal,jkreal;
 | 
			
		||||
 | 
			
		||||
	n = poly->GetNumPoints();
 | 
			
		||||
| 
						 | 
				
			
			@ -919,7 +929,7 @@ int TPPLPartition::ConvexPartition_OPT(TPPLPoly *poly, list<TPPLPoly> *parts) {
 | 
			
		|||
		}
 | 
			
		||||
		if(!vertices[diagonal.index1].isConvex) {
 | 
			
		||||
			iter = pairs->end();
 | 
			
		||||
			--iter;
 | 
			
		||||
			iter--;
 | 
			
		||||
			j = iter->index2;
 | 
			
		||||
			newdiagonal.index1 = j;
 | 
			
		||||
			newdiagonal.index2 = diagonal.index2;
 | 
			
		||||
| 
						 | 
				
			
			@ -933,7 +943,7 @@ int TPPLPartition::ConvexPartition_OPT(TPPLPoly *poly, list<TPPLPoly> *parts) {
 | 
			
		|||
							break;
 | 
			
		||||
						}
 | 
			
		||||
						iter2 = pairs2->end();
 | 
			
		||||
						--iter2;
 | 
			
		||||
						iter2--;
 | 
			
		||||
						if(iter->index1 != iter2->index1) pairs2->pop_back();
 | 
			
		||||
						else break;
 | 
			
		||||
					}
 | 
			
		||||
| 
						 | 
				
			
			@ -1003,7 +1013,7 @@ int TPPLPartition::ConvexPartition_OPT(TPPLPoly *poly, list<TPPLPoly> *parts) {
 | 
			
		|||
			pairs = &(dpstates[diagonal.index1][diagonal.index2].pairs);
 | 
			
		||||
			if(!vertices[diagonal.index1].isConvex) {
 | 
			
		||||
				iter = pairs->end();
 | 
			
		||||
				--iter;
 | 
			
		||||
				iter--;
 | 
			
		||||
				j = iter->index2;
 | 
			
		||||
				if(iter->index1 != iter->index2) ijreal = false;
 | 
			
		||||
			} else {
 | 
			
		||||
| 
						 | 
				
			
			@ -1031,10 +1041,10 @@ int TPPLPartition::ConvexPartition_OPT(TPPLPoly *poly, list<TPPLPoly> *parts) {
 | 
			
		|||
			indices.push_back(j);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		indices.sort();
 | 
			
		||||
		std::sort(indices.begin(), indices.end());
 | 
			
		||||
		newpoly.Init((long)indices.size());
 | 
			
		||||
		k=0;
 | 
			
		||||
		for(iiter = indices.begin();iiter!=indices.end(); ++iiter) {
 | 
			
		||||
		for(iiter = indices.begin();iiter!=indices.end();iiter++) {
 | 
			
		||||
			newpoly[k] = vertices[*iiter].p;
 | 
			
		||||
			k++;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -1055,18 +1065,19 @@ int TPPLPartition::ConvexPartition_OPT(TPPLPoly *poly, list<TPPLPoly> *parts) {
 | 
			
		|||
//the algorithm used here is outlined in the book
 | 
			
		||||
//"Computational Geometry: Algorithms and Applications" 
 | 
			
		||||
//by Mark de Berg, Otfried Cheong, Marc van Kreveld and Mark Overmars
 | 
			
		||||
int TPPLPartition::MonotonePartition(list<TPPLPoly> *inpolys, list<TPPLPoly> *monotonePolys) {
 | 
			
		||||
	list<TPPLPoly>::iterator iter;
 | 
			
		||||
	MonotoneVertex *vertices;
 | 
			
		||||
int TPPLPartition::MonotonePartition(TPPLPolyList *inpolys, TPPLPolyList *monotonePolys) {
 | 
			
		||||
	TPPLPolyList::iterator iter;
 | 
			
		||||
	MonotoneVertex *vertices = NULL;
 | 
			
		||||
	long i,numvertices,vindex,vindex2,newnumvertices,maxnumvertices;
 | 
			
		||||
	long polystartindex, polyendindex;
 | 
			
		||||
	TPPLPoly *poly;
 | 
			
		||||
	MonotoneVertex *v,*v2,*vprev,*vnext;
 | 
			
		||||
	TPPLPoly *poly = NULL;
 | 
			
		||||
	MonotoneVertex *v = NULL,*v2 = NULL,*vprev = NULL,*vnext = NULL;
 | 
			
		||||
	ScanLineEdge newedge;
 | 
			
		||||
	bool error = false;
 | 
			
		||||
 | 
			
		||||
	numvertices = 0;
 | 
			
		||||
	for(iter = inpolys->begin(); iter != inpolys->end(); ++iter) {
 | 
			
		||||
	for(iter = inpolys->begin(); iter != inpolys->end(); iter++) {
 | 
			
		||||
		if(!iter->Valid()) return 0;
 | 
			
		||||
		numvertices += iter->GetNumPoints();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1075,7 +1086,7 @@ int TPPLPartition::MonotonePartition(list<TPPLPoly> *inpolys, list<TPPLPoly> *mo
 | 
			
		|||
	newnumvertices = numvertices;
 | 
			
		||||
 | 
			
		||||
	polystartindex = 0;
 | 
			
		||||
	for(iter = inpolys->begin(); iter != inpolys->end(); ++iter) {
 | 
			
		||||
	for(iter = inpolys->begin(); iter != inpolys->end(); iter++) {
 | 
			
		||||
		poly = &(*iter);
 | 
			
		||||
		polyendindex = polystartindex + poly->GetNumPoints()-1;
 | 
			
		||||
		for(i=0;i<poly->GetNumPoints();i++) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1130,6 +1141,7 @@ int TPPLPartition::MonotonePartition(list<TPPLPoly> *inpolys, list<TPPLPoly> *mo
 | 
			
		|||
	set<ScanLineEdge>::iterator *edgeTreeIterators,edgeIter;
 | 
			
		||||
	edgeTreeIterators = new set<ScanLineEdge>::iterator[maxnumvertices];
 | 
			
		||||
	pair<set<ScanLineEdge>::iterator,bool> edgeTreeRet;
 | 
			
		||||
	for(i = 0; i<numvertices; i++) edgeTreeIterators[i] = edgeTree.end();
 | 
			
		||||
 | 
			
		||||
	//for each vertex
 | 
			
		||||
	for(i=0;i<numvertices;i++) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1152,16 +1164,15 @@ int TPPLPartition::MonotonePartition(list<TPPLPoly> *inpolys, list<TPPLPoly> *mo
 | 
			
		|||
				break;
 | 
			
		||||
 | 
			
		||||
			case TPPL_VERTEXTYPE_END:
 | 
			
		||||
				if (edgeTreeIterators[v->previous] == edgeTree.end()) {
 | 
			
		||||
					error = true;
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				//if helper(ei-1) is a merge vertex
 | 
			
		||||
				if(vertextypes[helpers[v->previous]]==TPPL_VERTEXTYPE_MERGE) {
 | 
			
		||||
					//Insert the diagonal connecting vi to helper(ei-1) in D.
 | 
			
		||||
					AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous]);
 | 
			
		||||
					vertextypes[newnumvertices-2] = vertextypes[vindex];
 | 
			
		||||
					edgeTreeIterators[newnumvertices-2] = edgeTreeIterators[vindex];
 | 
			
		||||
					helpers[newnumvertices-2] = helpers[vindex];
 | 
			
		||||
					vertextypes[newnumvertices-1] = vertextypes[helpers[v->previous]];
 | 
			
		||||
					edgeTreeIterators[newnumvertices-1] = edgeTreeIterators[helpers[v->previous]];
 | 
			
		||||
					helpers[newnumvertices-1] = helpers[helpers[v->previous]];
 | 
			
		||||
					AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous], 
 | 
			
		||||
						vertextypes, edgeTreeIterators, &edgeTree, helpers);
 | 
			
		||||
				}
 | 
			
		||||
				//Delete ei-1 from T
 | 
			
		||||
				edgeTree.erase(edgeTreeIterators[v->previous]);
 | 
			
		||||
| 
						 | 
				
			
			@ -1176,15 +1187,10 @@ int TPPLPartition::MonotonePartition(list<TPPLPoly> *inpolys, list<TPPLPoly> *mo
 | 
			
		|||
					error = true;
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				--edgeIter;
 | 
			
		||||
				edgeIter--;
 | 
			
		||||
				//Insert the diagonal connecting vi to helper(ej) in D.
 | 
			
		||||
				AddDiagonal(vertices,&newnumvertices,vindex,helpers[edgeIter->index]);
 | 
			
		||||
				vertextypes[newnumvertices-2] = vertextypes[vindex];
 | 
			
		||||
				edgeTreeIterators[newnumvertices-2] = edgeTreeIterators[vindex];
 | 
			
		||||
				helpers[newnumvertices-2] = helpers[vindex];
 | 
			
		||||
				vertextypes[newnumvertices-1] = vertextypes[helpers[edgeIter->index]];
 | 
			
		||||
				edgeTreeIterators[newnumvertices-1] = edgeTreeIterators[helpers[edgeIter->index]];
 | 
			
		||||
				helpers[newnumvertices-1] = helpers[helpers[edgeIter->index]];
 | 
			
		||||
				AddDiagonal(vertices,&newnumvertices,vindex,helpers[edgeIter->index],
 | 
			
		||||
					vertextypes, edgeTreeIterators, &edgeTree, helpers);
 | 
			
		||||
				vindex2 = newnumvertices-2;
 | 
			
		||||
				v2 = &(vertices[vindex2]);
 | 
			
		||||
				//helper(e j)<29>vi
 | 
			
		||||
| 
						 | 
				
			
			@ -1199,16 +1205,15 @@ int TPPLPartition::MonotonePartition(list<TPPLPoly> *inpolys, list<TPPLPoly> *mo
 | 
			
		|||
				break;
 | 
			
		||||
 | 
			
		||||
			case TPPL_VERTEXTYPE_MERGE:
 | 
			
		||||
				if (edgeTreeIterators[v->previous] == edgeTree.end()) {
 | 
			
		||||
					error = true;
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				//if helper(ei-1) is a merge vertex
 | 
			
		||||
				if(vertextypes[helpers[v->previous]]==TPPL_VERTEXTYPE_MERGE) {
 | 
			
		||||
					//Insert the diagonal connecting vi to helper(ei-1) in D.
 | 
			
		||||
					AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous]);
 | 
			
		||||
					vertextypes[newnumvertices-2] = vertextypes[vindex];
 | 
			
		||||
					edgeTreeIterators[newnumvertices-2] = edgeTreeIterators[vindex];
 | 
			
		||||
					helpers[newnumvertices-2] = helpers[vindex];
 | 
			
		||||
					vertextypes[newnumvertices-1] = vertextypes[helpers[v->previous]];
 | 
			
		||||
					edgeTreeIterators[newnumvertices-1] = edgeTreeIterators[helpers[v->previous]];
 | 
			
		||||
					helpers[newnumvertices-1] = helpers[helpers[v->previous]];
 | 
			
		||||
					AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous],
 | 
			
		||||
						vertextypes, edgeTreeIterators, &edgeTree, helpers);
 | 
			
		||||
					vindex2 = newnumvertices-2;
 | 
			
		||||
					v2 = &(vertices[vindex2]);
 | 
			
		||||
				}
 | 
			
		||||
| 
						 | 
				
			
			@ -1222,17 +1227,12 @@ int TPPLPartition::MonotonePartition(list<TPPLPoly> *inpolys, list<TPPLPoly> *mo
 | 
			
		|||
					error = true;
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				--edgeIter;
 | 
			
		||||
				edgeIter--;
 | 
			
		||||
				//if helper(ej) is a merge vertex
 | 
			
		||||
				if(vertextypes[helpers[edgeIter->index]]==TPPL_VERTEXTYPE_MERGE) {
 | 
			
		||||
					//Insert the diagonal connecting vi to helper(e j) in D.
 | 
			
		||||
					AddDiagonal(vertices,&newnumvertices,vindex2,helpers[edgeIter->index]);
 | 
			
		||||
					vertextypes[newnumvertices-2] = vertextypes[vindex2];
 | 
			
		||||
					edgeTreeIterators[newnumvertices-2] = edgeTreeIterators[vindex2];
 | 
			
		||||
					helpers[newnumvertices-2] = helpers[vindex2];
 | 
			
		||||
					vertextypes[newnumvertices-1] = vertextypes[helpers[edgeIter->index]];
 | 
			
		||||
					edgeTreeIterators[newnumvertices-1] = edgeTreeIterators[helpers[edgeIter->index]];
 | 
			
		||||
					helpers[newnumvertices-1] = helpers[helpers[edgeIter->index]];
 | 
			
		||||
					AddDiagonal(vertices,&newnumvertices,vindex2,helpers[edgeIter->index],
 | 
			
		||||
						vertextypes, edgeTreeIterators, &edgeTree, helpers);
 | 
			
		||||
				}
 | 
			
		||||
				//helper(e j)<29>vi
 | 
			
		||||
				helpers[edgeIter->index] = vindex2;
 | 
			
		||||
| 
						 | 
				
			
			@ -1241,16 +1241,15 @@ int TPPLPartition::MonotonePartition(list<TPPLPoly> *inpolys, list<TPPLPoly> *mo
 | 
			
		|||
			case TPPL_VERTEXTYPE_REGULAR:
 | 
			
		||||
				//if the interior of P lies to the right of vi
 | 
			
		||||
				if(Below(v->p,vertices[v->previous].p)) {
 | 
			
		||||
					if (edgeTreeIterators[v->previous] == edgeTree.end()) {
 | 
			
		||||
						error = true;
 | 
			
		||||
						break;
 | 
			
		||||
					}
 | 
			
		||||
					//if helper(ei-1) is a merge vertex
 | 
			
		||||
					if(vertextypes[helpers[v->previous]]==TPPL_VERTEXTYPE_MERGE) {
 | 
			
		||||
						//Insert the diagonal connecting vi to helper(ei-1) in D.
 | 
			
		||||
						AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous]);
 | 
			
		||||
						vertextypes[newnumvertices-2] = vertextypes[vindex];
 | 
			
		||||
						edgeTreeIterators[newnumvertices-2] = edgeTreeIterators[vindex];
 | 
			
		||||
						helpers[newnumvertices-2] = helpers[vindex];
 | 
			
		||||
						vertextypes[newnumvertices-1] = vertextypes[helpers[v->previous]];
 | 
			
		||||
						edgeTreeIterators[newnumvertices-1] = edgeTreeIterators[helpers[v->previous]];
 | 
			
		||||
						helpers[newnumvertices-1] = helpers[helpers[v->previous]];
 | 
			
		||||
						AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous],
 | 
			
		||||
							vertextypes, edgeTreeIterators, &edgeTree, helpers);
 | 
			
		||||
						vindex2 = newnumvertices-2;
 | 
			
		||||
						v2 = &(vertices[vindex2]);
 | 
			
		||||
					}
 | 
			
		||||
| 
						 | 
				
			
			@ -1272,17 +1271,12 @@ int TPPLPartition::MonotonePartition(list<TPPLPoly> *inpolys, list<TPPLPoly> *mo
 | 
			
		|||
						error = true;
 | 
			
		||||
						break;
 | 
			
		||||
					}
 | 
			
		||||
					--edgeIter;
 | 
			
		||||
					edgeIter--;
 | 
			
		||||
					//if helper(ej) is a merge vertex
 | 
			
		||||
					if(vertextypes[helpers[edgeIter->index]]==TPPL_VERTEXTYPE_MERGE) {
 | 
			
		||||
						//Insert the diagonal connecting vi to helper(e j) in D.
 | 
			
		||||
						AddDiagonal(vertices,&newnumvertices,vindex,helpers[edgeIter->index]);
 | 
			
		||||
						vertextypes[newnumvertices-2] = vertextypes[vindex];
 | 
			
		||||
						edgeTreeIterators[newnumvertices-2] = edgeTreeIterators[vindex];
 | 
			
		||||
						helpers[newnumvertices-2] = helpers[vindex];
 | 
			
		||||
						vertextypes[newnumvertices-1] = vertextypes[helpers[edgeIter->index]];
 | 
			
		||||
						edgeTreeIterators[newnumvertices-1] = edgeTreeIterators[helpers[edgeIter->index]];
 | 
			
		||||
						helpers[newnumvertices-1] = helpers[helpers[edgeIter->index]];
 | 
			
		||||
						AddDiagonal(vertices,&newnumvertices,vindex,helpers[edgeIter->index],
 | 
			
		||||
							vertextypes, edgeTreeIterators, &edgeTree, helpers);
 | 
			
		||||
					}
 | 
			
		||||
					//helper(e j)<29>vi
 | 
			
		||||
					helpers[edgeIter->index] = vindex;
 | 
			
		||||
| 
						 | 
				
			
			@ -1342,7 +1336,10 @@ int TPPLPartition::MonotonePartition(list<TPPLPoly> *inpolys, list<TPPLPoly> *mo
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
//adds a diagonal to the doubly-connected list of vertices
 | 
			
		||||
void TPPLPartition::AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2) {
 | 
			
		||||
void TPPLPartition::AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2, 
 | 
			
		||||
								char *vertextypes, set<ScanLineEdge>::iterator *edgeTreeIterators, 
 | 
			
		||||
								set<ScanLineEdge> *edgeTree, long *helpers) 
 | 
			
		||||
{
 | 
			
		||||
	long newindex1,newindex2;
 | 
			
		||||
 | 
			
		||||
	newindex1 = *numvertices;
 | 
			
		||||
| 
						 | 
				
			
			@ -1364,6 +1361,18 @@ void TPPLPartition::AddDiagonal(MonotoneVertex *vertices, long *numvertices, lon
 | 
			
		|||
 | 
			
		||||
	vertices[index2].next = newindex1;
 | 
			
		||||
	vertices[newindex1].previous = index2;
 | 
			
		||||
 | 
			
		||||
	//update all relevant structures
 | 
			
		||||
	vertextypes[newindex1] = vertextypes[index1];
 | 
			
		||||
	edgeTreeIterators[newindex1] = edgeTreeIterators[index1];
 | 
			
		||||
	helpers[newindex1] = helpers[index1];
 | 
			
		||||
	if(edgeTreeIterators[newindex1] != edgeTree->end())
 | 
			
		||||
		edgeTreeIterators[newindex1]->index = newindex1;
 | 
			
		||||
	vertextypes[newindex2] = vertextypes[index2];
 | 
			
		||||
	edgeTreeIterators[newindex2] = edgeTreeIterators[index2];
 | 
			
		||||
	helpers[newindex2] = helpers[index2];
 | 
			
		||||
	if(edgeTreeIterators[newindex2] != edgeTree->end())
 | 
			
		||||
		edgeTreeIterators[newindex2]->index = newindex2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool TPPLPartition::Below(TPPLPoint &p1, TPPLPoint &p2) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1375,7 +1384,7 @@ bool TPPLPartition::Below(TPPLPoint &p1, TPPLPoint &p2) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
//sorts in the falling order of y values, if y is equal, x is used instead
 | 
			
		||||
bool TPPLPartition::VertexSorter::operator() (long index1, long index2) const {
 | 
			
		||||
bool TPPLPartition::VertexSorter::operator() (long index1, long index2) {
 | 
			
		||||
	if(vertices[index1].p.y > vertices[index2].p.y) return true;
 | 
			
		||||
	else if(vertices[index1].p.y == vertices[index2].p.y) {
 | 
			
		||||
		if(vertices[index1].p.x > vertices[index2].p.x) return true;
 | 
			
		||||
| 
						 | 
				
			
			@ -1412,19 +1421,21 @@ bool TPPLPartition::ScanLineEdge::operator < (const ScanLineEdge & other) const
 | 
			
		|||
 | 
			
		||||
//triangulates monotone polygon
 | 
			
		||||
//O(n) time, O(n) space complexity
 | 
			
		||||
int TPPLPartition::TriangulateMonotone(TPPLPoly *inPoly, list<TPPLPoly> *triangles) {
 | 
			
		||||
int TPPLPartition::TriangulateMonotone(TPPLPoly *inPoly, TPPLPolyList *triangles) {
 | 
			
		||||
	if(!inPoly->Valid()) return 0;
 | 
			
		||||
 | 
			
		||||
	long i,i2,j,topindex,bottomindex,leftindex,rightindex,vindex;
 | 
			
		||||
	TPPLPoint *points;
 | 
			
		||||
	TPPLPoint *points = NULL;
 | 
			
		||||
	long numpoints;
 | 
			
		||||
	TPPLPoly triangle;
 | 
			
		||||
 | 
			
		||||
	numpoints = inPoly->GetNumPoints();
 | 
			
		||||
	points = inPoly->GetPoints();
 | 
			
		||||
 | 
			
		||||
	//trivial calses
 | 
			
		||||
	if(numpoints < 3) return 0;
 | 
			
		||||
	//trivial case
 | 
			
		||||
	if(numpoints == 3) {
 | 
			
		||||
		triangles->push_back(*inPoly);
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	topindex = 0; bottomindex=0;
 | 
			
		||||
| 
						 | 
				
			
			@ -1544,19 +1555,19 @@ int TPPLPartition::TriangulateMonotone(TPPLPoly *inPoly, list<TPPLPoly> *triangl
 | 
			
		|||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int TPPLPartition::Triangulate_MONO(list<TPPLPoly> *inpolys, list<TPPLPoly> *triangles) {
 | 
			
		||||
	list<TPPLPoly> monotone;
 | 
			
		||||
	list<TPPLPoly>::iterator iter;
 | 
			
		||||
int TPPLPartition::Triangulate_MONO(TPPLPolyList *inpolys, TPPLPolyList *triangles) {
 | 
			
		||||
	TPPLPolyList monotone;
 | 
			
		||||
	TPPLPolyList::iterator iter;
 | 
			
		||||
 | 
			
		||||
	if(!MonotonePartition(inpolys,&monotone)) return 0;
 | 
			
		||||
	for(iter = monotone.begin(); iter!=monotone.end(); ++iter) {
 | 
			
		||||
	for(iter = monotone.begin(); iter!=monotone.end();iter++) {
 | 
			
		||||
		if(!TriangulateMonotone(&(*iter),triangles)) return 0;
 | 
			
		||||
	}
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int TPPLPartition::Triangulate_MONO(TPPLPoly *poly, list<TPPLPoly> *triangles) {
 | 
			
		||||
	list<TPPLPoly> polys;
 | 
			
		||||
int TPPLPartition::Triangulate_MONO(TPPLPoly *poly, TPPLPolyList *triangles) {
 | 
			
		||||
	TPPLPolyList polys;
 | 
			
		||||
	polys.push_back(*poly);
 | 
			
		||||
 | 
			
		||||
	return Triangulate_MONO(&polys, triangles);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,9 +18,11 @@
 | 
			
		|||
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
//THE SOFTWARE.
 | 
			
		||||
 | 
			
		||||
#ifndef POLYPARTITION_H
 | 
			
		||||
#define POLYPARTITION_H
 | 
			
		||||
 | 
			
		||||
#include <list>
 | 
			
		||||
using namespace std;
 | 
			
		||||
#include <set>
 | 
			
		||||
 | 
			
		||||
typedef double tppl_float;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -29,315 +31,349 @@ typedef double tppl_float;
 | 
			
		|||
 | 
			
		||||
//2D point structure
 | 
			
		||||
struct TPPLPoint {
 | 
			
		||||
	tppl_float x;
 | 
			
		||||
	tppl_float y;
 | 
			
		||||
 | 
			
		||||
	TPPLPoint operator + (const TPPLPoint& p) const {
 | 
			
		||||
		TPPLPoint r;
 | 
			
		||||
		r.x = x + p.x;
 | 
			
		||||
		r.y = y + p.y;
 | 
			
		||||
		return r;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	TPPLPoint operator - (const TPPLPoint& p) const {
 | 
			
		||||
		TPPLPoint r;
 | 
			
		||||
		r.x = x - p.x;
 | 
			
		||||
		r.y = y - p.y;
 | 
			
		||||
		return r;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	TPPLPoint operator * (const tppl_float f ) const {
 | 
			
		||||
		TPPLPoint r;
 | 
			
		||||
		r.x = x*f;
 | 
			
		||||
		r.y = y*f;
 | 
			
		||||
		return r;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	TPPLPoint operator / (const tppl_float f ) const {
 | 
			
		||||
		TPPLPoint r;
 | 
			
		||||
		r.x = x/f;
 | 
			
		||||
		r.y = y/f;
 | 
			
		||||
		return r;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool operator==(const TPPLPoint& p) const {
 | 
			
		||||
		if((x == p.x)&&(y==p.y)) return true;
 | 
			
		||||
		else return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool operator!=(const TPPLPoint& p) const {
 | 
			
		||||
		if((x == p.x)&&(y==p.y)) return false;
 | 
			
		||||
		else return true;
 | 
			
		||||
	}
 | 
			
		||||
    tppl_float x;
 | 
			
		||||
    tppl_float y;
 | 
			
		||||
    // User-specified vertex identifier.  Note that this isn't used internally
 | 
			
		||||
    // by the library, but will be faithfully copied around.
 | 
			
		||||
    int id;
 | 
			
		||||
    
 | 
			
		||||
    TPPLPoint operator + (const TPPLPoint& p) const {
 | 
			
		||||
        TPPLPoint r;
 | 
			
		||||
        r.x = x + p.x;
 | 
			
		||||
        r.y = y + p.y;
 | 
			
		||||
        return r;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    TPPLPoint operator - (const TPPLPoint& p) const {
 | 
			
		||||
        TPPLPoint r;
 | 
			
		||||
        r.x = x - p.x;
 | 
			
		||||
        r.y = y - p.y;
 | 
			
		||||
        return r;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    TPPLPoint operator * (const tppl_float f ) const {
 | 
			
		||||
        TPPLPoint r;
 | 
			
		||||
        r.x = x*f;
 | 
			
		||||
        r.y = y*f;
 | 
			
		||||
        return r;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    TPPLPoint operator / (const tppl_float f ) const {
 | 
			
		||||
        TPPLPoint r;
 | 
			
		||||
        r.x = x/f;
 | 
			
		||||
        r.y = y/f;
 | 
			
		||||
        return r;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    bool operator==(const TPPLPoint& p) const {
 | 
			
		||||
        if((x == p.x)&&(y==p.y)) return true;
 | 
			
		||||
        else return false;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    bool operator!=(const TPPLPoint& p) const {
 | 
			
		||||
        if((x == p.x)&&(y==p.y)) return false;
 | 
			
		||||
        else return true;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//Polygon implemented as an array of points with a 'hole' flag
 | 
			
		||||
class TPPLPoly {
 | 
			
		||||
protected:
 | 
			
		||||
    protected:
 | 
			
		||||
        
 | 
			
		||||
        TPPLPoint *points;
 | 
			
		||||
        long numpoints;
 | 
			
		||||
        bool hole;
 | 
			
		||||
        
 | 
			
		||||
    public:
 | 
			
		||||
        
 | 
			
		||||
        //constructors/destructors
 | 
			
		||||
        TPPLPoly();
 | 
			
		||||
        ~TPPLPoly();
 | 
			
		||||
        
 | 
			
		||||
        TPPLPoly(const TPPLPoly &src);
 | 
			
		||||
        TPPLPoly& operator=(const TPPLPoly &src);
 | 
			
		||||
        
 | 
			
		||||
        //getters and setters
 | 
			
		||||
        long GetNumPoints() const {
 | 
			
		||||
            return numpoints;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        bool IsHole() const {
 | 
			
		||||
            return hole;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        void SetHole(bool hole) {
 | 
			
		||||
            this->hole = hole;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        TPPLPoint &GetPoint(long i) {
 | 
			
		||||
            return points[i];
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        const TPPLPoint &GetPoint(long i) const {
 | 
			
		||||
            return points[i];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
	TPPLPoint *points;
 | 
			
		||||
	long numpoints;
 | 
			
		||||
	bool hole;
 | 
			
		||||
        TPPLPoint *GetPoints() {
 | 
			
		||||
            return points;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        TPPLPoint& operator[] (int i) {
 | 
			
		||||
            return points[i];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
        const TPPLPoint& operator[] (int i) const {
 | 
			
		||||
            return points[i];
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        //clears the polygon points
 | 
			
		||||
        void Clear();
 | 
			
		||||
        
 | 
			
		||||
        //inits the polygon with numpoints vertices
 | 
			
		||||
        void Init(long numpoints);
 | 
			
		||||
        
 | 
			
		||||
        //creates a triangle with points p1,p2,p3
 | 
			
		||||
        void Triangle(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3);
 | 
			
		||||
        
 | 
			
		||||
        //inverts the orfer of vertices
 | 
			
		||||
        void Invert();
 | 
			
		||||
        
 | 
			
		||||
        //returns the orientation of the polygon
 | 
			
		||||
        //possible values:
 | 
			
		||||
        //   TPPL_CCW : polygon vertices are in counter-clockwise order
 | 
			
		||||
        //   TPPL_CW : polygon vertices are in clockwise order
 | 
			
		||||
        //       0 : the polygon has no (measurable) area
 | 
			
		||||
        int GetOrientation() const;
 | 
			
		||||
        
 | 
			
		||||
        //sets the polygon orientation
 | 
			
		||||
        //orientation can be
 | 
			
		||||
        //   TPPL_CCW : sets vertices in counter-clockwise order
 | 
			
		||||
        //   TPPL_CW : sets vertices in clockwise order
 | 
			
		||||
        void SetOrientation(int orientation);
 | 
			
		||||
 | 
			
		||||
	//constructors/destructors
 | 
			
		||||
	TPPLPoly();
 | 
			
		||||
	~TPPLPoly();
 | 
			
		||||
 | 
			
		||||
	TPPLPoly(const TPPLPoly &src);
 | 
			
		||||
	TPPLPoly& operator=(const TPPLPoly &src);
 | 
			
		||||
 | 
			
		||||
	//getters and setters
 | 
			
		||||
	long GetNumPoints() const {
 | 
			
		||||
		return numpoints;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool IsHole() const {
 | 
			
		||||
		return hole;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void SetHole(bool hole) {
 | 
			
		||||
		this->hole = hole;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	TPPLPoint &GetPoint(long i) {
 | 
			
		||||
		return points[i];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	TPPLPoint *GetPoints() {
 | 
			
		||||
		return points;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	TPPLPoint& operator[] (int i) {
 | 
			
		||||
		return points[i];	
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//clears the polygon points
 | 
			
		||||
	void Clear();
 | 
			
		||||
 | 
			
		||||
	//inits the polygon with numpoints vertices
 | 
			
		||||
	void Init(long numpoints);
 | 
			
		||||
 | 
			
		||||
	//creates a triangle with points p1,p2,p3
 | 
			
		||||
	void Triangle(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3);
 | 
			
		||||
 | 
			
		||||
	//inverts the orfer of vertices
 | 
			
		||||
	void Invert();
 | 
			
		||||
 | 
			
		||||
	//returns the orientation of the polygon
 | 
			
		||||
	//possible values:
 | 
			
		||||
	//   TPPL_CCW : polygon vertices are in counter-clockwise order
 | 
			
		||||
	//   TPPL_CW : polygon vertices are in clockwise order
 | 
			
		||||
	//	 0 : the polygon has no (measurable) area
 | 
			
		||||
	int GetOrientation() const;
 | 
			
		||||
 | 
			
		||||
	//sets the polygon orientation
 | 
			
		||||
	//orientation can be
 | 
			
		||||
	//   TPPL_CCW : sets vertices in counter-clockwise order
 | 
			
		||||
	//   TPPL_CW : sets vertices in clockwise order
 | 
			
		||||
	void SetOrientation(int orientation);
 | 
			
		||||
        //checks whether a polygon is valid or not
 | 
			
		||||
        inline bool Valid() const { return this->numpoints >= 3; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#ifdef TPPL_ALLOCATOR
 | 
			
		||||
typedef std::list<TPPLPoly, TPPL_ALLOCATOR(TPPLPoly)> TPPLPolyList;
 | 
			
		||||
#else
 | 
			
		||||
typedef std::list<TPPLPoly> TPPLPolyList;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
class TPPLPartition {
 | 
			
		||||
protected:
 | 
			
		||||
	struct PartitionVertex {
 | 
			
		||||
		bool isActive;
 | 
			
		||||
		bool isConvex;
 | 
			
		||||
		bool isEar;
 | 
			
		||||
    protected:
 | 
			
		||||
        struct PartitionVertex {
 | 
			
		||||
            bool isActive;
 | 
			
		||||
            bool isConvex;
 | 
			
		||||
            bool isEar;
 | 
			
		||||
            
 | 
			
		||||
            TPPLPoint p;
 | 
			
		||||
            tppl_float angle;
 | 
			
		||||
            PartitionVertex *previous;
 | 
			
		||||
            PartitionVertex *next;
 | 
			
		||||
            
 | 
			
		||||
            PartitionVertex();
 | 
			
		||||
        };
 | 
			
		||||
        
 | 
			
		||||
        struct MonotoneVertex {
 | 
			
		||||
            TPPLPoint p;
 | 
			
		||||
            long previous;
 | 
			
		||||
            long next;
 | 
			
		||||
        };
 | 
			
		||||
        
 | 
			
		||||
        class VertexSorter{
 | 
			
		||||
            MonotoneVertex *vertices;
 | 
			
		||||
        public:
 | 
			
		||||
            VertexSorter(MonotoneVertex *v) : vertices(v) {}
 | 
			
		||||
            bool operator() (long index1, long index2);
 | 
			
		||||
        };
 | 
			
		||||
        
 | 
			
		||||
        struct Diagonal {
 | 
			
		||||
            long index1;
 | 
			
		||||
            long index2;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
		TPPLPoint p;
 | 
			
		||||
		tppl_float angle;
 | 
			
		||||
		PartitionVertex *previous;
 | 
			
		||||
		PartitionVertex *next;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	struct MonotoneVertex {
 | 
			
		||||
		TPPLPoint p;
 | 
			
		||||
		long previous;
 | 
			
		||||
		long next;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	class VertexSorter{
 | 
			
		||||
		MonotoneVertex *vertices;
 | 
			
		||||
	public:
 | 
			
		||||
		VertexSorter(MonotoneVertex *v) : vertices(v) {}
 | 
			
		||||
		bool operator() (long index1, long index2) const;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	struct Diagonal {
 | 
			
		||||
		long index1;
 | 
			
		||||
		long index2;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	//dynamic programming state for minimum-weight triangulation
 | 
			
		||||
	struct DPState {
 | 
			
		||||
		bool visible;
 | 
			
		||||
		tppl_float weight;
 | 
			
		||||
		long bestvertex;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	//dynamic programming state for convex partitioning
 | 
			
		||||
	struct DPState2 {
 | 
			
		||||
		bool visible;
 | 
			
		||||
		long weight;
 | 
			
		||||
		list<Diagonal> pairs;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	//edge that intersects the scanline
 | 
			
		||||
	struct ScanLineEdge {
 | 
			
		||||
		long index;
 | 
			
		||||
		TPPLPoint p1;
 | 
			
		||||
		TPPLPoint p2;
 | 
			
		||||
 | 
			
		||||
		//determines if the edge is to the left of another edge
 | 
			
		||||
		bool operator< (const ScanLineEdge & other) const;
 | 
			
		||||
 | 
			
		||||
		bool IsConvex(const TPPLPoint& p1, const TPPLPoint& p2, const TPPLPoint& p3) const;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	//standard helper functions
 | 
			
		||||
	bool IsConvex(TPPLPoint& p1, TPPLPoint& p2, TPPLPoint& p3);
 | 
			
		||||
	bool IsReflex(TPPLPoint& p1, TPPLPoint& p2, TPPLPoint& p3);
 | 
			
		||||
	bool IsInside(TPPLPoint& p1, TPPLPoint& p2, TPPLPoint& p3, TPPLPoint &p);
 | 
			
		||||
	
 | 
			
		||||
	bool InCone(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3, TPPLPoint &p);
 | 
			
		||||
	bool InCone(PartitionVertex *v, TPPLPoint &p);
 | 
			
		||||
 | 
			
		||||
	int Intersects(TPPLPoint &p11, TPPLPoint &p12, TPPLPoint &p21, TPPLPoint &p22);
 | 
			
		||||
 | 
			
		||||
	TPPLPoint Normalize(const TPPLPoint &p);
 | 
			
		||||
	tppl_float Distance(const TPPLPoint &p1, const TPPLPoint &p2);
 | 
			
		||||
 | 
			
		||||
	//helper functions for Triangulate_EC
 | 
			
		||||
	void UpdateVertexReflexity(PartitionVertex *v);
 | 
			
		||||
	void UpdateVertex(PartitionVertex *v,PartitionVertex *vertices, long numvertices);
 | 
			
		||||
 | 
			
		||||
	//helper functions for ConvexPartition_OPT
 | 
			
		||||
	void UpdateState(long a, long b, long w, long i, long j, DPState2 **dpstates);
 | 
			
		||||
	void TypeA(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates);
 | 
			
		||||
	void TypeB(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates);
 | 
			
		||||
 | 
			
		||||
	//helper functions for MonotonePartition
 | 
			
		||||
	bool Below(TPPLPoint &p1, TPPLPoint &p2);
 | 
			
		||||
	void AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2);
 | 
			
		||||
 | 
			
		||||
	//triangulates a monotone polygon, used in Triangulate_MONO
 | 
			
		||||
	int TriangulateMonotone(TPPLPoly *inPoly, list<TPPLPoly> *triangles);
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
	//simple heuristic procedure for removing holes from a list of polygons
 | 
			
		||||
	//works by creating a diagonal from the rightmost hole vertex to some visible vertex
 | 
			
		||||
	//time complexity: O(h*(n^2)), h is the number of holes, n is the number of vertices
 | 
			
		||||
	//space complexity: O(n)
 | 
			
		||||
	//params:
 | 
			
		||||
	//   inpolys : a list of polygons that can contain holes
 | 
			
		||||
	//             vertices of all non-hole polys have to be in counter-clockwise order
 | 
			
		||||
	//             vertices of all hole polys have to be in clockwise order
 | 
			
		||||
	//   outpolys : a list of polygons without holes
 | 
			
		||||
	//returns 1 on success, 0 on failure
 | 
			
		||||
	int RemoveHoles(list<TPPLPoly> *inpolys, list<TPPLPoly> *outpolys);
 | 
			
		||||
 | 
			
		||||
	//triangulates a polygon by ear clipping
 | 
			
		||||
	//time complexity O(n^2), n is the number of vertices
 | 
			
		||||
	//space complexity: O(n)
 | 
			
		||||
	//params:
 | 
			
		||||
	//   poly : an input polygon to be triangulated
 | 
			
		||||
	//          vertices have to be in counter-clockwise order
 | 
			
		||||
	//   triangles : a list of triangles (result)
 | 
			
		||||
	//returns 1 on success, 0 on failure
 | 
			
		||||
	int Triangulate_EC(TPPLPoly *poly, list<TPPLPoly> *triangles);
 | 
			
		||||
 | 
			
		||||
	//triangulates a list of polygons that may contain holes by ear clipping algorithm
 | 
			
		||||
	//first calls RemoveHoles to get rid of the holes, and then Triangulate_EC for each resulting polygon
 | 
			
		||||
	//time complexity: O(h*(n^2)), h is the number of holes, n is the number of vertices
 | 
			
		||||
	//space complexity: O(n)
 | 
			
		||||
	//params:
 | 
			
		||||
	//   inpolys : a list of polygons to be triangulated (can contain holes)
 | 
			
		||||
	//             vertices of all non-hole polys have to be in counter-clockwise order
 | 
			
		||||
	//             vertices of all hole polys have to be in clockwise order
 | 
			
		||||
	//   triangles : a list of triangles (result)
 | 
			
		||||
	//returns 1 on success, 0 on failure
 | 
			
		||||
	int Triangulate_EC(list<TPPLPoly> *inpolys, list<TPPLPoly> *triangles);
 | 
			
		||||
 | 
			
		||||
	//creates an optimal polygon triangulation in terms of minimal edge length
 | 
			
		||||
	//time complexity: O(n^3), n is the number of vertices
 | 
			
		||||
	//space complexity: O(n^2)
 | 
			
		||||
	//params:
 | 
			
		||||
	//   poly : an input polygon to be triangulated
 | 
			
		||||
	//          vertices have to be in counter-clockwise order
 | 
			
		||||
	//   triangles : a list of triangles (result)
 | 
			
		||||
	//returns 1 on success, 0 on failure
 | 
			
		||||
	int Triangulate_OPT(TPPLPoly *poly, list<TPPLPoly> *triangles);
 | 
			
		||||
 | 
			
		||||
	//triangulates a polygons by firstly partitioning it into monotone polygons
 | 
			
		||||
	//time complexity: O(n*log(n)), n is the number of vertices
 | 
			
		||||
	//space complexity: O(n)
 | 
			
		||||
	//params:
 | 
			
		||||
	//   poly : an input polygon to be triangulated
 | 
			
		||||
	//          vertices have to be in counter-clockwise order
 | 
			
		||||
	//   triangles : a list of triangles (result)
 | 
			
		||||
	//returns 1 on success, 0 on failure
 | 
			
		||||
	int Triangulate_MONO(TPPLPoly *poly, list<TPPLPoly> *triangles);
 | 
			
		||||
 | 
			
		||||
	//triangulates a list of polygons by firstly partitioning them into monotone polygons
 | 
			
		||||
	//time complexity: O(n*log(n)), n is the number of vertices
 | 
			
		||||
	//space complexity: O(n)
 | 
			
		||||
	//params:
 | 
			
		||||
	//   inpolys : a list of polygons to be triangulated (can contain holes)
 | 
			
		||||
	//             vertices of all non-hole polys have to be in counter-clockwise order
 | 
			
		||||
	//             vertices of all hole polys have to be in clockwise order
 | 
			
		||||
	//   triangles : a list of triangles (result)
 | 
			
		||||
	//returns 1 on success, 0 on failure
 | 
			
		||||
	int Triangulate_MONO(list<TPPLPoly> *inpolys, list<TPPLPoly> *triangles);
 | 
			
		||||
 | 
			
		||||
	//creates a monotone partition of a list of polygons that can contain holes
 | 
			
		||||
	//time complexity: O(n*log(n)), n is the number of vertices
 | 
			
		||||
	//space complexity: O(n)
 | 
			
		||||
	//params:
 | 
			
		||||
	//   inpolys : a list of polygons to be triangulated (can contain holes)
 | 
			
		||||
	//             vertices of all non-hole polys have to be in counter-clockwise order
 | 
			
		||||
	//             vertices of all hole polys have to be in clockwise order
 | 
			
		||||
	//   monotonePolys : a list of monotone polygons (result)
 | 
			
		||||
	//returns 1 on success, 0 on failure
 | 
			
		||||
	int MonotonePartition(list<TPPLPoly> *inpolys, list<TPPLPoly> *monotonePolys);
 | 
			
		||||
 | 
			
		||||
	//partitions a polygon into convex polygons by using Hertel-Mehlhorn algorithm
 | 
			
		||||
	//the algorithm gives at most four times the number of parts as the optimal algorithm
 | 
			
		||||
	//however, in practice it works much better than that and often gives optimal partition
 | 
			
		||||
	//uses triangulation obtained by ear clipping as intermediate result
 | 
			
		||||
	//time complexity O(n^2), n is the number of vertices
 | 
			
		||||
	//space complexity: O(n)
 | 
			
		||||
	//params:
 | 
			
		||||
	//   poly : an input polygon to be partitioned
 | 
			
		||||
	//          vertices have to be in counter-clockwise order
 | 
			
		||||
	//   parts : resulting list of convex polygons
 | 
			
		||||
	//returns 1 on success, 0 on failure
 | 
			
		||||
	int ConvexPartition_HM(TPPLPoly *poly, list<TPPLPoly> *parts);
 | 
			
		||||
 | 
			
		||||
	//partitions a list of polygons into convex parts by using Hertel-Mehlhorn algorithm
 | 
			
		||||
	//the algorithm gives at most four times the number of parts as the optimal algorithm
 | 
			
		||||
	//however, in practice it works much better than that and often gives optimal partition
 | 
			
		||||
	//uses triangulation obtained by ear clipping as intermediate result
 | 
			
		||||
	//time complexity O(n^2), n is the number of vertices
 | 
			
		||||
	//space complexity: O(n)
 | 
			
		||||
	//params:
 | 
			
		||||
	//   inpolys : an input list of polygons to be partitioned
 | 
			
		||||
	//             vertices of all non-hole polys have to be in counter-clockwise order
 | 
			
		||||
	//             vertices of all hole polys have to be in clockwise order
 | 
			
		||||
	//   parts : resulting list of convex polygons
 | 
			
		||||
	//returns 1 on success, 0 on failure
 | 
			
		||||
	int ConvexPartition_HM(list<TPPLPoly> *inpolys, list<TPPLPoly> *parts);
 | 
			
		||||
 | 
			
		||||
	//optimal convex partitioning (in terms of number of resulting convex polygons)
 | 
			
		||||
	//using the Keil-Snoeyink algorithm
 | 
			
		||||
	//M. Keil, J. Snoeyink, "On the time bound for convex decomposition of simple polygons", 1998
 | 
			
		||||
	//time complexity O(n^3), n is the number of vertices
 | 
			
		||||
	//space complexity: O(n^3)
 | 
			
		||||
	//   poly : an input polygon to be partitioned
 | 
			
		||||
	//          vertices have to be in counter-clockwise order
 | 
			
		||||
	//   parts : resulting list of convex polygons
 | 
			
		||||
	//returns 1 on success, 0 on failure
 | 
			
		||||
	int ConvexPartition_OPT(TPPLPoly *poly, list<TPPLPoly> *parts);
 | 
			
		||||
#ifdef TPPL_ALLOCATOR
 | 
			
		||||
        typedef std::list<Diagonal, TPPL_ALLOCATOR(Diagonal)> DiagonalList;
 | 
			
		||||
#else
 | 
			
		||||
        typedef std::list<Diagonal> DiagonalList;
 | 
			
		||||
#endif
 | 
			
		||||
        
 | 
			
		||||
        //dynamic programming state for minimum-weight triangulation
 | 
			
		||||
        struct DPState {
 | 
			
		||||
            bool visible;
 | 
			
		||||
            tppl_float weight;
 | 
			
		||||
            long bestvertex;
 | 
			
		||||
        };
 | 
			
		||||
        
 | 
			
		||||
        //dynamic programming state for convex partitioning
 | 
			
		||||
        struct DPState2 {
 | 
			
		||||
            bool visible;
 | 
			
		||||
            long weight;
 | 
			
		||||
            DiagonalList pairs;
 | 
			
		||||
        };
 | 
			
		||||
        
 | 
			
		||||
        //edge that intersects the scanline
 | 
			
		||||
        struct ScanLineEdge {
 | 
			
		||||
            mutable long index;
 | 
			
		||||
            TPPLPoint p1;
 | 
			
		||||
            TPPLPoint p2;
 | 
			
		||||
            
 | 
			
		||||
            //determines if the edge is to the left of another edge
 | 
			
		||||
            bool operator< (const ScanLineEdge & other) const;
 | 
			
		||||
            
 | 
			
		||||
            bool IsConvex(const TPPLPoint& p1, const TPPLPoint& p2, const TPPLPoint& p3) const;
 | 
			
		||||
        };
 | 
			
		||||
        
 | 
			
		||||
        //standard helper functions
 | 
			
		||||
        bool IsConvex(TPPLPoint& p1, TPPLPoint& p2, TPPLPoint& p3);
 | 
			
		||||
        bool IsReflex(TPPLPoint& p1, TPPLPoint& p2, TPPLPoint& p3);
 | 
			
		||||
        bool IsInside(TPPLPoint& p1, TPPLPoint& p2, TPPLPoint& p3, TPPLPoint &p);
 | 
			
		||||
        
 | 
			
		||||
        bool InCone(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3, TPPLPoint &p);
 | 
			
		||||
        bool InCone(PartitionVertex *v, TPPLPoint &p);
 | 
			
		||||
        
 | 
			
		||||
        int Intersects(TPPLPoint &p11, TPPLPoint &p12, TPPLPoint &p21, TPPLPoint &p22);
 | 
			
		||||
        
 | 
			
		||||
        TPPLPoint Normalize(const TPPLPoint &p);
 | 
			
		||||
        tppl_float Distance(const TPPLPoint &p1, const TPPLPoint &p2);
 | 
			
		||||
        
 | 
			
		||||
        //helper functions for Triangulate_EC
 | 
			
		||||
        void UpdateVertexReflexity(PartitionVertex *v);
 | 
			
		||||
        void UpdateVertex(PartitionVertex *v,PartitionVertex *vertices, long numvertices);
 | 
			
		||||
        
 | 
			
		||||
        //helper functions for ConvexPartition_OPT
 | 
			
		||||
        void UpdateState(long a, long b, long w, long i, long j, DPState2 **dpstates);
 | 
			
		||||
        void TypeA(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates);
 | 
			
		||||
        void TypeB(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates);
 | 
			
		||||
        
 | 
			
		||||
        //helper functions for MonotonePartition
 | 
			
		||||
        bool Below(TPPLPoint &p1, TPPLPoint &p2);
 | 
			
		||||
        void AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2,
 | 
			
		||||
            char *vertextypes, std::set<ScanLineEdge>::iterator *edgeTreeIterators,
 | 
			
		||||
            std::set<ScanLineEdge> *edgeTree, long *helpers);
 | 
			
		||||
        
 | 
			
		||||
        //triangulates a monotone polygon, used in Triangulate_MONO
 | 
			
		||||
        int TriangulateMonotone(TPPLPoly *inPoly, TPPLPolyList *triangles);
 | 
			
		||||
        
 | 
			
		||||
    public:
 | 
			
		||||
        
 | 
			
		||||
        //simple heuristic procedure for removing holes from a list of polygons
 | 
			
		||||
        //works by creating a diagonal from the rightmost hole vertex to some visible vertex
 | 
			
		||||
        //time complexity: O(h*(n^2)), h is the number of holes, n is the number of vertices
 | 
			
		||||
        //space complexity: O(n)
 | 
			
		||||
        //params:
 | 
			
		||||
        //   inpolys : a list of polygons that can contain holes
 | 
			
		||||
        //             vertices of all non-hole polys have to be in counter-clockwise order
 | 
			
		||||
        //             vertices of all hole polys have to be in clockwise order
 | 
			
		||||
        //   outpolys : a list of polygons without holes
 | 
			
		||||
        //returns 1 on success, 0 on failure
 | 
			
		||||
        int RemoveHoles(TPPLPolyList *inpolys, TPPLPolyList *outpolys);
 | 
			
		||||
        
 | 
			
		||||
        //triangulates a polygon by ear clipping
 | 
			
		||||
        //time complexity O(n^2), n is the number of vertices
 | 
			
		||||
        //space complexity: O(n)
 | 
			
		||||
        //params:
 | 
			
		||||
        //   poly : an input polygon to be triangulated
 | 
			
		||||
        //          vertices have to be in counter-clockwise order
 | 
			
		||||
        //   triangles : a list of triangles (result)
 | 
			
		||||
        //returns 1 on success, 0 on failure
 | 
			
		||||
        int Triangulate_EC(TPPLPoly *poly, TPPLPolyList *triangles);
 | 
			
		||||
        
 | 
			
		||||
        //triangulates a list of polygons that may contain holes by ear clipping algorithm
 | 
			
		||||
        //first calls RemoveHoles to get rid of the holes, and then Triangulate_EC for each resulting polygon
 | 
			
		||||
        //time complexity: O(h*(n^2)), h is the number of holes, n is the number of vertices
 | 
			
		||||
        //space complexity: O(n)
 | 
			
		||||
        //params:
 | 
			
		||||
        //   inpolys : a list of polygons to be triangulated (can contain holes)
 | 
			
		||||
        //             vertices of all non-hole polys have to be in counter-clockwise order
 | 
			
		||||
        //             vertices of all hole polys have to be in clockwise order
 | 
			
		||||
        //   triangles : a list of triangles (result)
 | 
			
		||||
        //returns 1 on success, 0 on failure
 | 
			
		||||
        int Triangulate_EC(TPPLPolyList *inpolys, TPPLPolyList *triangles);
 | 
			
		||||
        
 | 
			
		||||
        //creates an optimal polygon triangulation in terms of minimal edge length
 | 
			
		||||
        //time complexity: O(n^3), n is the number of vertices
 | 
			
		||||
        //space complexity: O(n^2)
 | 
			
		||||
        //params:
 | 
			
		||||
        //   poly : an input polygon to be triangulated
 | 
			
		||||
        //          vertices have to be in counter-clockwise order
 | 
			
		||||
        //   triangles : a list of triangles (result)
 | 
			
		||||
        //returns 1 on success, 0 on failure
 | 
			
		||||
        int Triangulate_OPT(TPPLPoly *poly, TPPLPolyList *triangles);
 | 
			
		||||
        
 | 
			
		||||
        //triangulates a polygons by firstly partitioning it into monotone polygons
 | 
			
		||||
        //time complexity: O(n*log(n)), n is the number of vertices
 | 
			
		||||
        //space complexity: O(n)
 | 
			
		||||
        //params:
 | 
			
		||||
        //   poly : an input polygon to be triangulated
 | 
			
		||||
        //          vertices have to be in counter-clockwise order
 | 
			
		||||
        //   triangles : a list of triangles (result)
 | 
			
		||||
        //returns 1 on success, 0 on failure
 | 
			
		||||
        int Triangulate_MONO(TPPLPoly *poly, TPPLPolyList *triangles);
 | 
			
		||||
        
 | 
			
		||||
        //triangulates a list of polygons by firstly partitioning them into monotone polygons
 | 
			
		||||
        //time complexity: O(n*log(n)), n is the number of vertices
 | 
			
		||||
        //space complexity: O(n)
 | 
			
		||||
        //params:
 | 
			
		||||
        //   inpolys : a list of polygons to be triangulated (can contain holes)
 | 
			
		||||
        //             vertices of all non-hole polys have to be in counter-clockwise order
 | 
			
		||||
        //             vertices of all hole polys have to be in clockwise order
 | 
			
		||||
        //   triangles : a list of triangles (result)
 | 
			
		||||
        //returns 1 on success, 0 on failure
 | 
			
		||||
        int Triangulate_MONO(TPPLPolyList *inpolys, TPPLPolyList *triangles);
 | 
			
		||||
        
 | 
			
		||||
        //creates a monotone partition of a list of polygons that can contain holes
 | 
			
		||||
        //time complexity: O(n*log(n)), n is the number of vertices
 | 
			
		||||
        //space complexity: O(n)
 | 
			
		||||
        //params:
 | 
			
		||||
        //   inpolys : a list of polygons to be triangulated (can contain holes)
 | 
			
		||||
        //             vertices of all non-hole polys have to be in counter-clockwise order
 | 
			
		||||
        //             vertices of all hole polys have to be in clockwise order
 | 
			
		||||
        //   monotonePolys : a list of monotone polygons (result)
 | 
			
		||||
        //returns 1 on success, 0 on failure
 | 
			
		||||
        int MonotonePartition(TPPLPolyList *inpolys, TPPLPolyList *monotonePolys);
 | 
			
		||||
        
 | 
			
		||||
        //partitions a polygon into convex polygons by using Hertel-Mehlhorn algorithm
 | 
			
		||||
        //the algorithm gives at most four times the number of parts as the optimal algorithm
 | 
			
		||||
        //however, in practice it works much better than that and often gives optimal partition
 | 
			
		||||
        //uses triangulation obtained by ear clipping as intermediate result
 | 
			
		||||
        //time complexity O(n^2), n is the number of vertices
 | 
			
		||||
        //space complexity: O(n)
 | 
			
		||||
        //params:
 | 
			
		||||
        //   poly : an input polygon to be partitioned
 | 
			
		||||
        //          vertices have to be in counter-clockwise order
 | 
			
		||||
        //   parts : resulting list of convex polygons
 | 
			
		||||
        //returns 1 on success, 0 on failure
 | 
			
		||||
        int ConvexPartition_HM(TPPLPoly *poly, TPPLPolyList *parts);
 | 
			
		||||
        
 | 
			
		||||
        //partitions a list of polygons into convex parts by using Hertel-Mehlhorn algorithm
 | 
			
		||||
        //the algorithm gives at most four times the number of parts as the optimal algorithm
 | 
			
		||||
        //however, in practice it works much better than that and often gives optimal partition
 | 
			
		||||
        //uses triangulation obtained by ear clipping as intermediate result
 | 
			
		||||
        //time complexity O(n^2), n is the number of vertices
 | 
			
		||||
        //space complexity: O(n)
 | 
			
		||||
        //params:
 | 
			
		||||
        //   inpolys : an input list of polygons to be partitioned
 | 
			
		||||
        //             vertices of all non-hole polys have to be in counter-clockwise order
 | 
			
		||||
        //             vertices of all hole polys have to be in clockwise order
 | 
			
		||||
        //   parts : resulting list of convex polygons
 | 
			
		||||
        //returns 1 on success, 0 on failure
 | 
			
		||||
        int ConvexPartition_HM(TPPLPolyList *inpolys, TPPLPolyList *parts);
 | 
			
		||||
        
 | 
			
		||||
        //optimal convex partitioning (in terms of number of resulting convex polygons)
 | 
			
		||||
        //using the Keil-Snoeyink algorithm
 | 
			
		||||
        //M. Keil, J. Snoeyink, "On the time bound for convex decomposition of simple polygons", 1998
 | 
			
		||||
        //time complexity O(n^3), n is the number of vertices
 | 
			
		||||
        //space complexity: O(n^3)
 | 
			
		||||
        //   poly : an input polygon to be partitioned
 | 
			
		||||
        //          vertices have to be in counter-clockwise order
 | 
			
		||||
        //   parts : resulting list of convex polygons
 | 
			
		||||
        //returns 1 on success, 0 on failure
 | 
			
		||||
        int ConvexPartition_OPT(TPPLPoly *poly, TPPLPolyList *parts);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1959,7 +1959,7 @@ bool GLBed::on_init_from_file(const std::string& filename, bool useVBOs)
 | 
			
		|||
    {
 | 
			
		||||
        model = Model::read_from_file(filename);
 | 
			
		||||
    }
 | 
			
		||||
    catch (std::exception &e)
 | 
			
		||||
    catch (std::exception & /* ex */)
 | 
			
		||||
    {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1978,7 +1978,7 @@ bool GLBed::on_init_from_file(const std::string& filename, bool useVBOs)
 | 
			
		|||
    else
 | 
			
		||||
        m_volume.indexed_vertex_array.load_mesh_flat_shading(mesh);
 | 
			
		||||
 | 
			
		||||
    float color[4] = { 0.235f, 0.235, 0.235f, 1.0f };
 | 
			
		||||
    float color[4] = { 0.235f, 0.235f, 0.235f, 1.0f };
 | 
			
		||||
    set_color(color, 4);
 | 
			
		||||
 | 
			
		||||
    m_volume.bounding_box = m_volume.indexed_vertex_array.bounding_box();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,7 @@
 | 
			
		|||
#include "GLCanvas3D.hpp"
 | 
			
		||||
 | 
			
		||||
#include "admesh/stl.h"
 | 
			
		||||
#include "polypartition.h"
 | 
			
		||||
#include "libslic3r/libslic3r.h"
 | 
			
		||||
#include "libslic3r/ClipperUtils.hpp"
 | 
			
		||||
#include "libslic3r/PrintConfig.hpp"
 | 
			
		||||
| 
						 | 
				
			
			@ -6431,6 +6432,219 @@ void GLCanvas3D::_render_camera_target() const
 | 
			
		|||
}
 | 
			
		||||
#endif // ENABLE_SHOW_CAMERA_TARGET
 | 
			
		||||
 | 
			
		||||
class TessWrapper {
 | 
			
		||||
public:
 | 
			
		||||
	static Pointf3s tesselate(const ExPolygon &expoly, double z_, bool flipped_)
 | 
			
		||||
	{
 | 
			
		||||
		z = z_;
 | 
			
		||||
		flipped = flipped_;
 | 
			
		||||
		triangles.clear();
 | 
			
		||||
		intersection_points.clear();
 | 
			
		||||
		std::vector<GLdouble> coords;
 | 
			
		||||
		{
 | 
			
		||||
			size_t num_coords = expoly.contour.points.size();
 | 
			
		||||
			for (const Polygon &poly : expoly.holes)
 | 
			
		||||
				num_coords += poly.points.size();
 | 
			
		||||
			coords.reserve(num_coords * 3);
 | 
			
		||||
		}
 | 
			
		||||
		GLUtesselator *tess = gluNewTess(); // create a tessellator
 | 
			
		||||
		// register callback functions
 | 
			
		||||
		gluTessCallback(tess, GLU_TESS_BEGIN,   (void(__stdcall*)(void))tessBeginCB);
 | 
			
		||||
		gluTessCallback(tess, GLU_TESS_END,     (void(__stdcall*)(void))tessEndCB);
 | 
			
		||||
		gluTessCallback(tess, GLU_TESS_ERROR,   (void(__stdcall*)(void))tessErrorCB);
 | 
			
		||||
		gluTessCallback(tess, GLU_TESS_VERTEX,  (void(__stdcall*)())tessVertexCB);
 | 
			
		||||
        gluTessCallback(tess, GLU_TESS_COMBINE, (void (__stdcall*)(void))tessCombineCB);
 | 
			
		||||
		gluTessBeginPolygon(tess, 0); // with NULL data
 | 
			
		||||
		gluTessBeginContour(tess);
 | 
			
		||||
		for (const Point &pt : expoly.contour.points) {
 | 
			
		||||
			coords.emplace_back(unscale<double>(pt[0]));
 | 
			
		||||
			coords.emplace_back(unscale<double>(pt[1]));
 | 
			
		||||
			coords.emplace_back(0.);
 | 
			
		||||
			gluTessVertex(tess, &coords[coords.size() - 3], &coords[coords.size() - 3]);
 | 
			
		||||
		}
 | 
			
		||||
		gluTessEndContour(tess);
 | 
			
		||||
		for (const Polygon &poly : expoly.holes) {
 | 
			
		||||
			gluTessBeginContour(tess);
 | 
			
		||||
			for (const Point &pt : poly.points) {
 | 
			
		||||
				coords.emplace_back(unscale<double>(pt[0]));
 | 
			
		||||
				coords.emplace_back(unscale<double>(pt[1]));
 | 
			
		||||
				coords.emplace_back(0.);
 | 
			
		||||
				gluTessVertex(tess, &coords[coords.size() - 3], &coords[coords.size() - 3]);
 | 
			
		||||
			}
 | 
			
		||||
			gluTessEndContour(tess);
 | 
			
		||||
		}
 | 
			
		||||
		gluTessEndPolygon(tess);
 | 
			
		||||
		gluDeleteTess(tess);
 | 
			
		||||
		return std::move(triangles);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	static void tessBeginCB(GLenum which)
 | 
			
		||||
	{
 | 
			
		||||
		assert(which == GL_TRIANGLES || which == GL_TRIANGLE_FAN || which == GL_TRIANGLE_STRIP);
 | 
			
		||||
		if (!(which == GL_TRIANGLES || which == GL_TRIANGLE_FAN || which == GL_TRIANGLE_STRIP))
 | 
			
		||||
			printf("Co je to za haluz!?\n");
 | 
			
		||||
		primitive_type = which;
 | 
			
		||||
		num_points = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static void tessEndCB()
 | 
			
		||||
	{
 | 
			
		||||
		num_points = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static void tessVertexCB(const GLvoid *data)
 | 
			
		||||
	{
 | 
			
		||||
		if (data == nullptr)
 | 
			
		||||
			return;
 | 
			
		||||
		const GLdouble *ptr = (const GLdouble*)data;
 | 
			
		||||
		++ num_points;
 | 
			
		||||
		if (num_points == 1) {
 | 
			
		||||
			memcpy(pt0, ptr, sizeof(GLdouble) * 3);
 | 
			
		||||
		} else if (num_points == 2) {
 | 
			
		||||
			memcpy(pt1, ptr, sizeof(GLdouble) * 3);
 | 
			
		||||
		} else {
 | 
			
		||||
			bool flip = flipped;
 | 
			
		||||
			if (primitive_type == GL_TRIANGLE_STRIP && num_points == 4) {
 | 
			
		||||
				flip = !flip;
 | 
			
		||||
				num_points = 2;
 | 
			
		||||
			}
 | 
			
		||||
			triangles.emplace_back(pt0[0], pt0[1], z);
 | 
			
		||||
			if (flip) {
 | 
			
		||||
				triangles.emplace_back(ptr[0], ptr[1], z);
 | 
			
		||||
				triangles.emplace_back(pt1[0], pt1[1], z);
 | 
			
		||||
			} else {
 | 
			
		||||
				triangles.emplace_back(pt1[0], pt1[1], z);
 | 
			
		||||
				triangles.emplace_back(ptr[0], ptr[1], z);
 | 
			
		||||
			}
 | 
			
		||||
			if (primitive_type == GL_TRIANGLE_STRIP) {
 | 
			
		||||
				memcpy(pt0, pt1, sizeof(GLdouble) * 3);
 | 
			
		||||
				memcpy(pt1, ptr, sizeof(GLdouble) * 3);
 | 
			
		||||
			} else if (primitive_type == GL_TRIANGLE_FAN) {
 | 
			
		||||
				memcpy(pt1, ptr, sizeof(GLdouble) * 3);
 | 
			
		||||
			} else {
 | 
			
		||||
				assert(which == GL_TRIANGLES);
 | 
			
		||||
				assert(num_points == 3);
 | 
			
		||||
				num_points = 0;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    static void tessCombineCB(const GLdouble newVertex[3], const GLdouble *neighborVertex[4], const GLfloat neighborWeight[4], GLdouble **outData)
 | 
			
		||||
    {
 | 
			
		||||
        intersection_points.emplace_back(newVertex[0], newVertex[1], newVertex[2]);
 | 
			
		||||
        *outData = intersection_points.back().data();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	static void tessErrorCB(GLenum errorCode)
 | 
			
		||||
	{
 | 
			
		||||
		const GLubyte *errorStr;
 | 
			
		||||
		errorStr = gluErrorString(errorCode);
 | 
			
		||||
		printf("Error: %s\n", (const char*)errorStr);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static GLenum   primitive_type;
 | 
			
		||||
	static GLdouble pt0[3];
 | 
			
		||||
	static GLdouble pt1[3];
 | 
			
		||||
	static int      num_points;
 | 
			
		||||
	static Pointf3s triangles;
 | 
			
		||||
    static std::deque<Vec3d> intersection_points;
 | 
			
		||||
	static double   z;
 | 
			
		||||
	static bool     flipped;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
GLenum   TessWrapper::primitive_type;
 | 
			
		||||
GLdouble TessWrapper::pt0[3];
 | 
			
		||||
GLdouble TessWrapper::pt1[3];
 | 
			
		||||
int      TessWrapper::num_points;
 | 
			
		||||
Pointf3s TessWrapper::triangles;
 | 
			
		||||
std::deque<Vec3d> TessWrapper::intersection_points;
 | 
			
		||||
double   TessWrapper::z;
 | 
			
		||||
bool     TessWrapper::flipped;
 | 
			
		||||
 | 
			
		||||
static Pointf3s triangulate_expolygons(const ExPolygons &polys, coordf_t z, bool flip)
 | 
			
		||||
{
 | 
			
		||||
	Pointf3s triangles;
 | 
			
		||||
#if 0
 | 
			
		||||
	for (const ExPolygon& poly : polys) {
 | 
			
		||||
		Polygons poly_triangles;
 | 
			
		||||
		// poly.triangulate() is based on a trapezoidal decomposition implemented in an extremely expensive way by clipping the whole input contour with a polygon!
 | 
			
		||||
		poly.triangulate(&poly_triangles);
 | 
			
		||||
		// poly.triangulate_p2t() is based on the poly2tri library, which is not quite stable, it often ends up in a nice stack overflow!
 | 
			
		||||
		//        poly.triangulate_p2t(&poly_triangles);
 | 
			
		||||
		for (const Polygon &t : poly_triangles)
 | 
			
		||||
			if (flip) {
 | 
			
		||||
				triangles.emplace_back(to_3d(unscale(t.points[2]), z));
 | 
			
		||||
				triangles.emplace_back(to_3d(unscale(t.points[1]), z));
 | 
			
		||||
				triangles.emplace_back(to_3d(unscale(t.points[0]), z));
 | 
			
		||||
			} else {
 | 
			
		||||
				triangles.emplace_back(to_3d(unscale(t.points[0]), z));
 | 
			
		||||
				triangles.emplace_back(to_3d(unscale(t.points[1]), z));
 | 
			
		||||
				triangles.emplace_back(to_3d(unscale(t.points[2]), z));
 | 
			
		||||
			}
 | 
			
		||||
	}
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
//	for (const ExPolygon &poly : union_ex(simplify_polygons(to_polygons(polys), true))) {
 | 
			
		||||
    for (const ExPolygon &poly : polys) {
 | 
			
		||||
		append(triangles, TessWrapper::tesselate(poly, z, flip));
 | 
			
		||||
		continue;
 | 
			
		||||
 | 
			
		||||
		std::list<TPPLPoly> input = expoly_to_polypartition_input(poly);
 | 
			
		||||
		std::list<TPPLPoly> output;
 | 
			
		||||
	//	int res = TPPLPartition().Triangulate_MONO(&input, &output);
 | 
			
		||||
		int res = TPPLPartition().Triangulate_EC(&input, &output);
 | 
			
		||||
		if (res == 1) {
 | 
			
		||||
			// Triangulation succeeded. Convert to triangles.
 | 
			
		||||
			size_t num_triangles = 0;
 | 
			
		||||
			for (const TPPLPoly &poly : output)
 | 
			
		||||
				if (poly.GetNumPoints() >= 3)
 | 
			
		||||
					num_triangles += (size_t)poly.GetNumPoints() - 2;
 | 
			
		||||
			triangles.reserve(triangles.size() + num_triangles * 3);
 | 
			
		||||
			for (const TPPLPoly &poly : output) {
 | 
			
		||||
				long num_points = poly.GetNumPoints();
 | 
			
		||||
				if (num_points >= 3) {
 | 
			
		||||
					const TPPLPoint *pt0 = &poly[0];
 | 
			
		||||
					const TPPLPoint *pt1 = nullptr;
 | 
			
		||||
					const TPPLPoint *pt2 = &poly[1];
 | 
			
		||||
					for (long i = 2; i < num_points; ++i) {
 | 
			
		||||
						pt1 = pt2;
 | 
			
		||||
						pt2 = &poly[i];
 | 
			
		||||
						if (flip) {
 | 
			
		||||
							triangles.emplace_back(unscale<double>(pt2->x), unscale<double>(pt2->y), z);
 | 
			
		||||
							triangles.emplace_back(unscale<double>(pt1->x), unscale<double>(pt1->y), z);
 | 
			
		||||
							triangles.emplace_back(unscale<double>(pt0->x), unscale<double>(pt0->y), z);
 | 
			
		||||
						} else {
 | 
			
		||||
							triangles.emplace_back(unscale<double>(pt0->x), unscale<double>(pt0->y), z);
 | 
			
		||||
							triangles.emplace_back(unscale<double>(pt1->x), unscale<double>(pt1->y), z);
 | 
			
		||||
							triangles.emplace_back(unscale<double>(pt2->x), unscale<double>(pt2->y), z);
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			// Triangulation by polypartition failed. Use the expensive slow implementation.
 | 
			
		||||
			Polygons poly_triangles;
 | 
			
		||||
			// poly.triangulate() is based on a trapezoidal decomposition implemented in an extremely expensive way by clipping the whole input contour with a polygon!
 | 
			
		||||
			poly.triangulate(&poly_triangles);
 | 
			
		||||
			// poly.triangulate_p2t() is based on the poly2tri library, which is not quite stable, it often ends up in a nice stack overflow!
 | 
			
		||||
			//        poly.triangulate_p2t(&poly_triangles);
 | 
			
		||||
			for (const Polygon &t : poly_triangles)
 | 
			
		||||
				if (flip) {
 | 
			
		||||
					triangles.emplace_back(to_3d(unscale(t.points[2]), z));
 | 
			
		||||
					triangles.emplace_back(to_3d(unscale(t.points[1]), z));
 | 
			
		||||
					triangles.emplace_back(to_3d(unscale(t.points[0]), z));
 | 
			
		||||
				} else {
 | 
			
		||||
					triangles.emplace_back(to_3d(unscale(t.points[0]), z));
 | 
			
		||||
					triangles.emplace_back(to_3d(unscale(t.points[1]), z));
 | 
			
		||||
					triangles.emplace_back(to_3d(unscale(t.points[2]), z));
 | 
			
		||||
				}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
	return triangles;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GLCanvas3D::_render_sla_slices() const
 | 
			
		||||
{
 | 
			
		||||
    if (!m_use_clipping_planes || wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA)
 | 
			
		||||
| 
						 | 
				
			
			@ -6448,34 +6662,32 @@ void GLCanvas3D::_render_sla_slices() const
 | 
			
		|||
    {
 | 
			
		||||
        const SLAPrintObject* obj = print_objects[i];
 | 
			
		||||
 | 
			
		||||
        Pointf3s bottom_obj_triangles;
 | 
			
		||||
        Pointf3s bottom_sup_triangles;
 | 
			
		||||
        Pointf3s top_obj_triangles;
 | 
			
		||||
        Pointf3s top_sup_triangles;
 | 
			
		||||
 | 
			
		||||
        double shift_z = obj->get_current_elevation();
 | 
			
		||||
        double min_z = clip_min_z - shift_z;
 | 
			
		||||
        double max_z = clip_max_z - shift_z;
 | 
			
		||||
 | 
			
		||||
        if (m_sla_caps[0].matches(min_z))
 | 
			
		||||
        SlaCap::ObjectIdToTrianglesMap::iterator it_caps_bottom = m_sla_caps[0].triangles.find(i);
 | 
			
		||||
        SlaCap::ObjectIdToTrianglesMap::iterator it_caps_top    = m_sla_caps[1].triangles.find(i);
 | 
			
		||||
        {
 | 
			
		||||
            SlaCap::ObjectIdToTrianglesMap::const_iterator it = m_sla_caps[0].triangles.find(i);
 | 
			
		||||
            if (it != m_sla_caps[0].triangles.end())
 | 
			
		||||
            {
 | 
			
		||||
                bottom_obj_triangles = it->second.object;
 | 
			
		||||
                bottom_sup_triangles = it->second.suppports;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (m_sla_caps[1].matches(max_z))
 | 
			
		||||
        {
 | 
			
		||||
            SlaCap::ObjectIdToTrianglesMap::const_iterator it = m_sla_caps[1].triangles.find(i);
 | 
			
		||||
            if (it != m_sla_caps[1].triangles.end())
 | 
			
		||||
            {
 | 
			
		||||
                top_obj_triangles = it->second.object;
 | 
			
		||||
                top_sup_triangles = it->second.suppports;
 | 
			
		||||
			if (it_caps_bottom == m_sla_caps[0].triangles.end())
 | 
			
		||||
				it_caps_bottom = m_sla_caps[0].triangles.emplace(i, SlaCap::Triangles()).first;
 | 
			
		||||
            if (! m_sla_caps[0].matches(min_z)) {
 | 
			
		||||
				m_sla_caps[0].z = min_z;
 | 
			
		||||
                it_caps_bottom->second.object.clear();
 | 
			
		||||
                it_caps_bottom->second.supports.clear();
 | 
			
		||||
            }
 | 
			
		||||
            if (it_caps_top == m_sla_caps[1].triangles.end())
 | 
			
		||||
				it_caps_top = m_sla_caps[1].triangles.emplace(i, SlaCap::Triangles()).first;
 | 
			
		||||
            if (! m_sla_caps[1].matches(max_z)) {
 | 
			
		||||
				m_sla_caps[1].z = max_z;
 | 
			
		||||
                it_caps_top->second.object.clear();
 | 
			
		||||
                it_caps_top->second.supports.clear();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        Pointf3s &bottom_obj_triangles = it_caps_bottom->second.object;
 | 
			
		||||
        Pointf3s &bottom_sup_triangles = it_caps_bottom->second.supports;
 | 
			
		||||
        Pointf3s &top_obj_triangles    = it_caps_top->second.object;
 | 
			
		||||
        Pointf3s &top_sup_triangles    = it_caps_top->second.supports;
 | 
			
		||||
 | 
			
		||||
        const std::vector<SLAPrintObject::Instance>& instances = obj->instances();
 | 
			
		||||
        struct InstanceTransform
 | 
			
		||||
| 
						 | 
				
			
			@ -6501,86 +6713,22 @@ void GLCanvas3D::_render_sla_slices() const
 | 
			
		|||
 | 
			
		||||
            if (it_min_z != index.end())
 | 
			
		||||
            {
 | 
			
		||||
                // calculate model bottom cap
 | 
			
		||||
                if (bottom_obj_triangles.empty() && (it_min_z->second.model_slices_idx < model_slices.size()))
 | 
			
		||||
                {
 | 
			
		||||
                    // calculate model bottom cap
 | 
			
		||||
                    const ExPolygons& polys = model_slices[it_min_z->second.model_slices_idx];
 | 
			
		||||
                    for (const ExPolygon& poly : polys)
 | 
			
		||||
                    {
 | 
			
		||||
                        Polygons poly_triangles;
 | 
			
		||||
                        poly.triangulate(&poly_triangles);
 | 
			
		||||
                        for (const Polygon& t : poly_triangles)
 | 
			
		||||
                        {
 | 
			
		||||
                            for (int v = 2; v >= 0; --v)
 | 
			
		||||
                            {
 | 
			
		||||
                                bottom_obj_triangles.emplace_back(to_3d(unscale(t.points[v]), min_z));
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                    bottom_obj_triangles = triangulate_expolygons(model_slices[it_min_z->second.model_slices_idx], min_z, true);
 | 
			
		||||
                // calculate support bottom cap
 | 
			
		||||
                if (bottom_sup_triangles.empty() && (it_min_z->second.support_slices_idx < support_slices.size()))
 | 
			
		||||
                {
 | 
			
		||||
                    // calculate support bottom cap
 | 
			
		||||
                    const ExPolygons& polys = support_slices[it_min_z->second.support_slices_idx];
 | 
			
		||||
                    for (const ExPolygon& poly : polys)
 | 
			
		||||
                    {
 | 
			
		||||
                        Polygons poly_triangles;
 | 
			
		||||
                        poly.triangulate(&poly_triangles);
 | 
			
		||||
                        for (const Polygon& t : poly_triangles)
 | 
			
		||||
                        {
 | 
			
		||||
                            for (int v = 2; v >= 0; --v)
 | 
			
		||||
                            {
 | 
			
		||||
                                bottom_sup_triangles.emplace_back(to_3d(unscale(t.points[v]), min_z));
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    m_sla_caps[0].triangles.insert(SlaCap::ObjectIdToTrianglesMap::value_type(i, { bottom_obj_triangles, bottom_sup_triangles }));
 | 
			
		||||
                    m_sla_caps[0].z = min_z;
 | 
			
		||||
                }
 | 
			
		||||
                    bottom_sup_triangles = triangulate_expolygons(support_slices[it_min_z->second.support_slices_idx], min_z, true);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (it_max_z != index.end())
 | 
			
		||||
            {
 | 
			
		||||
                // calculate model top cap
 | 
			
		||||
                if (top_obj_triangles.empty() && (it_max_z->second.model_slices_idx < model_slices.size()))
 | 
			
		||||
                {
 | 
			
		||||
                    // calculate model top cap
 | 
			
		||||
                    const ExPolygons& polys = model_slices[it_max_z->second.model_slices_idx];
 | 
			
		||||
                    for (const ExPolygon& poly : polys)
 | 
			
		||||
                    {
 | 
			
		||||
                        Polygons poly_triangles;
 | 
			
		||||
                        poly.triangulate(&poly_triangles);
 | 
			
		||||
                        for (const Polygon& t : poly_triangles)
 | 
			
		||||
                        {
 | 
			
		||||
                            for (int v = 0; v < 3; ++v)
 | 
			
		||||
                            {
 | 
			
		||||
                                top_obj_triangles.emplace_back(to_3d(unscale(t.points[v]), max_z));
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                    top_obj_triangles = triangulate_expolygons(model_slices[it_max_z->second.model_slices_idx], max_z, false);
 | 
			
		||||
                // calculate support top cap
 | 
			
		||||
                if (top_sup_triangles.empty() && (it_max_z->second.support_slices_idx < support_slices.size()))
 | 
			
		||||
                {
 | 
			
		||||
                    // calculate support top cap
 | 
			
		||||
                    const ExPolygons& polys = support_slices[it_max_z->second.support_slices_idx];
 | 
			
		||||
                    for (const ExPolygon& poly : polys)
 | 
			
		||||
                    {
 | 
			
		||||
                        Polygons poly_triangles;
 | 
			
		||||
                        poly.triangulate(&poly_triangles);
 | 
			
		||||
                        for (const Polygon& t : poly_triangles)
 | 
			
		||||
                        {
 | 
			
		||||
                            for (int v = 0; v < 3; ++v)
 | 
			
		||||
                            {
 | 
			
		||||
                                top_sup_triangles.emplace_back(to_3d(unscale(t.points[v]), max_z));
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                m_sla_caps[1].triangles.insert(SlaCap::ObjectIdToTrianglesMap::value_type(i, { top_obj_triangles, top_sup_triangles }));
 | 
			
		||||
                m_sla_caps[1].z = max_z;
 | 
			
		||||
					top_sup_triangles = triangulate_expolygons(support_slices[it_max_z->second.support_slices_idx], max_z, false);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -780,7 +780,7 @@ private:
 | 
			
		|||
        struct Triangles
 | 
			
		||||
        {
 | 
			
		||||
            Pointf3s object;
 | 
			
		||||
            Pointf3s suppports;
 | 
			
		||||
            Pointf3s supports;
 | 
			
		||||
        };
 | 
			
		||||
        typedef std::map<unsigned int, Triangles> ObjectIdToTrianglesMap;
 | 
			
		||||
        double z;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -245,8 +245,6 @@ void show_info(wxWindow* parent, const wxString& message, const wxString& title)
 | 
			
		|||
 | 
			
		||||
void warning_catcher(wxWindow* parent, const wxString& message)
 | 
			
		||||
{
 | 
			
		||||
	if (message == "GLUquadricObjPtr | " + _(L("Attempt to free unreferenced scalar")) )
 | 
			
		||||
		return;
 | 
			
		||||
	wxMessageDialog msg(parent, message, _(L("Warning")), wxOK | wxICON_WARNING);
 | 
			
		||||
	msg.ShowModal();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,6 +30,10 @@ PrintHostSendDialog::PrintHostSendDialog(const fs::path &path)
 | 
			
		|||
    , txt_filename(new wxTextCtrl(this, wxID_ANY, path.filename().wstring()))
 | 
			
		||||
    , box_print(new wxCheckBox(this, wxID_ANY, _(L("Start printing after upload"))))
 | 
			
		||||
{
 | 
			
		||||
#ifdef __APPLE__
 | 
			
		||||
    txt_filename->OSXDisableAllSmartSubstitutions();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    auto *label_dir_hint = new wxStaticText(this, wxID_ANY, _(L("Use forward slashes ( / ) as a directory separator if needed.")));
 | 
			
		||||
    label_dir_hint->Wrap(CONTENT_WIDTH);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue