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
/**********************************/
/* classes to handle copper zones */
/**********************************/
#ifndef CLASS_ZONE_H
#define CLASS_ZONE_H
#include <vector>
#include "gr_basic.h"
#include "PolyLine.h"
/* a small class used when filling areas with segments */
class SEGMENT
{
public:
wxPoint m_Start; // starting point of a segment
wxPoint m_End; // ending point of a segment
public:
SEGMENT() {}
SEGMENT( const wxPoint & aStart, const wxPoint & aEnd)
{
m_Start = aStart;
m_End = aEnd;
}
};
/************************/
/* class ZONE_CONTAINER */
/************************/
/* handle a list of polygons delimiting a copper zone
* a zone is described by a main polygon, a time stamp, a layer and a net name.
* others polygons inside this main polygon are holes.
*/
class ZONE_CONTAINER : public BOARD_ITEM
{
public:
wxString m_Netname; // Net Name
CPolyLine* m_Poly; // outlines
int m_CornerSelection; // For corner moving, corner index to drag, or -1 if no selection
int m_ZoneClearance; // clearance value
int m_ZoneMinThickness; // Min thickness value in filled areas
int m_FillMode; // How to fillingareas: 0 = use polygonal areas , != 0 fill with segments
int m_ArcToSegmentsCount; // number of segments to convert a circle to a polygon (uses 16 or 32)
int m_PadOption; //
int m_ThermalReliefGapValue; // tickness of the gap in thermal reliefs
int m_ThermalReliefCopperBridgeValue; // tickness of the copper bridge in thermal reliefs
int utility, utility2; // flags used in polygon calculations
bool m_IsFilled; // true when a zone was filled, false after deleting the filled areas
std::vector <CPolyPt> m_FilledPolysList; /* set of filled polygons used to draw a zone as a filled area.
* from outlines (m_Poly) but unlike m_Poly these filled polygons have no hole (they are all in one piece)
* In very simple cases m_FilledPolysList is same as m_Poly
* In less simple cases (when m_Poly has holes) m_FilledPolysList is a polygon equivalent to m_Poly, without holes
* but with extra outline segment connecting "holes" with external main outline
* In complex cases an ouline decribed by m_Poly can have many filled areas
*/
std::vector <SEGMENT> m_FillSegmList; /* set of segments used to fill area, when fill zone by segment is used.
* ( m_FillMode == 1 )
* in this case segments have m_ZoneMinThickness width
*/
private:
int m_NetCode; // Net number for fast comparisons
int m_ZoneSubnet; // variable used in rastnest computations:handle block number in zone connection calculations
public:
ZONE_CONTAINER( BOARD* parent );
~ZONE_CONTAINER();
bool Save( FILE* aFile ) const;
int ReadDescr( FILE* aFile, int* aLineNum = NULL );
/** virtual function GetPosition
* @return a wxPoint, position of the first point of the outline
*/
wxPoint& GetPosition();
/**
* Function copy
* copy usefull data from the source.
* flags and linked list pointers are NOT copied
*/
void Copy( ZONE_CONTAINER* src );
void DisplayInfo( WinEDA_DrawFrame* frame );
/**
* Function Draw
* Draws the zone outline.
* @param panel = current Draw Panel
* @param DC = current Device Context
* @param offset = Draw offset (usually wxPoint(0,0))
* @param aDrawMode = GR_OR, GR_XOR, GR_COPY ..
*/
void Draw( WinEDA_DrawPanel* panel,
wxDC* DC,
int aDrawMode,
const wxPoint& offset = ZeroOffset );
/**
* Function DrawDrawFilledArea
* Draws the filled area for this zone (polygon list .m_FilledPolysList)
* @param panel = current Draw Panel
* @param DC = current Device Context
* @param offset = Draw offset (usually wxPoint(0,0))
* @param aDrawMode = GR_OR, GR_XOR, GR_COPY ..
*/
void DrawFilledArea( WinEDA_DrawPanel* panel,
wxDC* DC,
int aDrawMode,
const wxPoint& offset = ZeroOffset );
/**
* Function DrawWhileCreateOutline
* Draws the zone outline when ir is created.
* The moving edges are in XOR graphic mode, old segment in draw_mode graphic mode (usually GR_OR)
* The closing edge has its owm shape
* @param panel = current Draw Panel
* @param DC = current Device Context
* @param draw_mode = draw mode: OR, XOR ..
*/
void DrawWhileCreateOutline( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode = GR_OR );
/* Function GetBoundingBox
* @return an EDA_Rect that is the bounding box of the zone outline
*/
EDA_Rect GetBoundingBox();
/**
* Function Test_For_Copper_Island_And_Remove__Insulated_Islands
* Remove insulated copper islands found in m_FilledPolysList.
* @param aPcb = the board to analyse
*/
void Test_For_Copper_Island_And_Remove_Insulated_Islands( BOARD* aPcb );
/** function CalculateSubAreaBoundaryBox
* Calculates the bounding box of a a filled area ( list of CPolyPt )
* use m_FilledPolysList as list of CPolyPt (that are the corners of one or more polygons or filled areas )
* @return an EDA_Rect as bounding box
* @param aIndexStart = index of the first corner of a polygon (filled area) in m_FilledPolysList
* @param aIndexEnd = index of the last corner of a polygon in m_FilledPolysList
*/
EDA_Rect CalculateSubAreaBoundaryBox( int aIndexStart, int aIndexEnd );
/**
* Function IsOnCopperLayer
* @return true if this zone is on a copper layer, false if on a technical layer
*/
bool IsOnCopperLayer( void )
{
return ( GetLayer() < FIRST_NO_COPPER_LAYER ) ? true : false;
}
/**
* Function GetZoneSubNet
* @return int - the sub net code in zone connections.
*/
int GetZoneSubNet() const { return m_ZoneSubnet; }
void SetZoneSubNet( int aSubNetCode ) { m_ZoneSubnet = aSubNetCode; }
int GetNet( void ) const
{
return m_NetCode;
}
void SetNet( int anet_code );
/**
* Function SetNetNameFromNetCode
* Fin the nat name corresponding to the net code.
* @return bool - true if net found, else false
*/
bool SetNetNameFromNetCode( void );
/**
* Function HitTest
* tests if the given wxPoint is within the bounds of this object.
* For zones, this means near an ouline segment
* @param refPos A wxPoint to test
* @return bool - true if a hit, else false
*/
bool HitTest( const wxPoint& refPos );
/**
* Function HitTestFilledArea
* tests if the given wxPoint is within the bounds of a filled area of this zone.
* @param aRefPos A wxPoint to test
* @return bool - true if a hit, else false
*/
bool HitTestFilledArea( const wxPoint& aRefPos );
/** function BuildFilledPolysListData
* Build m_FilledPolysList data from real outlines (m_Poly)
* in order to have drawable (and plottable) filled polygons
* drawable filled polygons are polygons without hole
* @param aPcb: the current board (can be NULL for non copper zones)
* @return number of polygons
* This function does not add holes for pads and tracks but calls
* AddClearanceAreasPolygonsToPolysList() to do that for copper layers
*/
int BuildFilledPolysListData( BOARD* aPcb );
/** function AddClearanceAreasPolygonsToPolysList
* Add non copper areas polygons (pads and tracks with clearence)
* to a filled copper area
* used in BuildFilledPolysListData when calculating filled areas in a zone
* Non copper areas are pads and track and their clearance area
* The filled copper area must be computed before
* BuildFilledPolysListData() call this function just after creating the
* filled copper area polygon (without clearence areas
* @param aPcb: the current board
*/
void AddClearanceAreasPolygonsToPolysList( BOARD* aPcb );
/** Function CopyPolygonsFromBoolengineToFilledPolysList
* Copy (Add) polygons created by kbool (after Do_Operation) to m_FilledPolysList
* @param aBoolengine = the kbool engine used in Do_Operation
* @return the corner count
*/
int CopyPolygonsFromBoolengineToFilledPolysList( Bool_Engine* aBoolengine );
/** Function CopyPolygonsFromFilledPolysListToBoolengine
* Copy (Add) polygons created by kbool (after Do_Operation) to m_FilledPolysList
* @param aBoolengine = kbool engine
* @param aGroup = group in kbool engine (GROUP_A or GROUP_B only)
* @return the corner count
*/
int CopyPolygonsFromFilledPolysListToBoolengine( Bool_Engine* aBoolengine,
GroupType aGroup = GROUP_A );
/**
* Function HitTestForCorner
* tests if the given wxPoint near a corner, or near the segment define by 2 corners.
* @return -1 if none, corner index in .corner <vector>
* @param refPos : A wxPoint to test
*/
int HitTestForCorner( const wxPoint& refPos );
/**
* Function HitTestForEdge
* tests if the given wxPoint near a corner, or near the segment define by 2 corners.
* @return -1 if none, or index of the starting corner in .corner <vector>
* @param refPos : A wxPoint to test
*/
int HitTestForEdge( const wxPoint& refPos );
/**
* Function HitTest (overlayed)
* tests if the given EDA_Rect contains the bounds of this object.
* @param refArea : the given EDA_Rect
* @return bool - true if a hit, else false
*/
bool HitTest( EDA_Rect& refArea );
/**
* Function Fill_Zone()
* Calculate the zone filling
* The zone outline is a frontier, and can be complex (with holes)
* The filling starts from starting points like pads, tracks.
* If exists the old filling is removed
* @param frame = reference to the main frame
* @param DC = current Device Context
* @param verbose = true to show error messages
* @return error level (0 = no error)
*/
int Fill_Zone( WinEDA_PcbFrame* frame, wxDC* DC, bool verbose = TRUE );
/** Function Fill_Zone_Areas_With_Segments()
* Fill sub areas in a zone with segments with m_ZoneMinThickness width
* A scan is made line per line, on the whole filled areas, with a step of m_ZoneMinThickness.
* all intersecting points with the horizontal infinite line and polygons to fill are calculated
* a list of SEGZONE items is built, line per line
* @param aFrame = reference to the main frame
* @return number of segments created
*/
int Fill_Zone_Areas_With_Segments( );
/* Geometric transformations: */
/**
* Function Move
* Move the outlines
* @param offset = moving vector
*/
void Move( const wxPoint& offset );
/**
* Function MoveEdge
* Move the outline Edge. m_CornerSelection is the start point of the outline edge
* @param offset = moving vector
*/
void MoveEdge( const wxPoint& offset );
/**
* Function Rotate
* Move the outlines
* @param centre = rot centre
* @param angle = in 0.1 degree
*/
void Rotate( const wxPoint& centre, int angle );
/**
* Function Flip
* Flip this object, i.e. change the board side for this object
* (like Mirror() but changes layer)
* @param const wxPoint& aCentre - the rotation point.
*/
virtual void Flip( const wxPoint& aCentre );
/**
* Function Mirror
* Mirror the outlines , relative to a given horizontal axis
* the layer is not changed
* @param mirror_ref = vertical axis position
*/
void Mirror( const wxPoint& mirror_ref );
/**
* Function GetClass
* returns the class name.
* @return wxString
*/
wxString GetClass() const
{
return wxT( "ZONE_CONTAINER" );
}
/** Acces to m_Poly parameters
*/
int GetNumCorners( void )
{
return m_Poly->GetNumCorners();
}
void RemoveAllContours( void )
{
m_Poly->RemoveAllContours();
}
wxPoint GetCornerPosition( int aCornerIndex )
{
return wxPoint( m_Poly->GetX( aCornerIndex ), m_Poly->GetY( aCornerIndex ) );
}
void SetCornerPosition( int aCornerIndex, wxPoint new_pos )
{
m_Poly->SetX( aCornerIndex, new_pos.x );
m_Poly->SetY( aCornerIndex, new_pos.y );
}
void AppendCorner( wxPoint position )
{
m_Poly->AppendCorner( position.x, position.y );
}
int GetHatchStyle() const
{
return m_Poly->GetHatchStyle();
}
/** function IsSame()
* test is 2 zones are equivalent:
* 2 zones are equivalent if they have same parameters and same outlines
* info relative to filling is not take in account
* @param aZoneToCompare = zone to compare with "this"
*/
bool IsSame( const ZONE_CONTAINER &aZoneToCompare);
};
#endif // #ifndef CLASS_ZONE_H