Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
LoopAreaTriangulation.h
Go to the documentation of this file.
1#ifndef model_LoopAreaTriangulation_h_
2#define model_LoopAreaTriangulation_h_
3
4#include <Eigen/Dense>
5#include <algorithm>
6#include <array>
7#include <cmath>
8#include <limits>
9#include <vector>
10
11namespace model
12{
13 // Rendering tessellation of a directed planar contour, using nonzero winding.
14 // Split at every vertex and crossing height. Within each open horizontal slab
15 // edges cannot exchange order, so filled intervals are trapezoids. Retraced
16 // bridges cancel, and self-intersections do not require a simple polygon.
17 inline std::vector<std::array<Eigen::Vector2d,3>> triangulateLoopArea(
18 const std::vector<Eigen::Vector2d>& contour)
19 {
20 using V=Eigen::Vector2d;
21 std::vector<std::array<V,3>> triangles;
22 if(contour.size()<3)
23 {
24 return triangles;
25 }
26 const V origin=contour.front();
27 double scale=0.0;
28 for(const auto& point : contour)
29 {
30 scale=std::max(scale,(point-origin).norm());
31 }
32 if(scale==0.0)
33 {
34 return triangles;
35 }
36 const double eps=128.0*std::numeric_limits<double>::epsilon();
37 const auto cross=[](const V& a,const V& b)
38 {
39 return a.x()*b.y()-a.y()*b.x();
40 };
41 struct Edge
42 {
43 V a,b;
44 double x(double y) const
45 {
46 return a.x()+(y-a.y())*(b.x()-a.x())/(b.y()-a.y());
47 }
48 };
49 std::vector<Edge> edges;
50 std::vector<double> levels;
51 for(size_t i=0;i<contour.size();++i)
52 {
53 const V a=(contour[i]-origin)/scale;
54 const V b=(contour[(i+1)%contour.size()]-origin)/scale;
55 levels.push_back(a.y());
56 if(std::abs(b.y()-a.y())>eps)
57 {
58 edges.push_back({a,b});
59 }
60 }
61 for(size_t i=0;i<edges.size();++i)
62 {
63 for(size_t j=i+1;j<edges.size();++j)
64 {
65 const V u=edges[i].b-edges[i].a;
66 const V v=edges[j].b-edges[j].a;
67 const V d=edges[j].a-edges[i].a;
68 const double denominator=cross(u,v);
69 if(std::abs(denominator)>eps*u.norm()*v.norm())
70 {
71 const double t=cross(d,v)/denominator;
72 const double s=cross(d,u)/denominator;
73 if(t>0.0 && t<1.0 && s>0.0 && s<1.0)
74 {
75 levels.push_back(edges[i].a.y()+t*u.y());
76 }
77 }
78 }
79 }
80 std::sort(levels.begin(),levels.end());
81 const auto append=[&](const V& a,const V& b,const V& c)
82 {
83 if(cross(b-a,c-a)>eps)
84 {
85 triangles.push_back({origin+scale*a,origin+scale*b,origin+scale*c});
86 }
87 };
88 for(size_t k=1;k<levels.size();++k)
89 {
90 const double low=levels[k-1];
91 const double high=levels[k];
92 if(high-low<=eps)
93 {
94 continue;
95 }
96 const double mid=(low+high)*0.5;
97 std::vector<const Edge*> active;
98 for(const auto& edge : edges)
99 {
100 if(mid>std::min(edge.a.y(),edge.b.y()) && mid<std::max(edge.a.y(),edge.b.y()))
101 {
102 active.push_back(&edge);
103 }
104 }
105 std::stable_sort(active.begin(),active.end(),[&](const Edge* a,const Edge* b)
106 {
107 return a->x(mid)<b->x(mid);
108 });
109 int winding=0;
110 for(size_t i=0;i+1<active.size();++i)
111 {
112 winding+=active[i]->b.y()>active[i]->a.y()?1:-1;
113 if(winding!=0 && active[i+1]->x(mid)-active[i]->x(mid)>eps)
114 {
115 const V a(active[i]->x(low),low);
116 const V b(active[i+1]->x(low),low);
117 const V c(active[i+1]->x(high),high);
118 const V d(active[i]->x(high),high);
119 append(a,b,c);
120 append(a,c,d);
121 }
122 }
123 }
124 return triangles;
125 }
126}
127#endif
Eigen::Vector3d V
final point of the source segment t
c
Definition int_R.m:15
a
Definition int_R.m:14
b
Definition int_R.m:16
x
Definition int_R.m:12
std::vector< std::array< Eigen::Vector2d, 3 > > triangulateLoopArea(const std::vector< Eigen::Vector2d > &contour)
REAL denominator
m edges
int j
REAL u[4]
int k
int i
REAL v[4]