Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
K
kicad-source-mirror
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
Elphel
kicad-source-mirror
Commits
f2f4cd53
Commit
f2f4cd53
authored
Nov 16, 2009
by
charras
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
rework on zones (continued):try to fix a filling problem with kbool: cleanup code
parent
537d4861
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
872 additions
and
678 deletions
+872
-678
board_items_to_polygon_shape_transform.cpp
pcbnew/board_items_to_polygon_shape_transform.cpp
+629
-60
class_drawsegment.h
pcbnew/class_drawsegment.h
+38
-17
class_pad.h
pcbnew/class_pad.h
+3
-2
class_pcb_text.h
pcbnew/class_pcb_text.h
+18
-0
class_track.h
pcbnew/class_track.h
+3
-2
debug_kbool_key_file_fct.cpp
pcbnew/debug_kbool_key_file_fct.cpp
+49
-44
debug_kbool_key_file_fct.h
pcbnew/debug_kbool_key_file_fct.h
+2
-2
zones_convert_brd_items_to_polygons.cpp
pcbnew/zones_convert_brd_items_to_polygons.cpp
+130
-551
No files found.
pcbnew/board_items_to_polygon_shape_transform.cpp
View file @
f2f4cd53
...
@@ -21,16 +21,151 @@
...
@@ -21,16 +21,151 @@
* @param aCornerBuffer = a buffer to store the polygon
* @param aCornerBuffer = a buffer to store the polygon
* @param aStart = the segment start point coordinate
* @param aStart = the segment start point coordinate
* @param aEnd = the segment end point coordinate
* @param aEnd = the segment end point coordinate
* @param aWidth = the segment width
* @param aCircleToSegmentsCount = the number of segments to approximate a circle
* @param aCircleToSegmentsCount = the number of segments to approximate a circle
* @param aWidth = the segment width
*/
*/
void
TransformRoundedEndsSegmentToPolygon
(
std
::
vector
<
wxPoin
t
>&
aCornerBuffer
,
void
TransformRoundedEndsSegmentToPolygon
(
std
::
vector
<
CPolyP
t
>&
aCornerBuffer
,
wxPoint
aStart
,
wxPoint
aEnd
,
wxPoint
aStart
,
wxPoint
aEnd
,
int
aCircleToSegmentsCount
,
int
aCircleToSegmentsCount
,
int
aWidth
);
int
aWidth
);
/** Function TransformTrackWithClearanceToPolygon
/** Function TransformArcToPolygon
* Creates a polygon from an Arc
* Convert arcs to multiple straight segments
* @param aCornerBuffer = a buffer to store the polygon
* @param aCentre = centre of the arc or circle
* @param aStart = start point of the arc, or a point on the circle
* @param aArcAngle = arc angle in 0.1 degrees. For a circle, aArcAngle = 3600
* @param aCircleToSegmentsCount = the number of segments to approximate a circle
* @param aWidth = width (thickness) of the line
*/
void
TransformArcToPolygon
(
std
::
vector
<
CPolyPt
>&
aCornerBuffer
,
wxPoint
aCentre
,
wxPoint
aStart
,
int
aArcAngle
,
int
aCircleToSegmentsCount
,
int
aWidth
)
{
wxPoint
arc_start
,
arc_end
;
int
delta
=
3600
/
aCircleToSegmentsCount
;
// rot angle in 0.1 degree
arc_end
=
arc_start
=
aStart
;
if
(
aArcAngle
!=
3600
)
{
RotatePoint
(
&
arc_end
,
aCentre
,
-
aArcAngle
);
}
if
(
aArcAngle
<
0
)
{
EXCHG
(
arc_start
,
arc_end
);
NEGATE
(
aArcAngle
);
}
// Compute the ends of segments and creates poly
wxPoint
curr_end
=
arc_start
;
wxPoint
curr_start
=
arc_start
;
for
(
int
ii
=
delta
;
ii
<
aArcAngle
;
ii
+=
delta
)
{
curr_end
=
arc_start
;
RotatePoint
(
&
curr_end
,
aCentre
,
-
ii
);
TransformRoundedEndsSegmentToPolygon
(
aCornerBuffer
,
curr_start
,
curr_end
,
aCircleToSegmentsCount
,
aWidth
);
curr_start
=
curr_end
;
}
if
(
curr_end
!=
arc_end
)
TransformRoundedEndsSegmentToPolygon
(
aCornerBuffer
,
curr_end
,
arc_end
,
aCircleToSegmentsCount
,
aWidth
);
}
/** Function TEXTE_PCB::TransformShapeWithClearanceToPolygon
* Convert the track shape to a closed polygon
* Used in filling zones calculations
* Circles and arcs are approximated by segments
* @param aCornerBuffer = a buffer to store the polygon
* @param aClearanceValue = the clearance around the pad
* @param aCircleToSegmentsCount = the number of segments to approximate a circle
* @param aCorrectionFactor = the correction to apply to circles radius to keep
* clearance when the circle is approximated by segment bigger or equal
* to the real clearance value (usually near from 1.0)
*/
void
TEXTE_PCB
::
TransformShapeWithClearanceToPolygon
(
std
::
vector
<
CPolyPt
>&
aCornerBuffer
,
int
aClearanceValue
,
int
aCircleToSegmentsCount
,
double
aCorrectionFactor
)
{
if
(
GetLength
()
==
0
)
return
;
CPolyPt
corners
[
4
];
// Buffer of polygon corners
EDA_Rect
rect
=
GetTextBox
(
-
1
);
rect
.
Inflate
(
aClearanceValue
,
aClearanceValue
);
corners
[
0
].
x
=
rect
.
GetOrigin
().
x
;
corners
[
0
].
y
=
rect
.
GetOrigin
().
y
;
corners
[
1
].
y
=
corners
[
0
].
y
;
corners
[
1
].
x
=
rect
.
GetRight
();
corners
[
2
].
x
=
corners
[
1
].
x
;
corners
[
2
].
y
=
rect
.
GetBottom
();
corners
[
3
].
y
=
corners
[
2
].
y
;
corners
[
3
].
x
=
corners
[
0
].
x
;
for
(
int
ii
=
0
;
ii
<
4
;
ii
++
)
{
// Rotate polygon
RotatePoint
(
&
corners
[
ii
].
x
,
&
corners
[
ii
].
y
,
m_Pos
.
x
,
m_Pos
.
y
,
m_Orient
);
aCornerBuffer
.
push_back
(
corners
[
ii
]
);
}
aCornerBuffer
.
back
().
end_contour
=
true
;
}
/** Function DRAWSEGMENT::TransformShapeWithClearanceToPolygon
* Convert the track shape to a closed polygon
* Used in filling zones calculations
* Circles and arcs are approximated by segments
* @param aCornerBuffer = a buffer to store the polygon
* @param aClearanceValue = the clearance around the pad
* @param aCircleToSegmentsCount = the number of segments to approximate a circle
* @param aCorrectionFactor = the correction to apply to circles radius to keep
* clearance when the circle is approxiamted by segment bigger or equal
* to the real clearance value (usually near from 1.0)
*/
void
DRAWSEGMENT
::
TransformShapeWithClearanceToPolygon
(
std
::
vector
<
CPolyPt
>&
aCornerBuffer
,
int
aClearanceValue
,
int
aCircleToSegmentsCount
,
double
aCorrectionFactor
)
{
switch
(
m_Shape
)
{
case
S_CIRCLE
:
TransformArcToPolygon
(
aCornerBuffer
,
m_Start
,
// Circle centre
m_End
,
3600
,
aCircleToSegmentsCount
,
m_Width
+
(
2
*
aClearanceValue
)
);
break
;
case
S_ARC
:
TransformArcToPolygon
(
aCornerBuffer
,
m_Start
,
m_End
,
m_Angle
,
aCircleToSegmentsCount
,
m_Width
+
(
2
*
aClearanceValue
)
);
break
;
default
:
TransformRoundedEndsSegmentToPolygon
(
aCornerBuffer
,
m_Start
,
m_End
,
aCircleToSegmentsCount
,
m_Width
+
(
2
*
aClearanceValue
)
);
break
;
}
}
/** Function TRACK::TransformShapeWithClearanceToPolygon
* Convert the track shape to a closed polygon
* Convert the track shape to a closed polygon
* Used in filling zones calculations
* Used in filling zones calculations
* Circles (vias) and arcs (ends of tracks) are approximated by segments
* Circles (vias) and arcs (ends of tracks) are approximated by segments
...
@@ -41,16 +176,15 @@ void TransformRoundedEndsSegmentToPolygon( std::vector <wxPoint>& aCornerBuffer,
...
@@ -41,16 +176,15 @@ void TransformRoundedEndsSegmentToPolygon( std::vector <wxPoint>& aCornerBuffer,
* clearance when the circle is approxiamted by segment bigger or equal
* clearance when the circle is approxiamted by segment bigger or equal
* to the real clearance value (usually near from 1.0)
* to the real clearance value (usually near from 1.0)
*/
*/
void
TRACK
::
TransformTrackWithClearanceToPolygon
(
std
::
vector
<
wxPoin
t
>&
aCornerBuffer
,
void
TRACK
::
TransformShapeWithClearanceToPolygon
(
std
::
vector
<
CPolyP
t
>&
aCornerBuffer
,
int
aClearanceValue
,
int
aClearanceValue
,
int
aCircleToSegmentsCount
,
int
aCircleToSegmentsCount
,
double
aCorrectionFactor
)
double
aCorrectionFactor
)
{
{
wxPoint
corner_position
;
wxPoint
corner_position
;
int
ii
,
angle
;
int
ii
,
angle
;
int
dx
=
(
m_Width
/
2
)
+
aClearanceValue
;
int
dx
=
(
m_Width
/
2
)
+
aClearanceValue
;
int
delta
=
3600
/
aCircleToSegmentsCount
;
// rot angle in 0.1 degree
int
delta
=
3600
/
aCircleToSegmentsCount
;
// rot angle in 0.1 degree
switch
(
Type
()
)
switch
(
Type
()
)
{
{
...
@@ -59,19 +193,25 @@ void TRACK::TransformTrackWithClearanceToPolygon( std::vector <wxPoint>& aCorner
...
@@ -59,19 +193,25 @@ void TRACK::TransformTrackWithClearanceToPolygon( std::vector <wxPoint>& aCorner
for
(
ii
=
0
;
ii
<
aCircleToSegmentsCount
;
ii
++
)
for
(
ii
=
0
;
ii
<
aCircleToSegmentsCount
;
ii
++
)
{
{
corner_position
=
wxPoint
(
dx
,
0
);
corner_position
=
wxPoint
(
dx
,
0
);
RotatePoint
(
&
corner_position
,
(
1800
/
aCircleToSegmentsCount
)
);
RotatePoint
(
&
corner_position
.
x
,
&
corner_position
.
y
,
(
1800
/
aCircleToSegmentsCount
)
);
angle
=
ii
*
delta
;
angle
=
ii
*
delta
;
RotatePoint
(
&
corner_position
,
angle
);
RotatePoint
(
&
corner_position
.
x
,
&
corner_position
.
y
,
angle
);
corner_position
+=
m_Start
;
corner_position
.
x
+=
m_Start
.
x
;
aCornerBuffer
.
push_back
(
corner_position
);
corner_position
.
y
+=
m_Start
.
y
;
CPolyPt
polypoint
(
corner_position
.
x
,
corner_position
.
y
);
aCornerBuffer
.
push_back
(
polypoint
);
}
}
aCornerBuffer
.
back
().
end_contour
=
true
;
break
;
break
;
default
:
default
:
TransformRoundedEndsSegmentToPolygon
(
aCornerBuffer
,
TransformRoundedEndsSegmentToPolygon
(
m_Start
,
m_End
,
aCircleToSegmentsCount
,
aCornerBuffer
,
m_Width
+
(
2
*
aClearanceValue
)
);
m_Start
,
m_End
,
aCircleToSegmentsCount
,
m_Width
+
(
2
*
aClearanceValue
)
);
break
;
break
;
}
}
}
}
...
@@ -79,7 +219,7 @@ void TRACK::TransformTrackWithClearanceToPolygon( std::vector <wxPoint>& aCorner
...
@@ -79,7 +219,7 @@ void TRACK::TransformTrackWithClearanceToPolygon( std::vector <wxPoint>& aCorner
/* Function TransformRoundedEndsSegmentToPolygon
/* Function TransformRoundedEndsSegmentToPolygon
*/
*/
void
TransformRoundedEndsSegmentToPolygon
(
std
::
vector
<
wxPoin
t
>&
aCornerBuffer
,
void
TransformRoundedEndsSegmentToPolygon
(
std
::
vector
<
CPolyP
t
>&
aCornerBuffer
,
wxPoint
aStart
,
wxPoint
aEnd
,
wxPoint
aStart
,
wxPoint
aEnd
,
int
aCircleToSegmentsCount
,
int
aCircleToSegmentsCount
,
int
aWidth
)
int
aWidth
)
...
@@ -89,6 +229,7 @@ void TransformRoundedEndsSegmentToPolygon( std::vector <wxPoint>& aCornerBuffer,
...
@@ -89,6 +229,7 @@ void TransformRoundedEndsSegmentToPolygon( std::vector <wxPoint>& aCornerBuffer,
wxPoint
startp
=
aStart
;
wxPoint
startp
=
aStart
;
wxPoint
corner
;
wxPoint
corner
;
int
seg_len
;
int
seg_len
;
CPolyPt
polypoint
;
// normalize the position in order to have endp.x >= 0;
// normalize the position in order to have endp.x >= 0;
if
(
endp
.
x
<
0
)
if
(
endp
.
x
<
0
)
...
@@ -105,12 +246,16 @@ void TransformRoundedEndsSegmentToPolygon( std::vector <wxPoint>& aCornerBuffer,
...
@@ -105,12 +246,16 @@ void TransformRoundedEndsSegmentToPolygon( std::vector <wxPoint>& aCornerBuffer,
corner
=
wxPoint
(
0
,
rayon
);
corner
=
wxPoint
(
0
,
rayon
);
RotatePoint
(
&
corner
,
-
delta_angle
);
RotatePoint
(
&
corner
,
-
delta_angle
);
corner
+=
startp
;
corner
+=
startp
;
aCornerBuffer
.
push_back
(
corner
);
polypoint
.
x
=
corner
.
x
;
polypoint
.
y
=
corner
.
y
;
aCornerBuffer
.
push_back
(
polypoint
);
corner
=
wxPoint
(
seg_len
,
rayon
);
corner
=
wxPoint
(
seg_len
,
rayon
);
RotatePoint
(
&
corner
,
-
delta_angle
);
RotatePoint
(
&
corner
,
-
delta_angle
);
corner
+=
startp
;
corner
+=
startp
;
aCornerBuffer
.
push_back
(
corner
);
polypoint
.
x
=
corner
.
x
;
polypoint
.
y
=
corner
.
y
;
aCornerBuffer
.
push_back
(
polypoint
);
// add right rounded end:
// add right rounded end:
for
(
int
ii
=
delta
;
ii
<
1800
;
ii
+=
delta
)
for
(
int
ii
=
delta
;
ii
<
1800
;
ii
+=
delta
)
...
@@ -120,18 +265,24 @@ void TransformRoundedEndsSegmentToPolygon( std::vector <wxPoint>& aCornerBuffer,
...
@@ -120,18 +265,24 @@ void TransformRoundedEndsSegmentToPolygon( std::vector <wxPoint>& aCornerBuffer,
corner
.
x
+=
seg_len
;
corner
.
x
+=
seg_len
;
RotatePoint
(
&
corner
,
-
delta_angle
);
RotatePoint
(
&
corner
,
-
delta_angle
);
corner
+=
startp
;
corner
+=
startp
;
aCornerBuffer
.
push_back
(
corner
);
polypoint
.
x
=
corner
.
x
;
polypoint
.
y
=
corner
.
y
;
aCornerBuffer
.
push_back
(
polypoint
);
}
}
corner
=
wxPoint
(
seg_len
,
-
rayon
);
corner
=
wxPoint
(
seg_len
,
-
rayon
);
RotatePoint
(
&
corner
,
-
delta_angle
);
RotatePoint
(
&
corner
,
-
delta_angle
);
corner
+=
startp
;
corner
+=
startp
;
aCornerBuffer
.
push_back
(
corner
);
polypoint
.
x
=
corner
.
x
;
polypoint
.
y
=
corner
.
y
;
aCornerBuffer
.
push_back
(
polypoint
);
corner
=
wxPoint
(
0
,
-
rayon
);
corner
=
wxPoint
(
0
,
-
rayon
);
RotatePoint
(
&
corner
,
-
delta_angle
);
RotatePoint
(
&
corner
,
-
delta_angle
);
corner
+=
startp
;
corner
+=
startp
;
aCornerBuffer
.
push_back
(
corner
);
polypoint
.
x
=
corner
.
x
;
polypoint
.
y
=
corner
.
y
;
aCornerBuffer
.
push_back
(
polypoint
);
// add left rounded end:
// add left rounded end:
for
(
int
ii
=
delta
;
ii
<
1800
;
ii
+=
delta
)
for
(
int
ii
=
delta
;
ii
<
1800
;
ii
+=
delta
)
...
@@ -140,12 +291,16 @@ void TransformRoundedEndsSegmentToPolygon( std::vector <wxPoint>& aCornerBuffer,
...
@@ -140,12 +291,16 @@ void TransformRoundedEndsSegmentToPolygon( std::vector <wxPoint>& aCornerBuffer,
RotatePoint
(
&
corner
,
ii
);
RotatePoint
(
&
corner
,
ii
);
RotatePoint
(
&
corner
,
-
delta_angle
);
RotatePoint
(
&
corner
,
-
delta_angle
);
corner
+=
startp
;
corner
+=
startp
;
aCornerBuffer
.
push_back
(
corner
);
polypoint
.
x
=
corner
.
x
;
polypoint
.
y
=
corner
.
y
;
aCornerBuffer
.
push_back
(
polypoint
);
}
}
aCornerBuffer
.
back
().
end_contour
=
true
;
}
}
/** function
TransformPad
WithClearanceToPolygon
/** function
D_PAD::TransformShape
WithClearanceToPolygon
* Convert the pad shape to a closed polygon
* Convert the pad shape to a closed polygon
* Used in filling zones calculations
* Used in filling zones calculations
* Circles and arcs are approximated by segments
* Circles and arcs are approximated by segments
...
@@ -156,22 +311,22 @@ void TransformRoundedEndsSegmentToPolygon( std::vector <wxPoint>& aCornerBuffer,
...
@@ -156,22 +311,22 @@ void TransformRoundedEndsSegmentToPolygon( std::vector <wxPoint>& aCornerBuffer,
* clearance when the circle is approxiamted by segment bigger or equal
* clearance when the circle is approxiamted by segment bigger or equal
* to the real clearance value (usually near from 1.0)
* to the real clearance value (usually near from 1.0)
*/
*/
void
D_PAD
::
TransformPadWithClearanceToPolygon
(
std
::
vector
<
wxPoin
t
>&
aCornerBuffer
,
void
D_PAD
::
TransformShapeWithClearanceToPolygon
(
std
::
vector
<
CPolyP
t
>&
aCornerBuffer
,
int
aClearanceValue
,
int
aClearanceValue
,
int
aCircleToSegmentsCount
,
int
aCircleToSegmentsCount
,
double
aCorrectionFactor
)
double
aCorrectionFactor
)
{
{
wxPoint
corner_position
;
wxPoint
corner_position
;
int
ii
,
angle
;
int
ii
,
angle
;
int
dx
=
(
m_Size
.
x
/
2
)
+
aClearanceValue
;
int
dx
=
(
m_Size
.
x
/
2
)
+
aClearanceValue
;
int
dy
=
(
m_Size
.
y
/
2
)
+
aClearanceValue
;
int
dy
=
(
m_Size
.
y
/
2
)
+
aClearanceValue
;
int
delta
=
3600
/
aCircleToSegmentsCount
;
// rot angle in 0.1 degree
int
delta
=
3600
/
aCircleToSegmentsCount
;
// rot angle in 0.1 degree
wxPoint
PadShapePos
=
ReturnShapePos
();
/* Note: for pad having a shape offset,
wxPoint
PadShapePos
=
ReturnShapePos
();
/* Note: for pad having a shape offset,
* the pad position is NOT the shape position */
* the pad position is NOT the shape position */
wxSize
psize
=
m_Size
;
/* pad size unsed in RECT and TRAPEZOIDAL pads
wxSize
psize
=
m_Size
;
/* pad size unsed in RECT and TRAPEZOIDAL pads
* trapezoidal pads are considered as rect pad shape having they boudary box size
* trapezoidal pads are considered as rect pad shape having they boudary box size
*/
*/
switch
(
m_PadShape
)
switch
(
m_PadShape
)
{
{
...
@@ -180,52 +335,63 @@ void D_PAD::TransformPadWithClearanceToPolygon( std::vector <wxPoint>& aCornerBu
...
@@ -180,52 +335,63 @@ void D_PAD::TransformPadWithClearanceToPolygon( std::vector <wxPoint>& aCornerBu
for
(
ii
=
0
;
ii
<
aCircleToSegmentsCount
;
ii
++
)
for
(
ii
=
0
;
ii
<
aCircleToSegmentsCount
;
ii
++
)
{
{
corner_position
=
wxPoint
(
dx
,
0
);
corner_position
=
wxPoint
(
dx
,
0
);
RotatePoint
(
&
corner_position
,
(
1800
/
aCircleToSegmentsCount
)
);
// Half increment offset to get more space between
RotatePoint
(
&
corner_position
,
(
1800
/
aCircleToSegmentsCount
)
);
// Half increment offset to get more space between
angle
=
ii
*
delta
;
angle
=
ii
*
delta
;
RotatePoint
(
&
corner_position
,
angle
);
RotatePoint
(
&
corner_position
,
angle
);
corner_position
+=
PadShapePos
;
corner_position
+=
PadShapePos
;
aCornerBuffer
.
push_back
(
corner_position
);
CPolyPt
polypoint
(
corner_position
.
x
,
corner_position
.
y
);
aCornerBuffer
.
push_back
(
polypoint
);
}
}
aCornerBuffer
.
back
().
end_contour
=
true
;
break
;
break
;
case
PAD_OVAL
:
case
PAD_OVAL
:
angle
=
m_Orient
;
angle
=
m_Orient
;
if
(
dy
>
dx
)
// Oval pad X/Y ratio for choosing translation axles
if
(
dy
>
dx
)
// Oval pad X/Y ratio for choosing translation axles
{
{
dy
=
(
int
)
(
dy
*
aCorrectionFactor
);
dy
=
(
int
)
(
dy
*
aCorrectionFactor
);
int
angle_pg
;
// Polygon angle
int
angle_pg
;
// Polygon angle
wxPoint
shape_offset
=
wxPoint
(
0
,
(
dy
-
dx
)
);
wxPoint
shape_offset
=
wxPoint
(
0
,
dy
-
dx
);
RotatePoint
(
&
shape_offset
,
angle
);
// Rotating shape offset vector with component
RotatePoint
(
&
shape_offset
,
angle
);
// Rotating shape offset vector with component
for
(
ii
=
0
;
ii
<
aCircleToSegmentsCount
/
2
+
1
;
ii
++
)
// Half circle end cap...
for
(
ii
=
0
;
ii
<
aCircleToSegmentsCount
/
2
+
1
;
ii
++
)
// Half circle end cap...
{
{
corner_position
=
wxPoint
(
dx
,
0
);
// Coordinate translation +dx
corner_position
=
wxPoint
(
dx
,
0
);
// Coordinate translation +dx
RotatePoint
(
&
corner_position
,
(
1800
/
aCircleToSegmentsCount
)
);
RotatePoint
(
&
corner_position
,
(
1800
/
aCircleToSegmentsCount
)
);
RotatePoint
(
&
corner_position
,
angle
);
RotatePoint
(
&
corner_position
,
angle
);
angle_pg
=
ii
*
delta
;
angle_pg
=
ii
*
delta
;
RotatePoint
(
&
corner_position
,
angle_pg
);
RotatePoint
(
&
corner_position
,
angle_pg
);
corner_position
+=
PadShapePos
-
shape_offset
;
corner_position
+=
PadShapePos
-
shape_offset
;
aCornerBuffer
.
push_back
(
corner_position
);
CPolyPt
polypoint
(
corner_position
.
x
,
corner_position
.
y
);
aCornerBuffer
.
push_back
(
polypoint
);
}
}
for
(
ii
=
0
;
ii
<
aCircleToSegmentsCount
/
2
+
1
;
ii
++
)
// Second half circle end cap...
for
(
ii
=
0
;
ii
<
aCircleToSegmentsCount
/
2
+
1
;
ii
++
)
// Second half circle end cap...
{
{
corner_position
=
wxPoint
(
-
dx
,
0
);
// Coordinate translation -dx
corner_position
=
wxPoint
(
-
dx
,
0
);
// Coordinate translation -dx
RotatePoint
(
&
corner_position
,
(
1800
/
aCircleToSegmentsCount
)
);
RotatePoint
(
&
corner_position
,
(
1800
/
aCircleToSegmentsCount
)
);
RotatePoint
(
&
corner_position
,
angle
);
RotatePoint
(
&
corner_position
,
angle
);
angle_pg
=
ii
*
delta
;
angle_pg
=
ii
*
delta
;
RotatePoint
(
&
corner_position
,
angle_pg
);
RotatePoint
(
&
corner_position
,
angle_pg
);
corner_position
+=
PadShapePos
+
shape_offset
;
corner_position
+=
PadShapePos
+
shape_offset
;
aCornerBuffer
.
push_back
(
corner_position
);
CPolyPt
polypoint
(
corner_position
.
x
,
corner_position
.
y
);
aCornerBuffer
.
push_back
(
polypoint
);
}
}
aCornerBuffer
.
back
().
end_contour
=
true
;
break
;
break
;
}
}
else
//if( dy <= dx )
else
//if( dy <= dx )
{
{
dx
=
(
int
)
(
dx
*
aCorrectionFactor
);
dx
=
(
int
)
(
dx
*
aCorrectionFactor
);
int
angle_pg
;
// Polygon angle
int
angle_pg
;
// Polygon angle
wxPoint
shape_offset
=
wxPoint
(
(
dy
-
dx
),
0
);
wxPoint
shape_offset
=
wxPoint
(
(
dy
-
dx
),
0
);
RotatePoint
(
&
shape_offset
,
angle
);
RotatePoint
(
&
shape_offset
,
angle
);
...
@@ -237,7 +403,8 @@ void D_PAD::TransformPadWithClearanceToPolygon( std::vector <wxPoint>& aCornerBu
...
@@ -237,7 +403,8 @@ void D_PAD::TransformPadWithClearanceToPolygon( std::vector <wxPoint>& aCornerBu
angle_pg
=
ii
*
delta
;
angle_pg
=
ii
*
delta
;
RotatePoint
(
&
corner_position
,
angle_pg
);
RotatePoint
(
&
corner_position
,
angle_pg
);
corner_position
+=
PadShapePos
-
shape_offset
;
corner_position
+=
PadShapePos
-
shape_offset
;
aCornerBuffer
.
push_back
(
corner_position
);
CPolyPt
polypoint
(
corner_position
.
x
,
corner_position
.
y
);
aCornerBuffer
.
push_back
(
polypoint
);
}
}
for
(
ii
=
0
;
ii
<
aCircleToSegmentsCount
/
2
+
1
;
ii
++
)
for
(
ii
=
0
;
ii
<
aCircleToSegmentsCount
/
2
+
1
;
ii
++
)
...
@@ -248,9 +415,11 @@ void D_PAD::TransformPadWithClearanceToPolygon( std::vector <wxPoint>& aCornerBu
...
@@ -248,9 +415,11 @@ void D_PAD::TransformPadWithClearanceToPolygon( std::vector <wxPoint>& aCornerBu
angle_pg
=
ii
*
delta
;
angle_pg
=
ii
*
delta
;
RotatePoint
(
&
corner_position
,
angle_pg
);
RotatePoint
(
&
corner_position
,
angle_pg
);
corner_position
+=
PadShapePos
+
shape_offset
;
corner_position
+=
PadShapePos
+
shape_offset
;
aCornerBuffer
.
push_back
(
corner_position
);
CPolyPt
polypoint
(
corner_position
.
x
,
corner_position
.
y
);
aCornerBuffer
.
push_back
(
polypoint
);
}
}
aCornerBuffer
.
back
().
end_contour
=
true
;
break
;
break
;
}
}
...
@@ -260,21 +429,28 @@ void D_PAD::TransformPadWithClearanceToPolygon( std::vector <wxPoint>& aCornerBu
...
@@ -260,21 +429,28 @@ void D_PAD::TransformPadWithClearanceToPolygon( std::vector <wxPoint>& aCornerBu
psize
.
y
+=
ABS
(
m_DeltaSize
.
x
);
psize
.
y
+=
ABS
(
m_DeltaSize
.
x
);
// fall through
// fall through
case
PAD_RECT
:
// Easy implementation for rectangular cutouts with rounded corners // Easy implementation for rectangular cutouts with rounded corners
case
PAD_RECT
:
// Easy implementation for rectangular cutouts with rounded corners // Easy implementation for rectangular cutouts with rounded corners
angle
=
m_Orient
;
angle
=
m_Orient
;
int
rounding_radius
=
(
int
)
(
aClearanceValue
*
aCorrectionFactor
);
// Corner rounding radius
int
rounding_radius
=
(
int
)
(
aClearanceValue
*
aCorrectionFactor
);
// Corner rounding radius
int
angle_pg
;
// Polygon increment angle
int
angle_pg
;
// Polygon increment angle
for
(
int
i
=
0
;
i
<
aCircleToSegmentsCount
/
4
+
1
;
i
++
)
for
(
int
i
=
0
;
i
<
aCircleToSegmentsCount
/
4
+
1
;
i
++
)
{
{
corner_position
=
wxPoint
(
0
,
-
rounding_radius
);
corner_position
=
wxPoint
(
0
,
-
rounding_radius
);
RotatePoint
(
&
corner_position
,
(
1800
/
aCircleToSegmentsCount
)
);
// Start at half increment offset
RotatePoint
(
&
corner_position
,
(
1800
/
aCircleToSegmentsCount
)
);
// Start at half increment offset
angle_pg
=
i
*
delta
;
angle_pg
=
i
*
delta
;
RotatePoint
(
&
corner_position
,
angle_pg
);
// Rounding vector rotation
RotatePoint
(
&
corner_position
,
angle_pg
);
corner_position
-=
psize
/
2
;
// Rounding vector + Pad corner offset
RotatePoint
(
&
corner_position
,
angle
);
// Rotate according to module orientation
// Rounding vector rotation
corner_position
+=
PadShapePos
;
// Shift origin to position
corner_position
-=
psize
/
2
;
// Rounding vector + Pad corner offset
aCornerBuffer
.
push_back
(
corner_position
);
RotatePoint
(
&
corner_position
,
angle
);
// Rotate according to module orientation
corner_position
+=
PadShapePos
;
// Shift origin to position
CPolyPt
polypoint
(
corner_position
.
x
,
corner_position
.
y
);
aCornerBuffer
.
push_back
(
polypoint
);
}
}
for
(
int
i
=
0
;
i
<
aCircleToSegmentsCount
/
4
+
1
;
i
++
)
for
(
int
i
=
0
;
i
<
aCircleToSegmentsCount
/
4
+
1
;
i
++
)
...
@@ -286,10 +462,13 @@ void D_PAD::TransformPadWithClearanceToPolygon( std::vector <wxPoint>& aCornerBu
...
@@ -286,10 +462,13 @@ void D_PAD::TransformPadWithClearanceToPolygon( std::vector <wxPoint>& aCornerBu
corner_position
-=
wxPoint
(
psize
.
x
/
2
,
-
psize
.
y
/
2
);
corner_position
-=
wxPoint
(
psize
.
x
/
2
,
-
psize
.
y
/
2
);
RotatePoint
(
&
corner_position
,
angle
);
RotatePoint
(
&
corner_position
,
angle
);
corner_position
+=
PadShapePos
;
corner_position
+=
PadShapePos
;
aCornerBuffer
.
push_back
(
corner_position
);
CPolyPt
polypoint
(
corner_position
.
x
,
corner_position
.
y
);
aCornerBuffer
.
push_back
(
polypoint
);
}
}
for
(
int
i
=
0
;
i
<
aCircleToSegmentsCount
/
4
+
1
;
i
++
)
for
(
int
i
=
0
;
i
<
aCircleToSegmentsCount
/
4
+
1
;
i
++
)
{
{
corner_position
=
wxPoint
(
0
,
rounding_radius
);
corner_position
=
wxPoint
(
0
,
rounding_radius
);
RotatePoint
(
&
corner_position
,
(
1800
/
aCircleToSegmentsCount
)
);
RotatePoint
(
&
corner_position
,
(
1800
/
aCircleToSegmentsCount
)
);
...
@@ -298,7 +477,8 @@ void D_PAD::TransformPadWithClearanceToPolygon( std::vector <wxPoint>& aCornerBu
...
@@ -298,7 +477,8 @@ void D_PAD::TransformPadWithClearanceToPolygon( std::vector <wxPoint>& aCornerBu
corner_position
+=
psize
/
2
;
corner_position
+=
psize
/
2
;
RotatePoint
(
&
corner_position
,
angle
);
RotatePoint
(
&
corner_position
,
angle
);
corner_position
+=
PadShapePos
;
corner_position
+=
PadShapePos
;
aCornerBuffer
.
push_back
(
corner_position
);
CPolyPt
polypoint
(
corner_position
.
x
,
corner_position
.
y
);
aCornerBuffer
.
push_back
(
polypoint
);
}
}
for
(
int
i
=
0
;
i
<
aCircleToSegmentsCount
/
4
+
1
;
i
++
)
for
(
int
i
=
0
;
i
<
aCircleToSegmentsCount
/
4
+
1
;
i
++
)
...
@@ -310,9 +490,398 @@ void D_PAD::TransformPadWithClearanceToPolygon( std::vector <wxPoint>& aCornerBu
...
@@ -310,9 +490,398 @@ void D_PAD::TransformPadWithClearanceToPolygon( std::vector <wxPoint>& aCornerBu
corner_position
-=
wxPoint
(
-
psize
.
x
/
2
,
psize
.
y
/
2
);
corner_position
-=
wxPoint
(
-
psize
.
x
/
2
,
psize
.
y
/
2
);
RotatePoint
(
&
corner_position
,
angle
);
RotatePoint
(
&
corner_position
,
angle
);
corner_position
+=
PadShapePos
;
corner_position
+=
PadShapePos
;
aCornerBuffer
.
push_back
(
corner_position
);
CPolyPt
polypoint
(
corner_position
.
x
,
corner_position
.
y
);
aCornerBuffer
.
push_back
(
polypoint
);
}
}
aCornerBuffer
.
back
().
end_contour
=
true
;
break
;
break
;
}
}
}
}
/** function CreateThermalReliefPadPolygon
* Add holes around a pad to create a thermal relief
* copper thickness is min (dx/2, aCopperWitdh) or min (dy/2, aCopperWitdh)
* @param aCornerBuffer = a buffer to store the polygon
* @param aPad = the current pad used to create the thermal shape
* @param aThermalGap = gap in thermal shape
* @param aMinThicknessValue = min copper thickness allowed
* @param aCircleToSegmentsCount = the number of segments to approximate a circle
* @param aCorrectionFactor = the correction to apply to circles radius to keep
* @param aThermalRot = for rond pads the rotation of thermal stubs (450 usually for 45 deg.)
*/
/* thermal reliefs are created as 4 polygons.
* each corner of a polygon if calculated for a pad at position 0, 0, orient 0,
* and then moved and rotated acroding to the pad position and orientation
*/
/* WARNING:
* When Kbool calculates the filled areas :
* i.e when substracting holes (thermal shapes) to the full zone area
* under certains circumstances kboll drop some holes.
* These circumstances are:
* some identical holes (same thermal shape and size) are *exactly* on the same vertical line
* And
* nothing else between holes
* And
* angles less than 90 deg between 2 consecutive lines in hole outline (sometime occurs without this condition)
* And
* a hole above the identical holes
*
* In fact, it is easy to find these conditions in pad arrays.
* So to avoid this, the workaround is do not use holes outlines that include
* angles less than 90 deg between 2 consecutive lines
* this is made in round and oblong thermal reliefs
*
* Note 1: polygons are drawm using outlines witk a thickness = aMinThicknessValue
* so shapes must keep in account this outline thickness
*
* Note 2:
* Trapezoidal pads are not considered here because they are very special case
* and are used in microwave applications and they *DO NOT* have a thermal relief that change the shape
* by creating stubs and destroy their properties.
*/
void
CreateThermalReliefPadPolygon
(
std
::
vector
<
CPolyPt
>&
aCornerBuffer
,
D_PAD
&
aPad
,
int
aThermalGap
,
int
aCopperThickness
,
int
aMinThicknessValue
,
int
aCircleToSegmentsCount
,
double
aCorrectionFactor
,
int
aThermalRot
)
{
wxPoint
corner
,
corner_end
;
wxPoint
PadShapePos
=
aPad
.
ReturnShapePos
();
/* Note: for pad having a shape offset,
* the pad position is NOT the shape position */
wxSize
copper_thickness
;
int
dx
=
aPad
.
m_Size
.
x
/
2
;
int
dy
=
aPad
.
m_Size
.
y
/
2
;
int
delta
=
3600
/
aCircleToSegmentsCount
;
// rot angle in 0.1 degree
/* Keep in account the polygon outline thickness
* aThermalGap must be increased by aMinThicknessValue/2 because drawing external outline
* with a thickness of aMinThicknessValue will reduce gap by aMinThicknessValue/2
*/
aThermalGap
+=
aMinThicknessValue
/
2
;
/* Keep in account the polygon outline thickness
* copper_thickness must be decreased by aMinThicknessValue because drawing outlines
* with a thickness of aMinThicknessValue will increase real thickness by aMinThicknessValue
*/
aCopperThickness
-=
aMinThicknessValue
;
if
(
aCopperThickness
<
0
)
aCopperThickness
=
0
;
copper_thickness
.
x
=
min
(
dx
,
aCopperThickness
);
copper_thickness
.
y
=
min
(
dy
,
aCopperThickness
);
switch
(
aPad
.
m_PadShape
)
{
case
PAD_CIRCLE
:
// Add 4 similar holes
{
/* we create 4 copper holes and put them in position 1, 2, 3 and 4
* here is the area of the rectangular pad + its thermal gap
* the 4 copper holes remove the copper in order to create the thermal gap
* 4 ------ 1
* | |
* | |
* | |
* | |
* 3 ------ 2
* holes 2, 3, 4 are the same as hole 1, rotated 90, 180, 270 deg
*/
// Build the hole pattern, for the hole in the X >0, Y > 0 plane:
// The pattern roughtly is a 90 deg arc pie
std
::
vector
<
wxPoint
>
corners_buffer
;
// Radius of outer arcs of the shape:
int
outer_radius
=
dx
+
aThermalGap
;
// The radius of the outer arc is pad radius + aThermalGap
// Crosspoint of thermal spoke sides, the first point of polygon buffer
corners_buffer
.
push_back
(
wxPoint
(
copper_thickness
.
x
/
2
,
copper_thickness
.
y
/
2
)
);
// Add an intermediate point on spoke sides, to allow a > 90 deg angle between side and first seg of arc approx
corner
.
x
=
copper_thickness
.
x
/
2
;
int
y
=
outer_radius
-
(
aThermalGap
/
4
);
corner
.
y
=
(
int
)
sqrt
(
(
(
(
double
)
y
*
y
)
-
(
double
)
corner
.
x
*
corner
.
x
)
);
if
(
aThermalRot
!=
0
)
corners_buffer
.
push_back
(
corner
);
// calculate the starting point of the outter arc
corner
.
x
=
copper_thickness
.
x
/
2
;
double
dtmp
=
sqrt
(
(
(
double
)
outer_radius
*
outer_radius
)
-
(
(
double
)
corner
.
x
*
corner
.
x
)
);
corner
.
y
=
(
int
)
dtmp
;
RotatePoint
(
&
corner
,
90
);
// calculate the ending point of the outter arc
corner_end
.
x
=
corner
.
y
;
corner_end
.
y
=
corner
.
x
;
// calculate intermediate points (y coordinate from corner.y to corner_end.y
while
(
(
corner
.
y
>
corner_end
.
y
)
&&
(
corner
.
x
<
corner_end
.
x
)
)
{
corners_buffer
.
push_back
(
corner
);
RotatePoint
(
&
corner
,
delta
);
}
corners_buffer
.
push_back
(
corner_end
);
/* add an intermediate point, to avoid angles < 90 deg between last arc approx line and radius line
*/
corner
.
x
=
corners_buffer
[
1
].
y
;
corner
.
y
=
corners_buffer
[
1
].
x
;
corners_buffer
.
push_back
(
corner
);
// Now, add the 4 holes ( each is the pattern, rotated by 0, 90, 180 and 270 deg
// WARNING: problems with kbool if angle = 0 (in fact when angle < 200):
// bad filled polygon on some cases, when pads are on a same vertical line
// this seems a bug in kbool polygon (exists in 2.0 kbool version)
// aThermalRot = 450 (45.0 degrees orientation) seems work fine.
// aThermalRot = 0 with thermal shapes without angle < 90 deg has problems in rare circumstances
// Note: with the 2 step build ( thermal shapes added after areas are built), 0 seems work
int
angle_pad
=
aPad
.
m_Orient
;
// Pad orientation
int
th_angle
=
aThermalRot
;
for
(
unsigned
ihole
=
0
;
ihole
<
4
;
ihole
++
)
{
for
(
unsigned
ii
=
0
;
ii
<
corners_buffer
.
size
();
ii
++
)
{
corner
=
corners_buffer
[
ii
];
RotatePoint
(
&
corner
,
th_angle
+
angle_pad
);
// Rotate by segment angle and pad orientation
corner
+=
PadShapePos
;
aCornerBuffer
.
push_back
(
CPolyPt
(
corner
.
x
,
corner
.
y
)
);
}
aCornerBuffer
.
back
().
end_contour
=
true
;
th_angle
+=
900
;
// Note: th_angle in in 0.1 deg.
}
}
break
;
case
PAD_OVAL
:
{
// Oval pad support along the lines of round and rectangular pads
std
::
vector
<
wxPoint
>
corners_buffer
;
// Polygon buffer as vector
int
dx
=
(
aPad
.
m_Size
.
x
/
2
)
+
aThermalGap
;
// Cutout radius x
int
dy
=
(
aPad
.
m_Size
.
y
/
2
)
+
aThermalGap
;
// Cutout radius y
wxPoint
shape_offset
;
// We want to calculate an oval shape with dx > dy.
// if this is not the case, exchange dx and dy, and rotate the shape 90 deg.
int
supp_angle
=
0
;
if
(
dx
<
dy
)
{
EXCHG
(
dx
,
dy
);
supp_angle
=
900
;
EXCHG
(
copper_thickness
.
x
,
copper_thickness
.
y
);
}
int
deltasize
=
dx
-
dy
;
// = distance between shape position and the 2 demi-circle ends centre
// here we have dx > dy
// Radius of outer arcs of the shape:
int
outer_radius
=
dy
;
// The radius of the outer arc is radius end + aThermalGap
// Some coordinate fiddling, depending on the shape offset direction
shape_offset
=
wxPoint
(
deltasize
,
0
);
// Crosspoint of thermal spoke sides, the first point of polygon buffer
corners_buffer
.
push_back
(
wxPoint
(
copper_thickness
.
x
/
2
,
copper_thickness
.
y
/
2
)
);
// Arc start point calculation, the intersecting point of cutout arc and thermal spoke edge
if
(
copper_thickness
.
x
>
deltasize
)
// If copper thickness is more than shape offset, we need to calculate arc intercept point.
{
corner
.
x
=
copper_thickness
.
x
/
2
;
corner
.
y
=
(
int
)
sqrt
(
(
(
double
)
outer_radius
*
outer_radius
)
-
(
(
double
)
(
corner
.
x
-
delta
)
*
(
corner
.
x
-
deltasize
)
)
);
corner
.
x
-=
deltasize
;
/* creates an intermediate point, to have a > 90 deg angle
* between the side and the first segment of arc approximation
*/
wxPoint
intpoint
=
corner
;
intpoint
.
y
-=
aThermalGap
/
4
;
corners_buffer
.
push_back
(
intpoint
+
shape_offset
);
RotatePoint
(
&
corner
,
90
);
}
else
{
corner
.
x
=
copper_thickness
.
x
/
2
;
corner
.
y
=
outer_radius
;
corners_buffer
.
push_back
(
corner
);
corner
.
x
=
(
deltasize
-
copper_thickness
.
x
)
/
2
;
}
// Add an intermediate point on spoke sides, to allow a > 90 deg angle between side and first seg of arc approx
wxPoint
last_corner
;
last_corner
.
y
=
copper_thickness
.
y
/
2
;
int
px
=
outer_radius
-
(
aThermalGap
/
4
);
last_corner
.
x
=
(
int
)
sqrt
(
(
(
(
double
)
px
*
px
)
-
(
double
)
last_corner
.
y
*
last_corner
.
y
)
);
// Arc stop point calculation, the intersecting point of cutout arc and thermal spoke edge
corner_end
.
y
=
copper_thickness
.
y
/
2
;
corner_end
.
x
=
(
int
)
sqrt
(
(
(
double
)
outer_radius
*
outer_radius
)
-
(
(
double
)
corner_end
.
y
*
corner_end
.
y
)
);
RotatePoint
(
&
corner_end
,
-
90
);
// calculate intermediate arc points till limit is reached
while
(
(
corner
.
y
>
corner_end
.
y
)
&&
(
corner
.
x
<
corner_end
.
x
)
)
{
corners_buffer
.
push_back
(
corner
+
shape_offset
);
RotatePoint
(
&
corner
,
delta
);
}
//corners_buffer.push_back(corner + shape_offset); // TODO: about one mil geometry error forms somewhere.
corners_buffer
.
push_back
(
corner_end
+
shape_offset
);
corners_buffer
.
push_back
(
last_corner
+
shape_offset
);
// Enabling the line above shows intersection point.
/* Create 2 holes, rotated by pad rotation.
*/
int
angle
=
aPad
.
m_Orient
+
supp_angle
;
for
(
int
irect
=
0
;
irect
<
2
;
irect
++
)
{
for
(
unsigned
ic
=
0
;
ic
<
corners_buffer
.
size
();
ic
++
)
{
wxPoint
cpos
=
corners_buffer
[
ic
];
RotatePoint
(
&
cpos
,
angle
);
cpos
+=
PadShapePos
;
aCornerBuffer
.
push_back
(
CPolyPt
(
cpos
.
x
,
cpos
.
y
)
);
}
aCornerBuffer
.
back
().
end_contour
=
true
;;
angle
+=
1800
;
// this is calculate hole 3
if
(
angle
>=
3600
)
angle
-=
3600
;
}
// Create holes, that are the mirrored from the previous holes
for
(
unsigned
ic
=
0
;
ic
<
corners_buffer
.
size
();
ic
++
)
{
wxPoint
swap
=
corners_buffer
[
ic
];
swap
.
x
=
-
swap
.
x
;
corners_buffer
[
ic
]
=
swap
;
}
// Now add corner 4 and 2 (2 is the corner 4 rotated by 180 deg
angle
=
aPad
.
m_Orient
+
supp_angle
;
for
(
int
irect
=
0
;
irect
<
2
;
irect
++
)
{
for
(
unsigned
ic
=
0
;
ic
<
corners_buffer
.
size
();
ic
++
)
{
wxPoint
cpos
=
corners_buffer
[
ic
];
RotatePoint
(
&
cpos
,
angle
);
cpos
+=
PadShapePos
;
aCornerBuffer
.
push_back
(
CPolyPt
(
cpos
.
x
,
cpos
.
y
)
);
}
aCornerBuffer
.
back
().
end_contour
=
true
;
angle
+=
1800
;
if
(
angle
>=
3600
)
angle
-=
3600
;
}
}
break
;
case
PAD_RECT
:
// draw 4 Holes
{
/* we create 4 copper holes and put them in position 1, 2, 3 and 4
* here is the area of the rectangular pad + its thermal gap
* the 4 copper holes remove the copper in order to create the thermal gap
* 4 ------ 1
* | |
* | |
* | |
* | |
* 3 ------ 2
* hole 3 is the same as hole 1, rotated 180 deg
* hole 4 is the same as hole 2, rotated 180 deg and is the same as hole 1, mirrored
*/
// First, create a rectangular hole for position 1 :
// 2 ------- 3
// | |
// | |
// | |
// 1 -------4
// Modified rectangles with one corner rounded. TODO: merging with oval thermals and possibly round too.
std
::
vector
<
wxPoint
>
corners_buffer
;
// Polygon buffer as vector
int
dx
=
(
aPad
.
m_Size
.
x
/
2
)
+
aThermalGap
;
// Cutout radius x
int
dy
=
(
aPad
.
m_Size
.
y
/
2
)
+
aThermalGap
;
// Cutout radius y
// The first point of polygon buffer is left lower corner, second the crosspoint of thermal spoke sides,
// the third is upper right corner and the rest are rounding vertices going anticlockwise. Note the inveted Y-axis in CG.
corners_buffer
.
push_back
(
wxPoint
(
-
dx
,
-
(
aThermalGap
/
4
+
copper_thickness
.
y
/
2
)
)
);
// Adds small miters to zone
corners_buffer
.
push_back
(
wxPoint
(
-
(
dx
-
aThermalGap
/
4
),
-
copper_thickness
.
y
/
2
)
);
// fill and spoke corner
corners_buffer
.
push_back
(
wxPoint
(
-
copper_thickness
.
x
/
2
,
-
copper_thickness
.
y
/
2
)
);
corners_buffer
.
push_back
(
wxPoint
(
-
copper_thickness
.
x
/
2
,
-
(
dy
-
aThermalGap
/
4
)
)
);
corners_buffer
.
push_back
(
wxPoint
(
-
(
aThermalGap
/
4
+
copper_thickness
.
x
/
2
),
-
dy
)
);
int
angle
=
aPad
.
m_Orient
;
int
rounding_radius
=
(
int
)
(
aThermalGap
*
aCorrectionFactor
);
// Corner rounding radius
int
angle_pg
;
// Polygon increment angle
for
(
int
i
=
0
;
i
<
aCircleToSegmentsCount
/
4
+
1
;
i
++
)
{
wxPoint
corner_position
=
wxPoint
(
0
,
-
rounding_radius
);
RotatePoint
(
&
corner_position
,
1800
/
aCircleToSegmentsCount
);
// Start at half increment offset
angle_pg
=
i
*
delta
;
RotatePoint
(
&
corner_position
,
angle_pg
);
// Rounding vector rotation
corner_position
-=
aPad
.
m_Size
/
2
;
// Rounding vector + Pad corner offset
corners_buffer
.
push_back
(
wxPoint
(
corner_position
.
x
,
corner_position
.
y
)
);
}
for
(
int
irect
=
0
;
irect
<
2
;
irect
++
)
{
for
(
unsigned
ic
=
0
;
ic
<
corners_buffer
.
size
();
ic
++
)
{
wxPoint
cpos
=
corners_buffer
[
ic
];
RotatePoint
(
&
cpos
,
angle
);
// Rotate according to module orientation
cpos
+=
PadShapePos
;
// Shift origin to position
aCornerBuffer
.
push_back
(
CPolyPt
(
cpos
.
x
,
cpos
.
y
)
);
}
aCornerBuffer
.
back
().
end_contour
=
true
;
angle
+=
1800
;
// this is calculate hole 3
if
(
angle
>=
3600
)
angle
-=
3600
;
}
// Create holes, that are the mirrored from the previous holes
for
(
unsigned
ic
=
0
;
ic
<
corners_buffer
.
size
();
ic
++
)
{
wxPoint
swap
=
corners_buffer
[
ic
];
swap
.
x
=
-
swap
.
x
;
corners_buffer
[
ic
]
=
swap
;
}
// Now add corner 4 and 2 (2 is the corner 4 rotated by 180 deg
for
(
int
irect
=
0
;
irect
<
2
;
irect
++
)
{
for
(
unsigned
ic
=
0
;
ic
<
corners_buffer
.
size
();
ic
++
)
{
wxPoint
cpos
=
corners_buffer
[
ic
];
RotatePoint
(
&
cpos
,
angle
);
cpos
+=
PadShapePos
;
aCornerBuffer
.
push_back
(
CPolyPt
(
cpos
.
x
,
cpos
.
y
)
);
}
aCornerBuffer
.
back
().
end_contour
=
true
;
angle
+=
1800
;
if
(
angle
>=
3600
)
angle
-=
3600
;
}
break
;
}
}
}
pcbnew/class_drawsegment.h
View file @
f2f4cd53
...
@@ -4,6 +4,7 @@
...
@@ -4,6 +4,7 @@
#ifndef CLASS_DRAWSEGMENT_H
#ifndef CLASS_DRAWSEGMENT_H
#define CLASS_DRAWSEGMENT_H
#define CLASS_DRAWSEGMENT_H
#include "polyline.h"
class
DRAWSEGMENT
:
public
BOARD_ITEM
class
DRAWSEGMENT
:
public
BOARD_ITEM
{
{
...
@@ -15,8 +16,8 @@ public:
...
@@ -15,8 +16,8 @@ public:
int
m_Shape
;
// Shape: line, Circle, Arc
int
m_Shape
;
// Shape: line, Circle, Arc
int
m_Type
;
// Used in complex associations ( Dimensions.. )
int
m_Type
;
// Used in complex associations ( Dimensions.. )
int
m_Angle
;
// Used only for Arcs: Arc angle in 1/10 deg
int
m_Angle
;
// Used only for Arcs: Arc angle in 1/10 deg
wxPoint
m_BezierC1
;
// Bezier Control Point 1
wxPoint
m_BezierC1
;
// Bezier Control Point 1
wxPoint
m_BezierC2
;
// Bezier Control Point 1
wxPoint
m_BezierC2
;
// Bezier Control Point 1
std
::
vector
<
wxPoint
>
m_BezierPoints
;
std
::
vector
<
wxPoint
>
m_BezierPoints
;
public
:
public
:
...
@@ -42,13 +43,13 @@ public:
...
@@ -42,13 +43,13 @@ public:
* Function GetStart
* Function GetStart
* returns the starting point of the graphic
* returns the starting point of the graphic
*/
*/
wxPoint
GetStart
()
const
;
wxPoint
GetStart
()
const
;
/**
/**
* Function GetEnd
* Function GetEnd
* returns the ending point of the graphic
* returns the ending point of the graphic
*/
*/
wxPoint
GetEnd
()
const
;
wxPoint
GetEnd
()
const
;
/**
/**
* Function Save
* Function Save
...
@@ -56,15 +57,15 @@ public:
...
@@ -56,15 +57,15 @@ public:
* @param aFile The FILE to write to.
* @param aFile The FILE to write to.
* @return bool - true if success writing else false.
* @return bool - true if success writing else false.
*/
*/
bool
Save
(
FILE
*
aFile
)
const
;
bool
Save
(
FILE
*
aFile
)
const
;
bool
ReadDrawSegmentDescr
(
FILE
*
File
,
int
*
LineNum
);
bool
ReadDrawSegmentDescr
(
FILE
*
File
,
int
*
LineNum
);
void
Copy
(
DRAWSEGMENT
*
source
);
void
Copy
(
DRAWSEGMENT
*
source
);
void
Draw
(
WinEDA_DrawPanel
*
panel
,
wxDC
*
DC
,
void
Draw
(
WinEDA_DrawPanel
*
panel
,
wxDC
*
DC
,
int
aDrawMode
,
const
wxPoint
&
offset
=
ZeroOffset
);
int
aDrawMode
,
const
wxPoint
&
offset
=
ZeroOffset
);
/**
/**
* Function DisplayInfo
* Function DisplayInfo
...
@@ -73,7 +74,7 @@ public:
...
@@ -73,7 +74,7 @@ public:
* Is virtual from EDA_BaseStruct.
* Is virtual from EDA_BaseStruct.
* @param frame A WinEDA_BasePcbFrame in which to print status information.
* @param frame A WinEDA_BasePcbFrame in which to print status information.
*/
*/
virtual
void
DisplayInfo
(
WinEDA_DrawFrame
*
frame
);
virtual
void
DisplayInfo
(
WinEDA_DrawFrame
*
frame
);
/**
/**
...
@@ -82,7 +83,7 @@ public:
...
@@ -82,7 +83,7 @@ public:
* @param ref_pos A wxPoint to test
* @param ref_pos A wxPoint to test
* @return bool - true if a hit, else false
* @return bool - true if a hit, else false
*/
*/
bool
HitTest
(
const
wxPoint
&
ref_pos
);
bool
HitTest
(
const
wxPoint
&
ref_pos
);
/**
/**
* Function HitTest (overlayed)
* Function HitTest (overlayed)
...
@@ -91,7 +92,7 @@ public:
...
@@ -91,7 +92,7 @@ public:
* @param refPos the given EDA_Rect to test
* @param refPos the given EDA_Rect to test
* @return bool - true if a hit, else false
* @return bool - true if a hit, else false
*/
*/
bool
HitTest
(
EDA_Rect
&
refArea
);
bool
HitTest
(
EDA_Rect
&
refArea
);
/**
/**
* Function GetClass
* Function GetClass
...
@@ -116,36 +117,56 @@ public:
...
@@ -116,36 +117,56 @@ public:
return
hypot
(
delta
.
x
,
delta
.
y
);
return
hypot
(
delta
.
x
,
delta
.
y
);
}
}
/**
/**
* Function Move
* Function Move
* move this object.
* move this object.
* @param const wxPoint& aMoveVector - the move vector for this object.
* @param const wxPoint& aMoveVector - the move vector for this object.
*/
*/
virtual
void
Move
(
const
wxPoint
&
aMoveVector
)
virtual
void
Move
(
const
wxPoint
&
aMoveVector
)
{
{
m_Start
+=
aMoveVector
;
m_Start
+=
aMoveVector
;
m_End
+=
aMoveVector
;
m_End
+=
aMoveVector
;
}
}
/**
/**
* Function Rotate
* Function Rotate
* Rotate this object.
* Rotate this object.
* @param const wxPoint& aRotCentre - the rotation point.
* @param const wxPoint& aRotCentre - the rotation point.
* @param aAngle - the rotation angle in 0.1 degree.
* @param aAngle - the rotation angle in 0.1 degree.
*/
*/
virtual
void
Rotate
(
const
wxPoint
&
aRotCentre
,
int
aAngle
);
virtual
void
Rotate
(
const
wxPoint
&
aRotCentre
,
int
aAngle
);
/**
/**
* Function Flip
* Function Flip
* Flip this object, i.e. change the board side for this object
* Flip this object, i.e. change the board side for this object
* @param const wxPoint& aCentre - the rotation point.
* @param const wxPoint& aCentre - the rotation point.
*/
*/
virtual
void
Flip
(
const
wxPoint
&
aCentre
);
virtual
void
Flip
(
const
wxPoint
&
aCentre
);
/** Function TransformShapeWithClearanceToPolygon
* Convert the track shape to a closed polygon
* Used in filling zones calculations
* Circles and arcs are approximated by segments
* @param aCornerBuffer = a buffer to store the polygon
* @param aClearanceValue = the clearance around the pad
* @param aCircleToSegmentsCount = the number of segments to approximate a circle
* @param aCorrectionFactor = the correction to apply to circles radius to keep
* clearance when the circle is approxiamted by segment bigger or equal
* to the real clearance value (usually near from 1.0)
*/
void
TransformShapeWithClearanceToPolygon
(
std
::
vector
<
CPolyPt
>&
aCornerBuffer
,
int
aClearanceValue
,
int
aCircleToSegmentsCount
,
double
aCorrectionFactor
);
#if defined(DEBUG)
#if defined(DEBUG)
void
Show
(
int
nestLevel
,
std
::
ostream
&
os
);
void
Show
(
int
nestLevel
,
std
::
ostream
&
os
);
#endif
#endif
};
};
...
...
pcbnew/class_pad.h
View file @
f2f4cd53
...
@@ -5,6 +5,7 @@
...
@@ -5,6 +5,7 @@
class
Pcb3D_GLCanvas
;
class
Pcb3D_GLCanvas
;
#include "pad_shapes.h"
#include "pad_shapes.h"
#include "polyline.h"
/* Default layers used for pads, according to the pad type.
/* Default layers used for pads, according to the pad type.
* this is default values only, they can be changed for a given pad
* this is default values only, they can be changed for a given pad
...
@@ -141,7 +142,7 @@ public:
...
@@ -141,7 +142,7 @@ public:
m_Pos
=
aPos
;
m_Pos
=
aPos
;
}
}
/** function Transform
Pad
WithClearanceToPolygon
/** function Transform
Shape
WithClearanceToPolygon
* Convert the pad shape to a closed polygon
* Convert the pad shape to a closed polygon
* Used in filling zones calculations
* Used in filling zones calculations
* Circles and arcs are approximated by segments
* Circles and arcs are approximated by segments
...
@@ -152,7 +153,7 @@ public:
...
@@ -152,7 +153,7 @@ public:
* clearance when the circle is approxiamted by segment bigger or equal
* clearance when the circle is approxiamted by segment bigger or equal
* to the real clearance value (usually near from 1.0)
* to the real clearance value (usually near from 1.0)
*/
*/
void
Transform
PadWithClearanceToPolygon
(
std
::
vector
<
wxPoin
t
>&
aCornerBuffer
,
void
Transform
ShapeWithClearanceToPolygon
(
std
::
vector
<
CPolyP
t
>&
aCornerBuffer
,
int
aClearanceValue
,
int
aCircleToSegmentsCount
,
double
aCorrectionFactor
);
int
aClearanceValue
,
int
aCircleToSegmentsCount
,
double
aCorrectionFactor
);
/**
/**
...
...
pcbnew/class_pcb_text.h
View file @
f2f4cd53
...
@@ -5,6 +5,7 @@
...
@@ -5,6 +5,7 @@
#define CLASS_PCB_TEXT_H
#define CLASS_PCB_TEXT_H
#include "base_struct.h"
#include "base_struct.h"
#include "polyline.h"
class
TEXTE_PCB
:
public
BOARD_ITEM
,
public
EDA_TextStruct
class
TEXTE_PCB
:
public
BOARD_ITEM
,
public
EDA_TextStruct
{
{
...
@@ -110,6 +111,23 @@ public:
...
@@ -110,6 +111,23 @@ public:
return
wxT
(
"PTEXT"
);
return
wxT
(
"PTEXT"
);
}
}
/** Function TransformShapeWithClearanceToPolygon
* Convert the track shape to a closed polygon
* Used in filling zones calculations
* Circles and arcs are approximated by segments
* @param aCornerBuffer = a buffer to store the polygon
* @param aClearanceValue = the clearance around the pad
* @param aCircleToSegmentsCount = the number of segments to approximate a circle
* @param aCorrectionFactor = the correction to apply to circles radius to keep
* clearance when the circle is approximated by segment bigger or equal
* to the real clearance value (usually near from 1.0)
*/
void
TransformShapeWithClearanceToPolygon
(
std
::
vector
<
CPolyPt
>&
aCornerBuffer
,
int
aClearanceValue
,
int
aCircleToSegmentsCount
,
double
aCorrectionFactor
);
#if defined(DEBUG)
#if defined(DEBUG)
/**
/**
* Function Show
* Function Show
...
...
pcbnew/class_track.h
View file @
f2f4cd53
...
@@ -6,6 +6,7 @@
...
@@ -6,6 +6,7 @@
#define CLASS_TRACK_H
#define CLASS_TRACK_H
#include "base_struct.h"
#include "base_struct.h"
#include "polyline.h"
// Via attributes (m_Shape parmeter)
// Via attributes (m_Shape parmeter)
...
@@ -148,7 +149,7 @@ public:
...
@@ -148,7 +149,7 @@ public:
/* divers */
/* divers */
int
Shape
()
const
{
return
m_Shape
&
0xFF
;
}
int
Shape
()
const
{
return
m_Shape
&
0xFF
;
}
/** Function Transform
Track
WithClearanceToPolygon
/** Function Transform
Shape
WithClearanceToPolygon
* Convert the track shape to a closed polygon
* Convert the track shape to a closed polygon
* Used in filling zones calculations
* Used in filling zones calculations
* Circles (vias) and arcs (ends of tracks) are approximated by segments
* Circles (vias) and arcs (ends of tracks) are approximated by segments
...
@@ -159,7 +160,7 @@ public:
...
@@ -159,7 +160,7 @@ public:
* clearance when the circle is approxiamted by segment bigger or equal
* clearance when the circle is approxiamted by segment bigger or equal
* to the real clearance value (usually near from 1.0)
* to the real clearance value (usually near from 1.0)
*/
*/
void
Transform
TrackWithClearanceToPolygon
(
std
::
vector
<
wxPoin
t
>&
aCornerBuffer
,
void
Transform
ShapeWithClearanceToPolygon
(
std
::
vector
<
CPolyP
t
>&
aCornerBuffer
,
int
aClearanceValue
,
int
aClearanceValue
,
int
aCircleToSegmentsCount
,
int
aCircleToSegmentsCount
,
double
aCorrectionFactor
);
double
aCorrectionFactor
);
...
...
pcbnew/debug_kbool_key_file_fct.cpp
View file @
f2f4cd53
...
@@ -14,9 +14,15 @@
...
@@ -14,9 +14,15 @@
#if defined (CREATE_KBOOL_KEY_FILES) || (CREATE_KBOOL_KEY_FILES_FIRST_PASS)
#if defined (CREATE_KBOOL_KEY_FILES) || (CREATE_KBOOL_KEY_FILES_FIRST_PASS)
// Helper class to handle a coordinate
struct
kfcoord
{
int
x
,
y
;
};
static
FILE
*
kdebugFile
;
static
FILE
*
kdebugFile
;
static
char
sDate_Time
[
256
];
static
char
sDate_Time
[
256
];
static
vector
<
kfcoord
>
s_EntityCoordinates
;
void
CreateKeyFile
()
void
CreateKeyFile
()
{
{
...
@@ -48,6 +54,8 @@ void CreateKeyFile()
...
@@ -48,6 +54,8 @@ void CreateKeyFile()
{
{
wxMessageBox
(
wxT
(
"CreateKeyFile() cannot create output file"
)
);
wxMessageBox
(
wxT
(
"CreateKeyFile() cannot create output file"
)
);
}
}
s_EntityCoordinates
.
clear
();
}
}
...
@@ -58,11 +66,11 @@ void CloseKeyFile()
...
@@ -58,11 +66,11 @@ void CloseKeyFile()
fprintf
(
kdebugFile
,
"
\n
ENDLIB;
\n
"
);
fprintf
(
kdebugFile
,
"
\n
ENDLIB;
\n
"
);
fclose
(
kdebugFile
);
fclose
(
kdebugFile
);
}
}
s_EntityCoordinates
.
clear
();
}
}
const
char
*
sCurrEntityName
=
NULL
;
const
char
*
sCurrEntityName
=
NULL
;
static
int
s_count
;
void
OpenKeyFileEntity
(
const
char
*
aName
)
void
OpenKeyFileEntity
(
const
char
*
aName
)
{
{
...
@@ -74,7 +82,7 @@ void OpenKeyFileEntity( const char* aName )
...
@@ -74,7 +82,7 @@ void OpenKeyFileEntity( const char* aName )
fprintf
(
kdebugFile
,
"STRNAME %s;
\n
"
,
aName
);
fprintf
(
kdebugFile
,
"STRNAME %s;
\n
"
,
aName
);
}
}
sCurrEntityName
=
aName
;
sCurrEntityName
=
aName
;
s_
count
=
0
;
s_
EntityCoordinates
.
clear
()
;
}
}
...
@@ -84,20 +92,45 @@ void CloseKeyFileEntity()
...
@@ -84,20 +92,45 @@ void CloseKeyFileEntity()
fprintf
(
kdebugFile
,
"
\n
ENDSTR %s;
\n
"
,
sCurrEntityName
);
fprintf
(
kdebugFile
,
"
\n
ENDSTR %s;
\n
"
,
sCurrEntityName
);
}
}
/* start a polygon entity in key file
void
StartKeyFilePolygon
(
int
aCornersCount
,
int
aLayer
)
*/
void
StartKeyFilePolygon
(
int
aLayer
)
{
{
s_EntityCoordinates
.
clear
();
fprintf
(
kdebugFile
,
"
\n
BOUNDARY; LAYER %d; DATATYPE 0;
\n
"
,
aLayer
);
fprintf
(
kdebugFile
,
"
\n
BOUNDARY; LAYER %d; DATATYPE 0;
\n
"
,
aLayer
);
fprintf
(
kdebugFile
,
" XY %d;
\n
"
,
aCornersCount
);
s_count
=
0
;
}
}
void
EndKeyFileElement
()
/* add a polygon corner to the current polygon entity in key file
*/
void
AddKeyFilePointXY
(
int
aXcoord
,
int
aYcoord
)
{
{
if
(
s_count
==
1
)
kfcoord
coord
;
fprintf
(
kdebugFile
,
"
\n
"
);
coord
.
x
=
aXcoord
;
fprintf
(
kdebugFile
,
"
\n
ENDEL;
\n
"
);
coord
.
y
=
aYcoord
;
s_count
=
0
;
s_EntityCoordinates
.
push_back
(
coord
);
}
/* Close a polygon entity in key file
* write the entire polygon data to the file
*/
void
EndKeyFilePolygon
()
{
// Polygon must be closed: test for that and close it if needed
if
(
s_EntityCoordinates
.
size
()
)
{
if
(
s_EntityCoordinates
.
back
().
x
!=
s_EntityCoordinates
[
0
].
x
||
s_EntityCoordinates
.
back
().
y
!=
s_EntityCoordinates
[
0
].
y
)
s_EntityCoordinates
.
push_back
(
s_EntityCoordinates
[
0
]
);
}
fprintf
(
kdebugFile
,
" XY %d;
\n
"
,
s_EntityCoordinates
.
size
()
);
for
(
unsigned
ii
=
0
;
ii
<
s_EntityCoordinates
.
size
();
ii
++
)
fprintf
(
kdebugFile
,
" X %d; Y %d;
\n
"
,
s_EntityCoordinates
[
ii
].
x
,
s_EntityCoordinates
[
ii
].
y
);
fprintf
(
kdebugFile
,
"ENDEL;
\n
"
);
s_EntityCoordinates
.
clear
();
}
}
void
CopyPolygonsFromFilledPolysListToKeyFile
(
ZONE_CONTAINER
*
aZone
,
int
aLayer
)
void
CopyPolygonsFromFilledPolysListToKeyFile
(
ZONE_CONTAINER
*
aZone
,
int
aLayer
)
...
@@ -106,30 +139,15 @@ void CopyPolygonsFromFilledPolysListToKeyFile( ZONE_CONTAINER* aZone, int aLayer
...
@@ -106,30 +139,15 @@ void CopyPolygonsFromFilledPolysListToKeyFile( ZONE_CONTAINER* aZone, int aLayer
return
;
return
;
unsigned
corners_count
=
aZone
->
m_FilledPolysList
.
size
();
unsigned
corners_count
=
aZone
->
m_FilledPolysList
.
size
();
int
count
=
0
;
unsigned
ic
=
0
;
unsigned
ic
=
0
;
CPolyPt
*
corner
;
while
(
ic
<
corners_count
)
while
(
ic
<
corners_count
)
{
{
// Count corners:
count
=
0
;
for
(
unsigned
ii
=
ic
;
ii
<
corners_count
;
ii
++
)
{
corner
=
&
aZone
->
m_FilledPolysList
[
ii
];
count
++
;
if
(
corner
->
end_contour
)
break
;
}
// write corners:
// write polygon:
StartKeyFilePolygon
(
count
+
1
,
aLayer
);
StartKeyFilePolygon
(
aLayer
);
corner
=
&
aZone
->
m_FilledPolysList
[
ic
];
int
startpointX
=
corner
->
x
;
int
startpointY
=
corner
->
y
;
for
(
;
ic
<
corners_count
;
ic
++
)
for
(
;
ic
<
corners_count
;
ic
++
)
{
{
corner
=
&
aZone
->
m_FilledPolysList
[
ic
];
CPolyPt
*
corner
=
&
aZone
->
m_FilledPolysList
[
ic
];
AddKeyFilePointXY
(
corner
->
x
,
corner
->
y
);
AddKeyFilePointXY
(
corner
->
x
,
corner
->
y
);
if
(
corner
->
end_contour
)
if
(
corner
->
end_contour
)
{
{
...
@@ -137,21 +155,8 @@ void CopyPolygonsFromFilledPolysListToKeyFile( ZONE_CONTAINER* aZone, int aLayer
...
@@ -137,21 +155,8 @@ void CopyPolygonsFromFilledPolysListToKeyFile( ZONE_CONTAINER* aZone, int aLayer
break
;
break
;
}
}
}
}
// Close polygon:
EndKeyFilePolygon
();
AddKeyFilePointXY
(
startpointX
,
startpointY
);
EndKeyFileElement
();
}
}
void
AddKeyFilePointXY
(
int
aXcoord
,
int
aYcoord
)
{
if
(
s_count
>=
2
)
{
s_count
=
0
;
fprintf
(
kdebugFile
,
"
\n
"
);
}
}
fprintf
(
kdebugFile
,
" X %d; Y %d;"
,
aXcoord
,
aYcoord
);
s_count
++
;
}
}
#endif
#endif
pcbnew/debug_kbool_key_file_fct.h
View file @
f2f4cd53
...
@@ -38,9 +38,9 @@ void CloseKeyFileEntity();
...
@@ -38,9 +38,9 @@ void CloseKeyFileEntity();
/* polygon creations:
/* polygon creations:
*/
*/
void
CopyPolygonsFromFilledPolysListToKeyFile
(
ZONE_CONTAINER
*
aZone
,
int
aLayer
);
void
CopyPolygonsFromFilledPolysListToKeyFile
(
ZONE_CONTAINER
*
aZone
,
int
aLayer
);
void
StartKeyFilePolygon
(
int
aCornersCount
,
int
aLayer
);
void
StartKeyFilePolygon
(
int
aLayer
);
void
AddKeyFilePointXY
(
int
aXcoord
,
int
aYcoord
);
void
AddKeyFilePointXY
(
int
aXcoord
,
int
aYcoord
);
void
EndKeyFile
Element
();
void
EndKeyFile
Polygon
();
#endif // CREATE_KBOOL_KEY_FILES
#endif // CREATE_KBOOL_KEY_FILES
...
...
pcbnew/zones_convert_brd_items_to_polygons.cpp
View file @
f2f4cd53
...
@@ -51,43 +51,40 @@
...
@@ -51,43 +51,40 @@
extern
void
Test_For_Copper_Island_And_Remove
(
BOARD
*
aPcb
,
extern
void
Test_For_Copper_Island_And_Remove
(
BOARD
*
aPcb
,
ZONE_CONTAINER
*
aZone_container
);
ZONE_CONTAINER
*
aZone_container
);
extern
void
TransformRoundedEndsSegmentToPolygon
(
std
::
vector
<
wxPoin
t
>&
aCornerBuffer
,
extern
void
TransformRoundedEndsSegmentToPolygon
(
std
::
vector
<
CPolyP
t
>&
aCornerBuffer
,
wxPoint
aStart
,
wxPoint
aEnd
,
wxPoint
aStart
,
wxPoint
aEnd
,
int
aCircleToSegmentsCount
,
int
aCircleToSegmentsCount
,
int
aWidth
);
int
aWidth
);
#ifdef CREATE_KBOOL_KEY_FILES
void
CreateThermalReliefPadPolygon
(
std
::
vector
<
CPolyPt
>&
aCornerBuffer
,
bool
s_GenDataForKbool
=
false
;
D_PAD
&
aPad
,
#endif
int
aThermalGap
,
int
aCopperThickness
,
int
aMinThicknessValue
,
int
aCircleToSegmentsCount
,
double
aCorrectionFactor
,
int
aThermalRot
);
// Local Functions:
// Local Functions:
#ifdef USE_STUBS_FOR_THERMAL
#ifdef USE_STUBS_FOR_THERMAL
#warning \
#warning \
USE_STUBS_FOR_THERMAL is defined: for test version only do not use for working pcbnew version
USE_STUBS_FOR_THERMAL is defined: for test version only do not use for working pcbnew version
void
CreateStubsForThermalShapes
(
BOARD
*
aPcb
,
ZONE_CONTAINER
*
aZone_container
,
void
CreateStubsForThermalShapes
(
BOARD
*
aPcb
,
ZONE_CONTAINER
*
aZone_container
,
int
aThermalGap
,
int
aThermalGap
,
int
aCopperThickness
,
int
aMinThicknessValue
);
int
aCopperThickness
,
int
aMinThicknessValue
);
#endif
#endif
void
AddTrackWithClearancePolygon
(
Bool_Engine
*
aBooleng
,
void
AddTrackWithClearancePolygon
(
Bool_Engine
*
aBooleng
,
TRACK
&
aTrack
,
int
aClearanceValue
);
TRACK
&
aTrack
,
int
aClearanceValue
);
void
AddPadWithClearancePolygon
(
Bool_Engine
*
aBooleng
,
D_PAD
&
aPad
,
int
aClearanceValue
);
void
AddPadWithClearancePolygon
(
Bool_Engine
*
aBooleng
,
D_PAD
&
aPad
,
int
aClearanceValue
);
void
AddThermalReliefPadPolygon
(
Bool_Engine
*
aBooleng
,
int
AddThermalReliefPadPolygon
(
Bool_Engine
*
aBooleng
,
D_PAD
&
aPad
,
D_PAD
&
aPad
,
int
aThermalGap
,
int
aThermalGap
,
int
aCopperThickness
,
int
aMinThicknessValue
);
int
aCopperThickness
,
int
aMinThicknessValue
);
void
AddRoundedEndsSegmentPolygon
(
Bool_Engine
*
aBooleng
,
void
AddRoundedEndsSegmentPolygon
(
Bool_Engine
*
aBooleng
,
wxPoint
aStart
,
wxPoint
aEnd
,
wxPoint
aStart
,
wxPoint
aEnd
,
int
aWidth
);
int
aWidth
);
void
AddTextBoxWithClearancePolygon
(
Bool_Engine
*
aBooleng
,
TEXTE_PCB
*
aText
,
int
aClearanceValue
);
static
void
AddRingPolygon
(
Bool_Engine
*
aBooleng
,
wxPoint
aCentre
,
wxPoint
aStart
,
int
aArcAngle
,
int
aWidth
);
// Local Variables:
// Local Variables:
/* how many segments are used to create a polygon from a circle: */
/* how many segments are used to create a polygon from a circle: */
...
@@ -300,47 +297,67 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
...
@@ -300,47 +297,67 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
if
(
item
->
GetLayer
()
!=
GetLayer
()
&&
item
->
GetLayer
()
!=
EDGE_N
)
if
(
item
->
GetLayer
()
!=
GetLayer
()
&&
item
->
GetLayer
()
!=
EDGE_N
)
continue
;
continue
;
static
std
::
vector
<
CPolyPt
>
cornerBuffer
;
cornerBuffer
.
clear
();
switch
(
item
->
Type
()
)
switch
(
item
->
Type
()
)
{
{
case
TYPE_DRAWSEGMENT
:
case
TYPE_DRAWSEGMENT
:
(
(
DRAWSEGMENT
*
)
item
)
->
TransformShapeWithClearanceToPolygon
(
switch
(
(
(
DRAWSEGMENT
*
)
item
)
->
m_Shape
)
cornerBuffer
,
{
m_ZoneClearance
,
case
S_CIRCLE
:
s_CircleToSegmentsCount
,
AddRingPolygon
(
booleng
,
(
(
DRAWSEGMENT
*
)
item
)
->
m_Start
,
// Circle centre
s_Correction
);
(
(
DRAWSEGMENT
*
)
item
)
->
m_End
,
3600
,
(
(
DRAWSEGMENT
*
)
item
)
->
m_Width
+
(
2
*
m_ZoneClearance
)
);
have_poly_to_substract
=
true
;
break
;
case
S_ARC
:
AddRingPolygon
(
booleng
,
(
(
DRAWSEGMENT
*
)
item
)
->
m_Start
,
// Arc centre
(
(
DRAWSEGMENT
*
)
item
)
->
m_End
,
(
(
DRAWSEGMENT
*
)
item
)
->
m_Angle
,
(
(
DRAWSEGMENT
*
)
item
)
->
m_Width
+
(
2
*
m_ZoneClearance
)
);
have_poly_to_substract
=
true
;
break
;
default
:
AddRoundedEndsSegmentPolygon
(
booleng
,
(
(
DRAWSEGMENT
*
)
item
)
->
m_Start
,
(
(
DRAWSEGMENT
*
)
item
)
->
m_End
,
(
(
DRAWSEGMENT
*
)
item
)
->
m_Width
+
(
2
*
m_ZoneClearance
)
);
have_poly_to_substract
=
true
;
break
;
}
break
;
break
;
case
TYPE_TEXTE
:
case
TYPE_TEXTE
:
AddTextBoxWithClearancePolygon
(
booleng
,
(
TEXTE_PCB
*
)
item
,
m_ZoneClearance
);
(
(
TEXTE_PCB
*
)
item
)
->
TransformShapeWithClearanceToPolygon
(
have_poly_to_substract
=
true
;
cornerBuffer
,
m_ZoneClearance
,
s_CircleToSegmentsCount
,
s_Correction
);
break
;
break
;
default
:
default
:
break
;
break
;
}
}
if
(
cornerBuffer
.
size
()
==
0
)
continue
;
// cornerBuffer can contain more than one polygon,
// so read cornerBuffer and verify if there is a end of polygon corner:
for
(
unsigned
icnt
=
0
;
icnt
<
cornerBuffer
.
size
();
)
{
booleng
->
StartPolygonAdd
(
GROUP_B
);
{
have_poly_to_substract
=
true
;
unsigned
ii
;
for
(
ii
=
icnt
;
ii
<
cornerBuffer
.
size
();
ii
++
)
{
booleng
->
AddPoint
(
cornerBuffer
[
ii
].
x
,
cornerBuffer
[
ii
].
y
);
if
(
cornerBuffer
[
ii
].
end_contour
)
break
;
}
booleng
->
EndPolygonAdd
();
#ifdef CREATE_KBOOL_KEY_FILES_FIRST_PASS
StartKeyFilePolygon
(
1
);
for
(
ii
=
icnt
;
ii
<
cornerBuffer
.
size
();
ii
++
)
{
AddKeyFilePointXY
(
cornerBuffer
[
ii
].
x
,
cornerBuffer
[
ii
].
y
);
if
(
cornerBuffer
[
ii
].
end_contour
)
break
;
}
EndKeyFilePolygon
();
#endif
icnt
=
ii
+
1
;
}
}
}
}
#ifdef CREATE_KBOOL_KEY_FILES_FIRST_PASS
#ifdef CREATE_KBOOL_KEY_FILES_FIRST_PASS
...
@@ -417,11 +434,11 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
...
@@ -417,11 +434,11 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
item_boundingbox
.
Inflate
(
m_ThermalReliefGapValue
,
m_ThermalReliefGapValue
);
item_boundingbox
.
Inflate
(
m_ThermalReliefGapValue
,
m_ThermalReliefGapValue
);
if
(
item_boundingbox
.
Intersects
(
zone_boundingbox
)
)
if
(
item_boundingbox
.
Intersects
(
zone_boundingbox
)
)
{
{
have_poly_to_substract
=
true
;
if
(
AddThermalReliefPadPolygon
(
booleng
,
*
pad
,
AddThermalReliefPadPolygon
(
booleng
,
*
pad
,
m_ThermalReliefGapValue
,
m_ThermalReliefGapValue
,
m_ThermalReliefCopperBridgeValue
,
m_ThermalReliefCopperBridgeValue
,
m_ZoneMinThickness
);
m_ZoneMinThickness
)
)
have_poly_to_substract
=
true
;
}
}
}
}
}
}
...
@@ -613,14 +630,14 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
...
@@ -613,14 +630,14 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
void
AddPadWithClearancePolygon
(
Bool_Engine
*
aBooleng
,
void
AddPadWithClearancePolygon
(
Bool_Engine
*
aBooleng
,
D_PAD
&
aPad
,
int
aClearanceValue
)
D_PAD
&
aPad
,
int
aClearanceValue
)
{
{
static
std
::
vector
<
wxPoin
t
>
cornerBuffer
;
static
std
::
vector
<
CPolyP
t
>
cornerBuffer
;
if
(
aBooleng
->
StartPolygonAdd
(
GROUP_B
)
==
0
)
if
(
aBooleng
->
StartPolygonAdd
(
GROUP_B
)
==
0
)
return
;
return
;
cornerBuffer
.
clear
();
cornerBuffer
.
clear
();
aPad
.
Transform
Pad
WithClearanceToPolygon
(
cornerBuffer
,
aPad
.
Transform
Shape
WithClearanceToPolygon
(
cornerBuffer
,
aClearanceValue
,
aClearanceValue
,
s_CircleToSegmentsCount
,
s_CircleToSegmentsCount
,
s_Correction
);
s_Correction
);
for
(
unsigned
ii
=
0
;
ii
<
cornerBuffer
.
size
();
ii
++
)
for
(
unsigned
ii
=
0
;
ii
<
cornerBuffer
.
size
();
ii
++
)
aBooleng
->
AddPoint
(
cornerBuffer
[
ii
].
x
,
cornerBuffer
[
ii
].
y
);
aBooleng
->
AddPoint
(
cornerBuffer
[
ii
].
x
,
cornerBuffer
[
ii
].
y
);
...
@@ -628,13 +645,11 @@ void AddPadWithClearancePolygon( Bool_Engine* aBooleng,
...
@@ -628,13 +645,11 @@ void AddPadWithClearancePolygon( Bool_Engine* aBooleng,
aBooleng
->
EndPolygonAdd
();
aBooleng
->
EndPolygonAdd
();
#ifdef CREATE_KBOOL_KEY_FILES_FIRST_PASS
#ifdef CREATE_KBOOL_KEY_FILES_FIRST_PASS
StartKeyFilePolygon
(
cornerBuffer
.
size
()
+
1
,
1
);
StartKeyFilePolygon
(
1
);
for
(
unsigned
ii
=
0
;
ii
<
cornerBuffer
.
size
();
ii
++
)
for
(
unsigned
ii
=
0
;
ii
<
cornerBuffer
.
size
();
ii
++
)
AddKeyFilePointXY
(
cornerBuffer
[
ii
].
x
,
cornerBuffer
[
ii
].
y
);
AddKeyFilePointXY
(
cornerBuffer
[
ii
].
x
,
cornerBuffer
[
ii
].
y
);
// Close polygon
EndKeyFilePolygon
();
AddKeyFilePointXY
(
cornerBuffer
[
0
].
x
,
cornerBuffer
[
0
].
y
);
EndKeyFileElement
();
#endif
#endif
}
}
...
@@ -642,6 +657,7 @@ void AddPadWithClearancePolygon( Bool_Engine* aBooleng,
...
@@ -642,6 +657,7 @@ void AddPadWithClearancePolygon( Bool_Engine* aBooleng,
/** function CreateStubsForThermalShapes()
/** function CreateStubsForThermalShapes()
* Only for testing the thermal shapes by stubs purposes
* Only for testing the thermal shapes by stubs purposes
* Do not use for working pcbnew versions
* Do not use for working pcbnew versions
* This is just for kbool test only
*/
*/
void
CreateStubsForThermalShapes
(
BOARD
*
aPcb
,
ZONE_CONTAINER
*
aZone_container
,
void
CreateStubsForThermalShapes
(
BOARD
*
aPcb
,
ZONE_CONTAINER
*
aZone_container
,
int
aThermalGap
,
int
aThermalGap
,
...
@@ -658,9 +674,6 @@ void CreateStubsForThermalShapes( BOARD* aPcb, ZONE_CONTAINER* aZone_cont
...
@@ -658,9 +674,6 @@ void CreateStubsForThermalShapes( BOARD* aPcb, ZONE_CONTAINER* aZone_cont
if
(
aCopperThickness
<=
aMinThicknessValue
)
if
(
aCopperThickness
<=
aMinThicknessValue
)
return
;
return
;
#ifdef CREATE_KBOOL_KEY_FILES
s_GenDataForKbool
=
true
;
#endif
for
(
MODULE
*
module
=
aPcb
->
m_Modules
;
module
;
module
=
module
->
Next
()
)
for
(
MODULE
*
module
=
aPcb
->
m_Modules
;
module
;
module
=
module
->
Next
()
)
{
{
for
(
D_PAD
*
pad
=
module
->
m_Pads
;
pad
!=
NULL
;
pad
=
pad
->
Next
()
)
for
(
D_PAD
*
pad
=
module
->
m_Pads
;
pad
!=
NULL
;
pad
=
pad
->
Next
()
)
...
@@ -737,9 +750,6 @@ void CreateStubsForThermalShapes( BOARD* aPcb, ZONE_CONTAINER* aZone_cont
...
@@ -737,9 +750,6 @@ void CreateStubsForThermalShapes( BOARD* aPcb, ZONE_CONTAINER* aZone_cont
}
}
}
}
#ifdef CREATE_KBOOL_KEY_FILES
s_GenDataForKbool
=
false
;
#endif
if
(
have_poly_to_add
)
if
(
have_poly_to_add
)
{
{
/* Add the main corrected polygon (i.e. the filled area using only one outline)
/* Add the main corrected polygon (i.e. the filled area using only one outline)
...
@@ -774,404 +784,60 @@ void CreateStubsForThermalShapes( BOARD* aPcb, ZONE_CONTAINER* aZone_cont
...
@@ -774,404 +784,60 @@ void CreateStubsForThermalShapes( BOARD* aPcb, ZONE_CONTAINER* aZone_cont
* When Kbool calculates the filled areas :
* When Kbool calculates the filled areas :
* i.e when substracting holes (thermal shapes) to the full zone area
* i.e when substracting holes (thermal shapes) to the full zone area
* under certains circumstances kboll drop some holes.
* under certains circumstances kboll drop some holes.
* These circumstances are:
* see CreateThermalReliefPadPolygon().
* some identical holes (same thermal shape and size) are *exactly* on the same vertical line
* And
* nothing else between holes
* And
* angles less than 90 deg between 2 consecutive lines in hole outline (sometime occurs without this condition)
* And
* a hole above the identical holes
*
* In fact, it is easy to find these conditions in pad arrays.
* So to avoid this, the workaround is do not use holes outlines that include
* angles less than 90 deg between 2 consecutive lines
* this is made in round and oblong thermal reliefs
*
* Note 1: polygons are drawm using outlines witk a thickness = aMinThicknessValue
* so shapes must keep in account this outline thickness
*
* Note 2:
* Trapezoidal pads are not considered here because they are very special case
* and are used in microwave applications and they *DO NOT* have a thermal relief that change the shape
* by creating stubs and destroy their properties.
*/
*/
void
AddThermalReliefPadPolygon
(
Bool_Engine
*
aBooleng
,
int
AddThermalReliefPadPolygon
(
Bool_Engine
*
aBooleng
,
D_PAD
&
aPad
,
D_PAD
&
aPad
,
int
aThermalGap
,
int
aThermalGap
,
int
aCopperThickness
,
int
aMinThicknessValue
)
int
aCopperThickness
,
int
aMinThicknessValue
)
{
{
wxPoint
corner
,
corner_end
;
static
std
::
vector
<
CPolyPt
>
cornerBuffer
;
wxPoint
PadShapePos
=
aPad
.
ReturnShapePos
();
/* Note: for pad having a shape offset,
cornerBuffer
.
clear
();
* the pad position is NOT the shape position */
int
angle
=
0
;
wxSize
copper_thickness
;
int
dx
=
aPad
.
m_Size
.
x
/
2
;
int
dy
=
aPad
.
m_Size
.
y
/
2
;
int
delta
=
3600
/
s_CircleToSegmentsCount
;
// rot angle in 0.1 degree
/* Keep in account the polygon outline thickness
* aThermalGap must be increased by aMinThicknessValue/2 because drawing external outline
* with a thickness of aMinThicknessValue will reduce gap by aMinThicknessValue/2
*/
aThermalGap
+=
aMinThicknessValue
/
2
;
/* Keep in account the polygon outline thickness
* copper_thickness must be decreased by aMinThicknessValue because drawing outlines
* with a thickness of aMinThicknessValue will increase real thickness by aMinThicknessValue
*/
aCopperThickness
-=
aMinThicknessValue
;
if
(
aCopperThickness
<
0
)
aCopperThickness
=
0
;
copper_thickness
.
x
=
min
(
dx
,
aCopperThickness
);
copper_thickness
.
y
=
min
(
dy
,
aCopperThickness
);
switch
(
aPad
.
m_PadShape
)
{
case
PAD_CIRCLE
:
// Add 4 similar holes
{
/* we create 4 copper holes and put them in position 1, 2, 3 and 4
* here is the area of the rectangular pad + its thermal gap
* the 4 copper holes remove the copper in order to create the thermal gap
* 4 ------ 1
* | |
* | |
* | |
* | |
* 3 ------ 2
* holes 2, 3, 4 are the same as hole 1, rotated 90, 180, 270 deg
*/
// Build the hole pattern, for the hole in the X >0, Y > 0 plane:
// The pattern roughtly is a 90 deg arc pie
std
::
vector
<
wxPoint
>
corners_buffer
;
// Radius of outer arcs of the shape:
int
outer_radius
=
dx
+
aThermalGap
;
// The radius of the outer arc is pad radius + aThermalGap
// Crosspoint of thermal spoke sides, the first point of polygon buffer
corners_buffer
.
push_back
(
wxPoint
(
copper_thickness
.
x
/
2
,
copper_thickness
.
y
/
2
)
);
// Add an intermediate point on spoke sides, to allow a > 90 deg angle between side and first seg of arc approx
corner
.
x
=
copper_thickness
.
x
/
2
;
int
y
=
outer_radius
-
(
aThermalGap
/
4
);
corner
.
y
=
(
int
)
sqrt
(
(
(
(
double
)
y
*
y
)
-
(
double
)
corner
.
x
*
corner
.
x
)
);
#ifndef CREATE_KBOOL_KEY_FILES_WITH_0_DEG
corners_buffer
.
push_back
(
corner
);
#endif
// calculate the starting point of the outter arc
corner
.
x
=
copper_thickness
.
x
/
2
;
double
dtmp
=
sqrt
(
(
(
double
)
outer_radius
*
outer_radius
)
-
(
(
double
)
corner
.
x
*
corner
.
x
)
);
corner
.
y
=
(
int
)
dtmp
;
RotatePoint
(
&
corner
,
90
);
// calculate the ending point of the outter arc
corner_end
.
x
=
corner
.
y
;
corner_end
.
y
=
corner
.
x
;
// calculate intermediate points (y coordinate from corner.y to corner_end.y
while
(
(
corner
.
y
>
corner_end
.
y
)
&&
(
corner
.
x
<
corner_end
.
x
)
)
{
corners_buffer
.
push_back
(
corner
);
RotatePoint
(
&
corner
,
delta
);
}
corners_buffer
.
push_back
(
corner_end
);
/* add an intermediate point, to avoid angles < 90 deg between last arc approx line and radius line
int
polycount
=
0
;
*/
int
thermalRot
=
450
;
corner
.
x
=
corners_buffer
[
1
].
y
;
corner
.
y
=
corners_buffer
[
1
].
x
;
corners_buffer
.
push_back
(
corner
);
// Now, add the 4 holes ( each is the pattern, rotated by 0, 90, 180 and 270 deg
// WARNING: problems with kbool if angle = 0 (in fact when angle < 200):
// bad filled polygon on some cases, when pads are on a same vertical line
// this seems a bug in kbool polygon (exists in 2.0 kbool version)
// angle = 450 (45.0 degrees orientation) seems work fine.
// angle = 0 with thermal shapes without angle < 90 deg has problems in rare circumstances
// Note: with the 2 step build ( thermal shapes added after areas are built), 0 seems work
#ifdef CREATE_KBOOL_KEY_FILES_WITH_0_DEG
#ifdef CREATE_KBOOL_KEY_FILES_WITH_0_DEG
angle
=
0
;
thermalRot
=
0
;
#else
angle
=
450
;
#endif
int
angle_pad
=
aPad
.
m_Orient
;
// Pad orientation
for
(
unsigned
ihole
=
0
;
ihole
<
4
;
ihole
++
)
{
if
(
aBooleng
->
StartPolygonAdd
(
GROUP_B
)
)
{
#ifdef CREATE_KBOOL_KEY_FILES
StartKeyFilePolygon
(
corners_buffer
.
size
()
+
1
,
1
);
#endif
for
(
unsigned
ii
=
0
;
ii
<
corners_buffer
.
size
();
ii
++
)
{
corner
=
corners_buffer
[
ii
];
RotatePoint
(
&
corner
,
angle
+
angle_pad
);
// Rotate by segment angle and pad orientation
corner
+=
PadShapePos
;
aBooleng
->
AddPoint
(
corner
.
x
,
corner
.
y
);
#ifdef CREATE_KBOOL_KEY_FILES
AddKeyFilePointXY
(
corner
.
x
,
corner
.
y
);
#endif
#endif
}
#ifdef CREATE_KBOOL_KEY_FILES
CreateThermalReliefPadPolygon
(
cornerBuffer
,
aPad
,
aThermalGap
,
aCopperThickness
,
// Close polygon
aMinThicknessValue
,
corner
=
corners_buffer
[
0
];
s_CircleToSegmentsCount
,
RotatePoint
(
&
corner
,
angle
+
angle_pad
);
// Rotate by segment angle and pad orientation
s_Correction
,
thermalRot
);
corner
+=
PadShapePos
;
AddKeyFilePointXY
(
corner
.
x
,
corner
.
y
);
#endif
aBooleng
->
EndPolygonAdd
();
// cornerBuffer can contain more than one polygon,
#ifdef CREATE_KBOOL_KEY_FILES
// so read cornerBuffer and verify if there is a end of polygon corner:
EndKeyFileElement
();
for
(
unsigned
icnt
=
0
;
icnt
<
cornerBuffer
.
size
();
)
#endif
angle
+=
900
;
// Note: angle in in 0.1 deg.
}
}
}
break
;
case
PAD_OVAL
:
{
{
// Oval pad support along the lines of round and rectangular pads
aBooleng
->
StartPolygonAdd
(
GROUP_B
);
std
::
vector
<
wxPoint
>
corners_buffer
;
// Polygon buffer as vector
polycount
++
;
unsigned
ii
;
int
dx
=
(
aPad
.
m_Size
.
x
/
2
)
+
aThermalGap
;
// Cutout radius x
for
(
ii
=
icnt
;
ii
<
cornerBuffer
.
size
();
ii
++
)
int
dy
=
(
aPad
.
m_Size
.
y
/
2
)
+
aThermalGap
;
// Cutout radius y
wxPoint
shape_offset
;
// We want to calculate an oval shape with dx > dy.
// if this is not the case, exchange dx and dy, and rotate the shape 90 deg.
int
supp_angle
=
0
;
if
(
dx
<
dy
)
{
EXCHG
(
dx
,
dy
);
supp_angle
=
900
;
EXCHG
(
copper_thickness
.
x
,
copper_thickness
.
y
);
}
int
deltasize
=
dx
-
dy
;
// = distance between shape position and the 2 demi-circle ends centre
// here we have dx > dy
// Radius of outer arcs of the shape:
int
outer_radius
=
dy
;
// The radius of the outer arc is radius end + aThermalGap
// Some coordinate fiddling, depending on the shape offset direction
shape_offset
=
wxPoint
(
deltasize
,
0
);
// Crosspoint of thermal spoke sides, the first point of polygon buffer
corners_buffer
.
push_back
(
wxPoint
(
copper_thickness
.
x
/
2
,
copper_thickness
.
y
/
2
)
);
// Arc start point calculation, the intersecting point of cutout arc and thermal spoke edge
if
(
copper_thickness
.
x
>
deltasize
)
// If copper thickness is more than shape offset, we need to calculate arc intercept point.
{
corner
.
x
=
copper_thickness
.
x
/
2
;
corner
.
y
=
(
int
)
sqrt
(
(
(
double
)
outer_radius
*
outer_radius
)
-
(
(
double
)
(
corner
.
x
-
delta
)
*
(
corner
.
x
-
deltasize
)
)
);
corner
.
x
-=
deltasize
;
/* creates an intermediate point, to have a > 90 deg angle
* between the side and the first segment of arc approximation
*/
wxPoint
intpoint
=
corner
;
intpoint
.
y
-=
aThermalGap
/
4
;
corners_buffer
.
push_back
(
intpoint
+
shape_offset
);
RotatePoint
(
&
corner
,
90
);
}
else
{
{
corner
.
x
=
copper_thickness
.
x
/
2
;
aBooleng
->
AddPoint
(
cornerBuffer
[
ii
].
x
,
cornerBuffer
[
ii
].
y
);
corner
.
y
=
outer_radius
;
if
(
cornerBuffer
[
ii
].
end_contour
)
corners_buffer
.
push_back
(
corner
);
break
;
corner
.
x
=
(
deltasize
-
copper_thickness
.
x
)
/
2
;
}
// Add an intermediate point on spoke sides, to allow a > 90 deg angle between side and first seg of arc approx
wxPoint
last_corner
;
last_corner
.
y
=
copper_thickness
.
y
/
2
;
int
px
=
outer_radius
-
(
aThermalGap
/
4
);
last_corner
.
x
=
(
int
)
sqrt
(
(
(
(
double
)
px
*
px
)
-
(
double
)
last_corner
.
y
*
last_corner
.
y
)
);
// Arc stop point calculation, the intersecting point of cutout arc and thermal spoke edge
corner_end
.
y
=
copper_thickness
.
y
/
2
;
corner_end
.
x
=
(
int
)
sqrt
(
(
(
double
)
outer_radius
*
outer_radius
)
-
(
(
double
)
corner_end
.
y
*
corner_end
.
y
)
);
RotatePoint
(
&
corner_end
,
-
90
);
// calculate intermediate arc points till limit is reached
while
(
(
corner
.
y
>
corner_end
.
y
)
&&
(
corner
.
x
<
corner_end
.
x
)
)
{
corners_buffer
.
push_back
(
corner
+
shape_offset
);
RotatePoint
(
&
corner
,
delta
);
}
}
//corners_buffer.push_back(corner + shape_offset); // TODO: about one mil geometry error forms somewhere.
aBooleng
->
EndPolygonAdd
();
corners_buffer
.
push_back
(
corner_end
+
shape_offset
);
corners_buffer
.
push_back
(
last_corner
+
shape_offset
);
// Enabling the line above shows intersection point.
/* Create 2 holes, rotated by pad rotation.
*/
angle
=
aPad
.
m_Orient
+
supp_angle
;
for
(
int
irect
=
0
;
irect
<
2
;
irect
++
)
{
if
(
aBooleng
->
StartPolygonAdd
(
GROUP_B
)
)
{
for
(
unsigned
ic
=
0
;
ic
<
corners_buffer
.
size
();
ic
++
)
{
wxPoint
cpos
=
corners_buffer
[
ic
];
RotatePoint
(
&
cpos
,
angle
);
cpos
+=
PadShapePos
;
aBooleng
->
AddPoint
(
cpos
.
x
,
cpos
.
y
);
}
aBooleng
->
EndPolygonAdd
();
angle
+=
1800
;
// this is calculate hole 3
if
(
angle
>=
3600
)
angle
-=
3600
;
}
}
// Create holes, that are the mirrored from the previous holes
#ifdef CREATE_KBOOL_KEY_FILES
for
(
unsigned
ic
=
0
;
ic
<
corners_buffer
.
size
();
ic
++
)
StartKeyFilePolygon
(
1
);
for
(
ii
=
icnt
;
ii
<
cornerBuffer
.
size
();
ii
++
)
{
{
wxPoint
swap
=
corners_buffer
[
ic
]
;
AddKeyFilePointXY
(
cornerBuffer
[
ii
].
x
,
cornerBuffer
[
ii
].
y
)
;
swap
.
x
=
-
swap
.
x
;
if
(
cornerBuffer
[
ii
].
end_contour
)
corners_buffer
[
ic
]
=
swap
;
break
;
}
}
// Now add corner 4 and 2 (2 is the corner 4 rotated by 180 deg
EndKeyFilePolygon
();
angle
=
aPad
.
m_Orient
+
supp_angle
;
#endif
for
(
int
irect
=
0
;
irect
<
2
;
irect
++
)
{
if
(
aBooleng
->
StartPolygonAdd
(
GROUP_B
)
)
{
for
(
unsigned
ic
=
0
;
ic
<
corners_buffer
.
size
();
ic
++
)
{
wxPoint
cpos
=
corners_buffer
[
ic
];
RotatePoint
(
&
cpos
,
angle
);
cpos
+=
PadShapePos
;
aBooleng
->
AddPoint
(
cpos
.
x
,
cpos
.
y
);
}
aBooleng
->
EndPolygonAdd
();
icnt
=
ii
+
1
;
angle
+=
1800
;
if
(
angle
>=
3600
)
angle
-=
3600
;
}
}
}
}
break
;
case
PAD_RECT
:
// draw 4 Holes
{
/* we create 4 copper holes and put them in position 1, 2, 3 and 4
* here is the area of the rectangular pad + its thermal gap
* the 4 copper holes remove the copper in order to create the thermal gap
* 4 ------ 1
* | |
* | |
* | |
* | |
* 3 ------ 2
* hole 3 is the same as hole 1, rotated 180 deg
* hole 4 is the same as hole 2, rotated 180 deg and is the same as hole 1, mirrored
*/
// First, create a rectangular hole for position 1 :
// 2 ------- 3
// | |
// | |
// | |
// 1 -------4
// Modified rectangles with one corner rounded. TODO: merging with oval thermals and possibly round too.
std
::
vector
<
wxPoint
>
corners_buffer
;
// Polygon buffer as vector
int
dx
=
(
aPad
.
m_Size
.
x
/
2
)
+
aThermalGap
;
// Cutout radius x
int
dy
=
(
aPad
.
m_Size
.
y
/
2
)
+
aThermalGap
;
// Cutout radius y
// The first point of polygon buffer is left lower corner, second the crosspoint of thermal spoke sides,
return
polycount
;
// the third is upper right corner and the rest are rounding vertices going anticlockwise. Note the inveted Y-axis in CG.
corners_buffer
.
push_back
(
wxPoint
(
-
dx
,
-
(
aThermalGap
/
4
+
copper_thickness
.
y
/
2
)
)
);
// Adds small miters to zone
corners_buffer
.
push_back
(
wxPoint
(
-
(
dx
-
aThermalGap
/
4
),
-
copper_thickness
.
y
/
2
)
);
// fill and spoke corner
corners_buffer
.
push_back
(
wxPoint
(
-
copper_thickness
.
x
/
2
,
-
copper_thickness
.
y
/
2
)
);
corners_buffer
.
push_back
(
wxPoint
(
-
copper_thickness
.
x
/
2
,
-
(
dy
-
aThermalGap
/
4
)
)
);
corners_buffer
.
push_back
(
wxPoint
(
-
(
aThermalGap
/
4
+
copper_thickness
.
x
/
2
),
-
dy
)
);
angle
=
aPad
.
m_Orient
;
int
rounding_radius
=
(
int
)
(
aThermalGap
*
s_Correction
);
// Corner rounding radius
int
angle_pg
;
// Polygon increment angle
for
(
int
i
=
0
;
i
<
s_CircleToSegmentsCount
/
4
+
1
;
i
++
)
{
wxPoint
corner_position
=
wxPoint
(
0
,
-
rounding_radius
);
RotatePoint
(
&
corner_position
,
(
1800
/
s_CircleToSegmentsCount
)
);
// Start at half increment offset
angle_pg
=
i
*
delta
;
RotatePoint
(
&
corner_position
,
angle_pg
);
// Rounding vector rotation
corner_position
-=
aPad
.
m_Size
/
2
;
// Rounding vector + Pad corner offset
corners_buffer
.
push_back
(
wxPoint
(
corner_position
.
x
,
corner_position
.
y
)
);
}
for
(
int
irect
=
0
;
irect
<
2
;
irect
++
)
{
if
(
aBooleng
->
StartPolygonAdd
(
GROUP_B
)
)
{
for
(
unsigned
ic
=
0
;
ic
<
corners_buffer
.
size
();
ic
++
)
{
wxPoint
cpos
=
corners_buffer
[
ic
];
RotatePoint
(
&
cpos
,
angle
);
// Rotate according to module orientation
cpos
+=
PadShapePos
;
// Shift origin to position
aBooleng
->
AddPoint
(
cpos
.
x
,
cpos
.
y
);
}
aBooleng
->
EndPolygonAdd
();
angle
+=
1800
;
// this is calculate hole 3
if
(
angle
>=
3600
)
angle
-=
3600
;
}
}
// Create holes, that are the mirrored from the previous holes
for
(
unsigned
ic
=
0
;
ic
<
corners_buffer
.
size
();
ic
++
)
{
wxPoint
swap
=
corners_buffer
[
ic
];
swap
.
x
=
-
swap
.
x
;
corners_buffer
[
ic
]
=
swap
;
}
// Now add corner 4 and 2 (2 is the corner 4 rotated by 180 deg
for
(
int
irect
=
0
;
irect
<
2
;
irect
++
)
{
if
(
aBooleng
->
StartPolygonAdd
(
GROUP_B
)
)
{
for
(
unsigned
ic
=
0
;
ic
<
corners_buffer
.
size
();
ic
++
)
{
wxPoint
cpos
=
corners_buffer
[
ic
];
RotatePoint
(
&
cpos
,
angle
);
cpos
+=
PadShapePos
;
aBooleng
->
AddPoint
(
cpos
.
x
,
cpos
.
y
);
}
aBooleng
->
EndPolygonAdd
();
angle
+=
1800
;
if
(
angle
>=
3600
)
angle
-=
3600
;
}
}
break
;
}
}
}
}
...
@@ -1182,9 +848,9 @@ void AddThermalReliefPadPolygon( Bool_Engine* aBooleng,
...
@@ -1182,9 +848,9 @@ void AddThermalReliefPadPolygon( Bool_Engine* aBooleng,
void
AddTrackWithClearancePolygon
(
Bool_Engine
*
aBooleng
,
void
AddTrackWithClearancePolygon
(
Bool_Engine
*
aBooleng
,
TRACK
&
aTrack
,
int
aClearanceValue
)
TRACK
&
aTrack
,
int
aClearanceValue
)
{
{
static
std
::
vector
<
wxPoin
t
>
cornerBuffer
;
static
std
::
vector
<
CPolyP
t
>
cornerBuffer
;
cornerBuffer
.
clear
();
cornerBuffer
.
clear
();
aTrack
.
Transform
Track
WithClearanceToPolygon
(
cornerBuffer
,
aTrack
.
Transform
Shape
WithClearanceToPolygon
(
cornerBuffer
,
aClearanceValue
,
aClearanceValue
,
s_CircleToSegmentsCount
,
s_CircleToSegmentsCount
,
s_Correction
);
s_Correction
);
...
@@ -1198,13 +864,11 @@ void AddTrackWithClearancePolygon( Bool_Engine* aBooleng,
...
@@ -1198,13 +864,11 @@ void AddTrackWithClearancePolygon( Bool_Engine* aBooleng,
aBooleng
->
EndPolygonAdd
();
aBooleng
->
EndPolygonAdd
();
#ifdef CREATE_KBOOL_KEY_FILES_FIRST_PASS
#ifdef CREATE_KBOOL_KEY_FILES_FIRST_PASS
StartKeyFilePolygon
(
cornerBuffer
.
size
()
+
1
,
1
);
StartKeyFilePolygon
(
1
);
for
(
unsigned
ii
=
0
;
ii
<
cornerBuffer
.
size
();
ii
++
)
for
(
unsigned
ii
=
0
;
ii
<
cornerBuffer
.
size
();
ii
++
)
AddKeyFilePointXY
(
cornerBuffer
[
ii
].
x
,
cornerBuffer
[
ii
].
y
);
AddKeyFilePointXY
(
cornerBuffer
[
ii
].
x
,
cornerBuffer
[
ii
].
y
);
// Close polygon
EndKeyFilePolygon
();
AddKeyFilePointXY
(
cornerBuffer
[
0
].
x
,
cornerBuffer
[
0
].
y
);
EndKeyFileElement
();
#endif
#endif
}
}
...
@@ -1217,12 +881,12 @@ void AddRoundedEndsSegmentPolygon( Bool_Engine* aBooleng,
...
@@ -1217,12 +881,12 @@ void AddRoundedEndsSegmentPolygon( Bool_Engine* aBooleng,
wxPoint
aStart
,
wxPoint
aEnd
,
wxPoint
aStart
,
wxPoint
aEnd
,
int
aWidth
)
int
aWidth
)
{
{
static
std
::
vector
<
wxPoin
t
>
cornerBuffer
;
static
std
::
vector
<
CPolyP
t
>
cornerBuffer
;
cornerBuffer
.
clear
();
cornerBuffer
.
clear
();
TransformRoundedEndsSegmentToPolygon
(
cornerBuffer
,
TransformRoundedEndsSegmentToPolygon
(
cornerBuffer
,
aStart
,
aEnd
,
aStart
,
aEnd
,
s_CircleToSegmentsCount
,
s_CircleToSegmentsCount
,
aWidth
);
aWidth
);
if
(
!
aBooleng
->
StartPolygonAdd
(
GROUP_B
)
)
if
(
!
aBooleng
->
StartPolygonAdd
(
GROUP_B
)
)
return
;
return
;
...
@@ -1233,100 +897,15 @@ void AddRoundedEndsSegmentPolygon( Bool_Engine* aBooleng,
...
@@ -1233,100 +897,15 @@ void AddRoundedEndsSegmentPolygon( Bool_Engine* aBooleng,
aBooleng
->
EndPolygonAdd
();
aBooleng
->
EndPolygonAdd
();
#ifdef CREATE_KBOOL_KEY_FILES
#ifdef CREATE_KBOOL_KEY_FILES
StartKeyFilePolygon
(
cornerBuffer
.
size
()
+
1
,
1
);
StartKeyFilePolygon
(
1
);
for
(
unsigned
ii
=
0
;
ii
<
cornerBuffer
.
size
();
ii
++
)
for
(
unsigned
ii
=
0
;
ii
<
cornerBuffer
.
size
();
ii
++
)
AddKeyFilePointXY
(
cornerBuffer
[
ii
].
x
,
cornerBuffer
[
ii
].
y
);
AddKeyFilePointXY
(
cornerBuffer
[
ii
].
x
,
cornerBuffer
[
ii
].
y
);
// Close polygon
EndKeyFilePolygon
();
AddKeyFilePointXY
(
cornerBuffer
[
0
].
x
,
cornerBuffer
[
0
].
y
);
EndKeyFileElement
();
#endif
#endif
}
}
/** Function AddRingPolygon
* Add a polygon cutout for an Arc in a zone area
* Convert arcs to multiple straight segments
* @param aBooleng = the bool engine to use
* @param aCentre = centre of the arc or circle
* @param aStart = start point of the arc, or apoint of the circle
* @param aArcAngle = arc angle in 0.1 degrees. For a circle, aArcAngle = 3600
* @param aWidth = width of the line
*/
void
AddRingPolygon
(
Bool_Engine
*
aBooleng
,
wxPoint
aCentre
,
wxPoint
aStart
,
int
aArcAngle
,
int
aWidth
)
{
wxPoint
arc_start
,
arc_end
;
int
delta
=
3600
/
s_CircleToSegmentsCount
;
// rot angle in 0.1 degree
arc_end
=
arc_start
=
aStart
;
if
(
aArcAngle
!=
3600
)
{
RotatePoint
(
&
arc_end
,
aCentre
,
-
aArcAngle
);
}
if
(
aArcAngle
<
0
)
{
EXCHG
(
arc_start
,
arc_end
);
NEGATE
(
aArcAngle
);
}
// Compute the ends of segments and creates poly
wxPoint
curr_end
=
arc_start
,
curr_start
=
arc_start
;
for
(
int
ii
=
delta
;
ii
<
aArcAngle
;
ii
+=
delta
)
{
curr_end
=
arc_start
;
RotatePoint
(
&
curr_end
,
aCentre
,
-
ii
);
AddRoundedEndsSegmentPolygon
(
aBooleng
,
curr_start
,
curr_end
,
aWidth
);
curr_start
=
curr_end
;
}
if
(
curr_end
!=
arc_end
)
AddRoundedEndsSegmentPolygon
(
aBooleng
,
curr_end
,
arc_end
,
aWidth
);
}
/** function AddTextBoxWithClearancePolygon
* creates a polygon containing the text and add it to bool engine
*/
void
AddTextBoxWithClearancePolygon
(
Bool_Engine
*
aBooleng
,
TEXTE_PCB
*
aText
,
int
aClearanceValue
)
{
if
(
aText
->
GetLength
()
==
0
)
return
;
wxPoint
corners
[
4
];
// Buffer of polygon corners
EDA_Rect
rect
=
aText
->
GetTextBox
(
-
1
);
rect
.
Inflate
(
aClearanceValue
,
aClearanceValue
);
corners
[
0
]
=
rect
.
GetOrigin
();
corners
[
1
].
y
=
corners
[
0
].
y
;
corners
[
1
].
x
=
rect
.
GetRight
();
corners
[
2
].
x
=
corners
[
1
].
x
;
corners
[
2
].
y
=
rect
.
GetBottom
();
corners
[
3
].
y
=
corners
[
2
].
y
;
corners
[
3
].
x
=
corners
[
0
].
x
;
if
(
aBooleng
->
StartPolygonAdd
(
GROUP_B
)
)
{
for
(
int
ii
=
0
;
ii
<
4
;
ii
++
)
{
// Rotate polygon
RotatePoint
(
&
corners
[
ii
].
x
,
&
corners
[
ii
].
y
,
aText
->
m_Pos
.
x
,
aText
->
m_Pos
.
y
,
aText
->
m_Orient
);
aBooleng
->
AddPoint
(
corners
[
ii
].
x
,
corners
[
ii
].
y
);
}
aBooleng
->
EndPolygonAdd
();
}
}
/***********************************************************************************************************/
/***********************************************************************************************************/
int
ZONE_CONTAINER
::
CopyPolygonsFromFilledPolysListToBoolengine
(
Bool_Engine
*
aBoolengine
,
int
ZONE_CONTAINER
::
CopyPolygonsFromFilledPolysListToBoolengine
(
Bool_Engine
*
aBoolengine
,
GroupType
aGroup
)
GroupType
aGroup
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment