fixed edge pointer bug - yay

This commit is contained in:
zzzzrrr 2010-01-19 17:23:38 -05:00
parent 9b279f68b5
commit d776b54e57
14 changed files with 216 additions and 193 deletions

View File

@ -329,5 +329,12 @@ Triangle& Triangle::NeighborAcross(Point& opoint) {
return *neighbors_[2]; return *neighbors_[2];
} }
void Triangle::DebugPrint() {
using namespace std;
cout << points_[0]->x << "," << points_[0]->y << " ";
cout << points_[1]->x << "," << points_[1]->y << " ";
cout << points_[2]->x << "," << points_[2]->y << endl;
}

View File

@ -28,7 +28,6 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
// Include guard // Include guard
#ifndef SHAPES_H #ifndef SHAPES_H
#define SHAPES_H #define SHAPES_H
@ -48,7 +47,8 @@ struct Point {
double x, y; double x, y;
/// Default constructor does nothing (for performance). /// Default constructor does nothing (for performance).
Point() {} Point() { x = 0.0; y = 0.0; }
/// The edges this point constitutes an upper ending point /// The edges this point constitutes an upper ending point
std::vector<Edge> edge_list; std::vector<Edge> edge_list;
@ -92,6 +92,18 @@ struct Point {
return len; return len;
} }
bool operator < (Point& b) {
if (y < b.y) {
return true;
} else if (y == b.y) {
// Make sure q is point with greater x value
if(x < b.x) {
return true;
}
}
return false;
}
}; };
// Represents a simple polygon's edge // Represents a simple polygon's edge
@ -110,6 +122,7 @@ struct Edge {
q = &p1; q = &p1;
p = &p2; p = &p2;
} else if(p1.x == p2.x) { } else if(p1.x == p2.x) {
// Repeat points
assert(false); assert(false);
} }
} }
@ -176,6 +189,8 @@ public:
Triangle& NeighborAcross(Point& opoint); Triangle& NeighborAcross(Point& opoint);
void DebugPrint();
private: private:
/// Triangle points /// Triangle points
@ -192,13 +207,6 @@ inline bool operator < (const Point& a, const Point& b) {
// Make sure q is point with greater x value // Make sure q is point with greater x value
if(a.x < b.x) { if(a.x < b.x) {
return true; 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; return false;

View File

@ -28,10 +28,11 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <stdexcept> #ifndef UTILS_H
#include <math.h> #define UTILS_H
#include "shapes.h" #include <exception>
#include <math.h>
template<typename T, int size> template<typename T, int size>
int array_length(T(&)[size]){return size;} int array_length(T(&)[size]){return size;}
@ -67,32 +68,35 @@ Orientation Orient2d(Point& pa, Point& pb, Point& pc ) {
bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd) { bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd) {
const double pdx = pd.x; double pdx = pd.x;
const double pdy = pd.y; double pdy = pd.y;
const double adx = pa.x - pdx; double adx = pa.x - pdx;
const double ady = pa.y - pdy; double ady = pa.y - pdy;
const double bdx = pb.x - pdx; double bdx = pb.x - pdx;
const double bdy = pb.y - pdy; double bdy = pb.y - pdy;
const double adxbdy = adx * bdy; double adxbdy = adx * bdy;
const double bdxady = bdx * ady; double bdxady = bdx * ady;
const double oabd = adxbdy - bdxady; double oabd = adxbdy - bdxady;
if(oabd <= 0) { if(oabd <= EPSILON) {
return false; return false;
} }
const double cdx = pc.x - pdx; double cdx = pc.x - pdx;
const double cdy = pc.y - pdy; double cdy = pc.y - pdy;
const double cdxady = cdx * ady; double cdxady = cdx * ady;
const double adxcdy = adx * cdy; double adxcdy = adx * cdy;
const double ocad = cdxady - adxcdy; double ocad = cdxady - adxcdy;
if(ocad <= 0) { if(ocad <= EPSILON) {
return false; return false;
} }
return true;
return true;
} }
#endif

View File

@ -86,10 +86,12 @@ Node* AdvancingFront::LocatePoint(Point* point) {
break; break;
} }
} }
search_node_ = node; if(node) search_node_ = node;
return node; return node;
} }
AdvancingFront::~AdvancingFront() { AdvancingFront::~AdvancingFront() {
delete head_; search_node_; tail_; delete head_;
delete search_node_;
delete tail_;
} }

View File

@ -30,7 +30,7 @@
*/ */
#include "cdt.h" #include "cdt.h"
CDT::CDT(Point polyline[], const int& point_count) { CDT::CDT(Point** polyline, const int& point_count) {
sweep_context_ = new SweepContext(polyline, point_count); sweep_context_ = new SweepContext(polyline, point_count);
sweep_ = new Sweep; sweep_ = new Sweep;
} }

View File

@ -39,7 +39,7 @@ class CDT
public: public:
/// Constructor /// Constructor
CDT(Point poly_line[], const int& point_count); CDT(Point** poly_line, const int& point_count);
/// Add a hole /// Add a hole
void AddHole(const Point poly_line[], const int point_count); void AddHole(const Point poly_line[], const int point_count);
/// Triangulate points /// Triangulate points

View File

@ -57,11 +57,13 @@ void Sweep::SweepPoints(SweepContext& tcx ) {
for(int i = 1; i < tcx.point_count(); i++ ) { for(int i = 1; i < tcx.point_count(); i++ ) {
Point& point = *tcx.GetPoint(i); Point& point = *tcx.GetPoint(i);
Node& node = PointEvent(tcx, point); Node& node = PointEvent(tcx, point);
for(int i = 0; i < point.edge_list.size(); i++) { for(int i = 0; i < point.edge_list.size(); i++) {
EdgeEvent(tcx, point.edge_list[i], node ); EdgeEvent(tcx, point.edge_list[i], node);
} }
} }
} }
@ -274,7 +276,7 @@ double Sweep::HoleAngle(Node& node) {
double ay = node.next->point->y - node.point->y; double ay = node.next->point->y - node.point->y;
double bx = node.prev->point->x - node.point->x; double bx = node.prev->point->x - node.point->x;
double by = node.prev->point->y - node.point->y; double by = node.prev->point->y - node.point->y;
return atan2(ax*by - ay*bx, ax*bx + ay*by); return atan2(ax * by - ay * bx, ax * bx + ay * by);
} }
/** /**
@ -380,7 +382,7 @@ bool Sweep::Incircle(Point& pa, Point& pb, Point& pc, Point& pd) {
double oabd = adxbdy - bdxady; double oabd = adxbdy - bdxady;
if( oabd <= 0 ) if( oabd <= 0 )
return false; return false;
double cdx = pc.x - pd.x; double cdx = pc.x - pd.x;
double cdy = pc.y - pd.y; double cdy = pc.y - pd.y;
@ -390,7 +392,7 @@ bool Sweep::Incircle(Point& pa, Point& pb, Point& pc, Point& pd) {
double ocad = cdxady - adxcdy; double ocad = cdxady - adxcdy;
if( ocad <= 0 ) if( ocad <= 0 )
return false; return false;
double bdxcdy = bdx * cdy; double bdxcdy = bdx * cdy;
double cdxbdy = cdx * bdy; double cdxbdy = cdx * bdy;
@ -788,25 +790,25 @@ void Sweep::FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& t,
} }
if(InScanArea(p, *t.PointCCW(p), *t.PointCW(p), op)) { if(InScanArea(p, *t.PointCCW(p), *t.PointCW(p), op)) {
// Lets rotate shared edge one vertex CW // Lets rotate shared edge one vertex CW
RotateTrianglePair(t, p, ot, op); RotateTrianglePair(t, p, ot, op);
tcx.MapTriangleToNodes(t); tcx.MapTriangleToNodes(t);
tcx.MapTriangleToNodes(ot); tcx.MapTriangleToNodes(ot);
if( p == eq && op == ep ) { if( p == eq && op == ep ) {
if(eq == *tcx.edge_event.constrained_edge->q && ep == *tcx.edge_event.constrained_edge->p) { if(eq == *tcx.edge_event.constrained_edge->q && ep == *tcx.edge_event.constrained_edge->p) {
t.MarkConstrainedEdge(&ep, &eq); t.MarkConstrainedEdge(&ep, &eq);
ot.MarkConstrainedEdge(&ep, &eq); ot.MarkConstrainedEdge(&ep, &eq);
Legalize(tcx, t); Legalize(tcx, t);
Legalize(tcx, ot); Legalize(tcx, ot);
} else { } else {
// XXX: I think one of the triangles should be legalized here? // XXX: I think one of the triangles should be legalized here?
} }
} else { } else {
Orientation o = Orient2d(eq, op, ep); Orientation o = Orient2d(eq, op, ep);
t = NextFlipTriangle(tcx, (int) o, t, ot, p, op); t = NextFlipTriangle(tcx, (int) o, t, ot, p, op);
FlipEdgeEvent(tcx, ep, eq, t, p); FlipEdgeEvent(tcx, ep, eq, t, p);
} }
} else { } else {
Point& newP = NextFlipPoint( ep, eq, ot, op); Point& newP = NextFlipPoint( ep, eq, ot, op);
FlipScanEdgeEvent(tcx, ep, eq, t, ot, newP); FlipScanEdgeEvent(tcx, ep, eq, t, ot, newP);
@ -816,36 +818,36 @@ void Sweep::FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& t,
Triangle& Sweep::NextFlipTriangle(SweepContext& tcx, int o, Triangle& t, Triangle& ot, Point& p, Point& op) { Triangle& Sweep::NextFlipTriangle(SweepContext& tcx, int o, Triangle& t, Triangle& ot, Point& p, Point& op) {
if(o == CCW ) { if(o == CCW) {
// ot is not crossing edge after flip // ot is not crossing edge after flip
int edge_index = ot.EdgeIndex(&p, &op); int edge_index = ot.EdgeIndex(&p, &op);
ot.delaunay_edge[edge_index] = true; ot.delaunay_edge[edge_index] = true;
Legalize(tcx, ot); Legalize(tcx, ot);
ot.ClearDelunayEdges(); ot.ClearDelunayEdges();
return t; return t;
} }
// t is not crossing edge after flip // t is not crossing edge after flip
int edge_index = t.EdgeIndex(&p, &op); int edge_index = t.EdgeIndex(&p, &op);
t.delaunay_edge[edge_index] = true; t.delaunay_edge[edge_index] = true;
Legalize(tcx, t); Legalize(tcx, t);
t.ClearDelunayEdges(); t.ClearDelunayEdges();
return ot; return ot;
} }
Point& Sweep::NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op ) { Point& Sweep::NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op) {
Orientation o2d = Orient2d(eq, op, ep); Orientation o2d = Orient2d(eq, op, ep);
if(o2d == CW) { if(o2d == CW) {
// Right // Right
return *ot.PointCCW(op); return *ot.PointCCW(op);
} else if(o2d == CCW) { } else if(o2d == CCW) {
// Left // Left
return *ot.PointCW(op); return *ot.PointCW(op);
} else { } else {
//throw new RuntimeException("[Unsupported] Opposing point on constrained edge"); //throw new RuntimeException("[Unsupported] Opposing point on constrained edge");
assert(0); assert(0);
} }
} }

View File

@ -37,8 +37,6 @@
* "FlipScan" Constrained Edge Algorithm invented by Thomas Åhlén, thahlen@gmail.com * "FlipScan" Constrained Edge Algorithm invented by Thomas Åhlén, thahlen@gmail.com
*/ */
#include <list>
class SweepContext; class SweepContext;
struct Node; struct Node;
struct Point; struct Point;

View File

@ -4,16 +4,17 @@
#include <GL/glfw.h> #include <GL/glfw.h>
#include "advancing_front.h" #include "advancing_front.h"
SweepContext::SweepContext(Point polyline[], const int& point_count) { SweepContext::SweepContext(Point** polyline, const int& point_count) {
basin = Basin(); basin = Basin();
edge_event = EdgeEvent(); edge_event = EdgeEvent();
point_count_ = point_count; for(int i = 0; i < point_count; i++) {
points_ = polyline; points_.push_back(**&polyline[i]);
}
InitEdges(polyline, point_count);
InitTriangulation(); InitTriangulation();
InitEdges();
} }
@ -27,7 +28,7 @@ void SweepContext::InitTriangulation() {
double ymax(points_[0].y), ymin(points_[0].y); double ymax(points_[0].y), ymin(points_[0].y);
// Calculate bounds. // Calculate bounds.
for(int i = 0; i < point_count_; i++) { for(int i = 0; i < points_.size(); i++) {
Point p = points_[i]; Point p = points_[i];
if(p.x > xmax) if(p.x > xmax)
xmax = p.x; xmax = p.x;
@ -46,22 +47,17 @@ void SweepContext::InitTriangulation() {
// Sort points along y-axis // Sort points along y-axis
double init_time = glfwGetTime(); double init_time = glfwGetTime();
std::sort(points_, points_ + point_count_); std::sort(points_.begin(), points_.end());
double dt = glfwGetTime() - init_time; double dt = glfwGetTime() - init_time;
printf("Sort time (secs) = %f\n", dt); 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() { void SweepContext::InitEdges(Point** polyline, const int& point_count) {
for(int i = 0; i < point_count_; i++) {
int j = i < point_count_ - 1 ? i + 1 : 0; for(int i = 0; i < point_count; i++) {
new Edge(points_[i], points_[j]); int j = i < points_.size() - 1 ? i + 1 : 0;
edge_list.push_back(new Edge(**&polyline[i], **&polyline[j]));
} }
} }
@ -157,7 +153,7 @@ void SweepContext::MeshCleanReq(Triangle& triangle ) {
*/ */
SweepContext::~SweepContext() { SweepContext::~SweepContext() {
delete [] points_; //delete [] points_;
delete head_; delete head_;
delete tail_; delete tail_;
delete front_; delete front_;

View File

@ -29,6 +29,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <list> #include <list>
#include <vector>
// Inital triangle factor, seed triangle will extend 30% of // Inital triangle factor, seed triangle will extend 30% of
// PointSet width to both left and right. // PointSet width to both left and right.
@ -46,7 +47,7 @@ class SweepContext {
public: public:
// Constructor // Constructor
SweepContext(Point polyline[], const int& point_count); SweepContext(Point** polyline, const int& point_count);
// Destructor // Destructor
~SweepContext(); ~SweepContext();
@ -81,6 +82,7 @@ public:
std::list<Triangle*> GetTriangles(); std::list<Triangle*> GetTriangles();
std::vector<Edge*> edge_list;
struct Basin { struct Basin {
@ -118,9 +120,7 @@ public:
private: private:
std::list<Triangle*> tri_list_; std::list<Triangle*> tri_list_;
std::vector<Point> points_;
Point* points_;
int point_count_;
// Advancing front // Advancing front
AdvancingFront* front_; AdvancingFront* front_;
@ -132,7 +132,7 @@ private:
//EdgeEvent edgeEvent = new EdgeEvent(); //EdgeEvent edgeEvent = new EdgeEvent();
void InitTriangulation(); void InitTriangulation();
void InitEdges(); void InitEdges(Point** polyline, const int& point_count);
//void MeshCleanReq(Triangle& triangle ) //void MeshCleanReq(Triangle& triangle )
@ -147,7 +147,7 @@ private:
inline AdvancingFront* SweepContext::front() { return front_; } inline AdvancingFront* SweepContext::front() { return front_; }
inline int SweepContext::point_count() { return point_count_; } inline int SweepContext::point_count() { return points_.size(); }
inline void SweepContext::set_head(Point* p1) { head_ = p1; } inline void SweepContext::set_head(Point* p1) { head_ = p1; }

View File

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

View File

@ -44,8 +44,8 @@ using namespace std;
void Init(); void Init();
void ShutDown(int return_code); void ShutDown(int return_code);
void MainLoop(); void MainLoop(const double zoom);
void Draw(); void Draw(const double zoom);
float rotate_y = 0, float rotate_y = 0,
rotate_z = 0; rotate_z = 0;
@ -63,6 +63,11 @@ double StringToDouble(const std::string& s) {
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
if (argc != 3) {
cout << "Usage: p2t filename zoom" << endl;
return 1;
}
/* /*
// initialize random seed: // initialize random seed:
srand ( time(NULL) ); srand ( time(NULL) );
@ -112,9 +117,9 @@ int main(int argc, char* argv[]) {
int num_points = points.size(); int num_points = points.size();
cout << "Number of points = " << num_points << endl; cout << "Number of points = " << num_points << endl;
Point* polyline = new Point[num_points]; Point** polyline = new Point *[num_points];
for(int i = 0; i < num_points; i++) { for(int i = 0; i < num_points; i++) {
polyline[i] = points[i]; polyline[i] = &points[i];
} }
Init(); Init();
@ -128,7 +133,7 @@ int main(int argc, char* argv[]) {
triangles = cdt->GetTriangles(); triangles = cdt->GetTriangles();
MainLoop(); MainLoop(atof(argv[2]));
delete [] polyline; delete [] polyline;
ShutDown(0); ShutDown(0);
@ -161,7 +166,7 @@ void ShutDown(int return_code)
exit(return_code); exit(return_code);
} }
void MainLoop() void MainLoop(const double zoom)
{ {
// the time of the previous frame // the time of the previous frame
double old_time = glfwGetTime(); double old_time = glfwGetTime();
@ -187,7 +192,7 @@ void MainLoop()
rotate_z += delta_rotate; rotate_z += delta_rotate;
// Draw the scene // Draw the scene
Draw(); Draw(zoom);
// swap back and front buffers // swap back and front buffers
glfwSwapBuffers(); glfwSwapBuffers();
} }
@ -217,11 +222,12 @@ void ResetZoom(double zoom, double cx, double cy, double width, double height) {
} }
void Draw() void Draw(const double zoom)
{ {
// reset zoom // reset zoom
double zoom = 0.5; Point center = Point(0, 0);
ResetZoom(zoom, 0, 0, 800, 600);
ResetZoom(zoom, center.x, center.y, 800, 600);
list<Triangle*>::iterator it; list<Triangle*>::iterator it;
for (it = triangles.begin(); it != triangles.end(); it++) { for (it = triangles.begin(); it != triangles.end(); it++) {

View File

@ -4,12 +4,12 @@ APPNAME='p2t'
srcdir = '.' srcdir = '.'
blddir = 'build' blddir = 'build'
p2t_source_files = ['poly2tri/sweep/cdt.cc', p2t_source_files = ['poly2tri/common/shapes.cc',
'poly2tri/sweep/cdt.cc',
'poly2tri/sweep/advancing_front.cc', 'poly2tri/sweep/advancing_front.cc',
'poly2tri/sweep/mesh.cc', 'poly2tri/sweep/mesh.cc',
'poly2tri/sweep/sweep_context.cc', 'poly2tri/sweep/sweep_context.cc',
'poly2tri/sweep/sweep.cc', 'poly2tri/sweep/sweep.cc']
'poly2tri/common/shapes.cc']
testbed_source_files = ['testbed/main.cc'] testbed_source_files = ['testbed/main.cc']