Commit 6a2f26e4 authored by JasonPries's avatar JasonPries
Browse files

Rewrote Mesh::locate_triangle function

The new implementation could be improved by removing calculations that get repeated when changing triangles and further optimizing return paths.
parent df6efdc2
...@@ -5,13 +5,14 @@ ...@@ -5,13 +5,14 @@
<sourceFolder url="file://$MODULE_DIR$/src/CMakeLists.txt" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/CMakeLists.txt" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Angle.cpp" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Angle.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Vertical.h" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Vertical.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Curve.h" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Sketch.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Coincident.cpp" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Coincident.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Vertical.cpp" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Vertical.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Angle.h" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Angle.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Vertex.h" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Vertex.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Curve.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Pattern.cpp" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Pattern.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Radius.h" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Length.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Coincident.h" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Coincident.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Constellation.h" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Constellation.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Radius.cpp" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Radius.cpp" isTestSource="false" />
...@@ -19,44 +20,43 @@ ...@@ -19,44 +20,43 @@
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Vertex.cpp" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Vertex.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/LineSegment.h" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/LineSegment.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Curve.cpp" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Curve.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Branch.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Rotation.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Tangency.cpp" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Tangency.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Rotation.cpp" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Rotation.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Branch.h" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Branch.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Constraint.cpp" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Branch.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/RotateCopy.h" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Tangency.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Constraint.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Star.cpp" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Star.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Symmetry.h" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Symmetry.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Constraint.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Length.h" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Length.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Length.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Constellation.cpp" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Constellation.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Contour.cpp" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Contour.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Fixation.h" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Fixation.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Radius.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Horizontal.cpp" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Horizontal.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/CircularArc.cpp" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/CircularArc.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Distance.cpp" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Distance.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Symmetry.cpp" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Symmetry.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Distance.h" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Distance.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/MirrorCopy.h" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/MirrorCopy.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Constraint.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Star.h" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Star.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/LineSegment.cpp" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/LineSegment.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/MirrorCopy.cpp" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/MirrorCopy.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Fixation.cpp" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Fixation.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Sketch.h" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Sketch.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/RotateCopy.cpp" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/RotateCopy.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Tangency.h" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/RotateCopy.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Contour.h" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Contour.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Pattern.h" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Pattern.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Sketch.cpp" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Rotation.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/CircularArc.h" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/CircularArc.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/include/Sketch.hpp" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/include/Sketch.hpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/CMakeLists.txt" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Sketch/CMakeLists.txt" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Mesh/src/Point.h" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Mesh/src/Point.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Mesh/src/Mesh.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Mesh/src/Point.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Mesh/src/Edge.cpp" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Mesh/src/Edge.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Mesh/src/Point.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Mesh/src/Mesh.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Mesh/src/Mesh.cpp" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Mesh/src/Mesh.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Mesh/src/util.h" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Mesh/src/util.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Mesh/src/Edge.h" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/Mesh/src/Edge.h" isTestSource="false" />
...@@ -71,8 +71,10 @@ ...@@ -71,8 +71,10 @@
<sourceFolder url="file://$MODULE_DIR$/lib/GoogleTest/googletest/cmake/internal_utils.cmake" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/lib/GoogleTest/googletest/cmake/internal_utils.cmake" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/CMakeLists.txt" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/CMakeLists.txt" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test/main.cpp" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/test/main.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test/Mesh/util.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test/Mesh/test_Mesh.cpp" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/test/Mesh/test_Mesh.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test/Mesh/test_Mesh.hpp" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/test/Mesh/test_Mesh.hpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test/Mesh/util.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test/CMakeLists.txt" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/test/CMakeLists.txt" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test/Sketch/test_Curve.cpp" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/test/Sketch/test_Curve.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test/Sketch/test_LineSegment.cpp" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/test/Sketch/test_LineSegment.cpp" isTestSource="false" />
......
#include "Mesh.hpp" #include "Mesh.hpp"
// Edge
Edge::Edge(Curve *c, bool direction) { Edge::Edge(Curve *c, bool direction) {
ConstraintCurve = c; ConstraintCurve = c;
Node = new Point(direction ? c->start() : c->end()); Node = new Point(direction ? c->start() : c->end());
...@@ -19,7 +18,6 @@ Edge::Edge(Curve *c, bool direction, const Point *v) { ...@@ -19,7 +18,6 @@ Edge::Edge(Curve *c, bool direction, const Point *v) {
Orientation = direction; Orientation = direction;
} }
// Test Methods
bool Edge::is_protruding() const { bool Edge::is_protruding() const {
/* /*
See Chapter 1.4 of "Triangulations and Applications" by Øyvind Hjelle and Morten Dæhlen See Chapter 1.4 of "Triangulations and Applications" by Øyvind Hjelle and Morten Dæhlen
...@@ -224,13 +222,13 @@ bool Edge::swap() { ...@@ -224,13 +222,13 @@ bool Edge::swap() {
bool Edge::recursive_swap() { bool Edge::recursive_swap() {
// TODO, May need to have two different recursive swap methods, one for midpoint insertion and one for circumcenter insertion // TODO, May need to have two different recursive swap methods, one for midpoint insertion and one for circumcenter insertion
if (!is_locally_optimal() && swap()) { if (!is_locally_optimal() && swap()) {
Edge * next = Next; Edge * enext = Next;
Edge * prev = Prev; Edge * eprev = Prev;
Edge * tnext = Twin->Next; Edge * tnext = Twin->Next;
Edge * tprev = Twin->Prev; Edge * tprev = Twin->Prev;
next->recursive_swap(); enext->recursive_swap();
prev->recursive_swap(); eprev->recursive_swap();
tnext->recursive_swap(); tnext->recursive_swap();
tprev->recursive_swap(); tprev->recursive_swap();
...@@ -251,7 +249,7 @@ void Edge::split_edge(std::vector<const Point *> &points, std::vector<Edge *> &e ...@@ -251,7 +249,7 @@ void Edge::split_edge(std::vector<const Point *> &points, std::vector<Edge *> &e
Curve *c; Curve *c;
if (ConstraintCurve != nullptr) { // Constrained Edge if (ConstraintCurve != nullptr) { // Constrained Edge
Vertex *v = new Vertex; // #TODO: Need to manage this memory. Destructors. Vertex *v = new Vertex; // TODO: Need to manage this memory. Destructors.
c = ConstraintCurve->split(v, 0.5); c = ConstraintCurve->split(v, 0.5);
p->X = v->x(); p->X = v->x();
...@@ -339,7 +337,6 @@ void Edge::split_edge(std::vector<const Point *> &points, std::vector<Edge *> &e ...@@ -339,7 +337,6 @@ void Edge::split_edge(std::vector<const Point *> &points, std::vector<Edge *> &e
} }
} }
// Calculation Methods
Point Edge::circumcenter() const { Point Edge::circumcenter() const {
double xa = Node->X; double xa = Node->X;
double ya = Node->Y; double ya = Node->Y;
...@@ -403,118 +400,9 @@ double Edge::shortest_edge_length() const { ...@@ -403,118 +400,9 @@ double Edge::shortest_edge_length() const {
return sqrt(dl); return sqrt(dl);
} }
// Auxillary Method
void Edge::recursive_mark() { void Edge::recursive_mark() {
if (Mark && Next->Mark && Prev->Mark) { if (Mark && Next->Mark && Prev->Mark) {
Next->Mark = false; Next->Mark = false;
Prev->Mark = false; Prev->Mark = false;
} }
}
// Friend Utility
bool are_intersecting(const Edge *e0, const Edge *e1) {
// #TODO, Make more detailed return type enumeration
if (e0->ConstraintCurve != nullptr && e0->ConstraintCurve == e1->ConstraintCurve) {
return false;
}
const Point *v00 = e0->base();
const Point *v01 = e0->tip();
const Point *v10 = e1->base();
const Point *v11 = e1->tip();
double xs0 = (v00->X + v01->X) / 2.0;
double ys0 = (v00->Y + v01->Y) / 2.0;
double xs1 = (v10->X + v11->X) / 2.0;
double ys1 = (v10->Y + v11->Y) / 2.0;
double xd0 = (v00->X - v01->X) / 2.0;
double yd0 = (v00->Y - v01->Y) / 2.0;
double xd1 = (v10->X - v11->X) / 2.0;
double yd1 = (v10->Y - v11->Y) / 2.0;
double d0 = xd0 * xd0 + yd0 * yd0;
double d1 = xd1 * xd1 + yd1 * yd1;
double cross = abs(xd0 * yd1 - xd1 * yd0);
double tol = (d0 * d1) * FLT_EPSILON;
if (cross < tol) {
/*
Lines are nearly parallel
There are four possible minimum distance points between the lines
*/
double s, dx, dy, dmin = DBL_MAX;
s = ((xd0 - xd1) * (xs0 - xs1) + (yd0 - yd1) * (ys0 - ys1)) /
((xd0 - xd1) * (xd0 - xd1) + (yd0 - yd1) * (yd0 - yd1));
if (abs(s) < 1.0 - FLT_EPSILON) {
dx = xs0 + xd0 * s - xs1 - xd1 * s;
dy = ys0 + yd0 * s - ys1 - yd1 * s;
dmin = fmin(dmin, dx * dx + dy * dy);
dx = xs0 - xd0 * s - xs1 + xd1 * s;
dy = ys0 - yd0 * s - ys1 + yd1 * s;
dmin = fmin(dmin, dx * dx + dy * dy);
}
s = ((xd0 + xd1) * (xs0 - xs1) + (yd0 + yd1) * (ys0 - ys1)) /
((xd0 + xd1) * (xd0 + xd1) + (yd0 + yd1) * (yd0 + yd1));
if (abs(s) < 1.0 - FLT_EPSILON) {
dx = xs0 + xd0 * s - xs1 + xd1 * s;
dy = ys0 + yd0 * s - ys1 + yd1 * s;
dmin = fmin(dmin, dx * dx + dy * dy);
dx = xs0 - xd0 * s - xs1 - xd1 * s;
dy = ys0 - yd0 * s - ys1 - yd1 * s;
dmin = fmin(dmin, dx * dx + dy * dy);
}
tol = (d0 + d1) * FLT_EPSILON;
return (dmin < tol);
} else {
// Lines are not parallel
double s0 = abs(xd1 * (ys0 - ys1) - yd1 * (xs0 - xs1));
double s1 = abs(xd0 * (ys0 - ys1) - yd0 * (xs0 - xs1));
tol = cross * (1.0 - FLT_EPSILON);
return (s0 < tol && s1 < tol);
}
}
// External Utility
void circumradius(std::vector<Edge *> &triangles, std::vector<double> &radii) {
radii.resize(0);
radii.reserve(triangles.size());
for (size_t i = 0; i < triangles.size(); ++i) {
radii.push_back(triangles[i]->circumradius());
}
}
void shortest_edge_length(std::vector<Edge *> &triangle, std::vector<double> &length) {
length.resize(0);
length.reserve(triangle.size());
for (size_t i = 0; i < triangle.size(); ++i) {
length.push_back(triangle[i]->shortest_edge_length());
}
}
void element_quality(std::vector<Edge *> &triangle, std::vector<double> &radii, std::vector<double> &quality) {
radii.resize(0);
quality.resize(0);
radii.reserve(triangle.size());
quality.reserve(triangle.size());
for (size_t i = 0; i < triangle.size(); ++i) {
double r = triangle[i]->circumradius();
double l = triangle[i]->shortest_edge_length();
radii.push_back(r);
quality.push_back(l / r);
}
}
void sort_permutation(std::vector<double> &values, std::vector<size_t> &index) {
index.resize(values.size());
std::iota(index.begin(), index.end(), 0);
std::sort(index.begin(), index.end(), [&](size_t i, size_t j) { return (values[i] < values[j]); });
} }
\ No newline at end of file
...@@ -14,7 +14,7 @@ public: ...@@ -14,7 +14,7 @@ public:
Edge(Point &v, Edge &n, Edge &p, Edge &t) : Node(&v), Next(&n), Prev(&p), Twin(&t), ConstraintCurve(nullptr), Orientation(true), Mark(false) {}; Edge(Point &v, Edge &n, Edge &p, Edge &t) : Node(&v), Next(&n), Prev(&p), Twin(&t), ConstraintCurve(nullptr), Orientation(true), Mark(false) {};
Edge(Curve *c, bool Orientaiton); Edge(Curve *c, bool Orientation);
Edge(Curve *c, bool Orientation, const Point *v); Edge(Curve *c, bool Orientation, const Point *v);
...@@ -37,12 +37,10 @@ public: ...@@ -37,12 +37,10 @@ public:
bool mark() const { return Mark; }; bool mark() const { return Mark; };
// Overloads
bool operator==(const Edge &e) const { bool operator==(const Edge &e) const {
return (node() == e.node()) && (constraint_curve() == e.constraint_curve()) && (twin()->node() == e.twin()->node()); return (node() == e.node()) && (constraint_curve() == e.constraint_curve()) && (twin()->node() == e.twin()->node());
}; };
// Calculation Methods
Point circumcenter() const; Point circumcenter() const;
double circumradius() const; double circumradius() const;
...@@ -51,7 +49,6 @@ public: ...@@ -51,7 +49,6 @@ public:
double shortest_edge_length() const; double shortest_edge_length() const;
// Test Methods
bool is_protruding() const; bool is_protruding() const;
bool is_constrained() const { return (ConstraintCurve != nullptr); }; bool is_constrained() const { return (ConstraintCurve != nullptr); };
...@@ -64,26 +61,24 @@ public: ...@@ -64,26 +61,24 @@ public:
bool is_attached(const Point *p, Edge *&e) const; bool is_attached(const Point *p, Edge *&e) const;
// Topology Alterating Methods
bool swap(); bool swap();
bool recursive_swap(); bool recursive_swap();
void split_edge(std::vector<const Point *> &verts, std::vector<Edge *> &edges); void split_edge(std::vector<const Point *> &verts, std::vector<Edge *> &edges);
// Auxillary Methods
void recursive_mark(); void recursive_mark();
protected: protected:
const Point *Node; //Start of edge const Point *Node; //Start of edge
Edge *Next; //In triangle Edge *Next; //In triangle
Edge *Twin; //Adjacent triangle Edge *Twin; //Adjacent triangle
Edge *Prev; //In triangle Edge *Prev; //In triangle
Curve *ConstraintCurve; //==nullptr if unconstrained Curve *ConstraintCurve; //==nullptr if unconstrained
bool Orientation; //undefined if unconstrained bool Orientation; //undefined if unconstrained
bool Mark; // Auxillary variable for mesh refinement bool Mark; // Auxillary variable for mesh refinement
}; };
#endif //OERSTED_EDGE_H #endif //OERSTED_EDGE_H
#include "Mesh.hpp" #include "Mesh.hpp"
Mesh::Mesh(Sketch &s) { Mesh::Mesh(Sketch &sketch) {
Boundary = s.boundary(); Boundary = sketch.boundary();
for (size_t i = 0; i != s.size_curves(); ++i) { for (size_t i = 0; i != sketch.size_curves(); ++i) {
Curves.push_back(s.curve(i)); auto c = sketch.curve(i);
if(!(c->ForConstruction)) {
Curves.push_back(c);
}
} }
for (size_t i = 0; i != s.size_contours(); ++i) { for (size_t i = 0; i != sketch.size_contours(); ++i) {
Contours.push_back(s.contour(i)); Contours.push_back(sketch.contour(i));
} }
} }
...@@ -34,59 +37,115 @@ LocateTriangleResult Mesh::locate_triangle(const Point *p, Edge *&e) const { ...@@ -34,59 +37,115 @@ LocateTriangleResult Mesh::locate_triangle(const Point *p, Edge *&e) const {
} }
LocateTriangleResult Mesh::locate_triangle(const Point *p, const Edge *&e) const { LocateTriangleResult Mesh::locate_triangle(const Point *p, const Edge *&e) const {
// TODO: Need to search along boundary triangles in order to ensure the internal/external status
const Edge *start = e;
double xp = p->X; double xp = p->X;
double yp = p->Y; double yp = p->Y;
while (true) { while (true) {
// Verticies const Point *p0 = e->node();
const Point *p0 = e->base(); const Point *p1 = e->next()->node();
const Point *p1 = e->tip(); const Point *p2 = e->prev()->node();
if (*p == *p0) { if (*p == *p0) {
return LocateTriangleResult::Point; return LocateTriangleResult::Point;
} else if (*p == *p1) { }
if (*p == *p1) {
e = e->next(); e = e->next();
return LocateTriangleResult::Point; return LocateTriangleResult::Point;
} }
// Signed area of triangle if (*p == *p2) {
e = e->prev();
return LocateTriangleResult::Point;
}
double dx0p = p0->X - xp; double dx0p = p0->X - xp;
double dy0p = p0->Y - yp; double dy0p = p0->Y - yp;
double dp0 = sqrt(dx0p * dx0p + dy0p * dy0p);
double dx1p = p1->X - xp; double dx1p = p1->X - xp;
double dy1p = p1->Y - yp; double dy1p = p1->Y - yp;
double dp1 = sqrt(dx1p * dx1p + dy1p * dy1p);
double dx2p = p2->X - xp;
double dy2p = p2->Y - yp;
double dp2 = sqrt(dx2p * dx2p + dy2p * dy2p);
double dx01 = p0->X - p1->X; double dx01 = p0->X - p1->X;
double dy01 = p0->Y - p1->Y; double dy01 = p0->Y - p1->Y;
double d01 = sqrt(dx01 * dx01 + dy01 * dy01);
double dx12 = p1->X - p2->X;
double dy12 = p1->Y - p2->Y;
double d12 = sqrt(dx12 * dx12 + dy12 * dy12);
double dx20 = p2->X - p0->X;
double dy20 = p2->Y - p0->Y;
double d20 = sqrt(dx20 * dx20 + dy20 * dy20);
double tola = abs(dx20 * dy01 - dy20 * dx01);
double tole = FLT_EPSILON * sqrt(tola);
tola *= FLT_EPSILON;
double area = dx0p * dy1p - dx1p * dy0p; double area01 = dx0p * dy1p - dx1p * dy0p;
double tol = FLT_EPSILON * (dx01 * dx01 + dy01 * dy01); double area12 = dx1p * dy2p - dx2p * dy1p;
double area20 = dx2p * dy0p - dx0p * dy2p;
if (area < -tol) { if (area01 > tola && area12 > tola && area20 > tola) {
return LocateTriangleResult::Interior;
}
if (area01 < -tola) {
if (e != e->twin()) { if (e != e->twin()) {
start = e->twin(); e = e->twin()->next();
e = start->next(); continue;
} else {
return LocateTriangleResult::Exterior;
} }
} else if (area < tol) { } else if (area01 < tola) {
double dp0 = sqrt(dx0p * dx0p + dy0p * dy0p); if (abs(dp0 + dp1 - d01) < tole) {
double dp1 = sqrt(dx1p * dx1p + dy1p * dy1p);
double d01 = sqrt(dx01 * dx01 + dy01 * dy01);
double tol = FLT_EPSILON * d01;
if (abs(dp0 + dp1 - d01) < tol) {
return LocateTriangleResult::Edge; return LocateTriangleResult::Edge;
} else if (e->next() != start) { }
}
if (area12 < -tola) {
if (e->next() != e->next()->twin()) {
e = e->next()->twin()->next();
continue;
}
} else if (area12 < tola) {
if (abs(dp1 + dp2 - d12) < tole) {
e = e->next(); e = e->next();
} else { return LocateTriangleResult::Edge;
throw std::exception(); //TODO: This branch should never be reached. Supply return value" }
}
if (area20 < -tola) {
if (e->prev() != e->prev()->twin()) {
e = e->prev()->twin()->next();
continue;
}
} else if (area20 < tola) {
if (abs(dp2 + dp0 - d20) < tole) {
e = e->prev();
return LocateTriangleResult::Edge;
} }
} else if (e->next() != start) { }
// If not Interior, not on Edge, and cannot continue, point is exterior
if (area01 < -tola) {
return LocateTriangleResult::Exterior;
}
if (area12 < -tola) {
e = e->next(); e = e->next();
} else { return LocateTriangleResult::Exterior;
return LocateTriangleResult::Interior; }
if (area20 < -tola) {
e = e->prev();
return LocateTriangleResult::Exterior;
} }