KiCad PCB EDA Suite
Loading...
Searching...
No Matches
vertex_set.h
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.TXT for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 3
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 *
19 * Based on Uniform Plane Subdivision algorithm from Lamot, Marko, and Borut Žalik.
20 * "A fast polygon triangulation algorithm based on uniform plane subdivision."
21 * Computers & graphics 27, no. 2 (2003): 239-253.
22 *
23 * Code derived from:
24 * K-3D which is Copyright (c) 2005-2006, Romain Behar, GPL-2, license above
25 * earcut which is Copyright (c) 2016, Mapbox, ISC
26 *
27 * ISC License:
28 * Permission to use, copy, modify, and/or distribute this software for any purpose
29 * with or without fee is hereby granted, provided that the above copyright notice
30 * and this permission notice appear in all copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
33 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
34 * FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
35 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
36 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
37 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
38 * THIS SOFTWARE.
39 *
40 */
41
42#ifndef VERTEX_SET_H
43#define VERTEX_SET_H
44
45#include <algorithm>
46#include <deque>
47#include <vector>
48
49#include <math/box2.h>
51
52class VERTEX_SET;
53
54class VERTEX
55{
56 public:
57
58 VERTEX( int aIndex, double aX, double aY, VERTEX_SET* aParent, void* aUserData = nullptr ) :
59 i( aIndex ),
60 x( aX ),
61 y( aY ),
62 parent( aParent ),
63 m_userData( aUserData )
64 {
65 }
66
67 VERTEX& operator=( const VERTEX& ) = delete;
68 VERTEX& operator=( VERTEX&& ) = delete;
69
70 bool operator==( const VERTEX& rhs ) const
71 {
72 return this->x == rhs.x && this->y == rhs.y;
73 }
74 bool operator!=( const VERTEX& rhs ) const { return !( *this == rhs ); }
75
76 void* GetUserData() const { return m_userData; }
77
81 void remove()
82 {
83 next->prev = prev;
84 prev->next = next;
85
86 if( prevZ )
87 prevZ->nextZ = nextZ;
88
89 if( nextZ )
90 nextZ->prevZ = prevZ;
91
92 next = nullptr;
93 prev = nullptr;
94 nextZ = nullptr;
95 prevZ = nullptr;
96 }
97
98
99
110 VERTEX* split( VERTEX* b );
111
112 void updateOrder();
113
119 {
120 VERTEX* p = next;
121
122 while( p != this )
123 {
127 if( *p == *p->next )
128 {
129 p = p->prev;
130 p->next->remove();
131
132 if( p == p->next )
133 break;
134 }
135
136 p->updateOrder();
137 p = p->next;
138 };
139
140 updateOrder();
141 zSort();
142 }
143
147 void zSort()
148 {
149 std::vector<VERTEX*> queue;
150
151 queue.push_back( this );
152
153 for( VERTEX* p = next; p && p != this; p = p->next )
154 queue.push_back( p );
155
156 std::sort( queue.begin(), queue.end(), []( const VERTEX* a, const VERTEX* b )
157 {
158 if( a->z != b->z )
159 return a->z < b->z;
160
161 if( a->x != b->x )
162 return a->x < b->x;
163
164 if( a->y != b->y )
165 return a->y < b->y;
166
167 return a->i < b->i;
168 } );
169
170 VERTEX* prev_elem = nullptr;
171
172 for( VERTEX* elem : queue )
173 {
174 // A cached ear blocker is only valid while it shares this z-order list
175 elem->m_earBlocker = nullptr;
176
177 if( prev_elem )
178 prev_elem->nextZ = elem;
179
180 elem->prevZ = prev_elem;
181 prev_elem = elem;
182 }
183
184 prev_elem->nextZ = nullptr;
185 }
186
187
191 bool inTriangle( const VERTEX& a, const VERTEX& b, const VERTEX& c )
192 {
193 return ( c.x - x ) * ( a.y - y ) - ( a.x - x ) * ( c.y - y ) >= 0
194 && ( a.x - x ) * ( b.y - y ) - ( b.x - x ) * ( a.y - y ) >= 0
195 && ( b.x - x ) * ( c.y - y ) - ( c.x - x ) * ( b.y - y ) >= 0;
196 }
197
202 double area( const VERTEX* aEnd = nullptr ) const
203 {
204 const VERTEX* p = this;
205 double a = 0.0;
206
207 do
208 {
209 a += ( p->x + p->next->x ) * ( p->next->y - p->y );
210 p = p->next;
211 } while( p != this && p != aEnd );
212
213 if( p != this )
214 a += ( p->x + x ) * ( y - p->y );
215
216 return a / 2;
217 }
218
232 bool isEar( bool aMatchUserData = false ) const;
233
234 const int i;
235 const double x;
236 const double y;
238
239 // previous and next vertices nodes in a polygon ring
240 VERTEX* prev = nullptr;
241 VERTEX* next = nullptr;
242
243 // z-order curve value
244 uint32_t z = 0;
245
246 // previous and next nodes in z-order
247 VERTEX* prevZ = nullptr;
248 VERTEX* nextZ = nullptr;
249
250 void* m_userData = nullptr;
251
252 // Last vertex found inside this vertex's ear, rechecked before rescanning the z-order list
253 mutable VERTEX* m_earBlocker = nullptr;
254
255 // Whether the last VERTEX_SET::buildReflexIndex() call recorded this vertex
256 bool m_inReflexIndex = false;
257};
258
260{
261 friend class VERTEX;
262
263public:
264 VERTEX_SET( int aSimplificationLevel )
265 {
266 m_simplificationLevel = aSimplificationLevel * ( VECTOR2I::extended_type ) aSimplificationLevel;
267 }
269
270 void SetBoundingBox( const BOX2I& aBBox );
271
280 VERTEX* insertVertex( int aIndex, const VECTOR2I& pt, VERTEX* last, void* aUserData = nullptr );
281
289 VERTEX* createList( const SHAPE_LINE_CHAIN& points, VERTEX* aTail = nullptr, void* aUserData = nullptr );
290
291protected:
292
299 VERTEX* getNextOutlineVertex( const VERTEX* aPt ) const;
300
307 VERTEX* getPrevOutlineVertex( const VERTEX* aPt ) const;
308
318 bool locallyInside( const VERTEX* a, const VERTEX* b ) const;
319
326 bool middleInside( const VERTEX* a, const VERTEX* b ) const;
327
334 bool same_point( const VERTEX* aA, const VERTEX* aB ) const;
335
341 uint32_t zOrder( const double aX, const double aY ) const;
342
346 double area( const VERTEX* p, const VERTEX* q, const VERTEX* r ) const;
347
355 void buildReflexIndex( VERTEX* aStart );
356
358 {
359 uint32_t z;
360 double x;
361 double y;
363 };
364
366 std::deque<VERTEX> m_vertices;
368 std::vector<REFLEX_ENTRY> m_reflexIndex;
369 bool m_reflexIndexValid = false;
370};
371
372
373
374#endif // VERTEX_SET_H
BOX2< VECTOR2I > BOX2I
Definition box2.h:914
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
VECTOR2_TRAITS< int32_t >::extended_type extended_type
Definition vector2d.h:69
std::deque< VERTEX > m_vertices
Definition vertex_set.h:366
friend class VERTEX
Definition vertex_set.h:261
bool middleInside(const VERTEX *a, const VERTEX *b) const
Check if the middle of the segment from a to b is inside the polygon.
VERTEX * createList(const SHAPE_LINE_CHAIN &points, VERTEX *aTail=nullptr, void *aUserData=nullptr)
Create a list of vertices from a line chain.
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...
BOX2I m_bbox
Definition vertex_set.h:365
VERTEX * getPrevOutlineVertex(const VERTEX *aPt) const
Get the previous vertex in the outline, avoiding steiner points and points that overlap with splits.
void SetBoundingBox(const BOX2I &aBBox)
void buildReflexIndex(VERTEX *aStart)
Index the reflex vertices of the ring containing aStart in z-order.
std::vector< REFLEX_ENTRY > m_reflexIndex
Definition vertex_set.h:368
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.
VERTEX * insertVertex(int aIndex, const VECTOR2I &pt, VERTEX *last, void *aUserData=nullptr)
Insert a vertex into the vertex set.
VERTEX_SET(int aSimplificationLevel)
Definition vertex_set.h:264
VECTOR2I::extended_type m_simplificationLevel
Definition vertex_set.h:367
VERTEX * getNextOutlineVertex(const VERTEX *aPt) const
Get the next vertex in the outline, avoiding steiner points and points that overlap with splits.
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 ...
bool m_reflexIndexValid
Definition vertex_set.h:369
bool same_point(const VERTEX *aA, const VERTEX *aB) const
Check if two vertices are at the same point.
void zSort()
Sort all vertices in this vertex's list by their Morton code.
Definition vertex_set.h:147
VERTEX * split(VERTEX *b)
Split the referenced polygon between the reference point and vertex b, assuming they are in the same ...
VERTEX & operator=(const VERTEX &)=delete
const double x
Definition vertex_set.h:235
bool operator!=(const VERTEX &rhs) const
Definition vertex_set.h:74
VERTEX * next
Definition vertex_set.h:241
VERTEX * prevZ
Definition vertex_set.h:247
void updateList()
After inserting or changing nodes, this function should be called to remove duplicate vertices and en...
Definition vertex_set.h:118
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
bool operator==(const VERTEX &rhs) const
Definition vertex_set.h:70
VERTEX * m_earBlocker
Definition vertex_set.h:253
void * GetUserData() const
Definition vertex_set.h:76
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:81
bool m_inReflexIndex
Definition vertex_set.h:256
VERTEX(int aIndex, double aX, double aY, VERTEX_SET *aParent, void *aUserData=nullptr)
Definition vertex_set.h:58
VERTEX & operator=(VERTEX &&)=delete
double area(const VERTEX *aEnd=nullptr) const
Returns the signed area of the polygon connected to the current vertex, optionally ending at a specif...
Definition vertex_set.h:202
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.
const double y
Definition vertex_set.h:236
void updateOrder()
VERTEX_SET * parent
Definition vertex_set.h:237
Definition vertex_set.h:358
double y
Definition vertex_set.h:361
double x
Definition vertex_set.h:360
VERTEX * v
Definition vertex_set.h:362
uint32_t z
Definition vertex_set.h:359
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708