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
Show 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 @@
* @param aCornerBuffer = a buffer to store the polygon
* @param aStart = the segment start 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 aWidth = the segment width
*/
void
TransformRoundedEndsSegmentToPolygon
(
std
::
vector
<
wxPoin
t
>&
aCornerBuffer
,
void
TransformRoundedEndsSegmentToPolygon
(
std
::
vector
<
CPolyP
t
>&
aCornerBuffer
,
wxPoint
aStart
,
wxPoint
aEnd
,
int
aCircleToSegmentsCount
,
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
* Used in filling zones calculations
* Circles (vias) and arcs (ends of tracks) are approximated by segments
...
...
@@ -41,7 +176,7 @@ void TransformRoundedEndsSegmentToPolygon( std::vector <wxPoint>& aCornerBuffer,
* clearance when the circle is approxiamted by segment bigger or equal
* 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
aCircleToSegmentsCount
,
double
aCorrectionFactor
)
...
...
@@ -49,7 +184,6 @@ void TRACK::TransformTrackWithClearanceToPolygon( std::vector <wxPoint>& aCorner
wxPoint
corner_position
;
int
ii
,
angle
;
int
dx
=
(
m_Width
/
2
)
+
aClearanceValue
;
int
delta
=
3600
/
aCircleToSegmentsCount
;
// rot angle in 0.1 degree
switch
(
Type
()
)
...
...
@@ -59,19 +193,25 @@ void TRACK::TransformTrackWithClearanceToPolygon( std::vector <wxPoint>& aCorner
for
(
ii
=
0
;
ii
<
aCircleToSegmentsCount
;
ii
++
)
{
corner_position
=
wxPoint
(
dx
,
0
);
RotatePoint
(
&
corner_position
,
(
1800
/
aCircleToSegmentsCount
)
);
RotatePoint
(
&
corner_position
.
x
,
&
corner_position
.
y
,
(
1800
/
aCircleToSegmentsCount
)
);
angle
=
ii
*
delta
;
RotatePoint
(
&
corner_position
,
angle
);
corner_position
+=
m_Start
;
aCornerBuffer
.
push_back
(
corner_position
);
RotatePoint
(
&
corner_position
.
x
,
&
corner_position
.
y
,
angle
);
corner_position
.
x
+=
m_Start
.
x
;
corner_position
.
y
+=
m_Start
.
y
;
CPolyPt
polypoint
(
corner_position
.
x
,
corner_position
.
y
);
aCornerBuffer
.
push_back
(
polypoint
);
}
aCornerBuffer
.
back
().
end_contour
=
true
;
break
;
default
:
TransformRoundedEndsSegmentToPolygon
(
aCornerBuffer
,
m_Start
,
m_End
,
aCircleToSegmentsCount
,
m_Width
+
(
2
*
aClearanceValue
)
);
TransformRoundedEndsSegmentToPolygon
(
aCornerBuffer
,
m_Start
,
m_End
,
aCircleToSegmentsCount
,
m_Width
+
(
2
*
aClearanceValue
)
);
break
;
}
}
...
...
@@ -79,7 +219,7 @@ void TRACK::TransformTrackWithClearanceToPolygon( std::vector <wxPoint>& aCorner
/* Function TransformRoundedEndsSegmentToPolygon
*/
void
TransformRoundedEndsSegmentToPolygon
(
std
::
vector
<
wxPoin
t
>&
aCornerBuffer
,
void
TransformRoundedEndsSegmentToPolygon
(
std
::
vector
<
CPolyP
t
>&
aCornerBuffer
,
wxPoint
aStart
,
wxPoint
aEnd
,
int
aCircleToSegmentsCount
,
int
aWidth
)
...
...
@@ -89,6 +229,7 @@ void TransformRoundedEndsSegmentToPolygon( std::vector <wxPoint>& aCornerBuffer,
wxPoint
startp
=
aStart
;
wxPoint
corner
;
int
seg_len
;
CPolyPt
polypoint
;
// normalize the position in order to have endp.x >= 0;
if
(
endp
.
x
<
0
)
...
...
@@ -105,12 +246,16 @@ void TransformRoundedEndsSegmentToPolygon( std::vector <wxPoint>& aCornerBuffer,
corner
=
wxPoint
(
0
,
rayon
);
RotatePoint
(
&
corner
,
-
delta_angle
);
corner
+=
startp
;
aCornerBuffer
.
push_back
(
corner
);
polypoint
.
x
=
corner
.
x
;
polypoint
.
y
=
corner
.
y
;
aCornerBuffer
.
push_back
(
polypoint
);
corner
=
wxPoint
(
seg_len
,
rayon
);
RotatePoint
(
&
corner
,
-
delta_angle
);
corner
+=
startp
;
aCornerBuffer
.
push_back
(
corner
);
polypoint
.
x
=
corner
.
x
;
polypoint
.
y
=
corner
.
y
;
aCornerBuffer
.
push_back
(
polypoint
);
// add right rounded end:
for
(
int
ii
=
delta
;
ii
<
1800
;
ii
+=
delta
)
...
...
@@ -120,18 +265,24 @@ void TransformRoundedEndsSegmentToPolygon( std::vector <wxPoint>& aCornerBuffer,
corner
.
x
+=
seg_len
;
RotatePoint
(
&
corner
,
-
delta_angle
);
corner
+=
startp
;
aCornerBuffer
.
push_back
(
corner
);
polypoint
.
x
=
corner
.
x
;
polypoint
.
y
=
corner
.
y
;
aCornerBuffer
.
push_back
(
polypoint
);
}
corner
=
wxPoint
(
seg_len
,
-
rayon
);
RotatePoint
(
&
corner
,
-
delta_angle
);
corner
+=
startp
;
aCornerBuffer
.
push_back
(
corner
);
polypoint
.
x
=
corner
.
x
;
polypoint
.
y
=
corner
.
y
;
aCornerBuffer
.
push_back
(
polypoint
);
corner
=
wxPoint
(
0
,
-
rayon
);
RotatePoint
(
&
corner
,
-
delta_angle
);
corner
+=
startp
;
aCornerBuffer
.
push_back
(
corner
);
polypoint
.
x
=
corner
.
x
;
polypoint
.
y
=
corner
.
y
;
aCornerBuffer
.
push_back
(
polypoint
);
// add left rounded end:
for
(
int
ii
=
delta
;
ii
<
1800
;
ii
+=
delta
)
...
...
@@ -140,12 +291,16 @@ void TransformRoundedEndsSegmentToPolygon( std::vector <wxPoint>& aCornerBuffer,
RotatePoint
(
&
corner
,
ii
);
RotatePoint
(
&
corner
,
-
delta_angle
);
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
* Used in filling zones calculations
* Circles and arcs are approximated by segments
...
...
@@ -156,7 +311,7 @@ void TransformRoundedEndsSegmentToPolygon( std::vector <wxPoint>& aCornerBuffer,
* clearance when the circle is approxiamted by segment bigger or equal
* 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
aCircleToSegmentsCount
,
double
aCorrectionFactor
)
...
...
@@ -180,13 +335,17 @@ void D_PAD::TransformPadWithClearanceToPolygon( std::vector <wxPoint>& aCornerBu
for
(
ii
=
0
;
ii
<
aCircleToSegmentsCount
;
ii
++
)
{
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
;
RotatePoint
(
&
corner_position
,
angle
);
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
;
case
PAD_OVAL
:
...
...
@@ -195,31 +354,38 @@ void D_PAD::TransformPadWithClearanceToPolygon( std::vector <wxPoint>& aCornerBu
{
dy
=
(
int
)
(
dy
*
aCorrectionFactor
);
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
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
,
angle
);
angle_pg
=
ii
*
delta
;
RotatePoint
(
&
corner_position
,
angle_pg
);
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...
{
corner_position
=
wxPoint
(
-
dx
,
0
);
// Coordinate translation -dx
corner_position
=
wxPoint
(
-
dx
,
0
);
// Coordinate translation -dx
RotatePoint
(
&
corner_position
,
(
1800
/
aCircleToSegmentsCount
)
);
RotatePoint
(
&
corner_position
,
angle
);
angle_pg
=
ii
*
delta
;
RotatePoint
(
&
corner_position
,
angle_pg
);
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
;
}
else
//if( dy <= dx )
...
...
@@ -237,7 +403,8 @@ void D_PAD::TransformPadWithClearanceToPolygon( std::vector <wxPoint>& aCornerBu
angle_pg
=
ii
*
delta
;
RotatePoint
(
&
corner_position
,
angle_pg
);
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
++
)
...
...
@@ -248,9 +415,11 @@ void D_PAD::TransformPadWithClearanceToPolygon( std::vector <wxPoint>& aCornerBu
angle_pg
=
ii
*
delta
;
RotatePoint
(
&
corner_position
,
angle_pg
);
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
;
}
...
...
@@ -268,13 +437,20 @@ void D_PAD::TransformPadWithClearanceToPolygon( std::vector <wxPoint>& aCornerBu
for
(
int
i
=
0
;
i
<
aCircleToSegmentsCount
/
4
+
1
;
i
++
)
{
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
;
RotatePoint
(
&
corner_position
,
angle_pg
);
// Rounding vector rotation
RotatePoint
(
&
corner_position
,
angle_pg
);
// Rounding vector rotation
corner_position
-=
psize
/
2
;
// Rounding vector + Pad corner offset
RotatePoint
(
&
corner_position
,
angle
);
// Rotate according to module orientation
RotatePoint
(
&
corner_position
,
angle
);
// Rotate according to module orientation
corner_position
+=
PadShapePos
;
// Shift origin to position
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
++
)
...
...
@@ -286,10 +462,13 @@ void D_PAD::TransformPadWithClearanceToPolygon( std::vector <wxPoint>& aCornerBu
corner_position
-=
wxPoint
(
psize
.
x
/
2
,
-
psize
.
y
/
2
);
RotatePoint
(
&
corner_position
,
angle
);
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
);
RotatePoint
(
&
corner_position
,
(
1800
/
aCircleToSegmentsCount
)
);
...
...
@@ -298,7 +477,8 @@ void D_PAD::TransformPadWithClearanceToPolygon( std::vector <wxPoint>& aCornerBu
corner_position
+=
psize
/
2
;
RotatePoint
(
&
corner_position
,
angle
);
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
++
)
...
...
@@ -310,9 +490,398 @@ void D_PAD::TransformPadWithClearanceToPolygon( std::vector <wxPoint>& aCornerBu
corner_position
-=
wxPoint
(
-
psize
.
x
/
2
,
psize
.
y
/
2
);
RotatePoint
(
&
corner_position
,
angle
);
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
;
}
}
/** 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 @@
#ifndef CLASS_DRAWSEGMENT_H
#define CLASS_DRAWSEGMENT_H
#include "polyline.h"
class
DRAWSEGMENT
:
public
BOARD_ITEM
{
...
...
@@ -116,36 +117,56 @@ public:
return
hypot
(
delta
.
x
,
delta
.
y
);
}
/**
* Function Move
* move 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_End
+=
aMoveVector
;
}
/**
* Function Rotate
* Rotate this object.
* @param const wxPoint& aRotCentre - the rotation point.
* @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
* Flip this object, i.e. change the board side for this object
* @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)
void
Show
(
int
nestLevel
,
std
::
ostream
&
os
);
#endif
#endif
};
...
...
pcbnew/class_pad.h
View file @
f2f4cd53
...
...
@@ -5,6 +5,7 @@
class
Pcb3D_GLCanvas
;
#include "pad_shapes.h"
#include "polyline.h"
/* Default layers used for pads, according to the pad type.
* this is default values only, they can be changed for a given pad
...
...
@@ -141,7 +142,7 @@ public:
m_Pos
=
aPos
;
}
/** function Transform
Pad
WithClearanceToPolygon
/** function Transform
Shape
WithClearanceToPolygon
* Convert the pad shape to a closed polygon
* Used in filling zones calculations
* Circles and arcs are approximated by segments
...
...
@@ -152,7 +153,7 @@ public:
* clearance when the circle is approxiamted by segment bigger or equal
* 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
);
/**
...
...
pcbnew/class_pcb_text.h
View file @
f2f4cd53
...
...
@@ -5,6 +5,7 @@
#define CLASS_PCB_TEXT_H
#include "base_struct.h"
#include "polyline.h"
class
TEXTE_PCB
:
public
BOARD_ITEM
,
public
EDA_TextStruct
{
...
...
@@ -110,6 +111,23 @@ public:
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)
/**
* Function Show
...
...
pcbnew/class_track.h
View file @
f2f4cd53
...
...
@@ -6,6 +6,7 @@
#define CLASS_TRACK_H
#include "base_struct.h"
#include "polyline.h"
// Via attributes (m_Shape parmeter)
...
...
@@ -148,7 +149,7 @@ public:
/* divers */
int
Shape
()
const
{
return
m_Shape
&
0xFF
;
}
/** Function Transform
Track
WithClearanceToPolygon
/** Function Transform
Shape
WithClearanceToPolygon
* Convert the track shape to a closed polygon
* Used in filling zones calculations
* Circles (vias) and arcs (ends of tracks) are approximated by segments
...
...
@@ -159,7 +160,7 @@ public:
* clearance when the circle is approxiamted by segment bigger or equal
* 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
aCircleToSegmentsCount
,
double
aCorrectionFactor
);
...
...
pcbnew/debug_kbool_key_file_fct.cpp
View file @
f2f4cd53
...
...
@@ -14,9 +14,15 @@
#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
char
sDate_Time
[
256
];
static
vector
<
kfcoord
>
s_EntityCoordinates
;
void
CreateKeyFile
()
{
...
...
@@ -48,6 +54,8 @@ void CreateKeyFile()
{
wxMessageBox
(
wxT
(
"CreateKeyFile() cannot create output file"
)
);
}
s_EntityCoordinates
.
clear
();
}
...
...
@@ -58,11 +66,11 @@ void CloseKeyFile()
fprintf
(
kdebugFile
,
"
\n
ENDLIB;
\n
"
);
fclose
(
kdebugFile
);
}
s_EntityCoordinates
.
clear
();
}
const
char
*
sCurrEntityName
=
NULL
;
static
int
s_count
;
void
OpenKeyFileEntity
(
const
char
*
aName
)
{
...
...
@@ -74,7 +82,7 @@ void OpenKeyFileEntity( const char* aName )
fprintf
(
kdebugFile
,
"STRNAME %s;
\n
"
,
aName
);
}
sCurrEntityName
=
aName
;
s_
count
=
0
;
s_
EntityCoordinates
.
clear
()
;
}
...
...
@@ -84,20 +92,45 @@ void CloseKeyFileEntity()
fprintf
(
kdebugFile
,
"
\n
ENDSTR %s;
\n
"
,
sCurrEntityName
);
}
void
StartKeyFilePolygon
(
int
aCornersCount
,
int
aLayer
)
/* start a polygon entity in key file
*/
void
StartKeyFilePolygon
(
int
aLayer
)
{
s_EntityCoordinates
.
clear
();
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
)
fprintf
(
kdebugFile
,
"
\n
"
);
fprintf
(
kdebugFile
,
"
\n
ENDEL;
\n
"
);
s_count
=
0
;
kfcoord
coord
;
coord
.
x
=
aXcoord
;
coord
.
y
=
aYcoord
;
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
)
...
...
@@ -106,30 +139,15 @@ void CopyPolygonsFromFilledPolysListToKeyFile( ZONE_CONTAINER* aZone, int aLayer
return
;
unsigned
corners_count
=
aZone
->
m_FilledPolysList
.
size
();
int
count
=
0
;
unsigned
ic
=
0
;
CPolyPt
*
corner
;
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:
StartKeyFilePolygon
(
count
+
1
,
aLayer
);
corner
=
&
aZone
->
m_FilledPolysList
[
ic
];
int
startpointX
=
corner
->
x
;
int
startpointY
=
corner
->
y
;
// write polygon:
StartKeyFilePolygon
(
aLayer
);
for
(
;
ic
<
corners_count
;
ic
++
)
{
corner
=
&
aZone
->
m_FilledPolysList
[
ic
];
CPolyPt
*
corner
=
&
aZone
->
m_FilledPolysList
[
ic
];
AddKeyFilePointXY
(
corner
->
x
,
corner
->
y
);
if
(
corner
->
end_contour
)
{
...
...
@@ -137,21 +155,8 @@ void CopyPolygonsFromFilledPolysListToKeyFile( ZONE_CONTAINER* aZone, int aLayer
break
;
}
}
// Close polygon:
AddKeyFilePointXY
(
startpointX
,
startpointY
);
EndKeyFileElement
();
}
}
void
AddKeyFilePointXY
(
int
aXcoord
,
int
aYcoord
)
{
if
(
s_count
>=
2
)
{
s_count
=
0
;
fprintf
(
kdebugFile
,
"
\n
"
);
EndKeyFilePolygon
();
}
fprintf
(
kdebugFile
,
" X %d; Y %d;"
,
aXcoord
,
aYcoord
);
s_count
++
;
}
#endif
pcbnew/debug_kbool_key_file_fct.h
View file @
f2f4cd53
...
...
@@ -38,9 +38,9 @@ void CloseKeyFileEntity();
/* polygon creations:
*/
void
CopyPolygonsFromFilledPolysListToKeyFile
(
ZONE_CONTAINER
*
aZone
,
int
aLayer
);
void
StartKeyFilePolygon
(
int
aCornersCount
,
int
aLayer
);
void
StartKeyFilePolygon
(
int
aLayer
);
void
AddKeyFilePointXY
(
int
aXcoord
,
int
aYcoord
);
void
EndKeyFile
Element
();
void
EndKeyFile
Polygon
();
#endif // CREATE_KBOOL_KEY_FILES
...
...
pcbnew/zones_convert_brd_items_to_polygons.cpp
View file @
f2f4cd53
...
...
@@ -51,14 +51,20 @@
extern
void
Test_For_Copper_Island_And_Remove
(
BOARD
*
aPcb
,
ZONE_CONTAINER
*
aZone_container
);
extern
void
TransformRoundedEndsSegmentToPolygon
(
std
::
vector
<
wxPoin
t
>&
aCornerBuffer
,
extern
void
TransformRoundedEndsSegmentToPolygon
(
std
::
vector
<
CPolyP
t
>&
aCornerBuffer
,
wxPoint
aStart
,
wxPoint
aEnd
,
int
aCircleToSegmentsCount
,
int
aWidth
);
#ifdef CREATE_KBOOL_KEY_FILES
bool
s_GenDataForKbool
=
false
;
#endif
void
CreateThermalReliefPadPolygon
(
std
::
vector
<
CPolyPt
>&
aCornerBuffer
,
D_PAD
&
aPad
,
int
aThermalGap
,
int
aCopperThickness
,
int
aMinThicknessValue
,
int
aCircleToSegmentsCount
,
double
aCorrectionFactor
,
int
aThermalRot
);
// Local Functions:
#ifdef USE_STUBS_FOR_THERMAL
...
...
@@ -72,7 +78,7 @@ void CreateStubsForThermalShapes( BOARD* aPcb, ZONE_CONTAINER* aZone_cont
void
AddTrackWithClearancePolygon
(
Bool_Engine
*
aBooleng
,
TRACK
&
aTrack
,
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
,
int
aThermalGap
,
int
aCopperThickness
,
int
aMinThicknessValue
);
...
...
@@ -80,15 +86,6 @@ void AddRoundedEndsSegmentPolygon( Bool_Engine* aBooleng,
wxPoint
aStart
,
wxPoint
aEnd
,
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:
/* how many segments are used to create a polygon from a circle: */
static
int
s_CircleToSegmentsCount
=
16
;
/* default value. the real value will be changed to 32
...
...
@@ -300,47 +297,67 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
if
(
item
->
GetLayer
()
!=
GetLayer
()
&&
item
->
GetLayer
()
!=
EDGE_N
)
continue
;
static
std
::
vector
<
CPolyPt
>
cornerBuffer
;
cornerBuffer
.
clear
();
switch
(
item
->
Type
()
)
{
case
TYPE_DRAWSEGMENT
:
switch
(
(
(
DRAWSEGMENT
*
)
item
)
->
m_Shape
)
{
case
S_CIRCLE
:
AddRingPolygon
(
booleng
,
(
(
DRAWSEGMENT
*
)
item
)
->
m_Start
,
// Circle centre
(
(
DRAWSEGMENT
*
)
item
)
->
m_End
,
3600
,
(
(
DRAWSEGMENT
*
)
item
)
->
m_Width
+
(
2
*
m_ZoneClearance
)
);
have_poly_to_substract
=
true
;
(
(
DRAWSEGMENT
*
)
item
)
->
TransformShapeWithClearanceToPolygon
(
cornerBuffer
,
m_ZoneClearance
,
s_CircleToSegmentsCount
,
s_Correction
);
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
;
case
TYPE_TEXTE
:
(
(
TEXTE_PCB
*
)
item
)
->
TransformShapeWithClearanceToPolygon
(
cornerBuffer
,
m_ZoneClearance
,
s_CircleToSegmentsCount
,
s_Correction
);
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
;
if
(
cornerBuffer
.
size
()
==
0
)
continue
;
case
TYPE_TEXTE
:
AddTextBoxWithClearancePolygon
(
booleng
,
(
TEXTE_PCB
*
)
item
,
m_ZoneClearance
);
// 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
;
}
default
:
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
...
...
@@ -417,11 +434,11 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
item_boundingbox
.
Inflate
(
m_ThermalReliefGapValue
,
m_ThermalReliefGapValue
);
if
(
item_boundingbox
.
Intersects
(
zone_boundingbox
)
)
{
have_poly_to_substract
=
true
;
AddThermalReliefPadPolygon
(
booleng
,
*
pad
,
if
(
AddThermalReliefPadPolygon
(
booleng
,
*
pad
,
m_ThermalReliefGapValue
,
m_ThermalReliefCopperBridgeValue
,
m_ZoneMinThickness
);
m_ZoneMinThickness
)
)
have_poly_to_substract
=
true
;
}
}
}
...
...
@@ -613,11 +630,11 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
void
AddPadWithClearancePolygon
(
Bool_Engine
*
aBooleng
,
D_PAD
&
aPad
,
int
aClearanceValue
)
{
static
std
::
vector
<
wxPoin
t
>
cornerBuffer
;
static
std
::
vector
<
CPolyP
t
>
cornerBuffer
;
if
(
aBooleng
->
StartPolygonAdd
(
GROUP_B
)
==
0
)
return
;
cornerBuffer
.
clear
();
aPad
.
Transform
Pad
WithClearanceToPolygon
(
cornerBuffer
,
aPad
.
Transform
Shape
WithClearanceToPolygon
(
cornerBuffer
,
aClearanceValue
,
s_CircleToSegmentsCount
,
s_Correction
);
...
...
@@ -628,13 +645,11 @@ void AddPadWithClearancePolygon( Bool_Engine* aBooleng,
aBooleng
->
EndPolygonAdd
();
#ifdef CREATE_KBOOL_KEY_FILES_FIRST_PASS
StartKeyFilePolygon
(
cornerBuffer
.
size
()
+
1
,
1
);
StartKeyFilePolygon
(
1
);
for
(
unsigned
ii
=
0
;
ii
<
cornerBuffer
.
size
();
ii
++
)
AddKeyFilePointXY
(
cornerBuffer
[
ii
].
x
,
cornerBuffer
[
ii
].
y
);
// Close polygon
AddKeyFilePointXY
(
cornerBuffer
[
0
].
x
,
cornerBuffer
[
0
].
y
);
EndKeyFileElement
();
EndKeyFilePolygon
();
#endif
}
...
...
@@ -642,6 +657,7 @@ void AddPadWithClearancePolygon( Bool_Engine* aBooleng,
/** function CreateStubsForThermalShapes()
* Only for testing the thermal shapes by stubs purposes
* Do not use for working pcbnew versions
* This is just for kbool test only
*/
void
CreateStubsForThermalShapes
(
BOARD
*
aPcb
,
ZONE_CONTAINER
*
aZone_container
,
int
aThermalGap
,
...
...
@@ -658,9 +674,6 @@ void CreateStubsForThermalShapes( BOARD* aPcb, ZONE_CONTAINER* aZone_cont
if
(
aCopperThickness
<=
aMinThicknessValue
)
return
;
#ifdef CREATE_KBOOL_KEY_FILES
s_GenDataForKbool
=
true
;
#endif
for
(
MODULE
*
module
=
aPcb
->
m_Modules
;
module
;
module
=
module
->
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
}
}
#ifdef CREATE_KBOOL_KEY_FILES
s_GenDataForKbool
=
false
;
#endif
if
(
have_poly_to_add
)
{
/* 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
* 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.
* see CreateThermalReliefPadPolygon().
*/
void
AddThermalReliefPadPolygon
(
Bool_Engine
*
aBooleng
,
int
AddThermalReliefPadPolygon
(
Bool_Engine
*
aBooleng
,
D_PAD
&
aPad
,
int
aThermalGap
,
int
aCopperThickness
,
int
aMinThicknessValue
)
{
wxPoint
corner
,
corner_end
;
wxPoint
PadShapePos
=
aPad
.
ReturnShapePos
();
/* Note: for pad having a shape offset,
* 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
);
static
std
::
vector
<
CPolyPt
>
cornerBuffer
;
cornerBuffer
.
clear
();
/* 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)
// 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
int
polycount
=
0
;
int
thermalRot
=
450
;
#ifdef CREATE_KBOOL_KEY_FILES_WITH_0_DEG
angle
=
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
);
thermalRot
=
0
;
#endif
}
#ifdef CREATE_KBOOL_KEY_FILES
// Close polygon
corner
=
corners_buffer
[
0
];
RotatePoint
(
&
corner
,
angle
+
angle_pad
);
// Rotate by segment angle and pad orientation
corner
+=
PadShapePos
;
AddKeyFilePointXY
(
corner
.
x
,
corner
.
y
);
#endif
aBooleng
->
EndPolygonAdd
();
#ifdef CREATE_KBOOL_KEY_FILES
EndKeyFileElement
();
#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
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.
*/
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
for
(
unsigned
ic
=
0
;
ic
<
corners_buffer
.
size
();
ic
++
)
{
wxPoint
swap
=
corners_buffer
[
ic
];
swap
.
x
=
-
swap
.
x
;
corners_buffer
[
ic
]
=
swap
;
}
CreateThermalReliefPadPolygon
(
cornerBuffer
,
aPad
,
aThermalGap
,
aCopperThickness
,
aMinThicknessValue
,
s_CircleToSegmentsCount
,
s_Correction
,
thermalRot
);
// 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
++
)
{
if
(
aBooleng
->
StartPolygonAdd
(
GROUP_B
)
)
// 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
();
)
{
for
(
unsigned
ic
=
0
;
ic
<
corners_buffer
.
size
();
ic
++
)
aBooleng
->
StartPolygonAdd
(
GROUP_B
);
polycount
++
;
unsigned
ii
;
for
(
ii
=
icnt
;
ii
<
cornerBuffer
.
size
();
ii
++
)
{
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
;
}
}
}
aBooleng
->
AddPoint
(
cornerBuffer
[
ii
].
x
,
cornerBuffer
[
ii
].
y
);
if
(
cornerBuffer
[
ii
].
end_contour
)
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
)
);
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
++
)
#ifdef CREATE_KBOOL_KEY_FILES
StartKeyFilePolygon
(
1
);
for
(
ii
=
icnt
;
ii
<
cornerBuffer
.
size
();
ii
++
)
{
wxPoint
swap
=
corners_buffer
[
ic
]
;
swap
.
x
=
-
swap
.
x
;
corners_buffer
[
ic
]
=
swap
;
AddKeyFilePointXY
(
cornerBuffer
[
ii
].
x
,
cornerBuffer
[
ii
].
y
)
;
if
(
cornerBuffer
[
ii
].
end_contour
)
break
;
}
// 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
);
}
EndKeyFilePolygon
();
#endif
aBooleng
->
EndPolygonAdd
();
angle
+=
1800
;
if
(
angle
>=
3600
)
angle
-=
3600
;
}
icnt
=
ii
+
1
;
}
break
;
}
}
return
polycount
;
}
...
...
@@ -1182,9 +848,9 @@ void AddThermalReliefPadPolygon( Bool_Engine* aBooleng,
void
AddTrackWithClearancePolygon
(
Bool_Engine
*
aBooleng
,
TRACK
&
aTrack
,
int
aClearanceValue
)
{
static
std
::
vector
<
wxPoin
t
>
cornerBuffer
;
static
std
::
vector
<
CPolyP
t
>
cornerBuffer
;
cornerBuffer
.
clear
();
aTrack
.
Transform
Track
WithClearanceToPolygon
(
cornerBuffer
,
aTrack
.
Transform
Shape
WithClearanceToPolygon
(
cornerBuffer
,
aClearanceValue
,
s_CircleToSegmentsCount
,
s_Correction
);
...
...
@@ -1198,13 +864,11 @@ void AddTrackWithClearancePolygon( Bool_Engine* aBooleng,
aBooleng
->
EndPolygonAdd
();
#ifdef CREATE_KBOOL_KEY_FILES_FIRST_PASS
StartKeyFilePolygon
(
cornerBuffer
.
size
()
+
1
,
1
);
StartKeyFilePolygon
(
1
);
for
(
unsigned
ii
=
0
;
ii
<
cornerBuffer
.
size
();
ii
++
)
AddKeyFilePointXY
(
cornerBuffer
[
ii
].
x
,
cornerBuffer
[
ii
].
y
);
// Close polygon
AddKeyFilePointXY
(
cornerBuffer
[
0
].
x
,
cornerBuffer
[
0
].
y
);
EndKeyFileElement
();
EndKeyFilePolygon
();
#endif
}
...
...
@@ -1217,7 +881,7 @@ void AddRoundedEndsSegmentPolygon( Bool_Engine* aBooleng,
wxPoint
aStart
,
wxPoint
aEnd
,
int
aWidth
)
{
static
std
::
vector
<
wxPoin
t
>
cornerBuffer
;
static
std
::
vector
<
CPolyP
t
>
cornerBuffer
;
cornerBuffer
.
clear
();
TransformRoundedEndsSegmentToPolygon
(
cornerBuffer
,
aStart
,
aEnd
,
...
...
@@ -1233,100 +897,15 @@ void AddRoundedEndsSegmentPolygon( Bool_Engine* aBooleng,
aBooleng
->
EndPolygonAdd
();
#ifdef CREATE_KBOOL_KEY_FILES
StartKeyFilePolygon
(
cornerBuffer
.
size
()
+
1
,
1
);
StartKeyFilePolygon
(
1
);
for
(
unsigned
ii
=
0
;
ii
<
cornerBuffer
.
size
();
ii
++
)
AddKeyFilePointXY
(
cornerBuffer
[
ii
].
x
,
cornerBuffer
[
ii
].
y
);
// Close polygon
AddKeyFilePointXY
(
cornerBuffer
[
0
].
x
,
cornerBuffer
[
0
].
y
);
EndKeyFileElement
();
EndKeyFilePolygon
();
#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
,
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