KiCad PCB EDA Suite
Loading...
Searching...
No Matches
vertex_set.cpp
Go to the documentation of this file.
2
3void VERTEX_SET::SetBoundingBox( const BOX2I& aBBox ) { m_bbox = aBBox; }
4
5
9VERTEX* VERTEX_SET::createList( const SHAPE_LINE_CHAIN& points, VERTEX* aTail, void* aUserData )
10{
11 VERTEX* tail = aTail;
12 double sum = 0.0;
13
14 // Check for winding order
15 for( int i = 0; i < points.PointCount(); i++ )
16 {
17 VECTOR2D p1 = points.CPoint( i );
18 VECTOR2D p2 = points.CPoint( i + 1 );
19
20 sum += ( ( p2.x - p1.x ) * ( p2.y + p1.y ) );
21 }
22
23 VECTOR2I last_pt{ std::numeric_limits<int>::max(), std::numeric_limits<int>::max() };
24
25 auto addVertex = [&]( int i )
26 {
27 const VECTOR2I& pt = points.CPoint( i );
28 VECTOR2I diff = pt - last_pt;
30 {
31 tail = insertVertex( i, pt, tail, aUserData );
32 last_pt = pt;
33 }
34 };
35
36 if( sum > 0.0 )
37 {
38 for( int i = points.PointCount() - 1; i >= 0; i-- )
39 addVertex( i );
40 }
41 else
42 {
43 for( int i = 0; i < points.PointCount(); i++ )
44 addVertex( i );
45 }
46
47 if( tail && ( *tail == *tail->next ) )
48 {
49 tail->next->remove();
50 }
51
52 return tail;
53}
54
55
61int32_t VERTEX_SET::zOrder( const double aX, const double aY ) const
62{
63 int32_t x = static_cast<int32_t>( 32767.0 * ( aX - m_bbox.GetX() ) / m_bbox.GetWidth() );
64 int32_t y = static_cast<int32_t>( 32767.0 * ( aY - m_bbox.GetY() ) / m_bbox.GetHeight() );
65
66 x = ( x | ( x << 8 ) ) & 0x00FF00FF;
67 x = ( x | ( x << 4 ) ) & 0x0F0F0F0F;
68 x = ( x | ( x << 2 ) ) & 0x33333333;
69 x = ( x | ( x << 1 ) ) & 0x55555555;
70
71 y = ( y | ( y << 8 ) ) & 0x00FF00FF;
72 y = ( y | ( y << 4 ) ) & 0x0F0F0F0F;
73 y = ( y | ( y << 2 ) ) & 0x33333333;
74 y = ( y | ( y << 1 ) ) & 0x55555555;
75
76 return x | ( y << 1 );
77}
78
79
83double VERTEX_SET::area( const VERTEX* p, const VERTEX* q, const VERTEX* r ) const
84{
85 return ( q->y - p->y ) * ( r->x - q->x ) - ( q->x - p->x ) * ( r->y - q->y );
86}
87
88
89bool VERTEX_SET::same_point( const VERTEX* aA, const VERTEX* aB ) const
90{
91 return aA && aB && aA->x == aB->x && aA->y == aB->y;
92}
93
95{
96 VERTEX* nz = aPt->nextZ;
97 VERTEX* pz = aPt->prevZ;
98
99 // If we hit a fracture point, we want to continue around the
100 // edge we are working on and not switch to the pair edge
101 // However, this will depend on which direction the initial
102 // fracture hit is. If we find that we skip directly to
103 // a new fracture point, then we know that we are proceeding
104 // in the wrong direction from the fracture and should
105 // fall through to the next point
106 if( same_point( aPt, nz ) && same_point( aPt->next, nz->prev )
107 && aPt->y == aPt->next->y )
108 {
109 return nz->next;
110 }
111
112 if( same_point( aPt, pz ) && same_point( aPt->next, pz->prev )
113 && aPt->y == aPt->next->y )
114 {
115 return pz->next;
116 }
117
118 return aPt->next;
119}
120
122{
123 VERTEX* nz = aPt->nextZ;
124 VERTEX* pz = aPt->prevZ;
125
126 // If we hit a fracture point, we want to continue around the
127 // edge we are working on and not switch to the pair edge
128 // However, this will depend on which direction the initial
129 // fracture hit is. If we find that we skip directly to
130 // a new fracture point, then we know that we are proceeding
131 // in the wrong direction from the fracture and should
132 // fall through to the next point
133 if( same_point( aPt, nz )
134 && aPt->y == aPt->prev->y)
135 {
136 return nz->prev;
137 }
138
139 if( same_point( aPt, pz )
140 && aPt->y == aPt->prev->y )
141 {
142 return pz->prev;
143 }
144
145 return aPt->prev;
146
147}
148
149
150bool VERTEX_SET::locallyInside( const VERTEX* a, const VERTEX* b ) const
151{
152 const VERTEX* an = getNextOutlineVertex( a );
153 const VERTEX* ap = getPrevOutlineVertex( a );
154
155 if( area( ap, a, an ) < 0 )
156 return area( a, b, an ) >= 0 && area( a, ap, b ) >= 0;
157 else
158 return area( a, b, ap ) < 0 || area( a, an, b ) < 0;
159}
160
161
162bool VERTEX_SET::middleInside( const VERTEX* a, const VERTEX* b ) const
163{
164 const VERTEX* p = a;
165 bool inside = false;
166 double px = ( a->x + b->x ) / 2;
167 double py = ( a->y + b->y ) / 2;
168
169 do
170 {
171 if( ( ( p->y > py ) != ( p->next->y > py ) )
172 && ( px < ( p->next->x - p->x ) * ( py - p->y ) / ( p->next->y - p->y ) + p->x ) )
173 inside = !inside;
174
175 p = p->next;
176 } while( p != a );
177
178 return inside;
179}
180
187VERTEX* VERTEX_SET::insertVertex( int aIndex, const VECTOR2I& pt, VERTEX* last, void* aUserData )
188{
189 m_vertices.emplace_back( aIndex, pt.x, pt.y, this, aUserData );
190
191 VERTEX* p = &m_vertices.back();
192
193 if( !last )
194 {
195 p->prev = p;
196 p->next = p;
197 }
198 else
199 {
200 p->next = last->next;
201 p->prev = last;
202 last->next->prev = p;
203 last->next = p;
204 }
205 return p;
206}
207
208
210{
211 parent->m_vertices.emplace_back( i, x, y, parent, m_userData );
212 VERTEX* a2 = parent->insertVertex( i, VECTOR2I( x, y ), nullptr, m_userData );
213 parent->m_vertices.emplace_back( b->i, b->x, b->y, parent, m_userData );
214 VERTEX* b2 = &parent->m_vertices.back();
215 VERTEX* an = next;
216 VERTEX* bp = b->prev;
217
218 next = b;
219 b->prev = this;
220
221 a2->next = an;
222 an->prev = a2;
223
224 b2->next = a2;
225 a2->prev = b2;
226
227 bp->next = b2;
228 b2->prev = bp;
229
230 return b2;
231}
232
233
235{
236 if( !z )
237 z = parent->zOrder( x, y );
238}
239
240
241bool VERTEX::isEar() const
242{
243 const VERTEX* a = prev;
244 const VERTEX* b = this;
245 const VERTEX* c = next;
246
247 // If the area >=0, then the three points for a concave sequence
248 // with b as the reflex point
249 if( parent->area( a, b, c ) >= 0 )
250 return false;
251
252 // triangle bbox
253 const double minTX = std::min( a->x, std::min( b->x, c->x ) );
254 const double minTY = std::min( a->y, std::min( b->y, c->y ) );
255 const double maxTX = std::max( a->x, std::max( b->x, c->x ) );
256 const double maxTY = std::max( a->y, std::max( b->y, c->y ) );
257
258 // z-order range for the current triangle bounding box
259 const int32_t minZ = parent->zOrder( minTX, minTY );
260 const int32_t maxZ = parent->zOrder( maxTX, maxTY );
261
262 // first look for points inside the triangle in increasing z-order
263 VERTEX* p = nextZ;
264
265 while( p && p->z <= maxZ )
266 {
267 if( p != a && p != c
268 && p->inTriangle( *a, *b, *c )
269 && parent->area( p->prev, p, p->next ) >= 0 )
270 return false;
271
272 p = p->nextZ;
273 }
274
275 // then look for points in decreasing z-order
276 p = prevZ;
277
278 while( p && p->z >= minZ )
279 {
280 if( p != a && p != c
281 && p->inTriangle( *a, *b, *c )
282 && parent->area( p->prev, p, p->next ) >= 0 )
283 return false;
284
285 p = p->prevZ;
286 }
287
288 return true;
289}
size_type GetHeight() const
Definition: box2.h:205
size_type GetWidth() const
Definition: box2.h:204
coord_type GetY() const
Definition: box2.h:198
coord_type GetX() const
Definition: box2.h:197
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
int PointCount() const
Return the number of points (vertices) in this line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
extended_type SquaredEuclideanNorm() const
Compute the squared euclidean norm of the vector, which is defined as (x ** 2 + y ** 2).
Definition: vector2d.h:302
std::deque< VERTEX > m_vertices
Definition: vertex_set.h:339
int32_t zOrder(const double aX, const double aY) const
Note that while the inputs are doubles, these are scaled by the size of the bounding box to fit into ...
Definition: vertex_set.cpp:61
bool middleInside(const VERTEX *a, const VERTEX *b) const
Check if the middle of the segment from a to b is inside the polygon.
Definition: vertex_set.cpp:162
VERTEX * createList(const SHAPE_LINE_CHAIN &points, VERTEX *aTail=nullptr, void *aUserData=nullptr)
Create a list of vertices from a line chain.
Definition: vertex_set.cpp:9
bool locallyInside(const VERTEX *a, const VERTEX *b) const
Check whether the segment from vertex a -> vertex b is inside the polygon around the immediate area o...
Definition: vertex_set.cpp:150
BOX2I m_bbox
Definition: vertex_set.h:338
VERTEX * getPrevOutlineVertex(const VERTEX *aPt) const
Get the previous vertex in the outline, avoiding steiner points and points that overlap with splits.
Definition: vertex_set.cpp:121
void SetBoundingBox(const BOX2I &aBBox)
Definition: vertex_set.cpp:3
double area(const VERTEX *p, const VERTEX *q, const VERTEX *r) const
Return the twice the signed area of the triangle formed by vertices p, q, and r.
Definition: vertex_set.cpp:83
VERTEX * insertVertex(int aIndex, const VECTOR2I &pt, VERTEX *last, void *aUserData=nullptr)
Insert a vertex into the vertex set.
Definition: vertex_set.cpp:187
VECTOR2I::extended_type m_simplificationLevel
Definition: vertex_set.h:340
VERTEX * getNextOutlineVertex(const VERTEX *aPt) const
Get the next vertex in the outline, avoiding steiner points and points that overlap with splits.
Definition: vertex_set.cpp:94
bool same_point(const VERTEX *aA, const VERTEX *aB) const
Check if two vertices are at the same point.
Definition: vertex_set.cpp:89
VERTEX * split(VERTEX *b)
Split the referenced polygon between the reference point and vertex b, assuming they are in the same ...
Definition: vertex_set.cpp:209
const double x
Definition: vertex_set.h:231
VERTEX * next
Definition: vertex_set.h:237
VERTEX * prevZ
Definition: vertex_set.h:243
bool inTriangle(const VERTEX &a, const VERTEX &b, const VERTEX &c)
Check to see if triangle surrounds our current vertex.
Definition: vertex_set.h:191
VERTEX * nextZ
Definition: vertex_set.h:244
VERTEX * prev
Definition: vertex_set.h:236
const int i
Definition: vertex_set.h:230
void * m_userData
Definition: vertex_set.h:246
void remove()
Remove the node from the linked list and z-ordered linked list.
Definition: vertex_set.h:84
int32_t z
Definition: vertex_set.h:240
bool isEar() const
Check whether the given vertex is in the middle of an ear.
Definition: vertex_set.cpp:241
const double y
Definition: vertex_set.h:232
void updateOrder()
Definition: vertex_set.cpp:234
VERTEX_SET * parent
Definition: vertex_set.h:233
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:673