checked in c++ code

This commit is contained in:
zzzzrrr 2010-01-17 11:41:09 -05:00
parent 29bbeb2973
commit 9b279f68b5
33 changed files with 16223 additions and 0 deletions

333
poly2tri/common/shapes.cc Normal file
View File

@ -0,0 +1,333 @@
/*
* Poly2Tri Copyright (c) 2009-2010, Mason Green
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "shapes.h"
Triangle::Triangle(Point& a, Point& b, Point& c) {
points_[0] = &a; points_[1] = &b; points_[2] = &c;
neighbors_[0] = NULL; neighbors_[1] = NULL; neighbors_[2] = NULL;
constrained_edge[0] = constrained_edge[1] = constrained_edge[2] = false;
delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false;
interior = false;
}
Triangle::~Triangle() {
printf("bye triangle\n");
}
// Update neighbor pointers
void Triangle::MarkNeighbor(Point* p1, Point* p2, Triangle* t) {
if((p1 == points_[2] && p2 == points_[1]) || (p1 == points_[1] && p2 == points_[2]))
neighbors_[0] = t;
else if((p1 == points_[0] && p2 == points_[2]) || (p1 == points_[2] && p2 == points_[0]))
neighbors_[1] = t;
else if((p1 == points_[0] && p2 == points_[1]) || (p1 == points_[1] && p2 == points_[0]))
neighbors_[2] = t;
else
assert(0);
}
// Exhaustive search to update neighbor pointers
void Triangle::MarkNeighbor(Triangle& t) {
if (t.Contains(points_[1], points_[2])) {
neighbors_[0] = &t;
t.MarkNeighbor(points_[1], points_[2], this);
} else if(t.Contains(points_[0], points_[2])) {
neighbors_[1] = &t;
t.MarkNeighbor(points_[0], points_[2], this);
} else if (t.Contains(points_[0], points_[1])) {
neighbors_[2] = &t;
t.MarkNeighbor(points_[0], points_[1], this);
}
}
void Triangle::ClearNeighbors() {
neighbors_[0] = NULL;
neighbors_[1] = NULL;
neighbors_[2] = NULL;
}
void Triangle::ClearDelunayEdges() {
delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false;
}
Point* Triangle::OppositePoint(Triangle& t, Point& p) {
Point *cw = t.PointCW(p);
double x = cw->x;
double y = cw->y;
x = p.x;
y = p.y;
Point* ham = PointCW(*cw);
return PointCW(*cw);
}
// Legalized triangle by rotating clockwise around point(0)
void Triangle::Legalize(Point& point) {
points_[1] = points_[0];
points_[0] = points_[2];
points_[2] = &point;
}
// Legalize triagnle by rotating clockwise around oPoint
void Triangle::Legalize(Point& opoint, Point& npoint) {
if(&opoint == points_[0]) {
points_[1] = points_[0];
points_[0] = points_[2];
points_[2] = &npoint;
} else if (&opoint == points_[1]) {
points_[2] = points_[1];
points_[1] = points_[0];
points_[0] = &npoint;
} else if (&opoint == points_[2]) {
points_[0] = points_[2];
points_[2] = points_[1];
points_[1] = &npoint;
} else {
assert(0);
}
}
int Triangle::Index(const Point* p) {
if(p == points_[0]) {
return 0;
} else if(p == points_[1]) {
return 1;
} else if(p == points_[2]) {
return 2;
}
assert(0);
}
int Triangle::EdgeIndex(const Point* p1, const Point* p2) {
if(points_[0] == p1) {
if(points_[1] == p2){
return 2;
} else if(points_[2] == p2){
return 1;
}
}
else if(points_[1] == p1) {
if(points_[2] == p2) {
return 0;
} else if(points_[0] == p2) {
return 2;
}
} else if(points_[2] == p1) {
if(points_[0] == p2 ) {
return 1;
} else if(points_[1] == p2) {
return 0;
}
}
return -1;
}
void Triangle::MarkConstrainedEdge(const int index) {
constrained_edge[index] = true;
}
void Triangle::MarkConstrainedEdge(Edge& edge) {
MarkConstrainedEdge(edge.p, edge.q);
if((edge.q == points_[0] && edge.p == points_[1]) || (edge.q == points_[1] && edge.p == points_[0])) {
constrained_edge[2] = true;
} else if((edge.q == points_[0] && edge.p == points_[2]) || (edge.q == points_[2] && edge.p == points_[0])) {
constrained_edge[1] = true;
} else if(( edge.q == points_[1] && edge.p == points_[2]) || (edge.q == points_[2] && edge.p == points_[1])) {
constrained_edge[0] = true;
}
}
// Mark edge as constrained
void Triangle::MarkConstrainedEdge(Point* p, Point* q) {
if((q == points_[0] && p == points_[1] ) || (q == points_[1] && p == points_[0])) {
constrained_edge[2] = true;
} else if((q == points_[0] && p == points_[2] ) || (q == points_[2] && p == points_[0])) {
constrained_edge[1] = true;
} else if((q == points_[1] && p == points_[2] ) || (q == points_[2] && p == points_[1])) {
constrained_edge[0] = true;
}
}
// The point counter-clockwise to given point
Point* Triangle::PointCW(Point& point) {
if(&point == points_[0]) {
return points_[2];
} else if(&point == points_[1]) {
return points_[0];
} else if(&point == points_[2]) {
return points_[1];
}
assert(0);
}
// The point counter-clockwise to given point
Point* Triangle::PointCCW(Point& point) {
if(&point == points_[0]) {
return points_[1];
} else if(&point == points_[1]) {
return points_[2];
} else if(&point == points_[2]) {
return points_[0];
}
assert(0);
}
// The neighbor clockwise to given point
Triangle* Triangle::NeighborCW(Point& point) {
if(&point == points_[0]) {
return neighbors_[1];
} else if(&point == points_[1]) {
return neighbors_[2];
}
return neighbors_[0];
}
// The neighbor counter-clockwise to given point
Triangle* Triangle::NeighborCCW(Point& point) {
if(&point == points_[0]) {
return neighbors_[2];
} else if(&point == points_[1]) {
return neighbors_[0];
}
return neighbors_[1];
}
bool Triangle::GetConstrainedEdgeCCW(Point& p) {
if(&p == points_[0]) {
return constrained_edge[2];
} else if(&p == points_[1]) {
return constrained_edge[0];
}
return constrained_edge[1];
}
bool Triangle::GetConstrainedEdgeCW(Point& p) {
if(&p == points_[0]) {
return constrained_edge[1];
} else if(&p == points_[1]) {
return constrained_edge[2];
}
return constrained_edge[0];
}
void Triangle::SetConstrainedEdgeCCW(Point& p, bool ce) {
if(&p == points_[0]) {
constrained_edge[2] = ce;
} else if(&p == points_[1]) {
constrained_edge[0] = ce;
} else {
constrained_edge[1] = ce;
}
}
void Triangle::SetConstrainedEdgeCW(Point& p, bool ce) {
if(&p == points_[0]) {
constrained_edge[1] = ce;
} else if(&p == points_[1]) {
constrained_edge[2] = ce;
} else {
constrained_edge[0] = ce;
}
}
bool Triangle::GetDelunayEdgeCCW(Point& p) {
if(&p == points_[0]){
return delaunay_edge[2];
} else if(&p == points_[1]) {
return delaunay_edge[0];
}
return delaunay_edge[1];
}
bool Triangle::GetDelunayEdgeCW(Point& p) {
if(&p == points_[0]) {
return delaunay_edge[1];
} else if(&p == points_[1]) {
return delaunay_edge[2];
}
return delaunay_edge[0];
}
void Triangle::SetDelunayEdgeCCW(Point& p, bool e) {
if(&p == points_[0]) {
delaunay_edge[2] = e;
} else if(&p == points_[1]) {
delaunay_edge[0] = e;
} else {
delaunay_edge[1] = e;
}
}
void Triangle::SetDelunayEdgeCW(Point& p, bool e) {
if(&p == points_[0]) {
delaunay_edge[1] = e;
} else if(&p == points_[1]) {
delaunay_edge[2] = e;
} else {
delaunay_edge[0] = e;
}
}
// The neighbor across to given point
Triangle& Triangle::NeighborAcross(Point& opoint) {
if(&opoint == points_[0]) {
return *neighbors_[0];
} else if(&opoint == points_[1]) {
return *neighbors_[1];
}
return *neighbors_[2];
}

277
poly2tri/common/shapes.h Normal file
View File

@ -0,0 +1,277 @@
/*
* Poly2Tri Copyright (c) 2009-2010, Mason Green
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Include guard
#ifndef SHAPES_H
#define SHAPES_H
#include <vector>
#include <cstddef>
#include <assert.h>
#include <cmath>
#include <stdio.h>
#include <iostream>
struct Node;
struct Edge;
struct Point {
double x, y;
/// Default constructor does nothing (for performance).
Point() {}
/// The edges this point constitutes an upper ending point
std::vector<Edge> edge_list;
/// Construct using coordinates.
Point(double x, double y) : x(x), y(y) {}
/// Set this point to all zeros.
void set_zero() { x = 0.0f; y = 0.0f; }
/// Set this point to some specified coordinates.
void set(double x_, double y_) { x = x_; y = y_; }
/// Negate this point.
Point operator -() const { Point v; v.set(-x, -y); return v; }
/// Add a point to this point.
void operator += (const Point& v) {
x += v.x; y += v.y;
}
/// Subtract a point from this point.
void operator -= (const Point& v) {
x -= v.x; y -= v.y;
}
/// Multiply this point by a scalar.
void operator *= (double a) {
x *= a; y *= a;
}
/// Get the length of this point (the norm).
double Length() const {
return sqrt(x * x + y * y);
}
/// Convert this point into a unit point. Returns the Length.
double Normalize() {
double len = Length();
x /= len;
y /= len;
return len;
}
};
// Represents a simple polygon's edge
struct Edge {
Point* p, *q;
/// Constructor
Edge(Point& p1, Point& p2) : p(&p1), q(&p2) {
if(p1.y > p2.y) {
q = &p1;
p = &p2;
} else if(p1.y == p2.y) {
if(p1.x > p2.x) {
q = &p1;
p = &p2;
} else if(p1.x == p2.x) {
assert(false);
}
}
q->edge_list.push_back(*this);
}
};
// Triangle-based data structures are know to have better performance than quad-edge structures
// See: J. Shewchuk, "Triangle: Engineering a 2D Quality Mesh Generator and Delaunay Triangulator"
// "Triangulations in CGAL"
class Triangle {
public:
/// Constructor
Triangle(Point& a, Point& b, Point& c);
// Destroctor
~Triangle();
/// Flags to determine if an edge is a Constrained edge
bool constrained_edge[3];
/// Flags to determine if an edge is a Delauney edge
bool delaunay_edge[3];
/// Has this triangle been marked as an interior triangle?
bool interior;
Point* GetPoint(const int& index);
Point* PointCW(Point& point);
Point* PointCCW(Point& point);
Point* OppositePoint(Triangle& t, Point& p);
Triangle* GetNeighbor(const int& index);
void MarkNeighbor(Point* p1, Point* p2, Triangle* t);
void MarkNeighbor(Triangle& t);
void MarkConstrainedEdge(const int index);
void MarkConstrainedEdge(Edge& edge);
void MarkConstrainedEdge(Point* p, Point* q);
int Index(const Point* p);
int EdgeIndex(const Point* p1, const Point* p2);
Triangle* NeighborCW(Point& point);
Triangle* NeighborCCW(Point& point);
bool GetConstrainedEdgeCCW(Point& p);
bool GetConstrainedEdgeCW(Point& p);
void SetConstrainedEdgeCCW(Point& p, bool ce);
void SetConstrainedEdgeCW(Point& p, bool ce);
bool GetDelunayEdgeCCW(Point& p);
bool GetDelunayEdgeCW(Point& p);
void SetDelunayEdgeCCW(Point& p, bool e);
void SetDelunayEdgeCW(Point& p, bool e);
bool Contains(Point* p);
bool Contains(const Edge& e);
bool Contains(Point* p, Point* q);
void Legalize(Point& point);
void Legalize(Point& opoint, Point& npoint);
void ClearNeighbors();
void ClearDelunayEdges();
Triangle& NeighborAcross(Point& opoint);
private:
/// Triangle points
Point* points_[3];
/// Neighbor list
Triangle* neighbors_[3];
};
inline bool operator < (const Point& a, const Point& b) {
if (a.y < b.y) {
return true;
} else if (a.y == b.y) {
// Make sure q is point with greater x value
if(a.x < b.x) {
return true;
} else if (a.x > b.x) {
return false;
} else {
// Repeat point
//std::cout << "Repeat points not alowed: ";
//std::cout << a.x << "," << a.y << " " << b.x << "," << b.y << std::endl;
//assert(false);
}
}
return false;
}
/// Add two points_ component-wise.
inline Point operator + (const Point& a, const Point& b) {
return Point(a.x + b.x, a.y + b.y);
}
/// Subtract two points_ component-wise.
inline Point operator - (const Point& a, const Point& b) {
return Point(a.x - b.x, a.y - b.y);
}
/// Multiply point by scalar
inline Point operator * (double s, const Point& a) {
return Point(s * a.x, s * a.y);
}
inline bool operator == (const Point& a, const Point& b) {
return a.x == b.x && a.y == b.y;
}
inline bool operator != (const Point& a, const Point& b) {
return a.x != b.x && a.y != b.y;
}
inline bool operator != (const Node& a, const Node& b) {
return a != b;
}
/// Peform the dot product on two vectors.
inline double Dot(const Point& a, const Point& b) {
return a.x * b.x + a.y * b.y;
}
/// Perform the cross product on two vectors. In 2D this produces a scalar.
inline double Cross(const Point& a, const Point& b) {
return a.x * b.y - a.y * b.x;
}
/// Perform the cross product on a point and a scalar. In 2D this produces
/// a point.
inline Point Cross(const Point& a, double s) {
return Point(s * a.y, -s * a.x);
}
/// Perform the cross product on a scalar and a point. In 2D this produces
/// a point.
inline Point Cross(const double s, const Point& a) {
return Point(-s * a.y, s * a.x);
}
inline Point* Triangle::GetPoint(const int& index) {
return points_[index];
}
inline Triangle* Triangle::GetNeighbor(const int& index) {
return neighbors_[index];
}
inline bool Triangle::Contains(Point* p) {
return p == points_[0] || p == points_[1] || p == points_[2];
}
inline bool Triangle::Contains(const Edge& e) {
return Contains(e.p) && Contains(e.q);
}
inline bool Triangle::Contains(Point* p, Point* q) {
return Contains(p) && Contains(q);
}
#endif

98
poly2tri/common/utils.h Normal file
View File

@ -0,0 +1,98 @@
/*
* Poly2Tri Copyright (c) 2009-2010, Mason Green
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdexcept>
#include <math.h>
#include "shapes.h"
template<typename T, int size>
int array_length(T(&)[size]){return size;}
const double PI_3div4 = 3*M_PI/4;
const double EPSILON = 1e-12;
enum Orientation { CW, CCW, COLLINEAR };
/**
* Forumla to calculate signed area<br>
* Positive if CCW<br>
* Negative if CW<br>
* 0 if collinear<br>
* <pre>
* A[P1,P2,P3] = (x1*y2 - y1*x2) + (x2*y3 - y2*x3) + (x3*y1 - y3*x1)
* = (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3)
* </pre>
*/
Orientation Orient2d(Point& pa, Point& pb, Point& pc ) {
double detleft = (pa.x - pc.x) * (pb.y - pc.y);
double detright = (pa.y - pc.y) * (pb.x - pc.x);
double val = detleft - detright;
if( val > -EPSILON && val < EPSILON ) {
return COLLINEAR;
} else if( val > 0 ) {
return CCW;
}
return CW;
}
bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd) {
const double pdx = pd.x;
const double pdy = pd.y;
const double adx = pa.x - pdx;
const double ady = pa.y - pdy;
const double bdx = pb.x - pdx;
const double bdy = pb.y - pdy;
const double adxbdy = adx * bdy;
const double bdxady = bdx * ady;
const double oabd = adxbdy - bdxady;
if(oabd <= 0) {
return false;
}
const double cdx = pc.x - pdx;
const double cdy = pc.y - pdy;
const double cdxady = cdx * ady;
const double adxcdy = adx * cdy;
const double ocad = cdxady - adxcdy;
if(ocad <= 0) {
return false;
}
return true;
}

2
poly2tri/poly2tri.h Normal file
View File

@ -0,0 +1,2 @@
#include "common/shapes.h"
#include "sweep/cdt.h"

View File

@ -0,0 +1,95 @@
/*
* Poly2Tri Copyright (c) 2009-2010, Mason Green
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "advancing_front.h"
Node* AdvancingFront::Locate(const double& x) {
Node* node = search_node_;
if(x < node->value) {
while((node = node->prev) != NULL) {
if(x >= node->value) {
search_node_ = node;
return node;
}
}
} else {
while((node = node->next) != NULL) {
if(x < node->value) {
search_node_ = node->prev;
return node->prev;
}
}
}
return NULL;
}
Node* AdvancingFront::FindSearchNode(const double& x) {
// TODO: implement BST index
return search_node_;
}
Node* AdvancingFront::LocatePoint(Point* point) {
const double px = point->x;
Node* node = FindSearchNode(px);
const double nx = node->point->x;
if(px == nx) {
if(point != node->point) {
// We might have two nodes with same x value for a short time
if(point == node->prev->point) {
node = node->prev;
} else if(point == node->next->point) {
node = node->next;
} else {
assert(0);
}
}
} else if(px < nx) {
while((node = node->prev) != NULL) {
if(point == node->point) {
break;
}
}
} else {
while((node = node->next) != NULL) {
if(point == node->point)
break;
}
}
search_node_ = node;
return node;
}
AdvancingFront::~AdvancingFront() {
delete head_; search_node_; tail_;
}

View File

@ -0,0 +1,98 @@
/*
* Poly2Tri Copyright (c) 2009-2010, Mason Green
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "../common/shapes.h"
struct Node;
// Advancing front node
struct Node {
Point* point;
Triangle* triangle;
Node* next;
Node* prev;
double value;
Node(Point& p) : point(&p), triangle(NULL), value(p.x), next(NULL), prev(NULL) {}
Node(Point& p, Triangle& t) : point(&p), triangle(&t), value(p.x),
next(NULL), prev(NULL) {}
/*
~Node() {
printf("going... ");
printf("bye node");
printf(" ... gone!\n");
}
*/
};
// Advancing front
class AdvancingFront {
public:
// Destructor
~AdvancingFront();
Node* head();
void set_head(Node* node);
Node* tail();
void set_tail(Node* node);
Node* search();
void set_search(Node* node);
/// Locate insertion point along advancing front
Node* Locate(const double& x);
Node* LocatePoint(Point* point);
private:
Node* head_, *tail_, *search_node_;
Node* FindSearchNode(const double& x);
};
inline Node* AdvancingFront::head() { return head_; }
inline void AdvancingFront::set_head(Node* node) { head_ = node; }
inline Node* AdvancingFront::tail() { return tail_; }
inline void AdvancingFront::set_tail(Node* node) { tail_ = node; }
inline Node* AdvancingFront::search() { return search_node_; }
inline void AdvancingFront::set_search(Node* node) { search_node_ = node; }

54
poly2tri/sweep/cdt.cc Normal file
View File

@ -0,0 +1,54 @@
/*
* Poly2Tri Copyright (c) 2009-2010, Mason Green
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "cdt.h"
CDT::CDT(Point polyline[], const int& point_count) {
sweep_context_ = new SweepContext(polyline, point_count);
sweep_ = new Sweep;
}
void CDT::AddHole(const Point poly_line[], const int point_count) {
}
void CDT::Triangulate() {
sweep_->Triangulate(*sweep_context_);
}
std::list<Triangle*> CDT::GetTriangles() {
return sweep_context_->GetTriangles();
}
CDT::~CDT() {
delete sweep_context_;
delete sweep_;
}

58
poly2tri/sweep/cdt.h Normal file
View File

@ -0,0 +1,58 @@
/*
* Poly2Tri Copyright (c) 2009-2010, Mason Green
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "advancing_front.h"
#include "mesh.h"
#include "sweep_context.h"
#include "sweep.h"
class CDT
{
public:
/// Constructor
CDT(Point poly_line[], const int& point_count);
/// Add a hole
void AddHole(const Point poly_line[], const int point_count);
/// Triangulate points
void Triangulate();
/// Get Delaunay triangles
std::list<Triangle*> GetTriangles();
private:
SweepContext* sweep_context_;
Sweep* sweep_;
/// Destructor
~CDT();
};

49
poly2tri/sweep/mesh.cc Normal file
View File

@ -0,0 +1,49 @@
/*
* Poly2Tri Copyright (c) 2009-2010, Mason Green
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "mesh.h"
// Recursively collect interior triangles and clean the mesh
// Excludes exterior triangles outside constrained edges
// Depth first search
void Mesh::clean(Triangle& triangle)
{
/*
if(triangle != NULL && !triangle.interior)
{
triangle.interior = true;
triangles += triangle;
for(i <- 0 until 3)
if(!triangle.edges(i))
clean(triangle.neighbors(i));
}
*/
}

50
poly2tri/sweep/mesh.h Normal file
View File

@ -0,0 +1,50 @@
/*
* Poly2Tri Copyright (c) 2009-2010, Mason Green
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <vector>
using namespace std;
class Triangle;
class Mesh
{
public:
/// Triangles that constitute the mesh
vector<Triangle> map;
// Debug triangles
//val debug = new ArrayBuffer[Triangle]
//val triangles = new ArrayBuffer[Triangle]
void clean(Triangle& triangle);
};

882
poly2tri/sweep/sweep.cc Normal file
View File

@ -0,0 +1,882 @@
/*
* Poly2Tri Copyright (c) 2009-2010, Mason Green
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "sweep.h"
#include "sweep_context.h"
#include "advancing_front.h"
#include "../common/utils.h"
// Triangulate simple polygon with holes
void Sweep::Triangulate(SweepContext& tcx) {
tcx.CreateAdvancingFront();
// Sweep points; build mesh
SweepPoints(tcx);
/*
// Finalize triangulation
if( tcx.getTriangulationMode() == TriangulationMode.Polygon ) {
finalizationPolygon( tcx );
} else {
finalizationConvexHull( tcx );
}
*/
}
void Sweep::SweepPoints(SweepContext& tcx ) {
for(int i = 1; i < tcx.point_count(); i++ ) {
Point& point = *tcx.GetPoint(i);
Node& node = PointEvent(tcx, point);
for(int i = 0; i < point.edge_list.size(); i++) {
EdgeEvent(tcx, point.edge_list[i], node );
}
}
}
/**
* Find closes node to the left of the new point and
* create a new triangle. If needed new holes and basins
* will be filled to.
*
* @param tcx
* @param point
* @return
*/
Node& Sweep::PointEvent(SweepContext& tcx, Point& point) {
Node& node = tcx.LocateNode(point);
Node& new_node = NewFrontTriangle(tcx, point, node);
// Only need to check +epsilon since point never have smaller
// x value than node due to how we fetch nodes from the front
if(point.x <= node.point->x + EPSILON) {
Fill(tcx, node);
}
//tcx.AddNode(new_node);
FillAdvancingFront(tcx, new_node);
return new_node;
}
void Sweep::EdgeEvent(SweepContext& tcx, Edge& edge, Node& node) {
tcx.edge_event.constrained_edge = &edge;
tcx.edge_event.right = edge.p->x > edge.q->x;
if(IsEdgeSideOfTriangle(*node.triangle, *edge.p, *edge.q)){
return;
}
// For now we will do all needed filling
// TODO: integrate with flip process might give some better performance
// but for now this avoid the issue with cases that needs both flips and fills
FillEdgeEvent(tcx, edge, node);
EdgeEvent(tcx, *edge.p, *edge.q , node.triangle, *edge.q);
}
void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangle, Point& point) {
if(IsEdgeSideOfTriangle(*triangle, ep, eq)) {
return;
}
Point* p1 = triangle->PointCCW(point);
Orientation o1 = Orient2d(eq, *p1, ep);
if(o1 == COLLINEAR) {
//throw new RuntimeException( "EdgeEvent - Collinear not supported" );
assert(false);
}
Point* p2 = triangle->PointCW(point);
Orientation o2 = Orient2d(eq, *p2, ep);
if(o2 == COLLINEAR) {
//throw new RuntimeException( "EdgeEvent - Collinear not supported" );
assert(false);
}
if(o1 == o2) {
// Need to decide if we are rotating CW or CCW to get to a triangle
// that will cross edge
if(o1 == CW) {
triangle = triangle->NeighborCCW(point);
} else {
triangle = triangle->NeighborCW(point);
}
EdgeEvent(tcx, ep, eq, triangle, point);
} else {
// This triangle crosses constraint so lets flippin start!
FlipEdgeEvent(tcx, ep, eq, *triangle, point);
}
}
bool Sweep::IsEdgeSideOfTriangle(Triangle& triangle, Point& ep, Point& eq) {
int index = triangle.EdgeIndex(&ep, &eq);
if(index != -1) {
triangle.MarkConstrainedEdge(index);
Triangle* t = triangle.GetNeighbor(index);
if(t){
t->MarkConstrainedEdge(&ep, &eq);
}
return true;
}
return false;
}
Node& Sweep::NewFrontTriangle(SweepContext& tcx, Point& point, Node& node ) {
Triangle* triangle = new Triangle(point, *node.point, *node.next->point);
triangle->MarkNeighbor(*node.triangle);
tcx.AddToMap(triangle);
Node* new_node = new Node(point);
new_node->next = node.next;
new_node->prev = &node;
node.next->prev = new_node;
node.next = new_node;
if(!Legalize(tcx, *triangle)) {
tcx.MapTriangleToNodes(*triangle);
}
return *new_node;
}
/**
* Adds a triangle to the advancing front to fill a hole.
* @param tcx
* @param node - middle node, that is the bottom of the hole
*/
void Sweep::Fill(SweepContext& tcx, Node& node) {
Triangle* triangle = new Triangle(*node.prev->point, *node.point,
*node.next->point);
// TODO: should copy the constrained_edge value from neighbor triangles
// for now constrained_edge values are copied during the legalize
triangle->MarkNeighbor(*node.prev->triangle);
triangle->MarkNeighbor(*node.triangle);
tcx.AddToMap(triangle);
// Update the advancing front
node.prev->next = node.next;
node.next->prev = node.prev;
// If it was legalized the triangle has already been mapped
if(!Legalize(tcx, *triangle)) {
tcx.MapTriangleToNodes(*triangle);
}
// TODO: delete node from memory
//tcx.RemoveNode(node);
}
/**
* Fills holes in the Advancing Front
*
*
* @param tcx
* @param n
*/
void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n) {
// Fill right holes
Node* node = n.next;
while(node->next) {
double angle = HoleAngle(*node);
if(angle > M_PI_2 || angle < -M_PI_2) break;
Fill(tcx, *node);
node = node->next;
}
// Fill left holes
node = n.prev;
while(node->prev) {
double angle = HoleAngle(*node);
if(angle > M_PI_2 || angle < -M_PI_2) break;
Fill(tcx, *node);
node = node->prev;
}
// Fill right basins
if(n.next && n.next->next) {
double angle = BasinAngle(n);
if(angle < PI_3div4) {
FillBasin(tcx, n);
}
}
}
double Sweep::BasinAngle(Node& node) {
double ax = node.point->x - node.next->next->point->x;
double ay = node.point->y - node.next->next->point->y;
return atan2(ay, ax);
}
/**
*
* @param node - middle node
* @return the angle between 3 front nodes
*/
double Sweep::HoleAngle(Node& node) {
/* Complex plane
* ab = cosA +i*sinA
* ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx)
* atan2(y,x) computes the principal value of the argument function
* applied to the complex number x+iy
* Where x = ax*bx + ay*by
* y = ax*by - ay*bx
*/
double ax = node.next->point->x - node.point->x;
double ay = node.next->point->y - node.point->y;
double bx = node.prev->point->x - node.point->x;
double by = node.prev->point->y - node.point->y;
return atan2(ax*by - ay*bx, ax*bx + ay*by);
}
/**
* Returns true if triangle was legalized
*/
bool Sweep::Legalize(SweepContext& tcx, Triangle& t) {
// To legalize a triangle we start by finding if any of the three edges
// violate the Delaunay condition
for(int i=0; i<3; i++) {
if(t.delaunay_edge[i])
continue;
Triangle* ot = t.GetNeighbor(i);
if(ot) {
Point* p = t.GetPoint(i);
Point* op = ot->OppositePoint(t, *p);
int oi = ot->Index(op);
// If this is a Constrained Edge or a Delaunay Edge(only during recursive legalization)
// then we should not try to legalize
if(ot->constrained_edge[oi] || ot->delaunay_edge[oi]) {
t.constrained_edge[i] = ot->constrained_edge[oi];
continue;
}
bool inside = Incircle(*p, *t.PointCCW(*p), *t.PointCW(*p), *op);
if(inside) {
// Lets mark this shared edge as Delaunay
t.delaunay_edge[i] = true;
ot->delaunay_edge[oi] = true;
// Lets rotate shared edge one vertex CW to legalize it
RotateTrianglePair(t, *p, *ot, *op);
// We now got one valid Delaunay Edge shared by two triangles
// This gives us 4 new edges to check for Delaunay
// Make sure that triangle to node mapping is done only one time for a specific triangle
bool not_legalized = !Legalize(tcx, t);
if(not_legalized) {
tcx.MapTriangleToNodes(t);
}
not_legalized = !Legalize(tcx, *ot);
if(not_legalized)
tcx.MapTriangleToNodes(*ot);
// Reset the Delaunay edges, since they only are valid Delaunay edges
// until we add a new triangle or point.
// XXX: need to think about this. Can these edges be tried after we
// return to previous recursive level?
t.delaunay_edge[i] = false;
ot->delaunay_edge[oi] = false;
// If triangle have been legalized no need to check the other edges since
// the recursive legalization will handles those so we can end here.
return true;
}
}
}
return false;
}
/**
* <b>Requirement</b>:<br>
* 1. a,b and c form a triangle.<br>
* 2. a and d is know to be on opposite side of bc<br>
* <pre>
* a
* +
* / \
* / \
* b/ \c
* +-------+
* / d \
* / \
* </pre>
* <b>Fact</b>: d has to be in area B to have a chance to be inside the circle formed by
* a,b and c<br>
* d is outside B if orient2d(a,b,d) or orient2d(c,a,d) is CW<br>
* This preknowledge gives us a way to optimize the incircle test
* @param a - triangle point, opposite d
* @param b - triangle point
* @param c - triangle point
* @param d - point opposite a
* @return true if d is inside circle, false if on circle edge
*/
bool Sweep::Incircle(Point& pa, Point& pb, Point& pc, Point& pd) {
double adx = pa.x - pd.x;
double ady = pa.y - pd.y;
double bdx = pb.x - pd.x;
double bdy = pb.y - pd.y;
double adxbdy = adx * bdy;
double bdxady = bdx * ady;
double oabd = adxbdy - bdxady;
if( oabd <= 0 )
return false;
double cdx = pc.x - pd.x;
double cdy = pc.y - pd.y;
double cdxady = cdx * ady;
double adxcdy = adx * cdy;
double ocad = cdxady - adxcdy;
if( ocad <= 0 )
return false;
double bdxcdy = bdx * cdy;
double cdxbdy = cdx * bdy;
double alift = adx * adx + ady * ady;
double blift = bdx * bdx + bdy * bdy;
double clift = cdx * cdx + cdy * cdy;
double det = alift * ( bdxcdy - cdxbdy ) + blift * ocad + clift * oabd;
return det > 0;
}
/**
* Rotates a triangle pair one vertex CW
*<pre>
* n2 n2
* P +-----+ P +-----+
* | t /| |\ t |
* | / | | \ |
* n1| / |n3 n1| \ |n3
* | / | after CW | \ |
* |/ oT | | oT \|
* +-----+ oP +-----+
* n4 n4
* </pre>
*/
void Sweep::RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op) {
Triangle* n1, *n2, *n3, *n4;
n1 = t.NeighborCCW(p);
n2 = t.NeighborCW(p);
n3 = ot.NeighborCCW(op);
n4 = ot.NeighborCW(op);
bool ce1,ce2,ce3,ce4;
ce1 = t.GetConstrainedEdgeCCW(p);
ce2 = t.GetConstrainedEdgeCW(p);
ce3 = ot.GetConstrainedEdgeCCW(op);
ce4 = ot.GetConstrainedEdgeCW(op);
bool de1,de2,de3,de4;
de1 = t.GetDelunayEdgeCCW(p);
de2 = t.GetDelunayEdgeCW(p);
de3 = ot.GetDelunayEdgeCCW(op);
de4 = ot.GetDelunayEdgeCW(op);
t.Legalize(p, op);
ot.Legalize(op, p);
// Remap delaunay_edge
ot.SetDelunayEdgeCCW(p, de1);
t.SetDelunayEdgeCW(p, de2);
t.SetDelunayEdgeCCW(op, de3);
ot.SetDelunayEdgeCW(op, de4);
// Remap constrained_edge
ot.SetConstrainedEdgeCCW(p, ce1);
t.SetConstrainedEdgeCW(p, ce2);
t.SetConstrainedEdgeCCW(op, ce3);
ot.SetConstrainedEdgeCW(op, ce4);
// Remap neighbors
// XXX: might optimize the markNeighbor by keeping track of
// what side should be assigned to what neighbor after the
// rotation. Now mark neighbor does lots of testing to find
// the right side.
t.ClearNeighbors();
ot.ClearNeighbors();
if(n1 != NULL) ot.MarkNeighbor(*n1);
if(n2 != NULL) t.MarkNeighbor(*n2);
if(n3 != NULL) t.MarkNeighbor(*n3);
if(n4 != NULL) ot.MarkNeighbor(*n4);
t.MarkNeighbor(ot);
}
/**
* Fills a basin that has formed on the Advancing Front to the right
* of given node.<br>
* First we decide a left,bottom and right node that forms the
* boundaries of the basin. Then we do a reqursive fill.
*
* @param tcx
* @param node - starting node, this or next node will be left node
*/
void Sweep::FillBasin(SweepContext& tcx, Node& node) {
if(Orient2d(*node.point, *node.next->point, *node.next->next->point ) == CCW) {
tcx.basin.left_node = node.next->next;
} else {
tcx.basin.left_node = node.next;
}
// Find the bottom and right node
tcx.basin.bottom_node = tcx.basin.left_node;
while(tcx.basin.bottom_node->next
&& tcx.basin.bottom_node->point->y >= tcx.basin.bottom_node->next->point->y) {
tcx.basin.bottom_node = tcx.basin.bottom_node->next;
}
if(tcx.basin.bottom_node == tcx.basin.left_node) {
// No valid basin
return;
}
tcx.basin.right_node = tcx.basin.bottom_node;
while(tcx.basin.right_node->next
&& tcx.basin.right_node->point->y < tcx.basin.right_node->next->point->y) {
tcx.basin.right_node = tcx.basin.right_node->next;
}
if(tcx.basin.right_node == tcx.basin.bottom_node) {
// No valid basins
return;
}
tcx.basin.width = tcx.basin.right_node->point->x - tcx.basin.left_node->point->x;
tcx.basin.left_highest = tcx.basin.left_node->point->y > tcx.basin.right_node->point->y;
FillBasinReq(tcx, *tcx.basin.bottom_node);
}
/**
* Recursive algorithm to fill a Basin with triangles
*
* @param tcx
* @param node - bottom_node
* @param cnt - counter used to alternate on even and odd numbers
*/
void Sweep::FillBasinReq(SweepContext& tcx, Node& node) {
// if shallow stop filling
if(IsShallow(tcx, node)) {
return;
}
Fill(tcx, node);
if(node.prev == tcx.basin.left_node && node.next == tcx.basin.right_node) {
return;
} else if(node.prev == tcx.basin.left_node) {
Orientation o = Orient2d(*node.point, *node.next->point, *node.next->next->point );
if(o == CW) {
return;
}
node = *node.next;
} else if(node.next == tcx.basin.right_node) {
Orientation o = Orient2d(*node.point, *node.prev->point, *node.prev->prev->point);
if(o == CCW) {
return;
}
node = *node.prev;
} else {
// Continue with the neighbor node with lowest Y value
if(node.prev->point->y < node.next->point->y) {
node = *node.prev;
} else {
node = *node.next;
}
}
FillBasinReq(tcx, node);
}
bool Sweep::IsShallow(SweepContext& tcx, Node& node) {
double height;
if(tcx.basin.left_highest) {
height = tcx.basin.left_node->point->y - node.point->y;
} else {
height = tcx.basin.right_node->point->y - node.point->y;
}
// if shallow stop filling
if(tcx.basin.width > height) {
return true;
}
return false;
}
void Sweep::FinalizationConvexHull(SweepContext& tcx) {
Node& n1 = *tcx.front()->head()->next;
Node& n2 = *n1.next;
Node& n3 = *n2.next;
Point& first = *n1.point;
TurnAdvancingFrontConvex(tcx, n2, n3);
// TODO: implement ConvexHull for lower right and left boundary
// Lower right boundary
first = *tcx.front()->head()->point;
n2 = *tcx.front()->tail()->prev;
Triangle& t1 = *n2.triangle;
Point& p1 = *n2.point;
do {
tcx.RemoveFromMap(&t1);
p1 = *t1.PointCCW(p1);
if(p1 == first) break;
t1 = *t1.NeighborCCW(p1);
} while(true);
// Lower left boundary
first = *tcx.front()->head()->next->point;
p1 = *t1.PointCW(*tcx.front()->head()->point);
t1 = *t1.NeighborCW(*tcx.front()->head()->point);
do {
tcx.RemoveFromMap(&t1);
p1 = *t1.PointCCW(p1);
t1 = *t1.NeighborCCW(p1);
} while(p1 != first);
//tcx.FinalizeTriangulation();
}
void Sweep::TurnAdvancingFrontConvex(SweepContext& tcx, Node& b, Node& c) {
Node& first = b;
while(c != *tcx.front()->tail()) {
if(Orient2d(*b.point, *c.point, *c.next->point) == CCW) {
// [b,c,d] Concave - fill around c
Fill(tcx, c);
c = *c.next;
} else {
// [b,c,d] Convex
if(b != first && Orient2d(*b.prev->point, *b.point, *c.point) == CCW) {
// [a,b,c] Concave - fill around b
Fill(tcx, b);
b = *b.prev;
} else {
// [a,b,c] Convex - nothing to fill
b = c;
c = *c.next;
}
}
}
}
void Sweep::FillEdgeEvent(SweepContext& tcx, Edge& edge, Node& node) {
if(tcx.edge_event.right) {
FillRightAboveEdgeEvent(tcx, edge, node);
} else {
FillLeftAboveEdgeEvent(tcx, edge, node);
}
}
void Sweep::FillRightAboveEdgeEvent(SweepContext& tcx, Edge& edge, Node& node) {
while(node.next->point->x < edge.p->x) {
// Check if next node is below the edge
if(Orient2d(*edge.q, *node.next->point, *edge.p) == CCW) {
FillRightBelowEdgeEvent(tcx, edge, node);
} else {
node = *node.next;
}
}
}
void Sweep::FillRightBelowEdgeEvent(SweepContext& tcx, Edge& edge, Node& node) {
if(node.point->x < edge.p->x) {
if(Orient2d(*node.point, *node.next->point, *node.next->next->point ) == CCW ) {
// Concave
FillRightConcaveEdgeEvent(tcx, edge, node );
} else {
// Convex
FillRightConvexEdgeEvent(tcx, edge, node );
// Retry this one
FillRightBelowEdgeEvent(tcx, edge, node );
}
}
}
void Sweep::FillRightConcaveEdgeEvent(SweepContext& tcx, Edge& edge, Node& node) {
Fill(tcx, *node.next);
if(node.next->point != edge.p) {
// Next above or below edge?
if(Orient2d(*edge.q, *node.next->point, *edge.p) == CCW) {
// Below
if(Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) {
// Next is concave
FillRightConcaveEdgeEvent(tcx, edge, node);
} else {
// Next is convex
}
}
}
}
void Sweep::FillRightConvexEdgeEvent(SweepContext& tcx, Edge& edge, Node& node) {
// Next concave or convex?
if(Orient2d(*node.next->point, *node.next->next->point, *node.next->next->next->point ) == CCW) {
// Concave
FillRightConcaveEdgeEvent(tcx, edge, *node.next);
} else{
// Convex
// Next above or below edge?
if(Orient2d(*edge.q, *node.next->next->point, *edge.p) == CCW) {
// Below
FillRightConvexEdgeEvent(tcx, edge, *node.next);
} else{
// Above
}
}
}
void Sweep::FillLeftAboveEdgeEvent(SweepContext& tcx, Edge& edge, Node& node) {
while(node.prev->point->x > edge.p->x) {
// Check if next node is below the edge
if(Orient2d(*edge.q, *node.prev->point, *edge.p) == CW) {
FillLeftBelowEdgeEvent(tcx, edge, node);
} else {
node = *node.prev;
}
}
}
void Sweep::FillLeftBelowEdgeEvent(SweepContext& tcx, Edge& edge, Node& node) {
if( node.point->x > edge.p->x) {
if(Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW ) {
// Concave
FillLeftConcaveEdgeEvent(tcx, edge, node);
} else {
// Convex
FillLeftConvexEdgeEvent(tcx, edge, node);
// Retry this one
FillLeftBelowEdgeEvent(tcx, edge, node);
}
}
}
void Sweep::FillLeftConvexEdgeEvent(SweepContext& tcx, Edge& edge, Node& node) {
// Next concave or convex?
if(Orient2d(*node.prev->point, *node.prev->prev->point, *node.prev->prev->prev->point) == CW) {
// Concave
FillLeftConcaveEdgeEvent(tcx, edge, *node.prev);
} else {
// Convex
// Next above or below edge?
if(Orient2d(*edge.q, *node.prev->prev->point, *edge.p) == CW) {
// Below
FillLeftConvexEdgeEvent(tcx, edge, *node.prev);
} else {
// Above
}
}
}
void Sweep::FillLeftConcaveEdgeEvent(SweepContext& tcx, Edge& edge, Node& node) {
Fill(tcx, *node.prev);
if(node.prev->point != edge.p) {
// Next above or below edge?
if(Orient2d(*edge.q, *node.prev->point, *edge.p) == CW) {
// Below
if(Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW) {
// Next is concave
FillLeftConcaveEdgeEvent(tcx, edge, node);
} else {
// Next is convex
}
}
}
}
void Sweep::FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& t, Point& p) {
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(p, *t.PointCCW(p), *t.PointCW(p), op)) {
// Lets rotate shared edge one vertex CW
RotateTrianglePair(t, p, ot, op);
tcx.MapTriangleToNodes(t);
tcx.MapTriangleToNodes(ot);
if( p == eq && op == ep ) {
if(eq == *tcx.edge_event.constrained_edge->q && ep == *tcx.edge_event.constrained_edge->p) {
t.MarkConstrainedEdge(&ep, &eq);
ot.MarkConstrainedEdge(&ep, &eq);
Legalize(tcx, t);
Legalize(tcx, ot);
} else {
// XXX: I think one of the triangles should be legalized here?
}
} else {
Orientation o = Orient2d(eq, op, ep);
t = NextFlipTriangle(tcx, (int) o, t, ot, p, op);
FlipEdgeEvent(tcx, ep, eq, t, p);
}
} else {
Point& newP = NextFlipPoint( ep, eq, ot, op);
FlipScanEdgeEvent(tcx, ep, eq, t, ot, newP);
EdgeEvent(tcx, ep, eq, &t, p);
}
}
Triangle& Sweep::NextFlipTriangle(SweepContext& tcx, int o, Triangle& t, Triangle& ot, Point& p, Point& op) {
if(o == CCW ) {
// ot is not crossing edge after flip
int edge_index = ot.EdgeIndex(&p, &op);
ot.delaunay_edge[edge_index] = true;
Legalize(tcx, ot);
ot.ClearDelunayEdges();
return t;
}
// t is not crossing edge after flip
int edge_index = t.EdgeIndex(&p, &op);
t.delaunay_edge[edge_index] = true;
Legalize(tcx, t);
t.ClearDelunayEdges();
return ot;
}
Point& Sweep::NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op ) {
Orientation o2d = Orient2d(eq, op, ep);
if(o2d == CW) {
// Right
return *ot.PointCCW(op);
} else if(o2d == CCW) {
// Left
return *ot.PointCW(op);
} else {
//throw new RuntimeException("[Unsupported] Opposing point on constrained edge");
assert(0);
}
}
void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle,
Triangle& t, Point& p ) {
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);
// TODO: Actually I just figured out that it should be possible to
// improve this by getting the next ot and op before the the above
// flip and continue the flipScanEdgeEvent here
// set new ot and op here and loop back to inScanArea test
// also need to set a new flip_triangle first
// Turns out at first glance that this is somewhat complicated
// so it will have to wait.
} else {
Point& newP = NextFlipPoint(ep, eq, ot, op);
FlipScanEdgeEvent(tcx, ep, eq, flip_triangle, ot, newP);
}
}

118
poly2tri/sweep/sweep.h Normal file
View File

@ -0,0 +1,118 @@
/*
* Poly2Tri Copyright (c) 2009-2010, Mason Green
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* Sweep-line, Constrained Delauney Triangulation (CDT) See: Domiter, V. and
* Zalik, B.(2008)'Sweep-line algorithm for constrained Delaunay triangulation',
* International Journal of Geographical Information Science
*
* "FlipScan" Constrained Edge Algorithm invented by Thomas Åhlén, thahlen@gmail.com
*/
#include <list>
class SweepContext;
struct Node;
struct Point;
struct Edge;
class Triangle;
class Sweep {
public:
void Triangulate(SweepContext& tcx);
private:
void SweepPoints(SweepContext& tcx);
Node& PointEvent(SweepContext& tcx, Point& point);
void EdgeEvent(SweepContext& tcx, Edge& edge, Node& node);
void EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangle, Point& point);
Node& NewFrontTriangle(SweepContext& tcx, Point& point, Node& node);
void Fill(SweepContext& tcx, Node& node);
bool Legalize(SweepContext& tcx, Triangle& t);
bool Incircle(Point& pa, Point& pb, Point& pc, Point& pd);
void RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op);
void FillAdvancingFront(SweepContext& tcx, Node& n);
double HoleAngle(Node& node);
double BasinAngle(Node& node);
void FillBasin(SweepContext& tcx, Node& node);
void FillBasinReq(SweepContext& tcx, Node& node);
bool IsShallow(SweepContext& tcx, Node& node);
void FinalizationConvexHull(SweepContext& tcx);
void TurnAdvancingFrontConvex(SweepContext& tcx, Node& b, Node& c);
bool IsEdgeSideOfTriangle(Triangle& triangle, Point& ep, Point& eq);
void FillEdgeEvent(SweepContext& tcx, Edge& edge, Node& node);
void FillRightAboveEdgeEvent(SweepContext& tcx, Edge& edge, Node& node);
void FillRightBelowEdgeEvent(SweepContext& tcx, Edge& edge, Node& node);
void FillRightConcaveEdgeEvent(SweepContext& tcx, Edge& edge, Node& node);
void FillRightConvexEdgeEvent(SweepContext& tcx, Edge& edge, Node& node);
void FillLeftAboveEdgeEvent(SweepContext& tcx, Edge& edge, Node& node);
void FillLeftBelowEdgeEvent(SweepContext& tcx, Edge& edge, Node& node);
void FillLeftConcaveEdgeEvent(SweepContext& tcx, Edge& edge, Node& node);
void FillLeftConvexEdgeEvent(SweepContext& tcx, Edge& edge, Node& node);
void FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& t, Point& p);
Triangle& NextFlipTriangle(SweepContext& tcx, int o, Triangle& t, Triangle& ot, Point& p, Point& op);
Point& NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op );
void FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle, Triangle& t, Point& p);
};

View File

@ -0,0 +1,164 @@
#include "sweep_context.h"
#include <algorithm>
#include <GL/glfw.h>
#include "advancing_front.h"
SweepContext::SweepContext(Point polyline[], const int& point_count) {
basin = Basin();
edge_event = EdgeEvent();
point_count_ = point_count;
points_ = polyline;
InitTriangulation();
InitEdges();
}
std::list<Triangle*> SweepContext::GetTriangles() {
return tri_list_;
}
void SweepContext::InitTriangulation() {
double xmax(points_[0].x), xmin(points_[0].x);
double ymax(points_[0].y), ymin(points_[0].y);
// Calculate bounds.
for(int i = 0; i < point_count_; i++) {
Point p = points_[i];
if(p.x > xmax)
xmax = p.x;
if(p.x < xmin)
xmin = p.x;
if(p.y > ymax)
ymax = p.y;
if(p.y < ymin)
ymin = p.y;
}
double dx = kAlpha * ( xmax - xmin );
double dy = kAlpha * ( ymax - ymin );
head_ = new Point(xmax + dx, ymin - dy);
tail_ = new Point(xmin - dx, ymin - dy);
// Sort points along y-axis
double init_time = glfwGetTime();
std::sort(points_, points_ + point_count_);
double dt = glfwGetTime() - init_time;
printf("Sort time (secs) = %f\n", dt);
/*
for(int i = 0; i < point_count_; i++) {
printf("%i: %f, %f\n", i+1, points_[i].x, points_[i].y);
}
*/
}
void SweepContext::InitEdges() {
for(int i = 0; i < point_count_; i++) {
int j = i < point_count_ - 1 ? i + 1 : 0;
new Edge(points_[i], points_[j]);
}
}
Point* SweepContext::GetPoint(const int& index) {
return &points_[index];
}
void SweepContext::AddToMap(Triangle* triangle ) {
tri_list_.push_back(triangle);
}
Node& SweepContext::LocateNode(Point& point) {
// TODO implement search tree
return *front_->Locate(point.x);
}
void SweepContext::CreateAdvancingFront() {
// Initial triangle
Triangle* triangle = new Triangle(points_[0], *tail_, *head_);
tri_list_.push_back(triangle);
front_ = new AdvancingFront;
front_->set_head(new Node(*triangle->GetPoint(1)));
front_->head()->triangle = triangle;
Node* middle = new Node(*triangle->GetPoint(0));
middle->triangle = triangle;
front_->set_tail(new Node(*triangle->GetPoint(2)));
front_->set_search(middle);
// TODO: More intuitive if head is middles next and not previous?
// so swap head and tail
front_->head()->next = middle;
middle->next = front_->tail();
middle->prev = front_->head();
front_->tail()->prev = middle;
}
void SweepContext::RemoveNode(Node* node) {
delete node;
}
void SweepContext::MapTriangleToNodes(Triangle& t) {
for(int i=0; i<3; i++) {
if(t.GetNeighbor(i) == NULL) {
Node* n = front_->LocatePoint(t.PointCW(*t.GetPoint(i)));
if(n)
n->triangle = &t;
}
}
}
void SweepContext::RemoveFromMap(Triangle* triangle) {
tri_list_.remove(triangle);
}
/*
void SweepContext::MeshClean(Triangle& triangle) {
pointset_.ClearTriangulation();
MeshCleanReq(triangle);
}
AFront SweepContext::front_() {
return front_;
}
void SweepContext::Clear() {
super.clear();
tri_list_.Clear();
}
Node* SweepContext::LocateNode(Point& point) {
// TODO implement tree
return front_.Locate(point.x);
}
/*
void SweepContext::MeshCleanReq(Triangle& triangle ) {
if(triangle != NULL && !triangle.isInterior()) {
triangle.IsInterior(true);
pointset_.AddTriangle(triangle);
for(int i = 0; i < 3; i++) {
if(!triangle.cEdge[i])
MeshCleanReq(triangle.neighbors[i]);
}
}
}
*/
SweepContext::~SweepContext() {
delete [] points_;
delete head_;
delete tail_;
delete front_;
}

View File

@ -0,0 +1,158 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <list>
// Inital triangle factor, seed triangle will extend 30% of
// PointSet width to both left and right.
const double kAlpha = 0.3;
struct Point;
class Triangle;
struct Node;
struct Edge;
class AdvancingFront;
class SweepContext {
public:
// Constructor
SweepContext(Point polyline[], const int& point_count);
// Destructor
~SweepContext();
//void MeshClean(Triangle& triangle);
// Get Advancing Front
//AdvancingFront front();
void set_head(Point* p1);
Point* head();
void set_tail(Point* p1 );
Point* tail();
int point_count();
Node& LocateNode(Point& point);
void RemoveNode(Node* node);
void CreateAdvancingFront();
// Try to map a node to all sides of this triangle that don't have a neighbor
void MapTriangleToNodes(Triangle& t);
void AddToMap(Triangle* triangle);
Point* GetPoint(const int& index);
Point* GetPoints();
void RemoveFromMap(Triangle* triangle);
AdvancingFront* front();
std::list<Triangle*> GetTriangles();
struct Basin {
Node* left_node;
Node* bottom_node;
Node* right_node;
double width;
bool left_highest;
Basin() : left_node(NULL), bottom_node(NULL), right_node(NULL),
width(0.0), left_highest(false) {}
void Clear() {
left_node = NULL;
bottom_node = NULL;
right_node = NULL;
width = 0.0;
left_highest = false;
}
};
struct EdgeEvent {
Edge* constrained_edge;
bool right;
EdgeEvent() : constrained_edge(NULL), right(false) {}
};
Basin basin;
EdgeEvent edge_event;
private:
std::list<Triangle*> tri_list_;
Point* points_;
int point_count_;
// Advancing front
AdvancingFront* front_;
// head point used with advancing front
Point* head_;
// tail point used with advancing front
Point* tail_;
//EdgeEvent edgeEvent = new EdgeEvent();
void InitTriangulation();
void InitEdges();
//void MeshCleanReq(Triangle& triangle )
/*
class EdgeEvent {
Edge* constrainedEdge;
bool right;
};
*/
};
inline AdvancingFront* SweepContext::front() { return front_; }
inline int SweepContext::point_count() { return point_count_; }
inline void SweepContext::set_head(Point* p1) { head_ = p1; }
inline Point* SweepContext::head() { return head_; }
inline void SweepContext::set_tail(Point* p1) { tail_ = p1; }
inline Point* SweepContext::tail() { return tail_; }

60
testbed/data/2.dat Normal file
View File

@ -0,0 +1,60 @@
2158.9981,2350.2286
2158.9981,3245.4557
-1042.9463,3245.4557
-1042.9463,2496.1895
91.149593,800.20639
441.75649,251.73749
648.06929,-97.04991
765.46219,-332.30851
849.31479,-540.20071
899.62689,-720.72671
916.39869,-873.88651
896.13819,-1060.7944
835.35969,-1193.3788
789.54889,-1239.4959
733.15879,-1272.4376
666.18939,-1292.204
588.64059,-1298.7951
511.08979,-1291.4964
444.11959,-1269.6012
387.73029,-1233.1107
341.92169,-1182.0263
306.46619,-1109.2461
281.14119,-1007.6808
260.88259,-718.19491
260.88259,-218.68401
-1042.9463,-218.68401
-1042.9463,-410.05511
-1030.3404,-804.55201
-992.52205,-1105.8022
-958.08057,-1232.6032
-905.18018,-1358.3923
-833.82067,-1483.1695
-744.00213,-1606.9348
-637.5262,-1722.6871
-516.1928,-1823.4397
-380.00205,-1909.1927
-228.95374,-1979.9461
-62.599167,-2035.2866
119.51329,-2074.8167
317.38399,-2098.5364
531.01279,-2106.4456
938.57049,-2082.2155
1122.512,-2051.9328
1293.2285,-2009.5383
1450.7202,-1955.0316
1594.987,-1888.4129
1726.0289,-1809.6817
1843.846,-1718.8382
2038.4505,-1512.159
2177.4543,-1279.7356
2260.8578,-1021.5681
2288.6606,-737.65631
2273.0151,-508.98211
2226.0792,-273.82221
2147.8538,-32.17651
2038.3398,215.95519
1852.2859,537.88159
1544.4495,1000.9025
1114.8304,1605.018
563.42839,2350.2286

275
testbed/data/bird.dat Normal file
View File

@ -0,0 +1,275 @@
4.57998 4.03402
4.06435 4.06435
3.51839 4.21601
3.09376 4.42832
2.60846 4.57998
2.09284 4.7013
1.51655 4.82263
0.909929 4.94395
0.242648 5.06527
-0.30331 5.0956
-1.15258 5.12594
-1.72887 5.12594
-2.48714 5.12594
-2.85111 5.03494
-3.36674 5.30792
-3.70038 5.52024
-4.15534 5.9752
-4.7013 6.27851
-5.0956 6.61215
-5.73255 6.67281
-6.55149 6.73348
-6.88513 6.61215
-7.46142 6.36951
-7.88605 6.18752
-8.25003 5.91454
-8.64433 5.61123
-8.88698 5.30792
-9.06896 5.00461
-9.25095 4.88329
-9.94856 4.73163
-10.6462 4.64064
-11.1011 4.54965
-11.3741 4.42832
-11.5561 4.21601
-11.0101 4.21601
-10.1305 3.94303
-9.61492 3.73071
-9.15996 3.4274
-8.73532 3.00277
-8.34102 2.6388
-7.97705 2.36582
-7.61308 2.03218
-7.18844 1.45589
-6.79414 1.12225
-6.64248 0.788605
-6.36951 0.242648
-6.24818 -0.212317
-6.00553 -0.515627
-5.73255 -0.818936
-5.24726 -1.2739
-4.7923 -1.60754
-4.42832 -2.00184
-3.67005 -2.21416
-3.18475 -2.39615
-2.5478 -2.69946
-1.91085 -2.79045
-1.06158 -2.88144
-0.333641 -2.88144
0.242648 -2.85111
0.94026 -2.82078
1.2739 -2.85111
1.42556 -3.0331
1.42556 -3.30608
1.33456 -3.57905
1.15258 -4.00369
1.03125 -4.57998
0.849267 -5.15627
0.63695 -5.5809
0.30331 -5.91454
0.060662 -6.15719
-0.333641 -6.27851
-0.697612 -6.27851
-1.15258 -6.36951
-1.57721 -6.39984
-2.09284 -6.52116
-2.36582 -6.79414
-2.48714 -7.06712
-2.18383 -6.97612
-1.85019 -6.79414
-1.42556 -6.76381
-1.15258 -6.79414
-1.36489 -6.88513
-1.69853 -6.97612
-1.97151 -7.12778
-2.12317 -7.37043
-2.27482 -7.64341
-2.39615 -7.91639
-2.36582 -8.21969
-2.03218 -7.85572
-1.81986 -7.7344
-1.57721 -7.67374
-1.36489 -7.49175
-1.21324 -7.40076
-0.849267 -7.2491
-0.60662 -7.12778
-0.242648 -6.91546
0.030331 -6.70315
0.363972 -6.4605
0.242648 -6.61215
0.152837 -6.72007
-0.092855 -6.88818
-0.506653 -7.15974
-0.765276 -7.31491
-1.01097 -7.41836
-1.16614 -7.5606
-1.32132 -7.71577
-1.45063 -7.81922
-1.50235 -8.06492
-1.50235 -8.29768
-1.46356 -8.53044
-1.38597 -8.29768
-1.28252 -8.05199
-1.14028 -7.87095
-0.985106 -7.84509
-0.817001 -7.84509
-0.623033 -7.70284
-0.390272 -7.52181
-0.105787 -7.31491
0.178699 -7.06922
0.489047 -6.84939
0.670083 -6.66835
0.928707 -6.47438
1.16147 -6.33214
1.47182 -6.13817
1.82096 -5.91834
2.04079 -5.84076
2.15717 -5.71144
2.18303 -5.45282
2.06665 -5.28472
1.87268 -5.3623
1.49768 -5.63386
1.22612 -5.81489
1.03216 -5.91834
0.876982 -5.95714
0.954569 -5.80196
1.00629 -5.60799
1.16147 -5.29765
1.3425 -4.9873
1.45888 -4.65109
1.47182 -4.4054
1.73044 -3.95281
1.84682 -3.6166
1.98906 -3.30625
2.14424 -2.95711
2.26062 -2.75021
2.42872 -2.59503
2.63562 -2.50452
2.98476 -2.51745
3.12701 -2.71141
3.06235 -3.09935
2.9589 -3.4097
2.86838 -3.75884
2.79079 -4.12091
2.70028 -4.43126
2.55803 -4.75454
2.48045 -5.03902
2.3382 -5.37523
2.29941 -5.59506
2.23475 -5.90541
2.11837 -6.21576
1.7951 -6.65542
1.39423 -7.05628
1.09681 -7.26318
0.838188 -7.37956
0.41146 -7.49594
-0.002337 -7.62526
-0.416135 -7.7675
-0.687689 -8.05199
-0.907519 -8.40113
-0.70062 -8.19423
-0.312685 -8.05199
-0.015268 -7.89681
0.217493 -7.89681
0.243355 -7.90974
0.023525 -8.1425
-0.157511 -8.25888
-0.403203 -8.43992
-0.648896 -8.75027
-0.778207 -8.90544
-0.881657 -9.18993
-0.80407 -9.60372
-0.597171 -9.177
-0.14458 -8.9701
0.269217 -8.62096
0.695946 -8.28475
1.13561 -8.00026
1.52354 -7.62526
1.82096 -7.26318
1.95027 -7.09508
1.9632 -7.15974
1.66578 -7.58646
1.45888 -7.84509
1.13561 -8.20716
0.760601 -8.65975
0.450253 -8.99596
0.269217 -9.28045
0.126974 -9.65545
0.19163 -10.2761
0.333873 -9.84942
0.63129 -9.68131
0.980431 -9.26751
1.26492 -8.72441
1.60113 -8.31061
1.98906 -7.7675
2.36407 -7.34077
2.79079 -7.00456
3.13994 -6.7718
3.68304 -6.46145
4.14857 -6.33214
4.7434 -6.09938
5.19599 -6.13817
4.85978 -5.87955
4.29081 -5.76317
3.77356 -5.81489
3.34683 -6.07352
2.77786 -6.47438
2.41579 -6.60369
2.41579 -6.28042
2.59683 -5.84076
2.79079 -5.42696
2.99769 -4.90971
3.25632 -4.30195
3.50201 -3.52608
3.83822 -2.63383
4.07098 -2.40107
4.39426 -2.28469
4.79512 -2.23296
4.54943 -2.02606
4.49771 -1.6252
4.54943 -1.50882
4.91151 -1.50882
5.54513 -1.45709
6.12704 -1.39244
6.85118 -1.32778
7.44601 -1.14674
7.85981 -0.78467
7.79516 -0.409667
7.49774 -0.151043
7.84688 0.042924
8.23481 0.314479
8.64861 0.702414
8.70034 1.09035
8.41585 1.42656
8.11843 1.62053
8.3512 2.06019
8.53223 2.38347
8.67447 2.74554
8.66154 3.22399
8.80379 3.87055
8.90724 4.36193
9.1012 4.85332
9.43741 5.40936
9.90293 6.04298
10.3167 6.58609
10.7047 7.3749
10.9374 7.96973
11.1573 8.40939
11.1573 8.84905
10.9374 9.05595
10.6659 9.28871
10.3426 9.37922
9.99345 9.34043
9.63138 8.97836
9.20465 8.48697
8.86844 8.1249
8.50637 7.72404
8.17016 7.28438
7.74343 6.88351
7.43308 6.5473
7.16153 6.1723
6.70894 5.71971
6.20462 5.25418
5.72617 4.80159
5.13134 4.41366
4.87271 4.16797

7
testbed/data/custom.dat Normal file
View File

@ -0,0 +1,7 @@
0 130
-270 0
130 -40
10 -60
-10 -20
100 30
40 -40

200
testbed/data/debug.dat Normal file
View File

@ -0,0 +1,200 @@
1.2277408 0.0
1.3243141 0.041618247
1.0635862 0.06691518
0.952708 0.09005742
0.9624486 0.12158553
1.3459457 0.21317686
0.94439876 0.1801537
0.58555007 0.13088594
0.5811499 0.14921393
0.82454175 0.23955151
0.62284756 0.20237544
0.56452847 0.20324275
0.5578659 0.22087473
0.6222525 0.2692727
0.5428962 0.25546756
0.6560448 0.33427152
0.525784 0.28905222
0.71199375 0.42107195
0.8918749 0.56600106
0.93826324 0.63764304
0.5041431 0.36628145
0.74085724 0.57466775
0.55901116 0.46245426
0.45006666 0.3967871
0.43738118 0.41072828
0.42426407 0.42426407
0.41072828 0.43738118
0.3967871 0.45006666
0.41002733 0.4956379
0.7536917 0.9716534
1.0196112 1.4033744
0.66767913 0.98246
0.7202045 1.1348608
0.44231245 0.7479095
0.28905222 0.525784
0.2723943 0.5346039
0.5011288 1.0649529
0.27308202 0.6310553
0.22087473 0.5578659
0.20460863 0.56832236
0.3397839 1.0457473
0.26354295 0.9071208
0.2884009 1.1232473
0.15593462 0.69761133
0.16937841 0.88791275
0.21818724 1.37758
0.1523747 1.20617
0.11806885 1.249038
0.06135568 0.97522056
0.018846456 0.5997039
6.8178847E-17 1.113445
-0.028901286 0.91965383
-0.06209223 0.98692775
-0.05646499 0.5973372
-0.10701424 0.84710497
-0.09386068 0.592613
-0.1636339 0.8577989
-0.29984477 1.3414284
-0.45487383 1.7716166
-0.6387838 2.1987083
-0.6129905 1.8865908
-0.8446652 2.3461478
-0.9281012 2.344116
-1.0037318 2.3194876
-1.0196298 2.1668236
-0.8902802 1.7472732
-1.2330354 2.242883
-1.4297054 2.4174998
-1.6074804 2.5329838
-1.4688258 2.1613116
-1.7633557 2.427051
-1.6571896 2.136436
-1.912272 2.3115396
-1.6086806 1.82469
-1.6045313 1.7086523
-2.0598311 2.0598311
-1.8296968 1.7181997
-2.2503333 1.9839356
-2.1353924 1.7665502
-2.370465 1.8387212
-2.427051 1.7633557
-2.4812417 1.6862501
-2.5329838 1.6074804
-2.5773842 1.5242608
-2.62892 1.445261
-2.6730196 1.3619715
-2.714481 1.2773379
-2.753264 1.1914437
-2.7893295 1.1043737
-2.8226423 1.0162138
-2.8531694 0.927051
-2.5261154 0.73390436
-2.6257684 0.6741827
-2.9277503 0.65442973
-2.8118498 0.53638905
-2.963065 0.4693034
-2.976344 0.3759997
-2.617039 0.24738303
-2.99408 0.18837155
-2.860681 0.08990052
-3.0 3.6739403E-16
-2.6968896 -0.08475317
-2.99408 -0.18837155
-2.431072 -0.22980396
-2.4993353 -0.31573948
-2.3772683 -0.3765223
-2.523671 -0.48141596
-2.4523084 -0.54815584
-1.9428126 -0.49882948
-1.980212 -0.57530475
-1.6508379 -0.53638977
-1.7593161 -0.63339275
-1.1899233 -0.47112396
-0.8138197 -0.35217124
-0.5630522 -0.26495224
-0.5346039 -0.2723943
-0.878033 -0.4827027
-0.85542375 -0.5058962
-1.2059882 -0.76534337
-0.97923774 -0.66548926
-1.0108875 -0.7344528
-0.7830176 -0.6073707
-0.90356225 -0.74749166
-1.0288435 -0.90704757
-1.1261301 -1.0575066
-0.9001703 -0.9001703
-0.8477716 -0.902785
-0.5851195 -0.66368777
-0.47532755 -0.5745723
-0.6310177 -0.8135031
-0.40265256 -0.5542037
-0.33725002 -0.49624833
-0.32149607 -0.50659674
-0.46425027 -0.7850044
-0.38156003 -0.69405514
-0.2723943 -0.5346039
-0.25546756 -0.5428962
-0.23828873 -0.5506528
-0.22087473 -0.5578659
-0.20324275 -0.56452847
-0.20844458 -0.64152646
-0.16739467 -0.5761762
-0.14921393 -0.5811499
-0.13088594 -0.58555007
-0.14249685 -0.7469947
-0.11622784 -0.73383373
-0.081517614 -0.64527833
-0.07004014 -0.7409472
-0.05557717 -0.88337386
-0.025127873 -0.7995819
-1.1021821E-16 -0.6
0.029305225 -0.9325074
0.05083992 -0.8080774
0.10585039 -1.1197802
0.18259653 -1.4454004
0.21030101 -1.3277884
0.17551 -0.9200556
0.17963327 -0.8036331
0.14921393 -0.5811499
0.26661414 -0.9176919
0.1854102 -0.5706339
0.24760589 -0.6877518
0.251998 -0.6364744
0.23828873 -0.5506528
0.4822611 -1.024857
0.479923 -0.9419019
0.34421936 -0.62613267
0.55215293 -0.9336396
0.70164776 -1.1056199
0.9243659 -1.3601631
1.1842307 -1.6299537
1.4756334 -1.9023752
1.6572317 -2.003249
1.669321 -1.893473
1.8840985 -2.0063612
2.1213202 -2.1213202
2.1869059 -2.0536413
2.2503333 -1.9839356
2.3115396 -1.912272
2.2131321 -1.7166812
2.3906639 -1.7369189
2.0770426 -1.4115567
2.2302797 -1.4153785
2.4940982 -1.4750056
2.62892 -1.445261
2.23299 -1.1377653
2.5385184 -1.1945361
2.4313858 -1.0521545
2.686942 -1.0638356
2.8226423 -1.0162138
2.6503394 -0.86114746
2.6646125 -0.77414155
2.1942327 -0.56338316
1.7811928 -0.39814374
1.9936028 -0.38030007
1.5980223 -0.2531019
1.77933 -0.22478165
1.192731 -0.112746276
1.358207 -0.08545114
1.7209803 -0.054083984

10000
testbed/data/debug2.dat Normal file

File diff suppressed because it is too large Load Diff

10
testbed/data/diamond.dat Normal file
View File

@ -0,0 +1,10 @@
0.0 0.0
2.0 1.0
4.0 2.0
6.0 3.0
8.0 4.0
1.0 5.0
-8.0 4.0
-6.0 3.0
-4.0 2.0
-2.0 1.0

94
testbed/data/dude.dat Normal file
View File

@ -0,0 +1,94 @@
280.35714 648.79075
286.78571 662.8979
263.28607 661.17871
262.31092 671.41548
250.53571 677.00504
250.53571 683.43361
256.42857 685.21933
297.14286 669.50504
289.28571 649.50504
285 631.6479
285 608.79075
292.85714 585.21932
306.42857 563.79075
323.57143 548.79075
339.28571 545.21932
357.85714 547.36218
375 550.21932
391.42857 568.07647
404.28571 588.79075
413.57143 612.36218
417.14286 628.07647
438.57143 619.1479
438.03572 618.96932
437.5 609.50504
426.96429 609.86218
424.64286 615.57647
419.82143 615.04075
420.35714 605.04075
428.39286 598.43361
437.85714 599.68361
443.57143 613.79075
450.71429 610.21933
431.42857 575.21932
405.71429 550.21932
372.85714 534.50504
349.28571 531.6479
346.42857 521.6479
346.42857 511.6479
350.71429 496.6479
367.85714 476.6479
377.14286 460.93361
385.71429 445.21932
388.57143 404.50504
360 352.36218
337.14286 325.93361
330.71429 334.50504
347.14286 354.50504
337.85714 370.21932
333.57143 359.50504
319.28571 353.07647
312.85714 366.6479
350.71429 387.36218
368.57143 408.07647
375.71429 431.6479
372.14286 454.50504
366.42857 462.36218
352.85714 462.36218
336.42857 456.6479
332.85714 438.79075
338.57143 423.79075
338.57143 411.6479
327.85714 405.93361
320.71429 407.36218
315.71429 423.07647
314.28571 440.21932
325 447.71932
324.82143 460.93361
317.85714 470.57647
304.28571 483.79075
287.14286 491.29075
263.03571 498.61218
251.60714 503.07647
251.25 533.61218
260.71429 533.61218
272.85714 528.43361
286.07143 518.61218
297.32143 508.25504
297.85714 507.36218
298.39286 506.46932
307.14286 496.6479
312.67857 491.6479
317.32143 503.07647
322.5 514.1479
325.53571 521.11218
327.14286 525.75504
326.96429 535.04075
311.78571 540.04075
291.07143 552.71932
274.82143 568.43361
259.10714 592.8979
254.28571 604.50504
251.07143 621.11218
250.53571 649.1479
268.1955 654.36208

100
testbed/data/funny.dat Normal file
View File

@ -0,0 +1,100 @@
100.317505 0.0
146.29202 9.203914
129.52948 16.363379
95.36635 18.192104
88.769775 22.792204
102.68762 33.36523
142.4203 56.388184
132.23712 62.22607
134.04555 73.69216
121.24752 76.946014
140.18803 101.85256
124.024445 102.601944
119.727 112.43114
144.82764 154.22577
155.76044 188.28203
146.94632 202.25424
133.9567 211.08199
120.438416 219.07668
103.53854 220.03061
90.72225 229.13826
77.25425 237.76413
54.851055 213.63075
46.84533 245.57181
31.33331 248.02867
15.69763 249.50668
1.5308084E-14 250.0
-13.490268 214.42166
-29.863472 236.39372
-44.794296 234.81993
-50.172047 195.40721
-69.351425 213.44174
-75.72414 191.25734
-96.03964 204.09464
-120.438416 219.07668
-127.11785 200.30568
-119.31813 164.22733
-130.35721 157.57478
-112.00853 119.27697
-142.68515 133.99026
-117.65654 97.333954
-125.62218 91.26986
-114.24053 72.499245
-160.95981 88.4884
-138.49583 65.171196
-102.99021 40.776707
-141.48434 45.97105
-97.90232 25.137043
-116.9116 22.30208
-145.58727 18.391949
-183.83247 11.565759
-190.12851 2.3284026E-14
-157.68095 -9.9204445
-186.18002 -23.520008
-160.72182 -30.659325
-143.63857 -36.880116
-143.12222 -46.50323
-98.59685 -39.037254
-86.89141 -40.887993
-83.81993 -46.0804
-42.216396 -26.79134
-40.45085 -29.389263
-38.52566 -31.871199
-46.53258 -43.697002
-34.227356 -36.448433
-38.017994 -45.95586
-29.389263 -40.45085
-26.79134 -42.216396
-31.430187 -57.1713
-22.040213 -46.837833
-27.75829 -70.109436
-26.90105 -82.79292
-13.713537 -53.4107
-10.41509 -54.59781
-6.2666616 -49.605736
-3.139526 -49.901337
-9.184851E-15 -50.0
3.5057213 -55.721844
6.2666616 -49.605736
14.274147 -74.8277
19.75647 -76.946365
24.69724 -76.01029
24.807446 -62.656456
28.282286 -60.102917
37.102608 -67.489395
51.878616 -81.74762
46.092445 -63.440807
34.334026 -41.502712
34.227356 -36.448433
43.65427 -40.99409
38.52566 -31.871199
40.45085 -29.389263
42.216396 -26.79134
52.668476 -28.95474
86.38597 -40.650154
126.91717 -50.25006
83.21832 -27.039272
109.77473 -28.185358
105.45997 -20.117565
119.66038 -15.116621
74.30321 -4.674762

1036
testbed/data/nazca_heron.dat Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

82
testbed/data/polygon.dae Normal file
View File

@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
<asset>
<contributor>
<authoring_tool>Google SketchUp 7.1.4871</authoring_tool>
</contributor>
<created>2009-12-21T01:51:00Z</created>
<modified>2009-12-21T01:51:00Z</modified>
<unit meter="0.0254" name="inch" />
<up_axis>Z_UP</up_axis>
</asset>
<library_visual_scenes>
<visual_scene id="ID1">
<node name="SketchUp">
<instance_geometry url="#ID2">
<bind_material>
<technique_common>
<instance_material symbol="Material2" target="#ID4">
<bind_vertex_input semantic="UVSET0" input_semantic="TEXCOORD" input_set="0" />
</instance_material>
</technique_common>
</bind_material>
</instance_geometry>
</node>
</visual_scene>
</library_visual_scenes>
<library_geometries>
<geometry id="ID2">
<mesh>
<source id="ID5">
<float_array id="ID8" count="324">-112.9393 -5.134218 -5.952325e-030 -115.783 -26.39329 -4.065249e-030 -116.1693 -15.52189 -5.174618e-030 -111.8239 -36.52552 -2.74901e-030 -106.4564 3.601217 -6.310887e-030 -104.7373 -44.7788 -1.373963e-030 -66.76277 70.05491 -5.637993e-014 -68.21937 53.83701 -4.127297e-014 -68.55863 62.04185 -5.054886e-014 -65.7681 45.99956 -2.91844e-014 -62.95416 77.33014 -5.83688e-014 -61.37187 39.0636 -1.510696e-014 -57.39237 83.37173 -5.637993e-014 -55.33028 33.5018 0 -50.4564 87.76796 -5.054886e-014 -54.18848 31.40854 0 -52.54381 29.68213 0 -50.50835 28.44022 0 -48.22082 27.76744 0 -42.61895 90.21923 -4.127297e-014 -45.8371 27.70964 0 -43.51965 28.27076 0 -41.4264 29.41256 0 -34.41412 90.55849 -2.91844e-014 -38.42946 47.11159 0 -39.69999 31.05723 0 -38.45807 33.09269 0 -36.86605 53.9672 0 -33.69118 60.24126 0 -26.40105 88.76263 -1.510696e-014 -29.09332 65.56134 0 -23.3454 69.61164 0 -19.12582 84.95402 1.877284e-029 -16.7886 72.15173 0 -13.74167 81.56284 1.269697e-029 -9.81216 73.03084 0 -8.03964 78.73864 7.636926e-030 -2.830188 72.19677 0 -2.079244 76.51087 3.64551e-030 3.742859 69.69904 0 4.077324 74.9028 7.643719e-031 9.516804 65.68592 0 10.36582 73.93119 -9.764253e-031 14.1489 60.39562 0 16.72063 73.60619 -1.558716e-030 17.36419 54.14218 0 23.07544 73.93119 -9.764253e-031 19.14039 41.22425 0 92.15467 80.62257 -5.238305e-014 88.83104 50.24595 2.085226e-030 88.0531 85.73196 -5.423092e-014 92.70476 55.53018 -1.403599e-014 94.79408 74.62572 -4.696535e-014 95.07883 61.63694 -2.711546e-014 95.79146 68.15007 -3.834705e-014 -138.3173 50.47565 -5.441105e-014 -137.432 24.73624 -3.697808e-014 -140.3168 37.52194 -4.746962e-014 -131.7115 61.79639 -5.68373e-014 -130.0639 13.89615 -2.439509e-014 -121.4177 69.91023 -5.441105e-014 -119.2369 6.508783 -1.147007e-014 -108.8671 73.6891 -4.746962e-014 -95.8047 72.60761 -3.697808e-014 -95.3204 -50.22474 -9.478654e-032 -84.0465 66.81613 -2.439509e-014 -84.63247 -52.25073 9.446271e-031 -73.87579 -50.62886 1.627355e-030 -75.22729 57.11985 -1.147007e-014 -70.57319 44.86685 0 -64.26037 -45.54158 1.876598e-030 -69.61521 31.86262 0 -64.96236 19.68153 0 -57.00677 9.350201 0 -56.86785 -37.56115 1.664318e-030 -51.7342 -16.73615 -6.04464e-035 -46.41893 1.739326 0 -52.52979 -27.58529 1.014396e-030 -43.24859 -39.15101 -3.163366e-031 -34.09116 -2.50966 0 -28.50562 -58.04747 -5.308165e-031 -21.06243 -3.038659 0 -8.827904 -71.73027 -6.242584e-031 -8.430764 0.1969107 0 14.01921 -78.97189 -5.882796e-031 2.739249 6.924362 0 11.50623 16.57672 0 17.1313 28.34049 0 37.98603 -79.12265 -4.261077e-031 29.36394 74.9028 7.643719e-031 35.52051 76.51087 3.64551e-030 41.48091 78.73864 7.636926e-030 60.92244 -72.16905 -1.522917e-031 47.18293 81.56284 1.269697e-029 52.56709 84.95402 1.877284e-029 57.67648 89.0556 -1.403599e-014 63.67333 91.69501 -2.711546e-014 80.77074 -58.7349 2.086037e-031 70.14898 92.69238 -3.834705e-014 76.66211 91.97975 -4.696535e-014 82.76887 89.60568 -5.238305e-014 95.75028 -40.02542 6.242015e-031 100.8951 29.53631 1.822036e-030 104.5172 -17.71909 1.057217e-030 106.285 6.182927 1.468804e-030 -38.28861 40.08139 0 -37.78529 35.38022 0 -37.72749 37.76394 0</float_array>
<technique_common>
<accessor count="108" source="#ID8" stride="3">
<param name="X" type="float" />
<param name="Y" type="float" />
<param name="Z" type="float" />
</accessor>
</technique_common>
</source>
<source id="ID6">
<float_array id="ID9" count="324">5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1</float_array>
<technique_common>
<accessor count="108" source="#ID9" stride="3">
<param name="X" type="float" />
<param name="Y" type="float" />
<param name="Z" type="float" />
</accessor>
</technique_common>
</source>
<vertices id="ID7">
<input semantic="POSITION" source="#ID5" />
<input semantic="NORMAL" source="#ID6" />
</vertices>
<triangles count="106" material="Material2">
<input offset="0" semantic="VERTEX" source="#ID7" />
<p>0 1 2 1 0 3 3 0 4 3 4 5 6 7 8 7 6 9 9 6 10 9 10 11 11 10 12 11 12 13 13 12 14 13 14 15 15 14 16 16 14 17 17 14 18 18 14 19 18 19 20 20 19 21 21 19 22 22 19 23 22 23 24 22 24 25 25 24 26 24 23 27 27 23 28 28 23 29 28 29 30 30 29 31 31 29 32 31 32 33 33 32 34 33 34 35 35 34 36 35 36 37 37 36 38 37 38 39 39 38 40 39 40 41 41 40 42 41 42 43 43 42 44 43 44 45 45 44 46 45 46 47 48 49 50 49 48 51 51 48 52 51 52 53 53 52 54 55 56 57 56 55 58 56 58 59 59 58 60 59 60 61 61 60 62 61 62 4 4 62 63 4 63 5 5 63 64 64 63 65 64 65 66 66 65 67 67 65 68 67 68 69 67 69 70 70 69 71 70 71 72 70 72 73 70 73 74 74 73 75 75 73 76 74 75 77 75 76 78 78 76 79 78 79 80 80 79 81 80 81 82 82 81 83 82 83 84 84 83 85 84 85 86 84 86 87 84 87 88 88 87 47 88 47 46 88 46 89 88 89 90 88 90 91 88 91 92 92 91 93 92 93 94 92 94 95 92 95 96 92 96 97 97 96 98 97 98 99 97 99 100 97 100 101 101 100 49 49 100 50 101 49 102 101 102 103 103 102 104 26 105 106 105 26 24 106 105 107</p>
</triangles>
</mesh>
</geometry>
</library_geometries>
<library_materials>
<material id="ID4" name="material_0">
<instance_effect url="#ID3" />
</material>
</library_materials>
<library_effects>
<effect id="ID3">
<profile_COMMON>
<technique sid="COMMON">
<lambert>
<diffuse>
<color>1 1 1 1</color>
</diffuse>
</lambert>
</technique>
</profile_COMMON>
</effect>
</library_effects>
<scene>
<instance_visual_scene url="#ID1" />
</scene>
</COLLADA>

319
testbed/data/sketchup.dat Normal file
View File

@ -0,0 +1,319 @@
-112.9393 -5.134218
-115.783 -26.39329
-116.1693 -15.52189
-115.783 -26.39329
-112.9393 -5.134218
-111.8239 -36.52552
-111.8239 -36.52552
-112.9393 -5.134218
-106.4564 3.601217
-111.8239 -36.52552
-106.4564 3.601217
-104.7373 -44.7788
-66.76277 70.05491
-68.21937 53.83701
-68.55863 62.04185
-68.21937 53.83701
-66.76277 70.05491
-65.7681 45.99956
-65.7681 45.99956
-66.76277 70.05491
-62.95416 77.33014
-65.7681 45.99956
-62.95416 77.33014
-61.37187 39.0636
-61.37187 39.0636
-62.95416 77.33014
-57.39237 83.37173
-61.37187 39.0636
-57.39237 83.37173
-55.33028 33.5018
-55.33028 33.5018
-57.39237 83.37173
-50.4564 87.76796
-55.33028 33.5018
-50.4564 87.76796
-54.18848 31.40854
-54.18848 31.40854
-50.4564 87.76796
-52.54381 29.68213
-52.54381 29.68213
-50.4564 87.76796
-50.50835 28.44022
-50.50835 28.44022
-50.4564 87.76796
-48.22082 27.76744
-48.22082 27.76744
-50.4564 87.76796
-42.61895 90.21923
-48.22082 27.76744
-42.61895 90.21923
-45.8371 27.70964
-45.8371 27.70964
-42.61895 90.21923
-43.51965 28.27076
-43.51965 28.27076
-42.61895 90.21923
-41.4264 29.41256
-41.4264 29.41256
-42.61895 90.21923
-34.41412 90.55849
-41.4264 29.41256
-34.41412 90.55849
-38.42946 47.11159
-41.4264 29.41256
-38.42946 47.11159
-39.69999 31.05723
-39.69999 31.05723
-38.42946 47.11159
-38.45807 33.09269
-38.42946 47.11159
-34.41412 90.55849
-36.86605 53.9672
-36.86605 53.9672
-34.41412 90.55849
-33.69118 60.24126
-33.69118 60.24126
-34.41412 90.55849
-26.40105 88.76263
-33.69118 60.24126
-26.40105 88.76263
-29.09332 65.56134
-29.09332 65.56134
-26.40105 88.76263
-23.3454 69.61164
-23.3454 69.61164
-26.40105 88.76263
-19.12582 84.95402
-23.3454 69.61164
-19.12582 84.95402
-16.7886 72.15173
-16.7886 72.15173
-19.12582 84.95402
-13.74167 81.56284
-16.7886 72.15173
-13.74167 81.56284
-9.81216 73.03084
-9.81216 73.03084
-13.74167 81.56284
-8.03964 78.73864
-9.81216 73.03084
-8.03964 78.73864
-2.830188 72.19677
-2.830188 72.19677
-8.03964 78.73864
-2.079244 76.51087
-2.830188 72.19677
-2.079244 76.51087
3.742859 69.69904
3.742859 69.69904
-2.079244 76.51087
4.077324 74.9028
3.742859 69.69904
4.077324 74.9028
9.516804 65.68592
9.516804 65.68592
4.077324 74.9028
10.36582 73.93119
9.516804 65.68592
10.36582 73.93119
14.1489 60.39562
14.1489 60.39562
10.36582 73.93119
16.72063 73.60619
14.1489 60.39562
16.72063 73.60619
17.36419 54.14218
17.36419 54.14218
16.72063 73.60619
23.07544 73.93119
17.36419 54.14218
23.07544 73.93119
19.14039 41.22425
92.15467 80.62257
88.83104 50.24595
88.0531 85.73196
88.83104 50.24595
92.15467 80.62257
92.70476 55.53018
92.70476 55.53018
92.15467 80.62257
94.79408 74.62572
92.70476 55.53018
94.79408 74.62572
95.07883 61.63694
95.07883 61.63694
94.79408 74.62572
95.79146 68.15007
-138.3173 50.47565
-137.432 24.73624
-140.3168 37.52194
-137.432 24.73624
-138.3173 50.47565
-131.7115 61.79639
-137.432 24.73624
-131.7115 61.79639
-130.0639 13.89615
-130.0639 13.89615
-131.7115 61.79639
-121.4177 69.91023
-130.0639 13.89615
-121.4177 69.91023
-119.2369 6.508783
-119.2369 6.508783
-121.4177 69.91023
-108.8671 73.6891
-119.2369 6.508783
-108.8671 73.6891
-106.4564 3.601217
-106.4564 3.601217
-108.8671 73.6891
-95.8047 72.60761
-106.4564 3.601217
-95.8047 72.60761
-104.7373 -44.7788
-104.7373 -44.7788
-95.8047 72.60761
-95.3204 -50.22474
-95.3204 -50.22474
-95.8047 72.60761
-84.0465 66.81613
-95.3204 -50.22474
-84.0465 66.81613
-84.63247 -52.25073
-84.63247 -52.25073
-84.0465 66.81613
-73.87579 -50.62886
-73.87579 -50.62886
-84.0465 66.81613
-75.22729 57.11985
-73.87579 -50.62886
-75.22729 57.11985
-70.57319 44.86685
-73.87579 -50.62886
-70.57319 44.86685
-64.26037 -45.54158
-64.26037 -45.54158
-70.57319 44.86685
-69.61521 31.86262
-64.26037 -45.54158
-69.61521 31.86262
-64.96236 19.68153
-64.26037 -45.54158
-64.96236 19.68153
-57.00677 9.350201
-64.26037 -45.54158
-57.00677 9.350201
-56.86785 -37.56115
-56.86785 -37.56115
-57.00677 9.350201
-51.7342 -16.73615
-51.7342 -16.73615
-57.00677 9.350201
-46.41893 1.739326
-56.86785 -37.56115
-51.7342 -16.73615
-52.52979 -27.58529
-51.7342 -16.73615
-46.41893 1.739326
-43.24859 -39.15101
-43.24859 -39.15101
-46.41893 1.739326
-34.09116 -2.50966
-43.24859 -39.15101
-34.09116 -2.50966
-28.50562 -58.04747
-28.50562 -58.04747
-34.09116 -2.50966
-21.06243 -3.038659
-28.50562 -58.04747
-21.06243 -3.038659
-8.827904 -71.73027
-8.827904 -71.73027
-21.06243 -3.038659
-8.430764 0.1969107
-8.827904 -71.73027
-8.430764 0.1969107
14.01921 -78.97189
14.01921 -78.97189
-8.430764 0.1969107
2.739249 6.924362
14.01921 -78.97189
2.739249 6.924362
11.50623 16.57672
14.01921 -78.97189
11.50623 16.57672
17.1313 28.34049
14.01921 -78.97189
17.1313 28.34049
37.98603 -79.12265
37.98603 -79.12265
17.1313 28.34049
19.14039 41.22425
37.98603 -79.12265
19.14039 41.22425
23.07544 73.93119
37.98603 -79.12265
23.07544 73.93119
29.36394 74.9028
37.98603 -79.12265
29.36394 74.9028
35.52051 76.51087
37.98603 -79.12265
35.52051 76.51087
41.48091 78.73864
37.98603 -79.12265
41.48091 78.73864
60.92244 -72.16905
60.92244 -72.16905
41.48091 78.73864
47.18293 81.56284
60.92244 -72.16905
47.18293 81.56284
52.56709 84.95402
60.92244 -72.16905
52.56709 84.95402
57.67648 89.0556
60.92244 -72.16905
57.67648 89.0556
63.67333 91.69501
60.92244 -72.16905
63.67333 91.69501
80.77074 -58.7349
80.77074 -58.7349
63.67333 91.69501
70.14898 92.69238
80.77074 -58.7349
70.14898 92.69238
76.66211 91.97975
80.77074 -58.7349
76.66211 91.97975
82.76887 89.60568
80.77074 -58.7349
82.76887 89.60568
95.75028 -40.02542
95.75028 -40.02542
82.76887 89.60568
88.83104 50.24595
88.83104 50.24595
82.76887 89.60568
88.0531 85.73196
95.75028 -40.02542
88.83104 50.24595
100.8951 29.53631
95.75028 -40.02542
100.8951 29.53631
104.5172 -17.71909
104.5172 -17.71909
100.8951 29.53631
106.285 6.182927
-38.45807 33.09269
-38.28861 40.08139
-37.78529 35.38022
-38.28861 40.08139
-38.45807 33.09269
-38.42946 47.11159
-37.78529 35.38022
-38.28861 40.08139
-37.72749 37.76394

10
testbed/data/star.dat Normal file
View File

@ -0,0 +1,10 @@
350 75
379 161
469 161
397 215
423 301
350 250
277 301
303 215
231 161
321 161

16
testbed/data/strange.dat Normal file
View File

@ -0,0 +1,16 @@
400 472
500 392
520 272
460 232
580 212
480 152
360 172
360 52
300 112
200 32
120 92
200 72
340 272
208 212
180 352
300 312

55
testbed/data/tank.dat Normal file
View File

@ -0,0 +1,55 @@
-37.317758 260.65677
-37.317758 317.44301
-34.741139 339.73612
-27.330761 354.21222
59.525828 406.25724
444.17643 404.87856
538.9604 368.68832
555.15984 355.59089
558.95121 344.90615
559.64054 325.94936
568.19908 315.85885
572.586 322.56108
584.65003 322.31737
568.80837 296.11771
557.59736 289.78104
539.56224 286.49085
443.31476 286.82943
389.89106 280.79772
405.74583 272.00866
412.98388 262.01326
475.5413 262.1856
480.71134 267.01096
514.66123 266.66629
520.34827 262.01326
669.93463 262.01326
670.45162 264.08127
676.91417 263.82277
678.03434 262.09943
680.61936 261.66859
683.03204 255.46455
682.51504 249.94985
677.862 243.91814
668.81445 243.4873
665.28159 247.02016
520.86527 246.33082
514.66123 240.12678
479.67733 239.95444
475.5413 243.57347
412.98388 243.05647
397.64611 227.54636
324.74862 221.16998
323.88695 214.79361
328.36764 211.86392
326.6443 207.03856
300.79412 207.03856
295.62409 211.69159
285.28402 208.2449
272.01426 211.17458
96.577738 209.62357
80.205961 211.86392
58.491817 232.7164
74.863594 254.94755
168.61356 269.25131
175.16228 276.83403
87.271676 260.11758

6
testbed/data/test.dat Normal file
View File

@ -0,0 +1,6 @@
227.15518 452.33157
344.46202 352.32647
472.15156 452.33157
603.11967 352.32647
344.46202 725.78132
81.390847 352.32647

244
testbed/main.cc Normal file
View File

@ -0,0 +1,244 @@
/*
* Poly2Tri Copyright (c) 2009-2010, Mason Green
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <cstdlib>
#include <GL/glfw.h>
#include <time.h>
#include <fstream>
#include <string>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <iostream>
using namespace std;
#include "../poly2tri/poly2tri.h"
void Init();
void ShutDown(int return_code);
void MainLoop();
void Draw();
float rotate_y = 0,
rotate_z = 0;
const float rotations_per_tick = .2;
list<Triangle*> triangles;
double StringToDouble(const std::string& s) {
std::istringstream i(s);
double x;
if (!(i >> x))
return 0;
return x;
}
int main(int argc, char* argv[]) {
/*
// initialize random seed:
srand ( time(NULL) );
int a = 0;
int b = 2000;
for(int i = 0; i < num_points; i++) {
double x = rand() % (b - a - 1) + a + 1;
double y = rand() % (b - a - 1) + a + 1;
polyline[i] = Point(x, y);
}
polyline[0] = Point(5, 5);
polyline[1] = Point(-5, 5);
polyline[2] = Point(-5, -5);
polyline[3] = Point(5, -5);
//Point foo[] = {Point(5, 5.1), Point(-5, 5.2), Point(-5, -5.3), Point(5, -5.4), Point(5.1, 5.5), Point(5, 5.5),
// Point(-5, 5.6), Point(-5, -5.7), Point(5, -5.8), Point(5, 5.9), Point(-5, 5.1),
// Point(-5, -5.11), Point(5, -5.12), Point(5, 5.13), Point(-5, 5.14), Point(-5, -5.15), Point(5, -5.16)};
*/
string line;
ifstream myfile (argv[1]);
vector<Point> points;
if (myfile.is_open()) {
while (!myfile.eof()) {
getline (myfile,line);
if(line.size() == 0) {
break;
}
istringstream iss(line);
vector<string> tokens;
copy(istream_iterator<string>(iss), istream_iterator<string>(),
back_inserter<vector<string> >(tokens));
double x = StringToDouble(tokens[0]);
double y = StringToDouble(tokens[1]);
points.push_back(Point(x, y));
}
myfile.close();
} else {
cout << "File not opened" << endl;
}
int num_points = points.size();
cout << "Number of points = " << num_points << endl;
Point* polyline = new Point[num_points];
for(int i = 0; i < num_points; i++) {
polyline[i] = points[i];
}
Init();
// Perform triangulation
double init_time = glfwGetTime();
CDT * cdt = new CDT(polyline, num_points);
cdt->Triangulate();
double dt = glfwGetTime() - init_time;
cout << "Elapsed time (secs) = " << dt << endl;
triangles = cdt->GetTriangles();
MainLoop();
delete [] polyline;
ShutDown(0);
return 0;
}
void Init()
{
const int window_width = 800,
window_height = 600;
if (glfwInit() != GL_TRUE)
ShutDown(1);
// 800 x 600, 16 bit color, no depth, alpha or stencil buffers, windowed
if (glfwOpenWindow(window_width, window_height, 5, 6, 5, 0, 0, 0, GLFW_WINDOW) != GL_TRUE)
ShutDown(1);
glfwSetWindowTitle("The GLFW Window");
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(0.0, 0.0, 0.0, 0.0);
glHint (GL_LINE_SMOOTH_HINT, GL_NICEST);
}
void ShutDown(int return_code)
{
glfwTerminate();
exit(return_code);
}
void MainLoop()
{
// the time of the previous frame
double old_time = glfwGetTime();
// this just loops as long as the program runs
bool running = true;
while(running)
{
// calculate time elapsed, and the amount by which stuff rotates
double current_time = glfwGetTime(),
delta_rotate = (current_time - old_time) * rotations_per_tick * 360;
old_time = current_time;
// escape to quit, arrow keys to rotate view
// Check if ESC key was pressed or window was closed
running = !glfwGetKey( GLFW_KEY_ESC ) && glfwGetWindowParam( GLFW_OPENED );
if (glfwGetKey(GLFW_KEY_LEFT) == GLFW_PRESS)
rotate_y += delta_rotate;
if (glfwGetKey(GLFW_KEY_RIGHT) == GLFW_PRESS)
rotate_y -= delta_rotate;
// z axis always rotates
rotate_z += delta_rotate;
// Draw the scene
Draw();
// swap back and front buffers
glfwSwapBuffers();
}
}
void ResetZoom(double zoom, double cx, double cy, double width, double height) {
double left = -width / zoom;
double right = width / zoom;
double bottom = -height / zoom;
double top = height / zoom;
// Reset viewport
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Reset ortho view
glOrtho(left, right, bottom, top, 1, -1);
glTranslatef(-cx, -cy, 0);
glMatrixMode(GL_MODELVIEW);
glDisable(GL_DEPTH_TEST);
glLoadIdentity();
// Clear the screen
glClear(GL_COLOR_BUFFER_BIT);
}
void Draw()
{
// reset zoom
double zoom = 0.5;
ResetZoom(zoom, 0, 0, 800, 600);
list<Triangle*>::iterator it;
for (it = triangles.begin(); it != triangles.end(); it++) {
Triangle* t = *it;
Point* a = t->GetPoint(0);
Point* b = t->GetPoint(1);
Point* c = t->GetPoint(2);
// Red
glColor3f(1, 0, 0);
glBegin(GL_LINE_LOOP); // Drawing Using Triangles
glVertex2f(a->x, a->y); // Top
glVertex2f(b->x, b->y); // Bottom Left
glVertex2f(c->x, c->y); // Bottom Right
glEnd();
}
}

BIN
waf vendored Normal file

Binary file not shown.

69
wscript Normal file
View File

@ -0,0 +1,69 @@
VERSION='0.0.1'
import sys
APPNAME='p2t'
srcdir = '.'
blddir = 'build'
p2t_source_files = ['poly2tri/sweep/cdt.cc',
'poly2tri/sweep/advancing_front.cc',
'poly2tri/sweep/mesh.cc',
'poly2tri/sweep/sweep_context.cc',
'poly2tri/sweep/sweep.cc',
'poly2tri/common/shapes.cc']
testbed_source_files = ['testbed/main.cc']
#Platform specific libs
if sys.platform == 'win32':
# MS Windows
sys_libs = ['glfw', 'opengl32']
elif sys.platform == 'darwin':
# Apple OSX
sys_libs = ['glfw', 'OpenGL']
else:
# GNU/Linux, BSD, etc
sys_libs = ['glfw', 'GL']
def init():
print(' init called')
def set_options(opt):
print(' set_options')
opt.tool_options('g++')
def configure(conf):
print(' calling the configuration')
conf.check_tool('g++')
#conf.env.CXXFLAGS = ['-O0', '-pg', '-g']
conf.env.CXXFLAGS = ['-O0', '-g']
#conf.env.CXXFLAGS = ['-O3', '-ffast-math']
def build(bld):
print(' building')
'''
# A static library
# The extension (.a) is added automatically
bld.new_task_gen(
features = 'cxx cstaticlib',
source = p2t_source_files,
name = 'poly2tri',
target = 'poly2tri')
# 1. A simple program
bld.new_task_gen(
features = 'cxx cprogram',
source = testbed_source_files,
target = 'p2t',
uselib_local = 'poly2tri',
libs = sys_libs)
'''
bld.new_task_gen(
features = 'cxx cprogram',
source = testbed_source_files + p2t_source_files,
target = 'p2t',
libs = sys_libs)
def shutdown():
print(' shutdown called')