-
-
Notifications
You must be signed in to change notification settings - Fork 498
/
Copy patheda_shape.h
464 lines (367 loc) · 14.4 KB
/
eda_shape.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2018 Jean-Pierre Charras jp.charras at wanadoo.fr
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#pragma once
#include <core/mirror.h>
#include <geometry/shape_poly_set.h>
#include <geometry/approximation.h>
#include <properties/property.h>
#include <stroke_params.h>
#include <trigo.h>
#include <api/serializable.h>
class LINE_READER;
class EDA_DRAW_FRAME;
class FOOTPRINT;
class MSG_PANEL_ITEM;
using KIGFX::COLOR4D;
enum class SHAPE_T : int
{
UNDEFINED = -1,
SEGMENT = 0,
RECTANGLE, ///< Use RECTANGLE instead of RECT to avoid collision in a Windows header.
ARC,
CIRCLE,
POLY,
BEZIER
};
// WARNING: Do not change these values without updating dialogs that depend on their position values
enum class FILL_T : int
{
NO_FILL = 1,
FILLED_SHAPE, ///< Fill with object color.
FILLED_WITH_BG_BODYCOLOR, //< Fill with background body color.
FILLED_WITH_COLOR //< Fill with a separate color.
};
/// Holding struct to keep originating midpoint
struct ARC_MID
{
VECTOR2I mid;
VECTOR2I start;
VECTOR2I end;
VECTOR2I center;
};
class EDA_SHAPE : public SERIALIZABLE
{
public:
EDA_SHAPE( SHAPE_T aType, int aLineWidth, FILL_T aFill );
/// Construct an EDA_SHAPE from an abstract SHAPE geometry.
EDA_SHAPE( const SHAPE& aShape );
// Do not create a copy constructor & operator=.
// The ones generated by the compiler are adequate.
virtual ~EDA_SHAPE();
void SwapShape( EDA_SHAPE* aImage );
void Serialize( google::protobuf::Any &aContainer ) const override;
bool Deserialize( const google::protobuf::Any &aContainer ) override;
wxString ShowShape() const;
wxString SHAPE_T_asString() const;
virtual bool IsProxyItem() const { return m_proxyItem; }
virtual void SetIsProxyItem( bool aIsProxy = true ) { m_proxyItem = aIsProxy; }
bool IsFilled() const
{
return GetFillMode() != FILL_T::NO_FILL;
}
virtual bool IsFilledForHitTesting() const
{
return IsFilled();
}
virtual void SetFilled( bool aFlag )
{
setFilled( aFlag );
}
void SetFillMode( FILL_T aFill ) { m_fill = aFill; }
FILL_T GetFillMode() const { return m_fill; }
bool IsClosed() const;
COLOR4D GetFillColor() const { return m_fillColor; }
void SetFillColor( const COLOR4D& aColor ) { m_fillColor = aColor; }
void SetWidth( int aWidth ) { m_stroke.SetWidth( aWidth ); }
virtual int GetWidth() const { return m_stroke.GetWidth(); }
virtual int GetEffectiveWidth() const { return GetWidth(); }
void SetLineStyle( const LINE_STYLE aStyle );
LINE_STYLE GetLineStyle() const;
void SetLineColor( const COLOR4D& aColor ) { m_stroke.SetColor( aColor ); }
COLOR4D GetLineColor() const { return m_stroke.GetColor(); }
void SetShape( SHAPE_T aShape ) { m_shape = aShape; }
SHAPE_T GetShape() const { return m_shape; }
/**
* Return the starting point of the graphic.
*/
const VECTOR2I& GetStart() const { return m_start; }
int GetStartY() const { return m_start.y; }
int GetStartX() const { return m_start.x; }
void SetStart( const VECTOR2I& aStart )
{
m_start = aStart;
m_endsSwapped = false;
}
void SetStartY( int y )
{
m_start.y = y;
m_endsSwapped = false;
}
void SetStartX( int x )
{
m_start.x = x;
m_endsSwapped = false;
}
void SetCenterY( int y )
{
m_end.y += y - m_start.y;
m_start.y = y;
}
void SetCenterX( int x )
{
m_end.x += x - m_start.x;
m_start.x = x;
}
/**
* Return the ending point of the graphic.
*/
const VECTOR2I& GetEnd() const { return m_end; }
int GetEndY() const { return m_end.y; }
int GetEndX() const { return m_end.x; }
void SetEnd( const VECTOR2I& aEnd )
{
m_end = aEnd;
m_endsSwapped = false;
}
void SetEndY( int aY )
{
m_end.y = aY;
m_endsSwapped = false;
}
void SetEndX( int aX )
{
m_end.x = aX;
m_endsSwapped = false;
}
void SetRadius( int aX )
{
m_end = m_start + VECTOR2I( aX, 0 );
}
virtual VECTOR2I GetTopLeft() const { return GetStart(); }
virtual VECTOR2I GetBotRight() const { return GetEnd(); }
virtual void SetTop( int val ) { SetStartY( val ); }
virtual void SetLeft( int val ) { SetStartX( val ); }
virtual void SetRight( int val ) { SetEndX( val ); }
virtual void SetBottom( int val ) { SetEndY( val ); }
void SetBezierC1( const VECTOR2I& aPt ) { m_bezierC1 = aPt; }
const VECTOR2I& GetBezierC1() const { return m_bezierC1; }
void SetBezierC2( const VECTOR2I& aPt ) { m_bezierC2 = aPt; }
const VECTOR2I& GetBezierC2() const { return m_bezierC2; }
VECTOR2I getCenter() const;
void SetCenter( const VECTOR2I& aCenter );
/**
* Set the end point from the angle center and start.
*
* aAngle is:
* - clockwise in right-down coordinate system
* - counter-clockwise in right-up (libedit) coordinate system.
*/
void SetArcAngleAndEnd( const EDA_ANGLE& aAngle, bool aCheckNegativeAngle = false );
EDA_ANGLE GetArcAngle() const;
EDA_ANGLE GetSegmentAngle() const;
/**
* Have the start and end points been swapped since they were set?
*
* @return true if they have.
*/
bool EndsSwapped() const { return m_endsSwapped; }
// Some attributes are read only, since they are derived from m_Start, m_End, and m_Angle.
// No Set...() function for these attributes.
VECTOR2I GetArcMid() const;
std::vector<VECTOR2I> GetRectCorners() const;
/**
* Calc arc start and end angles such that aStartAngle < aEndAngle. Each may be between
* -360.0 and 360.0.
*/
void CalcArcAngles( EDA_ANGLE& aStartAngle, EDA_ANGLE& aEndAngle ) const;
int GetRadius() const;
/**
* Set the three controlling points for an arc.
*
* NB: these are NOT what's currently stored, so we have to do some calculations behind
* the scenes. However, they are what SHOULD be stored.
*/
void SetArcGeometry( const VECTOR2I& aStart, const VECTOR2I& aMid, const VECTOR2I& aEnd );
/**
* Set the data used for mid point caching.
*
* If the controlling points remain constant, then we keep the midpoint the same as it was
* when read in. This minimizes VCS churn.
*
* @param aStart Cached start point.
* @param aMid Cached mid point.
* @param aEnd Cached end point.
* @param aCenter Calculated center point using the preceeding three.
*/
void SetCachedArcData( const VECTOR2I& aStart, const VECTOR2I& aMid, const VECTOR2I& aEnd,
const VECTOR2I& aCenter );
const std::vector<VECTOR2I>& GetBezierPoints() const { return m_bezierPoints; }
/**
* Duplicate the list of corners in a std::vector<VECTOR2I>.
*
* It must be used only to convert the SHAPE_POLY_SET internal corner buffer
* to a list of VECTOR2Is, and nothing else, because it duplicates the buffer,
* that is inefficient to know for instance the corner count.
*/
void DupPolyPointsList( std::vector<VECTOR2I>& aBuffer ) const;
/**
* @return the number of corners of the polygonal shape.
*/
int GetPointCount() const;
// Accessors to the polygonal shape
SHAPE_POLY_SET& GetPolyShape() { return m_poly; }
const SHAPE_POLY_SET& GetPolyShape() const { return m_poly; }
/**
* @return true if the polygonal shape is valid (has more than 2 points).
*/
bool IsPolyShapeValid() const;
void SetPolyShape( const SHAPE_POLY_SET& aShape )
{
m_poly = aShape;
for( int ii = 0; ii < m_poly.OutlineCount(); ++ii )
{
if( m_poly.HoleCount( ii ) )
{
m_poly.Fracture();
break;
}
}
}
void SetPolyPoints( const std::vector<VECTOR2I>& aPoints );
/**
* Rebuild the m_bezierPoints vertex list that approximate the Bezier curve by a list of
* segments.
*
* Has meaning only for #BEZIER shape.
*
* @param aMinSegLen is the max deviation between the polyline and the curve.
*/
void RebuildBezierToSegmentsPointsList( int aMaxError );
/**
* Make a set of SHAPE objects representing the #EDA_SHAPE.
*
* Caller owns the objects.
*
* @param aEdgeOnly indicates only edges should be generated (even if 0 width), and no fill
* shapes.
*/
virtual std::vector<SHAPE*> MakeEffectiveShapes( bool aEdgeOnly = false ) const
{
return makeEffectiveShapes( aEdgeOnly );
}
void ShapeGetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList );
void SetLength( const double& aLength );
void SetRectangleHeight( const int& aHeight );
void SetRectangleWidth( const int& aWidth );
void SetRectangle( const long long int& aHeight, const long long int& aWidth );
void SetSegmentAngle( const EDA_ANGLE& aAngle );
bool IsClockwiseArc() const;
/**
* @return the length of the segment using the hypotenuse calculation.
*/
double GetLength() const;
int GetRectangleHeight() const;
int GetRectangleWidth() const;
/**
* Convert the shape to a closed polygon.
*
* Circles and arcs are approximated by segments.
*
* @param aBuffer is a buffer to store the polygon.
* @param aClearance is the clearance around the pad.
* @param aError is the maximum deviation from a true arc.
* @param aErrorLoc whether any approximation error should be placed inside or outside
* @param ignoreLineWidth is used for edge cut items where the line width is only for
* visualization
*/
void TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, int aClearance, int aError,
ERROR_LOC aErrorLoc, bool ignoreLineWidth = false ) const;
int Compare( const EDA_SHAPE* aOther ) const;
double Similarity( const EDA_SHAPE& aOther ) const;
bool operator==( const EDA_SHAPE& aOther ) const;
protected:
wxString getFriendlyName() const;
void setPosition( const VECTOR2I& aPos );
VECTOR2I getPosition() const;
virtual void setFilled( bool aFlag )
{
m_fill = aFlag ? FILL_T::FILLED_SHAPE : FILL_T::NO_FILL;
}
void move( const VECTOR2I& aMoveVector );
void rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle );
void flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection );
void scale( double aScale );
const BOX2I getBoundingBox() const;
void computeArcBBox( BOX2I& aBBox ) const;
bool hitTest( const VECTOR2I& aPosition, int aAccuracy = 0 ) const;
bool hitTest( const BOX2I& aRect, bool aContained, int aAccuracy = 0 ) const;
const std::vector<VECTOR2I> buildBezierToSegmentsPointsList( int aMaxError ) const;
void beginEdit( const VECTOR2I& aStartPoint );
bool continueEdit( const VECTOR2I& aPosition );
void calcEdit( const VECTOR2I& aPosition );
/**
* Finish editing the shape.
*
* @param aClosed Should polygon shapes be closed (yes for pcbnew/fpeditor, no for libedit).
*/
void endEdit( bool aClosed = true );
void setEditState( int aState ) { m_editState = aState; }
/**
* Make a set of #SHAPE objects representing the #EDA_SHAPE.
*
* Caller owns the objects.
*
* @param aEdgeOnly indicates only edges should be generated (even if 0 width), and no fill
* shapes.
* @param aLineChainOnly indicates #SHAPE_POLY_SET is being abused slightly to represent a
* lineChain rather than a closed polygon.
*/
// fixme: move to shape_compound
std::vector<SHAPE*> makeEffectiveShapes( bool aEdgeOnly, bool aLineChainOnly = false ) const;
protected:
bool m_endsSwapped; // true if start/end were swapped e.g. SetArcAngleAndEnd
SHAPE_T m_shape; // Shape: line, Circle, Arc
STROKE_PARAMS m_stroke; // Line style, width, etc.
FILL_T m_fill;
COLOR4D m_fillColor;
long long int m_rectangleHeight;
long long int m_rectangleWidth;
double m_segmentLength;
EDA_ANGLE m_segmentAngle;
VECTOR2I m_start; // Line start point or Circle center
VECTOR2I m_end; // Line end point or Circle 3 o'clock point
VECTOR2I m_arcCenter; // Used only for Arcs: arc end point
ARC_MID m_arcMidData; // Used to store originating data
VECTOR2I m_bezierC1; // Bezier Control Point 1
VECTOR2I m_bezierC2; // Bezier Control Point 2
std::vector<VECTOR2I> m_bezierPoints;
SHAPE_POLY_SET m_poly; // Stores the S_POLYGON shape
int m_editState;
bool m_proxyItem; // A shape storing proxy information (ie: a pad
// number box, thermal spoke template, etc.)
};
#ifndef SWIG
DECLARE_ENUM_TO_WXANY( SHAPE_T );
DECLARE_ENUM_TO_WXANY( LINE_STYLE );
#endif