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
48#include <math/box2.h>
50
51class VERTEX_SET;
52
53class VERTEX
54{
55 public:
56
57 VERTEX( int aIndex, double aX, double aY, VERTEX_SET* aParent, void* aUserData = nullptr ) :
58 i( aIndex ),
59 x( aX ),
60 y( aY ),
61 parent( aParent ),
62 m_userData( aUserData )
63 {
64 }
65
66 VERTEX& operator=( const VERTEX& ) = delete;
67 VERTEX& operator=( VERTEX&& ) = delete;
68
69 bool operator==( const VERTEX& rhs ) const
70 {
71 return this->x == rhs.x && this->y == rhs.y;
72 }
73 bool operator!=( const VERTEX& rhs ) const { return !( *this == rhs ); }
74
75 void* GetUserData() const { return m_userData; }
76
80 void remove()
81 {
82 next->prev = prev;
83 prev->next = next;
84
85 if( prevZ )
86 prevZ->nextZ = nextZ;
87
88 if( nextZ )
89 nextZ->prevZ = prevZ;
90
91 next = nullptr;
92 prev = nullptr;
93 nextZ = nullptr;
94 prevZ = nullptr;
95 }
96
97
98
109 VERTEX* split( VERTEX* b );
110
111 void updateOrder();
112
118 {
119 VERTEX* p = next;
120
121 while( p != this )
122 {
126 if( *p == *p->next )
127 {
128 p = p->prev;
129 p->next->remove();
130
131 if( p == p->next )
132 break;
133 }
134
135 p->updateOrder();
136 p = p->next;
137 };
138
139 updateOrder();
140 zSort();
141 }
142
146 void zSort()
147 {
148 std::vector<VERTEX*> queue;
149
150 queue.push_back( this );
151
152 for( VERTEX* p = next; p && p != this; p = p->next )
153 queue.push_back( p );
154
155 std::sort( queue.begin(), queue.end(), []( const VERTEX* a, const VERTEX* b )
156 {
157 if( a->z != b->z )
158 return a->z < b->z;
159
160 if( a->x != b->x )
161 return a->x < b->x;
162
163 if( a->y != b->y )
164 return a->y < b->y;
165
166 return a->i < b->i;
167 } );
168
169 VERTEX* prev_elem = nullptr;
170
171 for( VERTEX* elem : queue )
172 {
173 // A cached ear blocker is only valid while it shares this z-order list
174 elem->m_earBlocker = nullptr;
175
176 if( prev_elem )
177 prev_elem->nextZ = elem;
178
179 elem->prevZ = prev_elem;
180 prev_elem = elem;
181 }
182
183 prev_elem->nextZ = nullptr;
184 }
185
186
190 bool inTriangle( const VERTEX& a, const VERTEX& b, const VERTEX& c )
191 {
192 return ( c.x - x ) * ( a.y - y ) - ( a.x - x ) * ( c.y - y ) >= 0
193 && ( a.x - x ) * ( b.y - y ) - ( b.x - x ) * ( a.y - y ) >= 0
194 && ( b.x - x ) * ( c.y - y ) - ( c.x - x ) * ( b.y - y ) >= 0;
195 }
196
201 double area( const VERTEX* aEnd = nullptr ) const
202 {
203 const VERTEX* p = this;
204 double a = 0.0;
205
206 do
207 {
208 a += ( p->x + p->next->x ) * ( p->next->y - p->y );
209 p = p->next;
210 } while( p != this && p != aEnd );
211
212 if( p != this )
213 a += ( p->x + x ) * ( y - p->y );
214
215 return a / 2;
216 }
217
231 bool isEar( bool aMatchUserData = false ) const;
232
233 const int i;
234 const double x;
235 const double y;
237
238 // previous and next vertices nodes in a polygon ring
239 VERTEX* prev = nullptr;
240 VERTEX* next = nullptr;
241
242 // z-order curve value
243 uint32_t z = 0;
244
245 // previous and next nodes in z-order
246 VERTEX* prevZ = nullptr;
247 VERTEX* nextZ = nullptr;
248
249 void* m_userData = nullptr;
250
251 // Last vertex found inside this vertex's ear, rechecked before rescanning the z-order list
252 mutable VERTEX* m_earBlocker = nullptr;
253};
254
256{
257 friend class VERTEX;
258
259public:
260 VERTEX_SET( int aSimplificationLevel )
261 {
262 m_simplificationLevel = aSimplificationLevel * ( VECTOR2I::extended_type ) aSimplificationLevel;
263 }
265
266 void SetBoundingBox( const BOX2I& aBBox );
267
276 VERTEX* insertVertex( int aIndex, const VECTOR2I& pt, VERTEX* last, void* aUserData = nullptr );
277
285 VERTEX* createList( const SHAPE_LINE_CHAIN& points, VERTEX* aTail = nullptr, void* aUserData = nullptr );
286
287protected:
288
295 VERTEX* getNextOutlineVertex( const VERTEX* aPt ) const;
296
303 VERTEX* getPrevOutlineVertex( const VERTEX* aPt ) const;
304
314 bool locallyInside( const VERTEX* a, const VERTEX* b ) const;
315
322 bool middleInside( const VERTEX* a, const VERTEX* b ) const;
323
330 bool same_point( const VERTEX* aA, const VERTEX* aB ) const;
331
337 uint32_t zOrder( const double aX, const double aY ) const;
338
342 double area( const VERTEX* p, const VERTEX* q, const VERTEX* r ) const;
343
345 std::deque<VERTEX> m_vertices;
347};
348
349
350
351#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:345
friend class VERTEX
Definition vertex_set.h:257
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:344
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)
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:260
VECTOR2I::extended_type m_simplificationLevel
Definition vertex_set.h:346
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 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:146
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:234
bool operator!=(const VERTEX &rhs) const
Definition vertex_set.h:73
VERTEX * next
Definition vertex_set.h:240
VERTEX * prevZ
Definition vertex_set.h:246
void updateList()
After inserting or changing nodes, this function should be called to remove duplicate vertices and en...
Definition vertex_set.h:117
bool inTriangle(const VERTEX &a, const VERTEX &b, const VERTEX &c)
Check to see if triangle surrounds our current vertex.
Definition vertex_set.h:190
VERTEX * nextZ
Definition vertex_set.h:247
VERTEX * prev
Definition vertex_set.h:239
const int i
Definition vertex_set.h:233
bool operator==(const VERTEX &rhs) const
Definition vertex_set.h:69
VERTEX * m_earBlocker
Definition vertex_set.h:252
void * GetUserData() const
Definition vertex_set.h:75
void * m_userData
Definition vertex_set.h:249
void remove()
Remove the node from the linked list and z-ordered linked list.
Definition vertex_set.h:80
VERTEX(int aIndex, double aX, double aY, VERTEX_SET *aParent, void *aUserData=nullptr)
Definition vertex_set.h:57
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:201
uint32_t z
Definition vertex_set.h:243
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:235
void updateOrder()
VERTEX_SET * parent
Definition vertex_set.h:236
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708