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
61uint32_t VERTEX_SET::zOrder( const double aX, const double aY ) const
62{
63 double limit_x = std::clamp( ( aX - m_bbox.GetX() ) / m_bbox.GetWidth(), 0.0, 1.0 );
64 double limit_y = std::clamp( ( aY - m_bbox.GetY() ) / m_bbox.GetHeight(), 0.0, 1.0 );
65
66 uint32_t x = static_cast<uint32_t>( limit_x * 32767.0 );
67 uint32_t y = static_cast<uint32_t>( limit_y * 32767.0 );
68
69 x = ( x | ( x << 8 ) ) & 0x00FF00FF;
70 x = ( x | ( x << 4 ) ) & 0x0F0F0F0F;
71 x = ( x | ( x << 2 ) ) & 0x33333333;
72 x = ( x | ( x << 1 ) ) & 0x55555555;
73
74 y = ( y | ( y << 8 ) ) & 0x00FF00FF;
75 y = ( y | ( y << 4 ) ) & 0x0F0F0F0F;
76 y = ( y | ( y << 2 ) ) & 0x33333333;
77 y = ( y | ( y << 1 ) ) & 0x55555555;
78
79 return x | ( y << 1 );
80}
81
82
86double VERTEX_SET::area( const VERTEX* p, const VERTEX* q, const VERTEX* r ) const
87{
88 return ( q->y - p->y ) * ( r->x - q->x ) - ( q->x - p->x ) * ( r->y - q->y );
89}
90
91
92bool VERTEX_SET::same_point( const VERTEX* aA, const VERTEX* aB ) const
93{
94 return aA && aB && aA->x == aB->x && aA->y == aB->y;
95}
96
98{
99 VERTEX* nz = aPt->nextZ;
100 VERTEX* pz = aPt->prevZ;
101
102 // If we hit a fracture point, we want to continue around the
103 // edge we are working on and not switch to the pair edge
104 // However, this will depend on which direction the initial
105 // fracture hit is. If we find that we skip directly to
106 // a new fracture point, then we know that we are proceeding
107 // in the wrong direction from the fracture and should
108 // fall through to the next point
109 if( same_point( aPt, nz ) && same_point( aPt->next, nz->prev )
110 && aPt->y == aPt->next->y )
111 {
112 return nz->next;
113 }
114
115 if( same_point( aPt, pz ) && same_point( aPt->next, pz->prev )
116 && aPt->y == aPt->next->y )
117 {
118 return pz->next;
119 }
120
121 return aPt->next;
122}
123
125{
126 VERTEX* nz = aPt->nextZ;
127 VERTEX* pz = aPt->prevZ;
128
129 // If we hit a fracture point, we want to continue around the
130 // edge we are working on and not switch to the pair edge
131 // However, this will depend on which direction the initial
132 // fracture hit is. If we find that we skip directly to
133 // a new fracture point, then we know that we are proceeding
134 // in the wrong direction from the fracture and should
135 // fall through to the next point
136 if( same_point( aPt, nz )
137 && aPt->y == aPt->prev->y)
138 {
139 return nz->prev;
140 }
141
142 if( same_point( aPt, pz )
143 && aPt->y == aPt->prev->y )
144 {
145 return pz->prev;
146 }
147
148 return aPt->prev;
149
150}
151
152
153bool VERTEX_SET::locallyInside( const VERTEX* a, const VERTEX* b ) const
154{
155 const VERTEX* an = getNextOutlineVertex( a );
156 const VERTEX* ap = getPrevOutlineVertex( a );
157
158 if( area( ap, a, an ) < 0 )
159 return area( a, b, an ) >= 0 && area( a, ap, b ) >= 0;
160 else
161 return area( a, b, ap ) < 0 || area( a, an, b ) < 0;
162}
163
164
165bool VERTEX_SET::middleInside( const VERTEX* a, const VERTEX* b ) const
166{
167 const VERTEX* p = a;
168 bool inside = false;
169 double px = ( a->x + b->x ) / 2;
170 double py = ( a->y + b->y ) / 2;
171
172 do
173 {
174 if( ( ( p->y > py ) != ( p->next->y > py ) )
175 && ( px < ( p->next->x - p->x ) * ( py - p->y ) / ( p->next->y - p->y ) + p->x ) )
176 inside = !inside;
177
178 p = p->next;
179 } while( p != a );
180
181 return inside;
182}
183
190VERTEX* VERTEX_SET::insertVertex( int aIndex, const VECTOR2I& pt, VERTEX* last, void* aUserData )
191{
192 m_vertices.emplace_back( aIndex, pt.x, pt.y, this, aUserData );
193
194 VERTEX* p = &m_vertices.back();
195
196 if( !last )
197 {
198 p->prev = p;
199 p->next = p;
200 }
201 else
202 {
203 p->next = last->next;
204 p->prev = last;
205 last->next->prev = p;
206 last->next = p;
207 }
208 return p;
209}
210
211
213{
214 parent->m_vertices.emplace_back( i, x, y, parent, m_userData );
215 VERTEX* a2 = parent->insertVertex( i, VECTOR2I( x, y ), nullptr, m_userData );
216 parent->m_vertices.emplace_back( b->i, b->x, b->y, parent, m_userData );
217 VERTEX* b2 = &parent->m_vertices.back();
218 VERTEX* an = next;
219 VERTEX* bp = b->prev;
220
221 next = b;
222 b->prev = this;
223
224 a2->next = an;
225 an->prev = a2;
226
227 b2->next = a2;
228 a2->prev = b2;
229
230 bp->next = b2;
231 b2->prev = bp;
232
233 return b2;
234}
235
236
238{
239 if( !z )
240 z = parent->zOrder( x, y );
241}
242
243
244bool VERTEX::isEar( bool aMatchUserData ) const
245{
246 const VERTEX* a = prev;
247 const VERTEX* b = this;
248 const VERTEX* c = next;
249
250 if( aMatchUserData )
251 {
252 while( a->GetUserData() != m_userData )
253 a = a->prev;
254
255 while( c->GetUserData() != m_userData )
256 c = c->next;
257 }
258
259 // If the area >=0, then the three points for a concave sequence
260 // with b as the reflex point
261 if( parent->area( a, b, c ) >= 0 )
262 return false;
263
264 // triangle bbox
265 const double minTX = std::min( a->x, std::min( b->x, c->x ) );
266 const double minTY = std::min( a->y, std::min( b->y, c->y ) );
267 const double maxTX = std::max( a->x, std::max( b->x, c->x ) );
268 const double maxTY = std::max( a->y, std::max( b->y, c->y ) );
269
270 // z-order range for the current triangle bounding box
271 const uint32_t minZ = parent->zOrder( minTX, minTY );
272 const uint32_t maxZ = parent->zOrder( maxTX, maxTY );
273
274 // first look for points inside the triangle in increasing z-order
275 VERTEX* p = nextZ;
276
277 while( p && p->z <= maxZ )
278 {
279 if( ( !aMatchUserData || p->GetUserData() == m_userData )
280 && 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->nextZ;
286 }
287
288 // then look for points in decreasing z-order
289 p = prevZ;
290
291 while( p && p->z >= minZ )
292 {
293 if( ( !aMatchUserData || p->GetUserData() == m_userData )
294 && p != a && p != c
295 && p->inTriangle( *a, *b, *c )
296 && parent->area( p->prev, p, p->next ) >= 0 )
297 return false;
298
299 p = p->prevZ;
300 }
301
302 return true;
303}
constexpr coord_type GetY() const
Definition: box2.h:208
constexpr size_type GetWidth() const
Definition: box2.h:214
constexpr coord_type GetX() const
Definition: box2.h:207
constexpr size_type GetHeight() const
Definition: box2.h:215
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.
constexpr extended_type SquaredEuclideanNorm() const
Compute the squared euclidean norm of the vector, which is defined as (x ** 2 + y ** 2).
Definition: vector2d.h:307
std::deque< VERTEX > m_vertices
Definition: vertex_set.h:343
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:165
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:153
BOX2I m_bbox
Definition: vertex_set.h:342
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:124
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:86
VERTEX * insertVertex(int aIndex, const VECTOR2I &pt, VERTEX *last, void *aUserData=nullptr)
Insert a vertex into the vertex set.
Definition: vertex_set.cpp:190
VECTOR2I::extended_type m_simplificationLevel
Definition: vertex_set.h:344
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:97
uint32_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 same_point(const VERTEX *aA, const VERTEX *aB) const
Check if two vertices are at the same point.
Definition: vertex_set.cpp:92
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:212
const double x
Definition: vertex_set.h:235
VERTEX * next
Definition: vertex_set.h:241
VERTEX * prevZ
Definition: vertex_set.h:247
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:248
VERTEX * prev
Definition: vertex_set.h:240
const int i
Definition: vertex_set.h:234
void * GetUserData() const
Definition: vertex_set.h:79
void * m_userData
Definition: vertex_set.h:250
void remove()
Remove the node from the linked list and z-ordered linked list.
Definition: vertex_set.h:84
uint32_t z
Definition: vertex_set.h:244
bool isEar(bool aMatchUserData=false) const
Check whether the given vertex is in the middle of an ear.
Definition: vertex_set.cpp:244
const double y
Definition: vertex_set.h:236
void updateOrder()
Definition: vertex_set.cpp:237
VERTEX_SET * parent
Definition: vertex_set.h:237
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:691