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
c5973eb8
Commit
c5973eb8
authored
May 07, 2015
by
Mikhail Karpenko
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add documentation to .h files and update code formatting
parent
c25acdbb
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
827 additions
and
417 deletions
+827
-417
class_teardrop.cpp
pcbnew/class_teardrop.cpp
+223
-135
class_teardrop.h
pcbnew/class_teardrop.h
+79
-42
dialog_teardrops.cpp
pcbnew/dialogs/dialog_teardrops.cpp
+138
-89
dialog_teardrops.h
pcbnew/dialogs/dialog_teardrops.h
+91
-20
edit_teardrops.cpp
pcbnew/tools/edit_teardrops.cpp
+212
-114
edit_teardrops.h
pcbnew/tools/edit_teardrops.h
+84
-17
No files found.
pcbnew/class_teardrop.cpp
View file @
c5973eb8
...
@@ -11,54 +11,69 @@ TEARDROP::TEARDROP()
...
@@ -11,54 +11,69 @@ TEARDROP::TEARDROP()
m_type
=
TEARDROP_NONE
;
m_type
=
TEARDROP_NONE
;
}
}
bool
TEARDROP
::
Create
(
TRACK
&
aTrack
,
ENDPOINT_T
endPoint
,
TEARDROP_TYPE
type
=
TEARDROP_STRAIGHT
)
bool
TEARDROP
::
Create
(
TRACK
&
aTrack
,
ENDPOINT_T
aEndPoint
,
TEARDROP_TYPE
aType
=
TEARDROP_STRAIGHT
)
{
{
bool
result
=
false
;
bool
result
=
false
;
BOARD_CONNECTED_ITEM
*
anObject
=
GetObjectOnEnd
(
aTrack
,
endPoint
);
BOARD_CONNECTED_ITEM
*
object
=
getObjectOnEnd
(
aTrack
,
aEndPoint
);
VIA
*
aVia
=
NULL
;
VIA
*
aVia
=
NULL
;
if
(
anObject
==
NULL
)
{
if
(
object
==
NULL
)
{
return
false
;
return
false
;
}
}
else
{
else
switch
(
anObject
->
Type
())
{
{
switch
(
object
->
Type
()
)
{
case
PCB_VIA_T
:
case
PCB_VIA_T
:
aVia
=
dynamic_cast
<
VIA
*>
(
anObject
);
aVia
=
dynamic_cast
<
VIA
*>
(
object
);
break
;
break
;
case
PCB_PAD_T
:
case
PCB_PAD_T
:
aVia
=
new
VIA
(
NULL
);
aVia
=
new
VIA
(
NULL
);
aVia
->
SetLayer
(
anObject
->
GetLayer
());
aVia
->
SetPosition
(
anObject
->
GetPosition
());
aVia
->
SetLayer
(
object
->
GetLayer
()
);
aVia
->
SetWidth
(
2
*
dynamic_cast
<
D_PAD
*>
(
anObject
)
->
GetBoundingRadius
());
aVia
->
SetPosition
(
object
->
GetPosition
()
);
aVia
->
SetWidth
(
2
*
dynamic_cast
<
D_PAD
*>
(
object
)
->
GetBoundingRadius
()
);
break
;
break
;
default
:
default
:
break
;
break
;
}
}
}
}
if
(
type
==
TEARDROP_STRAIGHT
)
{
if
(
aType
==
TEARDROP_STRAIGHT
)
result
=
StraightSegments
(
aTrack
,
*
aVia
,
100
);
{
result
=
straightSegments
(
aTrack
,
*
aVia
,
100
);
}
}
else
if
(
type
==
TEARDROP_CURVED
)
{
else
if
(
aType
==
TEARDROP_CURVED
)
result
=
CurvedSegments
(
aTrack
,
*
aVia
);
{
result
=
curvedSegments
(
aTrack
,
*
aVia
);
}
}
return
result
;
return
result
;
}
}
bool
TEARDROP
::
SetVector
(
TRACK
&
aTrack
,
const
VIA
&
aVia
,
VECTOR2I
&
startPoint
,
VECTOR2I
&
endPoint
)
bool
TEARDROP
::
setVector
(
TRACK
&
aTrack
,
const
VIA
&
aVia
,
VECTOR2I
&
aStartPoint
,
VECTOR2I
&
aEndPoint
)
{
{
// Decide which end of the track is inside via and set this point as end of vector
// Decide which end of the track is inside via and set this point as end of vector
STATUS_FLAGS
status
=
aTrack
.
IsPointOnEnds
(
aVia
.
GetPosition
(),
aVia
.
GetWidth
()
/
2
);
STATUS_FLAGS
status
=
aTrack
.
IsPointOnEnds
(
aVia
.
GetPosition
(),
aVia
.
GetWidth
()
/
2
);
if
(
status
==
STARTPOINT
)
{
startPoint
=
aTrack
.
GetEnd
();
if
(
status
==
STARTPOINT
)
endPoint
=
aTrack
.
GetStart
();
{
aStartPoint
=
aTrack
.
GetEnd
();
aEndPoint
=
aTrack
.
GetStart
();
}
}
else
if
(
status
==
ENDPOINT
)
{
else
if
(
status
==
ENDPOINT
)
startPoint
=
aTrack
.
GetStart
();
{
endPoint
=
aTrack
.
GetEnd
();
aStartPoint
=
aTrack
.
GetStart
();
aEndPoint
=
aTrack
.
GetEnd
();
}
}
else
{
else
{
// The via is too far from any end or the track is too short
// The via is too far from any end or the track is too short
return
false
;
return
false
;
}
}
...
@@ -66,88 +81,120 @@ bool TEARDROP::SetVector(TRACK &aTrack, const VIA & aVia, VECTOR2I &startPoint,
...
@@ -66,88 +81,120 @@ bool TEARDROP::SetVector(TRACK &aTrack, const VIA & aVia, VECTOR2I &startPoint,
return
true
;
return
true
;
}
}
bool
TEARDROP
::
CurvedSegments
(
TRACK
&
aTrack
,
const
VIA
&
aVia
)
bool
TEARDROP
::
curvedSegments
(
TRACK
&
aTrack
,
const
VIA
&
aVia
)
{
{
VECTOR2I
startPoint
(
0
,
0
);
VECTOR2I
startPoint
(
0
,
0
);
VECTOR2I
endPoint
(
0
,
0
);
VECTOR2I
endPoint
(
0
,
0
);
std
::
vector
<
VECTOR2I
>
upperSegment
;
std
::
vector
<
VECTOR2I
>
lowerSegment
;
std
::
vector
<
VECTOR2I
>
lowerSegment
;
if
(
!
SetVector
(
aTrack
,
aVia
,
startPoint
,
endPoint
)
)
{
if
(
!
setVector
(
aTrack
,
aVia
,
startPoint
,
endPoint
)
)
{
return
false
;
return
false
;
}
}
// Check that the track is not too short
// Check that the track is not too short
double
segOutsideVia
=
aTrack
.
GetLength
()
-
(
aVia
.
GetWidth
()
/
2
);
double
segOutsideVia
=
aTrack
.
GetLength
()
-
(
aVia
.
GetWidth
()
/
2
);
double
minLength
=
(
150
*
aVia
.
GetWidth
()
/
2
)
/
100
;
double
minLength
=
(
150
*
aVia
.
GetWidth
()
/
2
)
/
100
;
if
(
segOutsideVia
<
minLength
)
{
if
(
segOutsideVia
<
minLength
)
{
return
false
;
return
false
;
}
}
VECTOR2I
point
(
0
,
0
);
VECTOR2I
point
(
0
,
0
);
VECTOR2I
viaCenter
(
aVia
.
GetPosition
().
x
,
aVia
.
GetPosition
().
y
);
VECTOR2I
viaCenter
(
aVia
.
GetPosition
().
x
,
aVia
.
GetPosition
().
y
);
VECTOR2I
apertureUpper
(
0
,
0
);
VECTOR2I
apertureUpper
(
0
,
0
);
VECTOR2I
apertureLower
(
0
,
0
);
VECTOR2I
apertureLower
(
0
,
0
);
double
radius
=
(
aVia
.
GetWidth
()
/
2
)
-
(
aTrack
.
GetWidth
()
/
2
);
double
radius
=
(
aVia
.
GetWidth
()
/
2
)
-
(
aTrack
.
GetWidth
()
/
2
);
double
rotationAngle
=
VECTOR2I
(
startPoint
-
endPoint
).
Angle
();
double
rotationAngle
=
VECTOR2I
(
startPoint
-
endPoint
).
Angle
();
// Calculate the segments of deltoid composing the outline of a teardrop
// Calculate the segments of deltoid composing the outline of a teardrop
for
(
int
i
=
10
;
i
<=
60
;
i
=
i
+
10
)
{
for
(
int
i
=
0
;
i
<=
60
;
i
=
i
+
10
)
PointOnCurve
(
i
,
radius
,
point
);
{
point
=
point
.
Rotate
(
rotationAngle
);
pointOnCurve
(
i
,
radius
,
point
);
point
=
point
.
Rotate
(
rotationAngle
);
point
+=
viaCenter
;
point
+=
viaCenter
;
m_coordinates
.
push_back
(
point
);
m_coordinates
.
push_back
(
point
);
if
(
i
==
50
)
{
if
(
i
==
50
)
{
apertureUpper
=
point
;
apertureUpper
=
point
;
}
}
}
}
for
(
int
i
=
300
;
i
<=
350
;
i
=
i
+
10
)
{
PointOnCurve
(
i
,
radius
,
point
);
for
(
int
i
=
300
;
i
<=
360
;
i
=
i
+
10
)
point
=
point
.
Rotate
(
rotationAngle
);
{
pointOnCurve
(
i
,
radius
,
point
);
point
=
point
.
Rotate
(
rotationAngle
);
point
+=
viaCenter
;
point
+=
viaCenter
;
m_coordinates
.
push_back
(
point
);
m_coordinates
.
push_back
(
point
);
if
(
i
==
340
)
{
if
(
i
==
340
)
{
apertureLower
=
point
;
apertureLower
=
point
;
}
}
}
}
// Calculate the number of segments needed to fill the area inside the teardrop
// Calculate the number of segments needed to fill the area inside the teardrop
if
(
aVia
.
GetWidth
()
/
2
>
2
*
aTrack
.
GetWidth
())
{
if
(
aVia
.
GetWidth
()
/
2
>
2
*
aTrack
.
GetWidth
()
)
{
// First, calculate the distance between two points on both sides of the track and
// First, calculate the distance between two points on both sides of the track and
// number of iterations required to fill the zone
// number of iterations required to fill the zone
SEG
aperture
(
apertureUpper
,
apertureLower
);
SEG
aperture
(
apertureUpper
,
apertureLower
);
int
numSegments
=
aperture
.
Length
()
/
aTrack
.
GetWidth
();
int
numSegments
=
aperture
.
Length
()
/
aTrack
.
GetWidth
();
int
delta
=
radius
/
numSegments
;
int
delta
=
radius
/
numSegments
;
for
(
int
iteration
=
0
;
iteration
<
numSegments
;
iteration
++
)
{
// Second, fill the inward teardrop area
for
(
int
iteration
=
0
;
iteration
<
numSegments
;
iteration
++
)
{
radius
=
radius
-
delta
;
radius
=
radius
-
delta
;
for
(
int
i
=
10
;
i
<=
60
;
i
=
i
+
10
)
{
for
(
int
i
=
10
;
i
<=
60
;
i
=
i
+
10
)
PointOnCurve
(
i
,
radius
,
point
);
{
point
=
point
.
Rotate
(
rotationAngle
);
pointOnCurve
(
i
,
radius
,
point
);
point
=
point
.
Rotate
(
rotationAngle
);
point
+=
viaCenter
;
point
+=
viaCenter
;
if
(
i
==
10
)
{
int
distance
=
SEG
(
viaCenter
,
point
).
Length
();
// Stop calculations in case the coordinates are inside the via
if
(
distance
<
aVia
.
GetWidth
()
/
2
)
{
if
(
i
==
10
)
{
int
distance
=
SEG
(
viaCenter
,
point
).
Length
();
if
(
distance
<
aVia
.
GetWidth
()
/
2
)
{
break
;
break
;
}
}
}
}
m_coordinates
.
push_back
(
point
);
m_coordinates
.
push_back
(
point
);
}
}
lowerSegment
.
clear
();
lowerSegment
.
clear
();
for
(
int
i
=
350
;
i
>=
300
;
i
=
i
-
10
)
{
for
(
int
i
=
350
;
i
>=
300
;
i
=
i
-
10
)
PointOnCurve
(
i
,
radius
,
point
);
{
point
=
point
.
Rotate
(
rotationAngle
);
pointOnCurve
(
i
,
radius
,
point
);
point
=
point
.
Rotate
(
rotationAngle
);
point
+=
viaCenter
;
point
+=
viaCenter
;
if
(
i
==
350
)
{
int
distance
=
SEG
(
viaCenter
,
point
).
Length
();
// Stop calculations in case the coordinates are inside the via
if
(
distance
<
aVia
.
GetWidth
()
/
2
)
{
if
(
i
==
350
)
{
int
distance
=
SEG
(
viaCenter
,
point
).
Length
();
if
(
distance
<
aVia
.
GetWidth
()
/
2
)
{
break
;
break
;
}
}
}
}
lowerSegment
.
push_back
(
point
);
lowerSegment
.
push_back
(
point
);
}
}
// Revert coordinates order
for
(
std
::
vector
<
VECTOR2I
>::
reverse_iterator
iter
=
lowerSegment
.
rbegin
();
iter
!=
lowerSegment
.
rend
();
++
iter
)
{
// Revert coordinates order. This is necessary to create tracks in correct order later on
m_coordinates
.
push_back
(
*
iter
);
for
(
std
::
vector
<
VECTOR2I
>::
reverse_iterator
iter
=
lowerSegment
.
rbegin
();
iter
!=
lowerSegment
.
rend
();
++
iter
)
{
m_coordinates
.
push_back
(
*
iter
);
}
}
}
}
}
}
...
@@ -155,140 +202,173 @@ bool TEARDROP::CurvedSegments(TRACK &aTrack, const VIA &aVia)
...
@@ -155,140 +202,173 @@ bool TEARDROP::CurvedSegments(TRACK &aTrack, const VIA &aVia)
return
true
;
return
true
;
}
}
bool
TEARDROP
::
StraightSegments
(
TRACK
&
aTrack
,
const
VIA
&
aVia
,
int
distance
=
100
)
bool
TEARDROP
::
straightSegments
(
TRACK
&
aTrack
,
const
VIA
&
aVia
,
int
aDistance
=
100
)
{
{
VECTOR2I
startPoint
(
0
,
0
);
VECTOR2I
startPoint
(
0
,
0
);
VECTOR2I
endPoint
(
0
,
0
);
VECTOR2I
endPoint
(
0
,
0
);
VECTOR2I
viaCenter
(
aVia
.
GetPosition
().
x
,
aVia
.
GetPosition
().
y
);
VECTOR2I
viaCenter
(
aVia
.
GetPosition
().
x
,
aVia
.
GetPosition
().
y
);
if
(
!
SetVector
(
aTrack
,
aVia
,
startPoint
,
endPoint
)
)
{
if
(
!
setVector
(
aTrack
,
aVia
,
startPoint
,
endPoint
)
)
{
return
false
;
return
false
;
}
}
// Check that the track is not too short
// Check that the track is not too short
double
segOutsideVia
=
aTrack
.
GetLength
()
-
(
aVia
.
GetWidth
()
/
2
);
double
segOutsideVia
=
aTrack
.
GetLength
()
-
(
aVia
.
GetWidth
()
/
2
);
double
minLength
=
(
distance
*
aVia
.
GetWidth
()
/
2
)
/
100
;
double
minLength
=
(
aDistance
*
aVia
.
GetWidth
()
/
2
)
/
100
;
if
(
segOutsideVia
<
minLength
)
{
if
(
segOutsideVia
<
minLength
)
{
return
false
;
return
false
;
}
}
// Equation coefficients
// Equation coefficients
double
r
=
(
aVia
.
GetWidth
()
/
2
)
+
((
distance
*
aVia
.
GetWidth
())
/
(
2
*
100
));
double
r
=
(
aVia
.
GetWidth
()
/
2
)
+
(
(
aDistance
*
aVia
.
GetWidth
())
/
(
2
*
100
)
);
double
a
=
pow
((
endPoint
.
x
-
startPoint
.
x
),
2
)
+
pow
((
endPoint
.
y
-
startPoint
.
y
),
2
);
double
a
=
pow
(
(
endPoint
.
x
-
startPoint
.
x
),
2
)
+
pow
(
(
endPoint
.
y
-
startPoint
.
y
),
2
);
double
b
=
2
*
(
double
)(
endPoint
.
x
-
startPoint
.
x
)
*
(
double
)(
startPoint
.
x
-
viaCenter
.
x
)
+
2
*
(
double
)(
endPoint
.
y
-
startPoint
.
y
)
*
(
double
)(
startPoint
.
y
-
viaCenter
.
y
);
double
b
=
2
*
(
double
)(
endPoint
.
x
-
startPoint
.
x
)
*
(
double
)(
startPoint
.
x
-
viaCenter
.
x
)
+
double
c
=
pow
((
startPoint
.
x
-
viaCenter
.
x
),
2
)
+
pow
((
startPoint
.
y
-
viaCenter
.
y
),
2
)
-
pow
(
r
,
2
);
2
*
(
double
)(
endPoint
.
y
-
startPoint
.
y
)
*
(
double
)(
startPoint
.
y
-
viaCenter
.
y
);
double
t
=
2
*
c
/
(
-
b
+
sqrt
(
b
*
b
-
4
*
a
*
c
));
double
c
=
pow
(
(
startPoint
.
x
-
viaCenter
.
x
),
2
)
+
pow
(
(
startPoint
.
y
-
viaCenter
.
y
),
2
)
-
pow
(
r
,
2
);
double
t
=
2
*
c
/
(
-
b
+
sqrt
(
b
*
b
-
4
*
a
*
c
));
double
x
=
(
endPoint
.
x
-
startPoint
.
x
)
*
t
+
startPoint
.
x
;
double
x
=
(
endPoint
.
x
-
startPoint
.
x
)
*
t
+
startPoint
.
x
;
double
y
=
(
endPoint
.
y
-
startPoint
.
y
)
*
t
+
startPoint
.
y
;
double
y
=
(
endPoint
.
y
-
startPoint
.
y
)
*
t
+
startPoint
.
y
;
VECTOR2I
linePoint
(
x
,
y
);
VECTOR2I
linePoint
(
x
,
y
);
int
correctedRadius
=
(
aVia
.
GetWidth
()
/
2
)
-
(
aTrack
.
GetWidth
()
/
2
);
int
correctedRadius
=
(
aVia
.
GetWidth
()
/
2
)
-
(
aTrack
.
GetWidth
()
/
2
);
c
=
pow
(
(
startPoint
.
x
-
viaCenter
.
x
),
2
)
+
pow
((
startPoint
.
y
-
viaCenter
.
y
),
2
)
-
pow
(
correctedRadius
,
2
);
c
=
pow
(
(
startPoint
.
x
-
viaCenter
.
x
),
2
)
+
pow
(
(
startPoint
.
y
-
viaCenter
.
y
),
2
)
-
pow
(
correctedRadius
,
2
);
t
=
2
*
c
/
(
-
b
+
sqrt
(
b
*
b
-
4
*
a
*
c
));
t
=
2
*
c
/
(
-
b
+
sqrt
(
b
*
b
-
4
*
a
*
c
));
x
=
(
endPoint
.
x
-
startPoint
.
x
)
*
t
+
startPoint
.
x
;
x
=
(
endPoint
.
x
-
startPoint
.
x
)
*
t
+
startPoint
.
x
;
y
=
(
endPoint
.
y
-
startPoint
.
y
)
*
t
+
startPoint
.
y
;
y
=
(
endPoint
.
y
-
startPoint
.
y
)
*
t
+
startPoint
.
y
;
VECTOR2I
circlePoint
(
x
,
y
);
VECTOR2I
circlePoint
(
x
,
y
);
VECTOR2I
upperPoint
=
circlePoint
-
viaCenter
;
VECTOR2I
upperPoint
=
circlePoint
-
viaCenter
;
VECTOR2I
lowerPoint
=
upperPoint
;
VECTOR2I
lowerPoint
=
upperPoint
;
upperPoint
=
upperPoint
.
Rotate
(
M_PI
/
2
);
upperPoint
=
upperPoint
.
Rotate
(
M_PI
/
2
);
lowerPoint
=
lowerPoint
.
Rotate
(
-
M_PI
/
2
);
lowerPoint
=
lowerPoint
.
Rotate
(
-
M_PI
/
2
);
upperPoint
+=
viaCenter
;
upperPoint
+=
viaCenter
;
lowerPoint
+=
viaCenter
;
lowerPoint
+=
viaCenter
;
// Calculate the number of segments needed to fill the area inside the teardrop
// Calculate the number of segments needed to fill the area inside the teardrop
std
::
vector
<
VECTOR2I
>
splitPoints
;
std
::
vector
<
VECTOR2I
>
splitPoints
;
if
(
aVia
.
GetWidth
()
/
2
>
2
*
aTrack
.
GetWidth
())
{
if
(
aVia
.
GetWidth
()
/
2
>
2
*
aTrack
.
GetWidth
()
)
{
// First, calculate the intersection point of the circle and one hand of the teardrop
// First, calculate the intersection point of the circle and one hand of the teardrop
r
=
aVia
.
GetWidth
()
/
2
;
r
=
aVia
.
GetWidth
()
/
2
;
a
=
pow
((
upperPoint
.
x
-
startPoint
.
x
),
2
)
+
pow
((
upperPoint
.
y
-
startPoint
.
y
),
2
);
a
=
pow
(
(
upperPoint
.
x
-
startPoint
.
x
),
2
)
+
pow
(
(
upperPoint
.
y
-
startPoint
.
y
),
2
);
b
=
2
*
(
double
)(
upperPoint
.
x
-
startPoint
.
x
)
*
(
double
)(
startPoint
.
x
-
viaCenter
.
x
)
+
2
*
(
double
)(
upperPoint
.
y
-
startPoint
.
y
)
*
(
double
)(
startPoint
.
y
-
viaCenter
.
y
);
b
=
2
*
(
double
)(
upperPoint
.
x
-
startPoint
.
x
)
*
(
double
)(
startPoint
.
x
-
viaCenter
.
x
)
+
c
=
pow
((
startPoint
.
x
-
viaCenter
.
x
),
2
)
+
pow
((
startPoint
.
y
-
viaCenter
.
y
),
2
)
-
pow
(
r
,
2
);
2
*
(
double
)(
upperPoint
.
y
-
startPoint
.
y
)
*
(
double
)
(
startPoint
.
y
-
viaCenter
.
y
);
t
=
2
*
c
/
(
-
b
+
sqrt
(
b
*
b
-
4
*
a
*
c
));
c
=
pow
(
(
startPoint
.
x
-
viaCenter
.
x
),
2
)
+
pow
(
(
startPoint
.
y
-
viaCenter
.
y
),
2
)
-
pow
(
r
,
2
);
t
=
2
*
c
/
(
-
b
+
sqrt
(
b
*
b
-
4
*
a
*
c
)
);
x
=
(
upperPoint
.
x
-
startPoint
.
x
)
*
t
+
startPoint
.
x
;
x
=
(
upperPoint
.
x
-
startPoint
.
x
)
*
t
+
startPoint
.
x
;
y
=
(
upperPoint
.
y
-
startPoint
.
y
)
*
t
+
startPoint
.
y
;
y
=
(
upperPoint
.
y
-
startPoint
.
y
)
*
t
+
startPoint
.
y
;
VECTOR2I
intersectionPoint
(
(
int
)
x
,
(
int
)
y
);
VECTOR2I
intersectionPoint
(
(
int
)
x
,
(
int
)
y
);
// Second, calculate the distance between the given track and the intersection point
// Second, calculate the distance between the given track and the intersection point
SEG
trackSegment
(
aTrack
.
GetStart
().
x
,
aTrack
.
GetStart
().
y
,
aTrack
.
GetEnd
().
x
,
aTrack
.
GetEnd
().
y
);
SEG
trackSegment
(
aTrack
.
GetStart
().
x
,
aTrack
.
GetStart
().
y
,
int
dist
=
trackSegment
.
LineDistance
(
intersectionPoint
);
aTrack
.
GetEnd
().
x
,
aTrack
.
GetEnd
().
y
);
int
dist
=
trackSegment
.
LineDistance
(
intersectionPoint
);
int
numSegments
=
2
*
dist
/
aTrack
.
GetWidth
();
int
numSegments
=
2
*
dist
/
aTrack
.
GetWidth
();
// Third, subdivide the diameter of the via and build additional segments
// Third, subdivide the diameter of the via and build additional segments
SEG
segDiameter
=
SEG
(
upperPoint
,
lowerPoint
);
SEG
segDiameter
=
SEG
(
upperPoint
,
lowerPoint
);
SplitSegment
(
segDiameter
,
numSegments
,
splitPoints
);
splitSegment
(
segDiameter
,
numSegments
,
splitPoints
);
}
}
std
::
list
<
VECTOR2I
>
outlinePoints
;
std
::
list
<
VECTOR2I
>
outlinePoints
;
outlinePoints
.
push_back
(
upperPoint
);
outlinePoints
.
push_back
(
upperPoint
);
for
(
size_t
i
=
0
;
i
<
splitPoints
.
size
();
i
++
)
{
for
(
size_t
i
=
0
;
i
<
splitPoints
.
size
();
i
++
)
outlinePoints
.
push_back
(
splitPoints
[
i
]);
{
outlinePoints
.
push_back
(
splitPoints
[
i
]
);
}
}
outlinePoints
.
push_back
(
lowerPoint
);
outlinePoints
.
push_back
(
lowerPoint
);
// Biuld triangles filling the teardrop
// Biuld triangles filling the teardrop
int
vertexNum
=
0
;
int
vertexNum
=
0
;
std
::
list
<
VECTOR2I
>::
iterator
iter
=
outlinePoints
.
begin
();
std
::
list
<
VECTOR2I
>::
iterator
iter
=
outlinePoints
.
begin
();
while
(
iter
!=
outlinePoints
.
end
()
)
{
while
(
iter
!=
outlinePoints
.
end
()
)
switch
(
vertexNum
)
{
{
switch
(
vertexNum
)
{
case
0
:
case
0
:
m_coordinates
.
push_back
(
linePoint
);
m_coordinates
.
push_back
(
linePoint
);
vertexNum
++
;
vertexNum
++
;
break
;
break
;
case
1
:
case
1
:
m_coordinates
.
push_back
(
*
iter
);
m_coordinates
.
push_back
(
*
iter
);
vertexNum
++
;
vertexNum
++
;
iter
++
;
iter
++
;
break
;
break
;
case
2
:
case
2
:
m_coordinates
.
push_back
(
*
iter
);
m_coordinates
.
push_back
(
*
iter
);
vertexNum
=
0
;
vertexNum
=
0
;
iter
++
;
iter
++
;
break
;
break
;
default
:
break
;
default
:
break
;
}
}
}
}
// Append additional vertexies in order to finish last triangle
// Append additional vertexies in order to finish last triangle
if
(
vertexNum
==
0
)
{
if
(
vertexNum
==
0
)
m_coordinates
.
push_back
(
linePoint
);
{
m_coordinates
.
push_back
(
linePoint
);
}
}
else
if
(
vertexNum
==
2
)
{
else
if
(
vertexNum
==
2
)
m_coordinates
.
push_back
(
m_coordinates
[
m_coordinates
.
size
()
-
3
]);
{
m_coordinates
.
push_back
(
linePoint
);
m_coordinates
.
push_back
(
m_coordinates
[
m_coordinates
.
size
()
-
3
]
);
m_coordinates
.
push_back
(
linePoint
);
}
}
return
true
;
return
true
;
}
}
// TODO: m_TracksConnected member is considered a temporary storage. Find another way to get an object
// TODO: m_TracksConnected member is considered a temporary storage. Find another way to get an object
BOARD_CONNECTED_ITEM
*
TEARDROP
::
GetObjectOnEnd
(
TRACK
&
aTrack
,
ENDPOINT_T
endPoint
)
BOARD_CONNECTED_ITEM
*
TEARDROP
::
getObjectOnEnd
(
TRACK
&
aTrack
,
ENDPOINT_T
aEndPoint
)
{
{
wxPoint
trackPoint
;
wxPoint
trackPoint
;
BOARD_CONNECTED_ITEM
*
item
=
NULL
;
BOARD_CONNECTED_ITEM
*
item
=
NULL
;
std
::
vector
<
TRACK
*>::
const_iterator
iter
;
std
::
vector
<
TRACK
*>::
const_iterator
iter
;
if
(
endPoint
==
ENDPOINT_START
)
{
if
(
aEndPoint
==
ENDPOINT_START
)
{
trackPoint
=
aTrack
.
GetStart
();
trackPoint
=
aTrack
.
GetStart
();
}
}
else
{
else
{
trackPoint
=
aTrack
.
GetEnd
();
trackPoint
=
aTrack
.
GetEnd
();
}
}
// Check for vias first
// Check for vias first
for
(
iter
=
aTrack
.
m_TracksConnected
.
begin
();
iter
!=
aTrack
.
m_TracksConnected
.
end
();
++
iter
)
{
for
(
iter
=
aTrack
.
m_TracksConnected
.
begin
();
iter
!=
aTrack
.
m_TracksConnected
.
end
();
++
iter
)
{
KICAD_T
type
=
(
*
iter
)
->
Type
();
KICAD_T
type
=
(
*
iter
)
->
Type
();
bool
hitTest
=
(
*
iter
)
->
HitTest
(
trackPoint
);
bool
hitTest
=
(
*
iter
)
->
HitTest
(
trackPoint
);
if
(
type
==
PCB_VIA_T
&&
hitTest
==
true
)
{
if
(
(
type
==
PCB_VIA_T
)
&&
(
hitTest
==
true
)
)
{
item
=
*
iter
;
item
=
*
iter
;
}
}
}
}
// Check for pads if via was not found on this end of the track
// Check for pads if via was not found on this end of the track
if
(
item
==
NULL
)
{
if
(
item
==
NULL
)
for
(
std
::
vector
<
D_PAD
*>::
iterator
iter
=
aTrack
.
m_PadsConnected
.
begin
();
iter
!=
aTrack
.
m_PadsConnected
.
end
();
++
iter
)
{
{
for
(
std
::
vector
<
D_PAD
*>::
iterator
iter
=
aTrack
.
m_PadsConnected
.
begin
();
iter
!=
aTrack
.
m_PadsConnected
.
end
();
++
iter
)
{
PAD_SHAPE_T
shape
=
(
*
iter
)
->
GetShape
();
PAD_SHAPE_T
shape
=
(
*
iter
)
->
GetShape
();
bool
hitTest
=
(
*
iter
)
->
HitTest
(
trackPoint
);
bool
hitTest
=
(
*
iter
)
->
HitTest
(
trackPoint
);
if
(
shape
==
PAD_CIRCLE
&&
hitTest
==
true
)
{
if
(
shape
==
PAD_CIRCLE
&&
hitTest
==
true
)
{
item
=
*
iter
;
item
=
*
iter
;
}
}
}
}
...
@@ -297,20 +377,28 @@ BOARD_CONNECTED_ITEM* TEARDROP::GetObjectOnEnd(TRACK &aTrack, ENDPOINT_T endPoin
...
@@ -297,20 +377,28 @@ BOARD_CONNECTED_ITEM* TEARDROP::GetObjectOnEnd(TRACK &aTrack, ENDPOINT_T endPoin
return
item
;
return
item
;
}
}
void
TEARDROP
::
SplitSegment
(
const
SEG
&
segment
,
int
splits
,
std
::
vector
<
VECTOR2I
>
&
points
)
void
TEARDROP
::
splitSegment
(
const
SEG
&
aSegment
,
int
aSplits
,
std
::
vector
<
VECTOR2I
>&
aPoints
)
{
{
int
dX
=
abs
((
segment
.
A
.
x
-
segment
.
B
.
x
)
/
splits
);
int
dX
=
abs
(
(
aSegment
.
A
.
x
-
aSegment
.
B
.
x
)
/
aSplits
);
int
dY
=
abs
((
segment
.
A
.
y
-
segment
.
B
.
y
)
/
splits
);
int
dY
=
abs
(
(
aSegment
.
A
.
y
-
aSegment
.
B
.
y
)
/
aSplits
);
if
(
segment
.
A
.
x
>
segment
.
B
.
x
)
{
if
(
aSegment
.
A
.
x
>
aSegment
.
B
.
x
)
{
dX
=
-
dX
;
dX
=
-
dX
;
}
}
if
(
segment
.
A
.
y
>
segment
.
B
.
y
)
{
if
(
aSegment
.
A
.
y
>
aSegment
.
B
.
y
)
{
dY
=
-
dY
;
dY
=
-
dY
;
}
}
VECTOR2I
delta
(
dX
,
dY
);
points
.
push_back
(
segment
.
A
+
delta
);
VECTOR2I
delta
(
dX
,
dY
);
aPoints
.
push_back
(
aSegment
.
A
+
delta
);
// The last point is excluded as it will coinside with already built tracks
// The last point is excluded as it will coinside with already built tracks
for
(
int
i
=
1
;
i
<
splits
-
1
;
i
++
)
{
for
(
int
i
=
1
;
i
<
aSplits
-
1
;
i
++
)
points
.
push_back
(
points
.
back
()
+
delta
);
{
aPoints
.
push_back
(
aPoints
.
back
()
+
delta
);
}
}
}
}
pcbnew/class_teardrop.h
View file @
c5973eb8
...
@@ -17,93 +17,130 @@
...
@@ -17,93 +17,130 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
*/
/**
* @file class_teardrop.h
* @brief Definitions for teardrops.
*/
#ifndef CLASS_TEARDROP_H
#ifndef CLASS_TEARDROP_H
#define CLASS_TEARDROP_H
#define CLASS_TEARDROP_H
#include "class_track.h"
#include "class_track.h"
#include "geometry/seg.h"
#include "geometry/seg.h"
/**
* @brief The TEARDROP class
* is base definition of a teardrop. It is intended for calculation and holding of points which
* compose a teardrop. This class does not contain any methods which create actual tracks.
*/
class
TEARDROP
class
TEARDROP
{
{
public
:
public
:
TEARDROP
();
TEARDROP
();
/**
/**
* @brief
D
efines the type of a teardrop.
* @brief
The TEARDROP_TYPE d
efines the type of a teardrop.
*/
*/
typedef
enum
{
typedef
enum
TEARDROP_NONE
,
///< The type is undefined
{
TEARDROP_STRAIGHT
,
///< The teardrop is created by two straight segments
TEARDROP_NONE
,
///< The type is undefined
TEARDROP_CURVED
///< The teardrop is created by several segments approximating a curve
TEARDROP_STRAIGHT
,
///< The teardrop is created by two straight segments
TEARDROP_CURVED
///< The teardrop is created by several segments approximating a curve
}
TEARDROP_TYPE
;
}
TEARDROP_TYPE
;
/**
/**
* @brief GetType returns the type of the teardrop.
* @brief Function \a GetType
* @return TEARDROP_TYPE
* returns the type of the teardrop.
* @return TEARDROP_TYPE - the type of the teardrop
*/
*/
TEARDROP_TYPE
GetType
()
const
{
return
m_type
;
}
TEARDROP_TYPE
GetType
()
const
{
return
m_type
;
}
/**
/**
* @brief Function Create creates a teardrop(s) for a given track
* @brief Function \a Create
* @param aTrack
* creates a teardrop(s) for a given track.
* @return \a true in case the teardrops were successfully built and \a false otherwise
* @param [in] aTrack is a track at which teardrop(s) should be created
* @param [in] aEndPoint is an end point at which a teardrop should be created
* @param [in] aType defines the type of a teardrop
* @return bool - \a true in case the teardrops were successfully built and \a false otherwise
*/
*/
bool
Create
(
TRACK
&
aTrack
,
ENDPOINT_T
endPoint
,
TEARDROP_TYPE
type
);
bool
Create
(
TRACK
&
aTrack
,
ENDPOINT_T
aEndPoint
,
TEARDROP_TYPE
aType
);
void
GetCoordinates
(
std
::
vector
<
VECTOR2I
>
&
points
)
const
{
points
=
m_coordinates
;}
/**
* @brief Function \a GetCoordinates
* returns the coordinates of created teardrop.
* @param [out] aPoints is a container for coordinates
*/
void
GetCoordinates
(
std
::
vector
<
VECTOR2I
>&
aPoints
)
const
{
aPoints
=
m_coordinates
;
}
private
:
private
:
///
>
Contains the type of teardrop
/// Contains the type of teardrop
TEARDROP_TYPE
m_type
;
TEARDROP_TYPE
m_type
;
///> \a m_upperSegment and \a m_lowerSegment contain coordinates of segments composing a teardrop
/// Contains the actual coordinates of teardrop
std
::
vector
<
VECTOR2I
>
m_upperSegment
;
std
::
vector
<
VECTOR2I
>
m_lowerSegment
;
std
::
vector
<
VECTOR2I
>
m_coordinates
;
std
::
vector
<
VECTOR2I
>
m_coordinates
;
/**
/**
* @brief Function \a CurvedSegments computes several points on deltoid curve and moves
* @brief Function \a curvedSegments
* these points along the vector defined by \a aTrack.
* computes several points on deltoid curve and moves these points along the vector
* defined by \a aTrack.
*
*
* This function computes the coordinates of points only and does not build actual track segments.
* This function computes the coordinates of points only and does not build actual track segments.
* See deltiod description and its parametric equations on [wiki page](http://en.wikipedia.org/wiki/Deltoid_curve).
* See deltiod description and its parametric equations on [wiki page](http://en.wikipedia.org/wiki/Deltoid_curve).
* @param [in] aTrack defines a vector along which the curved segments should be built
* @param [in] aTrack defines a vector along which the curved segments should be built
* @param [in] aVia used as the center of coordinates
* @param [in] aVia used as the center of coordinates
* @return \a true in case the segments were successfully built and \a false otherwise
* @return
bool -
\a true in case the segments were successfully built and \a false otherwise
*/
*/
bool
CurvedSegments
(
TRACK
&
aTrack
,
const
VIA
&
aVia
);
bool
curvedSegments
(
TRACK
&
aTrack
,
const
VIA
&
aVia
);
/**
/**
* @brief Function \a StraightSegments builds two tangent lines for a circle from a givent point.
* @brief Function \a straightSegments
* builds two tangent lines to a circle from a givent point.
*
*
* This function computes the coordinates of points only and does not build actual track segments.
* This function computes the coordinates of points only and does not build actual track segments.
* @param [in] aTrack defines a vector along which the segments should be built
* @param [in] aTrack defines a vector along which the segments should be built
* @param [in] aVia represents a circle to which the segments should be built
* @param [in] aVia represents a circle to which the segments should be built
* @param [in] distance is distance ratio (in percent) from circle center in respect to its diameter
* @param [in] aDistance is distance ratio (in percent) from circle center in respect to its diameter
* @return \a true in case the segments were successfully built and \a false otherwise
* @return bool - \a true in case the segments were successfully built and \a false otherwise
*/
bool
straightSegments
(
TRACK
&
aTrack
,
const
VIA
&
aVia
,
int
aDistance
);
/**
* @brief Function \a setVector
* creates a vector from \a aTrack directed into \a aVia.
* @param [in] aTrack is used to create a vector
* @param [in] aVia is an object to which the vector should be pointed to
* @param [out] aStartPoint is start point of resulting vector
* @param [out] aEndPoint is end point of resulting vector
* @return bool - \a true in case the vector is created successfully and \a false otherwise
*/
bool
setVector
(
TRACK
&
aTrack
,
const
VIA
&
aVia
,
VECTOR2I
&
aStartPoint
,
VECTOR2I
&
aEndPoint
);
/**
* @brief Function \a getObjectOnEnd
* returns an object (via or pad) at the given end of a track.
* @param [in] aTrack is a reference track
* @param [in] aEndPoint defines the end in question
* @return BOARD_CONNECTED_ITEM - the object found or NULL otherwise
*/
*/
bool
StraightSegments
(
TRACK
&
aTrack
,
const
VIA
&
aVia
,
int
distance
);
BOARD_CONNECTED_ITEM
*
getObjectOnEnd
(
TRACK
&
aTrack
,
ENDPOINT_T
aEndPoint
);
/**
/**
* @brief Function
SetVector creates a vector from \a aTrack directed into \a aVia
* @brief Function
\a splitSegment
*
@param aTrack is used to create a vector
*
splits a segment into given number of subsegments.
* @param
startPoint is start point of resulting vector
* @param
[in] aSegment is a segment to be split
* @param
endPoint is end point of resulting vector
* @param
[i] aSplits is a number of splits
* @
return \a true in case the vector is created successfully and \a false otherwise
* @
param [out] aPoints is a container for split points
*/
*/
bool
SetVector
(
TRACK
&
aTrack
,
const
VIA
&
aVia
,
VECTOR2I
&
startPoint
,
VECTOR2I
&
endPoint
);
void
splitSegment
(
const
SEG
&
aSegment
,
int
aSplits
,
std
::
vector
<
VECTOR2I
>&
aPoints
);
BOARD_CONNECTED_ITEM
*
GetObjectOnEnd
(
TRACK
&
aTrack
,
ENDPOINT_T
endPoint
);
/**
void
SplitSegment
(
const
SEG
&
segment
,
int
splits
,
std
::
vector
<
VECTOR2I
>
&
points
);
* @brief Function \a pointOnCurve
inline
void
PointOnCurve
(
int
angle
,
double
radius
,
VECTOR2I
&
point
)
{
* calculates a single point on a deltoid curve.
* @param [in] aAngle is an angle at which the point should be calculated
* @param [in] aRadius is the radius of a rolling circle
* @param [out] aPoint is a container for calculated point
*/
inline
void
pointOnCurve
(
int
aAngle
,
double
aRadius
,
VECTOR2I
&
aPoint
)
{
double
coeff
=
M_PI
/
180
.
0
;
double
coeff
=
M_PI
/
180
.
0
;
point
.
x
=
2
*
radius
*
cos
(
coeff
*
angle
)
+
radius
*
cos
(
2
*
coeff
*
angle
);
point
.
y
=
2
*
radius
*
sin
(
coeff
*
angle
)
-
radius
*
sin
(
2
*
coeff
*
angle
);
aPoint
.
x
=
2
*
aRadius
*
cos
(
coeff
*
aAngle
)
+
aRadius
*
cos
(
2
*
coeff
*
aAngle
);
aPoint
.
y
=
2
*
aRadius
*
sin
(
coeff
*
aAngle
)
-
aRadius
*
sin
(
2
*
coeff
*
aAngle
);
}
}
};
};
#endif // CLASS_TEARDROP_H
#endif
// CLASS_TEARDROP_H
pcbnew/dialogs/dialog_teardrops.cpp
View file @
c5973eb8
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Elphel, Inc.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dialog_teardrops.h"
#include "dialog_teardrops.h"
DIALOG_TEARDROPS
::
DIALOG_TEARDROPS
(
PCB_EDIT_FRAME
*
aParent
,
TEARDROPS_SETTINGS
*
settings
)
:
DIALOG_TEARDROPS
::
DIALOG_TEARDROPS
(
PCB_EDIT_FRAME
*
aParent
,
TEARDROPS_SETTINGS
*
aSettings
=
NULL
)
:
DIALOG_TEARDROPS_BASE
(
aParent
)
DIALOG_TEARDROPS_BASE
(
aParent
)
{
{
m_parent
=
aParent
;
m_parent
=
aParent
;
m_settings
=
settings
;
m_settings
=
aSettings
;
if
(
m_settings
!=
NULL
)
{
if
(
m_settings
!=
NULL
)
InitDialogSettings
();
{
initDialogSettings
();
}
}
}
}
void
DIALOG_TEARDROPS
::
I
nitDialogSettings
()
void
DIALOG_TEARDROPS
::
i
nitDialogSettings
()
{
{
wxASSERT
(
m_settings
!=
NULL
);
assert
(
m_settings
!=
NULL
);
if
(
m_modeRemove
->
GetValue
()
==
true
)
{
if
(
m_modeRemove
->
GetValue
()
==
true
)
{
m_settings
->
m_mode
=
TEARDROPS_MODE_REMOVE
;
m_settings
->
m_mode
=
TEARDROPS_MODE_REMOVE
;
}
}
else
{
else
{
m_settings
->
m_mode
=
TEARDROPS_MODE_ADD
;
m_settings
->
m_mode
=
TEARDROPS_MODE_ADD
;
}
}
if
(
m_tracksAll
->
GetValue
()
==
true
)
{
if
(
m_tracksAll
->
GetValue
()
==
true
)
{
m_settings
->
m_track
=
TEARDROPS_TRACKS_ALL
;
m_settings
->
m_track
=
TEARDROPS_TRACKS_ALL
;
}
}
else
{
else
{
m_settings
->
m_track
=
TEARDROPS_TRACKS_SELECTED
;
m_settings
->
m_track
=
TEARDROPS_TRACKS_SELECTED
;
}
}
m_settings
->
m_type
=
static_cast
<
TEARDROPS_TYPE
>
(
m_choiceStyle
->
GetSelection
()
);
m_settings
->
m_type
=
static_cast
<
TEARDROPS_TYPE
>
(
m_choiceStyle
->
GetSelection
()
);
m_settings
->
m_scope
=
TEARDROPS_SCOPE_NONE
;
m_settings
->
m_scope
=
TEARDROPS_SCOPE_NONE
;
if
(
m_scopeVias
->
IsChecked
()
==
true
)
{
if
(
m_scopeVias
->
IsChecked
()
==
true
)
m_settings
->
m_scope
=
static_cast
<
TEARDROPS_SCOPE
>
(
m_settings
->
m_scope
|
TEARDROPS_SCOPE_VIAS
);
{
m_settings
->
m_scope
=
static_cast
<
TEARDROPS_SCOPE
>
(
m_settings
->
m_scope
|
TEARDROPS_SCOPE_VIAS
);
}
}
if
(
m_scopePads
->
IsChecked
()
==
true
)
{
if
(
m_scopePads
->
IsChecked
()
==
true
)
m_settings
->
m_scope
=
static_cast
<
TEARDROPS_SCOPE
>
(
m_settings
->
m_scope
|
TEARDROPS_SCOPE_PADS
);
{
m_settings
->
m_scope
=
static_cast
<
TEARDROPS_SCOPE
>
(
m_settings
->
m_scope
|
TEARDROPS_SCOPE_PADS
);
}
}
if
(
m_scopeTracks
->
IsChecked
()
==
true
)
{
if
(
m_scopeTracks
->
IsChecked
()
==
true
)
m_settings
->
m_scope
=
static_cast
<
TEARDROPS_SCOPE
>
(
m_settings
->
m_scope
|
TEARDROPS_SCOPE_TRACKS
);
{
m_settings
->
m_scope
=
static_cast
<
TEARDROPS_SCOPE
>
(
m_settings
->
m_scope
|
TEARDROPS_SCOPE_TRACKS
);
}
}
m_settings
->
m_clearSelection
=
m_checkClear
->
IsChecked
();
m_settings
->
m_clearSelection
=
m_checkClear
->
IsChecked
();
m_settings
->
m_ignoreDrc
=
m_checkIgnore
->
IsChecked
();
m_settings
->
m_ignoreDrc
=
m_checkIgnore
->
IsChecked
();
}
}
void
DIALOG_TEARDROPS
::
OnModeAdd
(
wxCommandEvent
&
event
)
void
DIALOG_TEARDROPS
::
OnModeAdd
(
wxCommandEvent
&
aEvent
)
{
{
event
.
Skip
();
aEvent
.
Skip
();
if
(
m_settings
!=
NULL
)
{
if
(
m_settings
!=
NULL
)
{
m_settings
->
m_mode
=
TEARDROPS_MODE_ADD
;
m_settings
->
m_mode
=
TEARDROPS_MODE_ADD
;
LockOptionsControls
(
false
);
lockOptionsControls
(
false
);
LockTracksControls
(
false
);
lockTracksControls
(
false
);
LockScopeControls
(
false
);
lockScopeControls
(
false
);
}
}
}
}
void
DIALOG_TEARDROPS
::
OnModeRemove
(
wxCommandEvent
&
event
)
void
DIALOG_TEARDROPS
::
OnModeRemove
(
wxCommandEvent
&
aEvent
)
{
{
event
.
Skip
();
aEvent
.
Skip
();
if
(
m_settings
!=
NULL
)
{
if
(
m_settings
!=
NULL
)
{
m_settings
->
m_mode
=
TEARDROPS_MODE_REMOVE
;
m_settings
->
m_mode
=
TEARDROPS_MODE_REMOVE
;
LockOptionsControls
(
true
);
lockOptionsControls
(
true
);
LockTracksControls
(
true
);
lockTracksControls
(
true
);
LockScopeControls
(
true
);
lockScopeControls
(
true
);
}
}
}
}
void
DIALOG_TEARDROPS
::
OnTracksAll
(
wxCommandEvent
&
event
)
void
DIALOG_TEARDROPS
::
OnTracksAll
(
wxCommandEvent
&
aEvent
)
{
{
event
.
Skip
();
aEvent
.
Skip
();
if
(
m_settings
!=
NULL
)
{
if
(
m_settings
!=
NULL
)
{
m_settings
->
m_track
=
TEARDROPS_TRACKS_ALL
;
m_settings
->
m_track
=
TEARDROPS_TRACKS_ALL
;
}
}
m_checkClear
->
Enable
(
false
);
m_checkClear
->
Enable
(
false
);
}
}
void
DIALOG_TEARDROPS
::
OnTracksSelected
(
wxCommandEvent
&
event
)
void
DIALOG_TEARDROPS
::
OnTracksSelected
(
wxCommandEvent
&
aEvent
)
{
{
event
.
Skip
();
aEvent
.
Skip
();
if
(
m_settings
!=
NULL
)
{
if
(
m_settings
!=
NULL
)
{
m_settings
->
m_track
=
TEARDROPS_TRACKS_SELECTED
;
m_settings
->
m_track
=
TEARDROPS_TRACKS_SELECTED
;
}
}
m_checkClear
->
Enable
(
true
);
m_checkClear
->
Enable
(
true
);
}
}
void
DIALOG_TEARDROPS
::
OnScopeVias
(
wxCommandEvent
&
event
)
void
DIALOG_TEARDROPS
::
OnScopeVias
(
wxCommandEvent
&
aEvent
)
{
{
event
.
Skip
();
aEvent
.
Skip
();
if
(
m_settings
!=
NULL
)
{
if
(
m_settings
!=
NULL
)
if
(
m_scopeVias
->
IsChecked
())
{
{
m_settings
->
m_scope
=
static_cast
<
TEARDROPS_SCOPE
>
(
m_settings
->
m_scope
|
TEARDROPS_SCOPE_VIAS
);
if
(
m_scopeVias
->
IsChecked
()
)
{
m_settings
->
m_scope
=
static_cast
<
TEARDROPS_SCOPE
>
(
m_settings
->
m_scope
|
TEARDROPS_SCOPE_VIAS
);
}
}
else
{
else
m_settings
->
m_scope
=
static_cast
<
TEARDROPS_SCOPE
>
(
m_settings
->
m_scope
&
(
~
TEARDROPS_SCOPE_VIAS
));
{
m_settings
->
m_scope
=
static_cast
<
TEARDROPS_SCOPE
>
(
m_settings
->
m_scope
&
(
~
TEARDROPS_SCOPE_VIAS
)
);
}
}
}
}
}
}
void
DIALOG_TEARDROPS
::
OnScopePads
(
wxCommandEvent
&
event
)
void
DIALOG_TEARDROPS
::
OnScopePads
(
wxCommandEvent
&
aEvent
)
{
{
event
.
Skip
();
aEvent
.
Skip
();
if
(
m_settings
!=
NULL
)
{
if
(
m_settings
!=
NULL
)
if
(
m_scopePads
->
IsChecked
())
{
{
m_settings
->
m_scope
=
static_cast
<
TEARDROPS_SCOPE
>
(
m_settings
->
m_scope
|
TEARDROPS_SCOPE_PADS
);
if
(
m_scopePads
->
IsChecked
()
)
{
m_settings
->
m_scope
=
static_cast
<
TEARDROPS_SCOPE
>
(
m_settings
->
m_scope
|
TEARDROPS_SCOPE_PADS
);
}
}
else
{
else
m_settings
->
m_scope
=
static_cast
<
TEARDROPS_SCOPE
>
(
m_settings
->
m_scope
&
(
~
TEARDROPS_SCOPE_PADS
));
{
m_settings
->
m_scope
=
static_cast
<
TEARDROPS_SCOPE
>
(
m_settings
->
m_scope
&
(
~
TEARDROPS_SCOPE_PADS
)
);
}
}
}
}
}
}
void
DIALOG_TEARDROPS
::
OnStyleChanged
(
wxCommandEvent
&
event
)
void
DIALOG_TEARDROPS
::
OnStyleChanged
(
wxCommandEvent
&
aEvent
)
{
{
event
.
Skip
();
aEvent
.
Skip
();
if
(
m_settings
!=
NULL
)
{
if
(
m_settings
!=
NULL
)
m_settings
->
m_type
=
static_cast
<
TEARDROPS_TYPE
>
(
m_choiceStyle
->
GetSelection
());
{
m_settings
->
m_type
=
static_cast
<
TEARDROPS_TYPE
>
(
m_choiceStyle
->
GetSelection
()
);
}
}
}
}
void
DIALOG_TEARDROPS
::
OnClearSelection
(
wxCommandEvent
&
event
)
void
DIALOG_TEARDROPS
::
OnClearSelection
(
wxCommandEvent
&
aEvent
)
{
{
event
.
Skip
();
aEvent
.
Skip
();
if
(
m_settings
!=
NULL
)
{
if
(
m_settings
!=
NULL
)
{
m_settings
->
m_clearSelection
=
m_checkClear
->
IsChecked
();
m_settings
->
m_clearSelection
=
m_checkClear
->
IsChecked
();
}
}
}
}
void
DIALOG_TEARDROPS
::
OnIgnoreDrc
(
wxCommandEvent
&
event
)
void
DIALOG_TEARDROPS
::
OnIgnoreDrc
(
wxCommandEvent
&
aEvent
)
{
{
event
.
Skip
();
aEvent
.
Skip
();
if
(
m_settings
!=
NULL
)
{
if
(
m_settings
!=
NULL
)
{
m_settings
->
m_ignoreDrc
=
m_checkIgnore
->
IsChecked
();
m_settings
->
m_ignoreDrc
=
m_checkIgnore
->
IsChecked
();
}
}
}
}
void
DIALOG_TEARDROPS
::
LockOptionsControls
(
bool
state
)
void
DIALOG_TEARDROPS
::
lockOptionsControls
(
bool
state
)
{
{
if
(
state
==
true
)
{
if
(
state
==
true
)
if
(
m_tracksSelected
->
GetValue
()
==
false
)
{
{
m_checkClear
->
Enable
(
false
);
if
(
m_tracksSelected
->
GetValue
()
==
false
)
{
m_checkClear
->
Enable
(
false
);
}
}
m_checkIgnore
->
Enable
(
false
);
m_checkIgnore
->
Enable
(
false
);
m_choiceStyle
->
Enable
(
false
);
m_choiceStyle
->
Enable
(
false
);
}
}
else
{
else
if
(
m_tracksSelected
->
GetValue
()
==
true
)
{
{
m_checkClear
->
Enable
(
true
);
if
(
m_tracksSelected
->
GetValue
()
==
true
)
{
m_checkClear
->
Enable
(
true
);
}
}
m_checkIgnore
->
Enable
(
true
);
m_checkIgnore
->
Enable
(
true
);
m_choiceStyle
->
Enable
(
true
);
m_choiceStyle
->
Enable
(
true
);
}
}
}
}
void
DIALOG_TEARDROPS
::
LockTracksControls
(
bool
state
)
void
DIALOG_TEARDROPS
::
lockTracksControls
(
bool
state
)
{
{
if
(
state
==
true
)
{
if
(
state
==
true
)
m_tracksAll
->
Enable
(
false
);
{
m_tracksSelected
->
Enable
(
false
);
m_tracksAll
->
Enable
(
false
);
m_tracksSelected
->
Enable
(
false
);
}
}
else
{
else
m_tracksAll
->
Enable
(
true
);
{
m_tracksSelected
->
Enable
(
true
);
m_tracksAll
->
Enable
(
true
);
m_tracksSelected
->
Enable
(
true
);
}
}
}
}
void
DIALOG_TEARDROPS
::
LockScopeControls
(
bool
state
)
void
DIALOG_TEARDROPS
::
lockScopeControls
(
bool
state
)
{
{
if
(
state
==
true
)
{
if
(
state
==
true
)
m_scopePads
->
Enable
(
false
);
{
m_scopeVias
->
Enable
(
false
);
m_scopePads
->
Enable
(
false
);
}
m_scopeVias
->
Enable
(
false
);
else
{
}
m_scopePads
->
Enable
(
true
);
else
m_scopeVias
->
Enable
(
true
);
{
m_scopePads
->
Enable
(
true
);
m_scopeVias
->
Enable
(
true
);
}
}
}
}
pcbnew/dialogs/dialog_teardrops.h
View file @
c5973eb8
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Elphel, Inc.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DIALOG_TEARDROPS_H
#ifndef DIALOG_TEARDROPS_H
#define DIALOG_TEARDROPS_H
#define DIALOG_TEARDROPS_H
...
@@ -5,56 +24,108 @@
...
@@ -5,56 +24,108 @@
#include "dialog_teardrops_base.h"
#include "dialog_teardrops_base.h"
#include "wxPcbStruct.h"
#include "wxPcbStruct.h"
/**
* @brief The DIALOG_TEARDROPS class
* implements teardrop management dialog for current board.
*/
class
DIALOG_TEARDROPS
:
public
DIALOG_TEARDROPS_BASE
class
DIALOG_TEARDROPS
:
public
DIALOG_TEARDROPS_BASE
{
{
public
:
public
:
typedef
enum
{
/**
* @brief The TEARDROPS_MODE
* defines an action to be performed on teardrops.
*/
typedef
enum
{
/// Teardrops addition mode
TEARDROPS_MODE_ADD
,
TEARDROPS_MODE_ADD
,
/// Teardrops removal mode
TEARDROPS_MODE_REMOVE
TEARDROPS_MODE_REMOVE
}
TEARDROPS_MODE
;
}
TEARDROPS_MODE
;
typedef
enum
{
/**
* @brief The TEARDROPS_TRACKS
* determines selection processing.
*/
typedef
enum
{
/// Process all tracks
TEARDROPS_TRACKS_ALL
,
TEARDROPS_TRACKS_ALL
,
/// Process selected tracks only
TEARDROPS_TRACKS_SELECTED
TEARDROPS_TRACKS_SELECTED
}
TEARDROPS_TRACKS
;
}
TEARDROPS_TRACKS
;
typedef
enum
{
/**
* @brief The TEARDROPS_TYPE
* defines the shape of teardrops.
*/
typedef
enum
{
/// The shape is not defined
TEARDROPS_TYPE_NONE
=
-
1
,
TEARDROPS_TYPE_NONE
=
-
1
,
/// The teardops have straight outlines
TEARDROPS_TYPE_STRAIGHT
,
TEARDROPS_TYPE_STRAIGHT
,
/// The teardrops have curved outlines
TEARDROPS_TYPE_CURVED
TEARDROPS_TYPE_CURVED
}
TEARDROPS_TYPE
;
}
TEARDROPS_TYPE
;
typedef
enum
{
/**
* @brief The TEARDROPS_SCOPE
* defines the types of objects for which teardrops should be created. This is a bit field, each
* bit correcponds to an object type.
*/
typedef
enum
{
/// No objects are specified
TEARDROPS_SCOPE_NONE
,
TEARDROPS_SCOPE_NONE
,
/// Create teardrops for vias
TEARDROPS_SCOPE_VIAS
=
1
,
TEARDROPS_SCOPE_VIAS
=
1
,
/// Create teardrops for pads
TEARDROPS_SCOPE_PADS
=
2
,
TEARDROPS_SCOPE_PADS
=
2
,
/// Create teardrops for tracks (not implemented yet)
TEARDROPS_SCOPE_TRACKS
=
4
TEARDROPS_SCOPE_TRACKS
=
4
}
TEARDROPS_SCOPE
;
}
TEARDROPS_SCOPE
;
typedef
struct
{
/**
* @brief The TEARDROPS_SETTINGS
* class is a container for all the settings specified by the user.
*/
typedef
struct
{
/// The action to be performed (addition, deletion)
TEARDROPS_MODE
m_mode
;
TEARDROPS_MODE
m_mode
;
/// Process selection
TEARDROPS_TRACKS
m_track
;
TEARDROPS_TRACKS
m_track
;
/// Objects scope
TEARDROPS_SCOPE
m_scope
;
TEARDROPS_SCOPE
m_scope
;
/// Teardrops type
TEARDROPS_TYPE
m_type
;
TEARDROPS_TYPE
m_type
;
/// Clear selection after the processing has finished
bool
m_clearSelection
;
bool
m_clearSelection
;
/// Ignore DRC during processing
bool
m_ignoreDrc
;
bool
m_ignoreDrc
;
}
TEARDROPS_SETTINGS
;
}
TEARDROPS_SETTINGS
;
DIALOG_TEARDROPS
(
PCB_EDIT_FRAME
*
aParent
,
TEARDROPS_SETTINGS
*
settings
);
DIALOG_TEARDROPS
(
PCB_EDIT_FRAME
*
aParent
,
TEARDROPS_SETTINGS
*
aSettings
);
void
OnModeAdd
(
wxCommandEvent
&
event
);
void
OnModeRemove
(
wxCommandEvent
&
event
);
void
OnModeAdd
(
wxCommandEvent
&
aEvent
);
void
OnTracksAll
(
wxCommandEvent
&
event
);
void
OnModeRemove
(
wxCommandEvent
&
aEvent
);
void
OnTracksSelected
(
wxCommandEvent
&
event
);
void
OnTracksAll
(
wxCommandEvent
&
aEvent
);
void
OnStyleChanged
(
wxCommandEvent
&
event
);
void
OnTracksSelected
(
wxCommandEvent
&
aEvent
);
void
OnClearSelection
(
wxCommandEvent
&
event
);
void
OnStyleChanged
(
wxCommandEvent
&
aEvent
);
void
OnIgnoreDrc
(
wxCommandEvent
&
event
);
void
OnClearSelection
(
wxCommandEvent
&
aEvent
);
void
OnScopeVias
(
wxCommandEvent
&
event
);
void
OnIgnoreDrc
(
wxCommandEvent
&
aEvent
);
void
OnScopePads
(
wxCommandEvent
&
event
);
void
OnScopeVias
(
wxCommandEvent
&
aEvent
);
void
OnScopePads
(
wxCommandEvent
&
aEvent
);
private
:
private
:
PCB_EDIT_FRAME
*
m_parent
;
PCB_EDIT_FRAME
*
m_parent
;
TEARDROPS_SETTINGS
*
m_settings
;
TEARDROPS_SETTINGS
*
m_settings
;
void
I
nitDialogSettings
();
void
i
nitDialogSettings
();
void
LockOptionsControls
(
bool
state
);
void
lockOptionsControls
(
bool
aState
);
void
LockTracksControls
(
bool
state
);
void
lockTracksControls
(
bool
aState
);
void
LockScopeControls
(
bool
state
);
void
lockScopeControls
(
bool
aState
);
};
};
#endif // DIALOG_TEARDROPS_H
#endif // DIALOG_TEARDROPS_H
pcbnew/tools/edit_teardrops.cpp
View file @
c5973eb8
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Elphel, Inc.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "edit_teardrops.h"
#include "edit_teardrops.h"
#include "class_board.h"
#include "class_board.h"
#include "class_module.h"
#include "class_module.h"
#include "ratsnest_data.h"
#include "ratsnest_data.h"
#include "view/view.h"
#include "view/view.h"
#include "common_actions.h"
#include "common_actions.h"
#include "router/pns_utils.h"
#include "router/pns_router.h"
#include "router/pns_router.h"
TEARDROPS_EDITOR
::
TEARDROPS_EDITOR
()
:
TEARDROPS_EDITOR
::
TEARDROPS_EDITOR
()
:
TOOL_BASE
(
BATCH
,
TOOL_MANAGER
::
MakeToolId
(
"pcbnew.TeardropsEditor"
),
"pcbnew.TeardropsEditor"
)
TOOL_BASE
(
BATCH
,
TOOL_MANAGER
::
MakeToolId
(
"pcbnew.TeardropsEditor"
),
"pcbnew.TeardropsEditor"
)
{
{
m_frame
=
NULL
;
m_frame
=
NULL
;
m_view
=
NULL
;
m_view
=
NULL
;
m_type
=
TEARDROP
::
TEARDROP_STRAIGHT
;
m_type
=
TEARDROP
::
TEARDROP_STRAIGHT
;
m_strategy
=
DRC_COMPLY
;
m_strategy
=
DRC_COMPLY
;
}
}
TEARDROPS_EDITOR
::~
TEARDROPS_EDITOR
()
TEARDROPS_EDITOR
::~
TEARDROPS_EDITOR
()
{
{
}
}
void
TEARDROPS_EDITOR
::
Reset
(
RESET_REASON
aReason
)
void
TEARDROPS_EDITOR
::
Reset
(
RESET_REASON
aReason
)
{
{
m_frame
=
getEditFrame
<
PCB_EDIT_FRAME
>
();
m_frame
=
getEditFrame
<
PCB_EDIT_FRAME
>
();
m_view
=
getView
();
m_view
=
getView
();
m_type
=
TEARDROP
::
TEARDROP_STRAIGHT
;
m_type
=
TEARDROP
::
TEARDROP_STRAIGHT
;
m_strategy
=
DRC_COMPLY
;
m_strategy
=
DRC_COMPLY
;
}
}
void
TEARDROPS_EDITOR
::
FilterSelection
(
SELECTION
&
selection
)
void
TEARDROPS_EDITOR
::
filterSelection
(
SELECTION
&
aSelection
)
{
{
EDA_ITEM
*
item
=
NULL
;
EDA_ITEM
*
item
=
NULL
;
for
(
size_t
i
=
0
;
i
<
aSelection
.
items
.
GetCount
();
i
++
)
{
item
=
aSelection
.
items
.
GetPickedItem
(
i
);
for
(
size_t
i
=
0
;
i
<
selection
.
items
.
GetCount
();
i
++
)
{
if
(
(
item
!=
NULL
)
&&
(
item
->
Type
()
!=
PCB_TRACE_T
)
)
item
=
selection
.
items
.
GetPickedItem
(
i
);
{
if
((
item
!=
NULL
)
&&
(
item
->
Type
()
!=
PCB_TRACE_T
))
{
aSelection
.
items
.
RemovePicker
(
i
);
selection
.
items
.
RemovePicker
(
i
);
}
}
}
}
}
}
bool
TEARDROPS_EDITOR
::
EditTeardrops
(
const
DIALOG_TEARDROPS
::
TEARDROPS_SETTINGS
&
settings
)
bool
TEARDROPS_EDITOR
::
EditTeardrops
(
const
DIALOG_TEARDROPS
::
TEARDROPS_SETTINGS
&
aSettings
)
{
{
bool
retVal
=
false
;
bool
retVal
=
false
;
SELECTION
selection
=
GetManager
()
->
GetTool
<
SELECTION_TOOL
>
()
->
GetSelection
();
SELECTION
selection
=
GetManager
()
->
GetTool
<
SELECTION_TOOL
>
()
->
GetSelection
();
switch
(
settings
.
m_type
)
{
switch
(
aSettings
.
m_type
)
{
case
DIALOG_TEARDROPS
:
:
TEARDROPS_TYPE_CURVED
:
case
DIALOG_TEARDROPS
:
:
TEARDROPS_TYPE_CURVED
:
m_type
=
TEARDROP
::
TEARDROP_CURVED
;
m_type
=
TEARDROP
::
TEARDROP_CURVED
;
break
;
break
;
default
:
default
:
m_type
=
TEARDROP
::
TEARDROP_STRAIGHT
;
m_type
=
TEARDROP
::
TEARDROP_STRAIGHT
;
}
}
if
(
settings
.
m_ignoreDrc
==
true
)
{
if
(
aSettings
.
m_ignoreDrc
==
true
)
{
m_strategy
=
DRC_IGNORE
;
m_strategy
=
DRC_IGNORE
;
}
}
else
{
else
{
m_strategy
=
DRC_COMPLY
;
m_strategy
=
DRC_COMPLY
;
}
}
FilterSelection
(
selection
);
filterSelection
(
selection
);
if
(
settings
.
m_mode
==
DIALOG_TEARDROPS
::
TEARDROPS_MODE_ADD
)
{
if
(
settings
.
m_track
==
DIALOG_TEARDROPS
::
TEARDROPS_TRACKS_ALL
)
{
if
(
aSettings
.
m_mode
==
DIALOG_TEARDROPS
::
TEARDROPS_MODE_ADD
)
retVal
=
AddToAll
(
settings
);
{
if
(
aSettings
.
m_track
==
DIALOG_TEARDROPS
::
TEARDROPS_TRACKS_ALL
)
{
retVal
=
addToAll
(
aSettings
);
}
}
else
if
(
settings
.
m_track
==
DIALOG_TEARDROPS
::
TEARDROPS_TRACKS_SELECTED
)
{
else
if
(
aSettings
.
m_track
==
DIALOG_TEARDROPS
::
TEARDROPS_TRACKS_SELECTED
)
retVal
=
AddToSelected
(
selection
,
settings
);
{
retVal
=
addToSelected
(
selection
,
aSettings
);
}
}
}
}
else
if
(
settings
.
m_mode
==
DIALOG_TEARDROPS
::
TEARDROPS_MODE_REMOVE
)
{
else
if
(
aSettings
.
m_mode
==
DIALOG_TEARDROPS
::
TEARDROPS_MODE_REMOVE
)
RemoveAll
();
{
removeAll
();
retVal
=
true
;
retVal
=
true
;
}
}
return
retVal
;
return
retVal
;
}
}
bool
TEARDROPS_EDITOR
::
AddToAll
(
const
DIALOG_TEARDROPS
::
TEARDROPS_SETTINGS
&
settings
)
bool
TEARDROPS_EDITOR
::
addToAll
(
const
DIALOG_TEARDROPS
::
TEARDROPS_SETTINGS
&
aSettings
)
{
{
bool
added
=
false
;
bool
added
=
false
;
// Iterate through all vias and add teardrops to connected tracks
// Iterate through all vias and add teardrops to connected tracks
if
((
settings
.
m_scope
&
DIALOG_TEARDROPS
::
TEARDROPS_SCOPE_VIAS
)
==
DIALOG_TEARDROPS
::
TEARDROPS_SCOPE_VIAS
)
{
if
(
(
aSettings
.
m_scope
&
DIALOG_TEARDROPS
::
TEARDROPS_SCOPE_VIAS
)
==
for
(
VIA
*
via
=
GetFirstVia
(
m_frame
->
GetBoard
()
->
m_Track
);
via
!=
NULL
;
DIALOG_TEARDROPS
::
TEARDROPS_SCOPE_VIAS
)
via
=
GetFirstVia
(
via
->
Next
()))
{
{
if
(
IterateTracks
(
via
)
==
true
)
{
for
(
VIA
*
via
=
GetFirstVia
(
m_frame
->
GetBoard
()
->
m_Track
);
via
!=
NULL
;
via
=
GetFirstVia
(
via
->
Next
()
)
)
{
if
(
iterateTracks
(
via
)
==
true
)
{
added
=
true
;
added
=
true
;
}
}
}
}
}
}
// Iterate through all modules and add teardrops to tracks connected to their pads
// Iterate through all modules and add teardrops to tracks connected to their pads
if
((
settings
.
m_scope
&
DIALOG_TEARDROPS
::
TEARDROPS_SCOPE_PADS
)
==
DIALOG_TEARDROPS
::
TEARDROPS_SCOPE_PADS
)
{
if
(
(
aSettings
.
m_scope
&
DIALOG_TEARDROPS
::
TEARDROPS_SCOPE_PADS
)
==
for
(
MODULE
*
module
=
m_frame
->
GetBoard
()
->
m_Modules
.
GetFirst
();
module
!=
NULL
;
module
=
module
->
Next
())
{
DIALOG_TEARDROPS
::
TEARDROPS_SCOPE_PADS
)
D_PAD
*
pad
=
module
->
Pads
();
{
while
(
pad
!=
NULL
)
{
for
(
MODULE
*
module
=
m_frame
->
GetBoard
()
->
m_Modules
.
GetFirst
();
if
((
pad
->
GetShape
()
==
PAD_CIRCLE
)
&&
IterateTracks
(
pad
)
==
true
)
{
module
!=
NULL
;
added
=
true
;
module
=
module
->
Next
()
)
}
{
pad
=
pad
->
Next
();
D_PAD
*
pad
=
module
->
Pads
();
}
while
(
pad
!=
NULL
)
{
if
(
(
pad
->
GetShape
()
==
PAD_CIRCLE
)
&&
iterateTracks
(
pad
)
==
true
)
{
added
=
true
;
}
pad
=
pad
->
Next
();
}
}
}
}
}
if
(
added
==
true
)
{
if
(
added
==
true
)
m_frame
->
SaveCopyInUndoList
(
m_undoListPicker
,
UR_NEW
);
{
m_frame
->
SaveCopyInUndoList
(
m_undoListPicker
,
UR_NEW
);
m_undoListPicker
.
ClearItemsList
();
m_undoListPicker
.
ClearItemsList
();
}
}
return
added
;
return
added
;
}
}
bool
TEARDROPS_EDITOR
::
AddToSelected
(
SELECTION
&
selection
,
const
DIALOG_TEARDROPS
::
TEARDROPS_SETTINGS
&
settings
)
bool
TEARDROPS_EDITOR
::
addToSelected
(
SELECTION
&
aSelection
,
const
DIALOG_TEARDROPS
::
TEARDROPS_SETTINGS
&
aSettings
)
{
{
bool
retVal
=
false
;
bool
retVal
=
false
;
bool
added
=
false
;
bool
added
=
false
;
int
addedNum
=
0
;
int
addedNum
=
0
;
for
(
size_t
i
=
0
;
i
<
selection
.
items
.
GetCount
();
i
++
)
{
for
(
size_t
i
=
0
;
i
<
aSelection
.
items
.
GetCount
();
i
++
)
TRACK
*
track
=
static_cast
<
TRACK
*>
(
selection
.
items
.
GetPickedItem
(
i
));
{
TRACK
*
track
=
static_cast
<
TRACK
*>
(
aSelection
.
items
.
GetPickedItem
(
i
)
);
TEARDROP
teardropEnd
;
TEARDROP
teardropEnd
;
retVal
=
teardropEnd
.
Create
(
*
track
,
ENDPOINT_END
,
m_type
);
retVal
=
teardropEnd
.
Create
(
*
track
,
ENDPOINT_END
,
m_type
);
if
(
retVal
==
true
)
{
added
=
DrawSegments
(
teardropEnd
,
*
track
);
if
(
retVal
==
true
)
if
(
added
==
true
)
{
{
added
=
drawSegments
(
teardropEnd
,
*
track
);
if
(
added
==
true
)
{
addedNum
++
;
addedNum
++
;
}
}
}
}
TEARDROP
teardropStart
;
TEARDROP
teardropStart
;
retVal
=
teardropStart
.
Create
(
*
track
,
ENDPOINT_START
,
m_type
);
retVal
=
teardropStart
.
Create
(
*
track
,
ENDPOINT_START
,
m_type
);
if
(
retVal
==
true
)
{
added
=
DrawSegments
(
teardropStart
,
*
track
);
if
(
retVal
==
true
)
if
(
added
==
true
)
{
{
added
=
drawSegments
(
teardropStart
,
*
track
);
if
(
added
==
true
)
{
addedNum
++
;
addedNum
++
;
}
}
}
}
}
}
if
(
settings
.
m_clearSelection
==
true
)
{
GetManager
()
->
RunAction
(
COMMON_ACTIONS
::
selectionClear
,
true
);
if
(
aSettings
.
m_clearSelection
==
true
)
{
GetManager
()
->
RunAction
(
COMMON_ACTIONS
::
selectionClear
,
true
);
}
}
if
(
addedNum
>
0
)
{
if
(
addedNum
>
0
)
m_frame
->
SaveCopyInUndoList
(
m_undoListPicker
,
UR_NEW
);
{
m_frame
->
SaveCopyInUndoList
(
m_undoListPicker
,
UR_NEW
);
m_undoListPicker
.
ClearItemsList
();
m_undoListPicker
.
ClearItemsList
();
}
}
return
added
;
return
added
;
}
}
bool
TEARDROPS_EDITOR
::
IterateTracks
(
const
BOARD_CONNECTED_ITEM
*
aObject
)
bool
TEARDROPS_EDITOR
::
iterateTracks
(
const
BOARD_CONNECTED_ITEM
*
aObject
)
{
{
assert
(
aObject
);
assert
(
aObject
);
bool
retVal
=
false
;
bool
retVal
=
false
;
bool
flagAdded
=
false
;
bool
flagAdded
=
false
;
for
(
size_t
i
=
0
;
i
<
aObject
->
m_TracksConnected
.
size
();
i
++
)
{
for
(
size_t
i
=
0
;
i
<
aObject
->
m_TracksConnected
.
size
();
i
++
)
TRACK
*
track
=
aObject
->
m_TracksConnected
[
i
];
{
STATUS_FLAGS
objPosition
=
track
->
IsPointOnEnds
(
aObject
->
GetPosition
());
TRACK
*
track
=
aObject
->
m_TracksConnected
[
i
];
if
(
objPosition
==
STARTPOINT
||
objPosition
==
ENDPOINT
)
{
STATUS_FLAGS
objPosition
=
track
->
IsPointOnEnds
(
aObject
->
GetPosition
()
);
if
(
objPosition
==
STARTPOINT
||
objPosition
==
ENDPOINT
)
{
ENDPOINT_T
endpoint
=
(
objPosition
==
STARTPOINT
?
ENDPOINT_START
:
ENDPOINT_END
);
ENDPOINT_T
endpoint
=
(
objPosition
==
STARTPOINT
?
ENDPOINT_START
:
ENDPOINT_END
);
TEARDROP
teardrop
;
TEARDROP
teardrop
;
retVal
=
teardrop
.
Create
(
*
track
,
endpoint
,
m_type
);
retVal
=
teardrop
.
Create
(
*
track
,
endpoint
,
m_type
);
if
(
retVal
==
true
)
{
if
(
DrawSegments
(
teardrop
,
*
track
)
==
true
&&
flagAdded
==
false
)
{
if
(
retVal
==
true
)
{
if
(
drawSegments
(
teardrop
,
*
track
)
==
true
&&
flagAdded
==
false
)
{
flagAdded
=
true
;
flagAdded
=
true
;
}
}
}
}
}
}
}
}
return
flagAdded
;
return
flagAdded
;
}
}
void
TEARDROPS_EDITOR
::
RemoveAll
()
void
TEARDROPS_EDITOR
::
removeAll
()
{
{
ITEM_PICKER
picker
(
NULL
,
UR_DELETED
);
ITEM_PICKER
picker
(
NULL
,
UR_DELETED
);
TRACK
*
nextTrack
=
NULL
;
TRACK
*
nextTrack
=
NULL
;
bool
removed
=
false
;
bool
removed
=
false
;
for
(
TRACK
*
track
=
m_frame
->
GetBoard
()
->
m_Track
.
begin
();
track
!=
NULL
;
)
{
for
(
TRACK
*
track
=
m_frame
->
GetBoard
()
->
m_Track
.
begin
();
track
!=
NULL
;
)
{
nextTrack
=
track
->
Next
();
nextTrack
=
track
->
Next
();
if
(
track
->
GetState
(
FLAG1
)
==
FLAG1
)
{
picker
.
SetItem
(
track
);
if
(
track
->
GetState
(
FLAG1
)
==
FLAG1
)
m_undoListPicker
.
PushItem
(
picker
);
{
picker
.
SetItem
(
track
);
m_undoListPicker
.
PushItem
(
picker
);
removed
=
true
;
removed
=
true
;
m_view
->
Remove
(
track
);
m_view
->
Remove
(
track
);
m_frame
->
GetBoard
()
->
Remove
(
track
);
m_frame
->
GetBoard
()
->
Remove
(
track
);
}
}
track
=
nextTrack
;
track
=
nextTrack
;
}
}
m_frame
->
GetBoard
()
->
GetRatsnest
()
->
Recalculate
();
m_frame
->
GetBoard
()
->
GetRatsnest
()
->
Recalculate
();
if
(
removed
==
true
)
{
m_frame
->
SaveCopyInUndoList
(
m_undoListPicker
,
UR_DELETED
);
if
(
removed
==
true
)
{
m_frame
->
SaveCopyInUndoList
(
m_undoListPicker
,
UR_DELETED
);
m_undoListPicker
.
ClearItemsList
();
m_undoListPicker
.
ClearItemsList
();
}
}
}
}
bool
TEARDROPS_EDITOR
::
DrawSegments
(
TEARDROP
&
teardrop
,
TRACK
&
aTrack
)
bool
TEARDROPS_EDITOR
::
drawSegments
(
TEARDROP
&
aTeardrop
,
TRACK
&
aTrack
)
{
{
bool
tracksAdded
=
true
;
bool
tracksAdded
=
true
;
bool
proceedBuild
=
true
;
bool
proceedBuild
=
true
;
ITEM_PICKER
picker
(
NULL
,
UR_NEW
);
ITEM_PICKER
picker
(
NULL
,
UR_NEW
);
PNS_NODE
*
world
=
PNS_ROUTER
::
GetInstance
()
->
GetWorld
();
PNS_NODE
*
world
=
PNS_ROUTER
::
GetInstance
()
->
GetWorld
();
BOARD
*
board
=
aTrack
.
GetBoard
();
BOARD
*
board
=
aTrack
.
GetBoard
();
std
::
vector
<
TRACK
*>
tracks
;
std
::
vector
<
TRACK
*>
tracks
;
std
::
vector
<
VECTOR2I
>
coordinates
;
std
::
vector
<
VECTOR2I
>
coordinates
;
teardrop
.
GetCoordinates
(
coordinates
);
aTeardrop
.
GetCoordinates
(
coordinates
);
assert
(
coordinates
.
size
()
!=
0
);
assert
(
coordinates
.
size
()
!=
0
);
wxPoint
currentPoint
(
0
,
0
);
wxPoint
currentPoint
(
0
,
0
);
wxPoint
prevPoint
(
coordinates
[
0
].
x
,
coordinates
[
0
].
y
);
wxPoint
prevPoint
(
coordinates
[
0
].
x
,
coordinates
[
0
].
y
);
for
(
size_t
i
=
1
;
i
<
coordinates
.
size
();
i
++
)
{
for
(
size_t
i
=
1
;
i
<
coordinates
.
size
();
i
++
)
if
(
m_strategy
!=
DRC_IGNORE
)
{
{
PNS_SEGMENT
segment
(
SEG
(
coordinates
[
i
-
1
],
coordinates
[
i
]),
aTrack
.
GetNetCode
());
if
(
m_strategy
!=
DRC_IGNORE
)
segment
.
SetWidth
(
aTrack
.
GetWidth
());
{
segment
.
SetLayers
(
PNS_LAYERSET
(
aTrack
.
GetLayer
()));
PNS_SEGMENT
segment
(
SEG
(
coordinates
[
i
-
1
],
coordinates
[
i
]
),
aTrack
.
GetNetCode
()
);
segment
.
SetParent
(
&
aTrack
);
segment
.
SetWidth
(
aTrack
.
GetWidth
()
);
segment
.
SetLayers
(
PNS_LAYERSET
(
aTrack
.
GetLayer
()
)
);
segment
.
SetParent
(
&
aTrack
);
PNS_NODE
::
OBSTACLES
obstacles
;
PNS_NODE
::
OBSTACLES
obstacles
;
if
(
world
->
QueryColliding
(
&
segment
,
obstacles
,
PNS_ITEM
::
ANY
,
1
)
>
0
)
{
// DRC violation found, the segment of a teadrop can not be place
if
(
world
->
QueryColliding
(
&
segment
,
obstacles
,
PNS_ITEM
::
ANY
,
1
)
>
0
)
{
// DRC violation found, the segment of a teadrop can not be placed
tracksAdded
=
false
;
tracksAdded
=
false
;
proceedBuild
=
false
;
proceedBuild
=
false
;
break
;
break
;
}
}
}
}
if
(
proceedBuild
==
true
)
{
TRACK
*
track
=
new
TRACK
(
aTrack
);
if
(
proceedBuild
==
true
)
track
->
SetWidth
(
aTrack
.
GetWidth
());
{
track
->
SetLayer
(
aTrack
.
GetLayer
());
TRACK
*
track
=
new
TRACK
(
aTrack
);
track
->
SetNetCode
(
aTrack
.
GetNetCode
());
currentPoint
=
wxPoint
(
coordinates
[
i
].
x
,
coordinates
[
i
].
y
);
track
->
SetWidth
(
aTrack
.
GetWidth
()
);
track
->
SetStart
(
prevPoint
);
track
->
SetLayer
(
aTrack
.
GetLayer
()
);
track
->
SetEnd
(
currentPoint
);
track
->
SetNetCode
(
aTrack
.
GetNetCode
()
);
currentPoint
=
wxPoint
(
coordinates
[
i
].
x
,
coordinates
[
i
].
y
);
track
->
SetStart
(
prevPoint
);
track
->
SetEnd
(
currentPoint
);
track
->
ClearFlags
();
track
->
ClearFlags
();
track
->
SetState
(
FLAG1
,
true
);
track
->
SetState
(
FLAG1
,
true
);
tracks
.
push_back
(
track
);
tracks
.
push_back
(
track
);
prevPoint
=
currentPoint
;
prevPoint
=
currentPoint
;
picker
.
SetItem
(
track
);
picker
.
SetItem
(
track
);
m_undoListPicker
.
PushItem
(
picker
);
m_undoListPicker
.
PushItem
(
picker
);
}
}
prevPoint
=
currentPoint
;
prevPoint
=
currentPoint
;
}
}
if
(
tracksAdded
==
true
)
{
BOOST_FOREACH
(
TRACK
*
item
,
tracks
)
{
if
(
tracksAdded
==
true
)
board
->
Add
(
item
);
{
m_view
->
Add
(
item
);
// The actual addition is done here
BOOST_FOREACH
(
TRACK
*
item
,
tracks
)
{
board
->
Add
(
item
);
m_view
->
Add
(
item
);
}
}
}
}
else
{
else
{
// The teardrop can not be created thus delete all allocated tracks and
// The teardrop can not be created thus delete all allocated tracks and
// remove them from undo list
// remove them from undo list
BOOST_FOREACH
(
TRACK
*
item
,
tracks
)
{
BOOST_FOREACH
(
TRACK
*
item
,
tracks
)
{
m_undoListPicker
.
PopItem
();
m_undoListPicker
.
PopItem
();
delete
item
;
delete
item
;
}
}
...
...
pcbnew/tools/edit_teardrops.h
View file @
c5973eb8
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Elphel, Inc.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TEARDROPS_EDITOR_H
#ifndef TEARDROPS_EDITOR_H
#define TEARDROPS_EDITOR_H
#define TEARDROPS_EDITOR_H
...
@@ -7,51 +26,99 @@
...
@@ -7,51 +26,99 @@
#include "class_teardrop.h"
#include "class_teardrop.h"
#include "import_export.h"
#include "import_export.h"
/**
* @brief The TEARDROPS_EDITOR class
* creates actual tracks on the board in accordance with the preferences provided by
* the DIALOG_TEARDROPS class.
*/
class
APIEXPORT
TEARDROPS_EDITOR
:
public
TOOL_BASE
class
APIEXPORT
TEARDROPS_EDITOR
:
public
TOOL_BASE
{
{
public
:
public
:
TEARDROPS_EDITOR
();
TEARDROPS_EDITOR
();
~
TEARDROPS_EDITOR
();
~
TEARDROPS_EDITOR
();
bool
EditTeardrops
(
const
DIALOG_TEARDROPS
::
TEARDROPS_SETTINGS
&
settings
);
/**
* @brief Function \a EditTeardrops
* is invoked for any manupulation with the teardrops on current board.
* @param [in] aSettings contains user defined settings provided by teadrops editor dialog window
* @return bool - \a true in case teardrops were successfully created and \a false otherwise
*/
bool
EditTeardrops
(
const
DIALOG_TEARDROPS
::
TEARDROPS_SETTINGS
&
aSettings
);
/// @copydoc TOOL_INTERACTIVE::Reset
/// @copydoc TOOL_INTERACTIVE::Reset
void
Reset
(
RESET_REASON
aReason
);
void
Reset
(
RESET_REASON
aReason
);
private
:
private
:
typedef
enum
{
/**
* The DRC_STRATEGY
* defines the strategy when DRC violation is detected during teardop creation.
*/
typedef
enum
{
/// Do not violate DRC and quit teardrop building
DRC_COMPLY
,
DRC_COMPLY
,
/// Ignore DRC and finish teardop
DRC_IGNORE
,
DRC_IGNORE
,
/// Try to adjust the outline or size of a teardop (not implemented)
DRC_ADJUST
DRC_ADJUST
}
DRC_STRATEGY
;
}
DRC_STRATEGY
;
PCB_EDIT_FRAME
*
m_frame
;
PCB_EDIT_FRAME
*
m_frame
;
KIGFX
::
VIEW
*
m_view
;
KIGFX
::
VIEW
*
m_view
;
TEARDROP
::
TEARDROP_TYPE
m_type
;
TEARDROP
::
TEARDROP_TYPE
m_type
;
PICKED_ITEMS_LIST
m_undoListPicker
;
PICKED_ITEMS_LIST
m_undoListPicker
;
DRC_STRATEGY
m_strategy
;
DRC_STRATEGY
m_strategy
;
/**
/**
* @brief FilterSelection filters selected objects and removes all objects except tracks.
* @brief Function \a filterSelection
* @param selection contains the list of currently selected objects
* filters selected objects and removes all objects which can not be processed.
* @param [in,out] aSelection contains the list of currently selected objects on input and
* a list of valid for processing objects on output
*/
*/
void
FilterSelection
(
SELECTION
&
selection
);
void
filterSelection
(
SELECTION
&
aSelection
);
/**
/**
* @brief IterateTracks creates teardrop for all tracks connected to \a aObject
* @brief Function \a iterateTracks
* @param aObject is a board object a which teardrops should be created. Currently such an object can
* creates teardrop(s) for all tracks connected to \a aObject.
* @param [in] aObject is a board object at which teardrops should be created. Currently such an object can
* be via or circular pad.
* be via or circular pad.
* @return \a true if at least one teardrop was successfully added and \a false otherwise
* @return \a true if at least one teardrop was successfully added and \a false otherwise
*/
*/
bool
IterateTracks
(
const
BOARD_CONNECTED_ITEM
*
aObject
);
bool
iterateTracks
(
const
BOARD_CONNECTED_ITEM
*
aObject
);
bool
AddToAll
(
const
DIALOG_TEARDROPS
::
TEARDROPS_SETTINGS
&
settings
);
bool
AddToSelected
(
SELECTION
&
selection
,
const
DIALOG_TEARDROPS
::
TEARDROPS_SETTINGS
&
settings
);
/**
* @brief Function \a addToAll
* adds teardrops to all tracks on the board.
* @param [in] aSettings contains user defined settings
* @return bool - \a true in case teardops were successfully added and \a false otherwise
*/
bool
addToAll
(
const
DIALOG_TEARDROPS
::
TEARDROPS_SETTINGS
&
aSettings
);
/**
/**
* @brief RemoveAll removes all teardrops form board.
* @brief Function \a addToSelected
* adds teardrops to selected tracks.
* @param [in] aSelection contains a filtered list of selected tracks
* @param [in] aSettings contains user defined settings
* @return bool - \a true in case teardops were successfully added and \a false otherwise
*/
*/
void
RemoveAll
(
);
bool
addToSelected
(
SELECTION
&
aSelection
,
const
DIALOG_TEARDROPS
::
TEARDROPS_SETTINGS
&
aSettings
);
bool
DrawSegments
(
TEARDROP
&
teardrop
,
TRACK
&
track
);
/**
* @brief Function \a RemoveAll
* removes all teardrops form current board.
*/
void
removeAll
();
/**
* @brief Function \a drawSegments
* adds tracks composing a teardop to the board.
* @param [in] aTeardrop is a teardrop which should be created on the board
* @param [in] aTrack is a parent track, some of its parameters are copied to newly created
* segments
* @return bool - \a true in case all the tracks were successfully added and \a false
* otherwise
*/
bool
drawSegments
(
TEARDROP
&
aTeardrop
,
TRACK
&
aTrack
);
};
};
#endif // TEARDROPS_EDITOR_H
#endif
// TEARDROPS_EDITOR_H
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