mirror of
https://github.com/jhasse/poly2tri.git
synced 2025-08-14 03:05:39 +02:00
checked in c++ code
This commit is contained in:
95
poly2tri/sweep/advancing_front.cc
Normal file
95
poly2tri/sweep/advancing_front.cc
Normal 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_;
|
||||
}
|
98
poly2tri/sweep/advancing_front.h
Normal file
98
poly2tri/sweep/advancing_front.h
Normal 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
54
poly2tri/sweep/cdt.cc
Normal 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
58
poly2tri/sweep/cdt.h
Normal 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
49
poly2tri/sweep/mesh.cc
Normal 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
50
poly2tri/sweep/mesh.h
Normal 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
882
poly2tri/sweep/sweep.cc
Normal 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
118
poly2tri/sweep/sweep.h
Normal 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 <20>hl<68>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);
|
||||
|
||||
};
|
164
poly2tri/sweep/sweep_context.cc
Normal file
164
poly2tri/sweep/sweep_context.cc
Normal 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_;
|
||||
}
|
158
poly2tri/sweep/sweep_context.h
Normal file
158
poly2tri/sweep/sweep_context.h
Normal 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_; }
|
Reference in New Issue
Block a user