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()
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
;
BOARD_CONNECTED_ITEM
*
anObject
=
GetObjectOnEnd
(
aTrack
,
endPoint
);
VIA
*
aVia
=
NULL
;
if
(
anObject
==
NULL
)
{
BOARD_CONNECTED_ITEM
*
object
=
getObjectOnEnd
(
aTrack
,
aEndPoint
);
VIA
*
aVia
=
NULL
;
if
(
object
==
NULL
)
{
return
false
;
}
else
{
switch
(
anObject
->
Type
())
{
else
{
switch
(
object
->
Type
()
)
{
case
PCB_VIA_T
:
aVia
=
dynamic_cast
<
VIA
*>
(
anObject
);
aVia
=
dynamic_cast
<
VIA
*>
(
object
);
break
;
case
PCB_PAD_T
:
aVia
=
new
VIA
(
NULL
);
aVia
->
SetLayer
(
anObject
->
GetLayer
());
aVia
->
SetPosition
(
anObject
->
GetPosition
());
aVia
->
SetWidth
(
2
*
dynamic_cast
<
D_PAD
*>
(
anObject
)
->
GetBoundingRadius
());
aVia
=
new
VIA
(
NULL
);
aVia
->
SetLayer
(
object
->
GetLayer
()
);
aVia
->
SetPosition
(
object
->
GetPosition
()
);
aVia
->
SetWidth
(
2
*
dynamic_cast
<
D_PAD
*>
(
object
)
->
GetBoundingRadius
()
);
break
;
default
:
break
;
}
}
if
(
type
==
TEARDROP_STRAIGHT
)
{
result
=
StraightSegments
(
aTrack
,
*
aVia
,
100
);
if
(
aType
==
TEARDROP_STRAIGHT
)
{
result
=
straightSegments
(
aTrack
,
*
aVia
,
100
);
}
else
if
(
type
==
TEARDROP_CURVED
)
{
result
=
CurvedSegments
(
aTrack
,
*
aVia
);
else
if
(
aType
==
TEARDROP_CURVED
)
{
result
=
curvedSegments
(
aTrack
,
*
aVia
);
}
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
STATUS_FLAGS
status
=
aTrack
.
IsPointOnEnds
(
aVia
.
GetPosition
(),
aVia
.
GetWidth
()
/
2
);
if
(
status
==
STARTPOINT
)
{
startPoint
=
aTrack
.
GetEnd
();
endPoint
=
aTrack
.
GetStart
();
STATUS_FLAGS
status
=
aTrack
.
IsPointOnEnds
(
aVia
.
GetPosition
(),
aVia
.
GetWidth
()
/
2
);
if
(
status
==
STARTPOINT
)
{
aStartPoint
=
aTrack
.
GetEnd
();
aEndPoint
=
aTrack
.
GetStart
();
}
else
if
(
status
==
ENDPOINT
)
{
startPoint
=
aTrack
.
GetStart
();
endPoint
=
aTrack
.
GetEnd
();
else
if
(
status
==
ENDPOINT
)
{
aStartPoint
=
aTrack
.
GetStart
();
aEndPoint
=
aTrack
.
GetEnd
();
}
else
{
else
{
// The via is too far from any end or the track is too short
return
false
;
}
...
...
@@ -66,88 +81,120 @@ bool TEARDROP::SetVector(TRACK &aTrack, const VIA & aVia, VECTOR2I &startPoint,
return
true
;
}
bool
TEARDROP
::
CurvedSegments
(
TRACK
&
aTrack
,
const
VIA
&
aVia
)
bool
TEARDROP
::
curvedSegments
(
TRACK
&
aTrack
,
const
VIA
&
aVia
)
{
VECTOR2I
startPoint
(
0
,
0
);
VECTOR2I
endPoint
(
0
,
0
);
std
::
vector
<
VECTOR2I
>
upperSegment
;
std
::
vector
<
VECTOR2I
>
lowerSegment
;
VECTOR2I
startPoint
(
0
,
0
);
VECTOR2I
endPoint
(
0
,
0
);
std
::
vector
<
VECTOR2I
>
lowerSegment
;
if
(
!
SetVector
(
aTrack
,
aVia
,
startPoint
,
endPoint
)
)
{
if
(
!
setVector
(
aTrack
,
aVia
,
startPoint
,
endPoint
)
)
{
return
false
;
}
// Check that the track is not too short
double
segOutsideVia
=
aTrack
.
GetLength
()
-
(
aVia
.
GetWidth
()
/
2
);
double
minLength
=
(
150
*
aVia
.
GetWidth
()
/
2
)
/
100
;
if
(
segOutsideVia
<
minLength
)
{
if
(
segOutsideVia
<
minLength
)
{
return
false
;
}
VECTOR2I
point
(
0
,
0
);
VECTOR2I
viaCenter
(
aVia
.
GetPosition
().
x
,
aVia
.
GetPosition
().
y
);
VECTOR2I
apertureUpper
(
0
,
0
);
VECTOR2I
apertureLower
(
0
,
0
);
VECTOR2I
point
(
0
,
0
);
VECTOR2I
viaCenter
(
aVia
.
GetPosition
().
x
,
aVia
.
GetPosition
().
y
);
VECTOR2I
apertureUpper
(
0
,
0
);
VECTOR2I
apertureLower
(
0
,
0
);
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
for
(
int
i
=
10
;
i
<=
60
;
i
=
i
+
10
)
{
PointOnCurve
(
i
,
radius
,
point
);
point
=
point
.
Rotate
(
rotationAngle
);
for
(
int
i
=
0
;
i
<=
60
;
i
=
i
+
10
)
{
pointOnCurve
(
i
,
radius
,
point
);
point
=
point
.
Rotate
(
rotationAngle
);
point
+=
viaCenter
;
m_coordinates
.
push_back
(
point
);
if
(
i
==
50
)
{
m_coordinates
.
push_back
(
point
);
if
(
i
==
50
)
{
apertureUpper
=
point
;
}
}
for
(
int
i
=
300
;
i
<=
350
;
i
=
i
+
10
)
{
PointOnCurve
(
i
,
radius
,
point
);
point
=
point
.
Rotate
(
rotationAngle
);
for
(
int
i
=
300
;
i
<=
360
;
i
=
i
+
10
)
{
pointOnCurve
(
i
,
radius
,
point
);
point
=
point
.
Rotate
(
rotationAngle
);
point
+=
viaCenter
;
m_coordinates
.
push_back
(
point
);
if
(
i
==
340
)
{
m_coordinates
.
push_back
(
point
);
if
(
i
==
340
)
{
apertureLower
=
point
;
}
}
// 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
// number of iterations required to fill the zone
SEG
aperture
(
apertureUpper
,
apertureLower
);
SEG
aperture
(
apertureUpper
,
apertureLower
);
int
numSegments
=
aperture
.
Length
()
/
aTrack
.
GetWidth
();
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
;
for
(
int
i
=
10
;
i
<=
60
;
i
=
i
+
10
)
{
PointOnCurve
(
i
,
radius
,
point
);
point
=
point
.
Rotate
(
rotationAngle
);
for
(
int
i
=
10
;
i
<=
60
;
i
=
i
+
10
)
{
pointOnCurve
(
i
,
radius
,
point
);
point
=
point
.
Rotate
(
rotationAngle
);
point
+=
viaCenter
;
if
(
i
==
10
)
{
int
distance
=
SEG
(
viaCenter
,
point
).
Length
();
if
(
distance
<
aVia
.
GetWidth
()
/
2
)
{
// Stop calculations in case the coordinates are inside the via
if
(
i
==
10
)
{
int
distance
=
SEG
(
viaCenter
,
point
).
Length
();
if
(
distance
<
aVia
.
GetWidth
()
/
2
)
{
break
;
}
}
m_coordinates
.
push_back
(
point
);
m_coordinates
.
push_back
(
point
);
}
lowerSegment
.
clear
();
for
(
int
i
=
350
;
i
>=
300
;
i
=
i
-
10
)
{
PointOnCurve
(
i
,
radius
,
point
);
point
=
point
.
Rotate
(
rotationAngle
);
for
(
int
i
=
350
;
i
>=
300
;
i
=
i
-
10
)
{
pointOnCurve
(
i
,
radius
,
point
);
point
=
point
.
Rotate
(
rotationAngle
);
point
+=
viaCenter
;
if
(
i
==
350
)
{
int
distance
=
SEG
(
viaCenter
,
point
).
Length
();
if
(
distance
<
aVia
.
GetWidth
()
/
2
)
{
// Stop calculations in case the coordinates are inside the via
if
(
i
==
350
)
{
int
distance
=
SEG
(
viaCenter
,
point
).
Length
();
if
(
distance
<
aVia
.
GetWidth
()
/
2
)
{
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
)
{
m_coordinates
.
push_back
(
*
iter
);
// Revert coordinates order. This is necessary to create tracks in correct order later on
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)
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
endPoint
(
0
,
0
);
VECTOR2I
viaCenter
(
aVia
.
GetPosition
().
x
,
aVia
.
GetPosition
().
y
);
VECTOR2I
startPoint
(
0
,
0
);
VECTOR2I
endPoint
(
0
,
0
);
VECTOR2I
viaCenter
(
aVia
.
GetPosition
().
x
,
aVia
.
GetPosition
().
y
);
if
(
!
SetVector
(
aTrack
,
aVia
,
startPoint
,
endPoint
)
)
{
if
(
!
setVector
(
aTrack
,
aVia
,
startPoint
,
endPoint
)
)
{
return
false
;
}
// Check that the track is not too short
double
segOutsideVia
=
aTrack
.
GetLength
()
-
(
aVia
.
GetWidth
()
/
2
);
double
minLength
=
(
distance
*
aVia
.
GetWidth
()
/
2
)
/
100
;
if
(
segOutsideVia
<
minLength
)
{
double
minLength
=
(
aDistance
*
aVia
.
GetWidth
()
/
2
)
/
100
;
if
(
segOutsideVia
<
minLength
)
{
return
false
;
}
// Equation coefficients
double
r
=
(
aVia
.
GetWidth
()
/
2
)
+
((
distance
*
aVia
.
GetWidth
())
/
(
2
*
100
));
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
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
r
=
(
aVia
.
GetWidth
()
/
2
)
+
(
(
aDistance
*
aVia
.
GetWidth
())
/
(
2
*
100
)
);
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
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
y
=
(
endPoint
.
y
-
startPoint
.
y
)
*
t
+
startPoint
.
y
;
VECTOR2I
linePoint
(
x
,
y
);
VECTOR2I
linePoint
(
x
,
y
);
int
correctedRadius
=
(
aVia
.
GetWidth
()
/
2
)
-
(
aTrack
.
GetWidth
()
/
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
));
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
));
x
=
(
endPoint
.
x
-
startPoint
.
x
)
*
t
+
startPoint
.
x
;
y
=
(
endPoint
.
y
-
startPoint
.
y
)
*
t
+
startPoint
.
y
;
VECTOR2I
circlePoint
(
x
,
y
);
VECTOR2I
circlePoint
(
x
,
y
);
VECTOR2I
upperPoint
=
circlePoint
-
viaCenter
;
VECTOR2I
lowerPoint
=
upperPoint
;
upperPoint
=
upperPoint
.
Rotate
(
M_PI
/
2
);
lowerPoint
=
lowerPoint
.
Rotate
(
-
M_PI
/
2
);
upperPoint
+=
viaCenter
;
lowerPoint
+=
viaCenter
;
VECTOR2I
upperPoint
=
circlePoint
-
viaCenter
;
VECTOR2I
lowerPoint
=
upperPoint
;
upperPoint
=
upperPoint
.
Rotate
(
M_PI
/
2
);
lowerPoint
=
lowerPoint
.
Rotate
(
-
M_PI
/
2
);
upperPoint
+=
viaCenter
;
lowerPoint
+=
viaCenter
;
// Calculate the number of segments needed to fill the area inside the teardrop
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
r
=
aVia
.
GetWidth
()
/
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
);
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
));
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
);
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
;
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
SEG
trackSegment
(
aTrack
.
GetStart
().
x
,
aTrack
.
GetStart
().
y
,
aTrack
.
GetEnd
().
x
,
aTrack
.
GetEnd
().
y
);
int
dist
=
trackSegment
.
LineDistance
(
intersectionPoint
);
SEG
trackSegment
(
aTrack
.
GetStart
().
x
,
aTrack
.
GetStart
().
y
,
aTrack
.
GetEnd
().
x
,
aTrack
.
GetEnd
().
y
);
int
dist
=
trackSegment
.
LineDistance
(
intersectionPoint
);
int
numSegments
=
2
*
dist
/
aTrack
.
GetWidth
();
// Third, subdivide the diameter of the via and build additional segments
SEG
segDiameter
=
SEG
(
upperPoint
,
lowerPoint
);
SplitSegment
(
segDiameter
,
numSegments
,
splitPoints
);
SEG
segDiameter
=
SEG
(
upperPoint
,
lowerPoint
);
splitSegment
(
segDiameter
,
numSegments
,
splitPoints
);
}
std
::
list
<
VECTOR2I
>
outlinePoints
;
outlinePoints
.
push_back
(
upperPoint
);
for
(
size_t
i
=
0
;
i
<
splitPoints
.
size
();
i
++
)
{
outlinePoints
.
push_back
(
splitPoints
[
i
]);
outlinePoints
.
push_back
(
upperPoint
);
for
(
size_t
i
=
0
;
i
<
splitPoints
.
size
();
i
++
)
{
outlinePoints
.
push_back
(
splitPoints
[
i
]
);
}
outlinePoints
.
push_back
(
lowerPoint
);
outlinePoints
.
push_back
(
lowerPoint
);
// Biuld triangles filling the teardrop
int
vertexNum
=
0
;
std
::
list
<
VECTOR2I
>::
iterator
iter
=
outlinePoints
.
begin
();
while
(
iter
!=
outlinePoints
.
end
()
)
{
switch
(
vertexNum
)
{
while
(
iter
!=
outlinePoints
.
end
()
)
{
switch
(
vertexNum
)
{
case
0
:
m_coordinates
.
push_back
(
linePoint
);
m_coordinates
.
push_back
(
linePoint
);
vertexNum
++
;
break
;
case
1
:
m_coordinates
.
push_back
(
*
iter
);
m_coordinates
.
push_back
(
*
iter
);
vertexNum
++
;
iter
++
;
break
;
case
2
:
m_coordinates
.
push_back
(
*
iter
);
m_coordinates
.
push_back
(
*
iter
);
vertexNum
=
0
;
iter
++
;
break
;
default
:
break
;
default
:
break
;
}
}
// Append additional vertexies in order to finish last triangle
if
(
vertexNum
==
0
)
{
m_coordinates
.
push_back
(
linePoint
);
if
(
vertexNum
==
0
)
{
m_coordinates
.
push_back
(
linePoint
);
}
else
if
(
vertexNum
==
2
)
{
m_coordinates
.
push_back
(
m_coordinates
[
m_coordinates
.
size
()
-
3
]);
m_coordinates
.
push_back
(
linePoint
);
else
if
(
vertexNum
==
2
)
{
m_coordinates
.
push_back
(
m_coordinates
[
m_coordinates
.
size
()
-
3
]
);
m_coordinates
.
push_back
(
linePoint
);
}
return
true
;
}
// 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
;
BOARD_CONNECTED_ITEM
*
item
=
NULL
;
std
::
vector
<
TRACK
*>::
const_iterator
iter
;
BOARD_CONNECTED_ITEM
*
item
=
NULL
;
std
::
vector
<
TRACK
*>::
const_iterator
iter
;
if
(
endPoint
==
ENDPOINT_START
)
{
if
(
aEndPoint
==
ENDPOINT_START
)
{
trackPoint
=
aTrack
.
GetStart
();
}
else
{
else
{
trackPoint
=
aTrack
.
GetEnd
();
}
// 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
();
bool
hitTest
=
(
*
iter
)
->
HitTest
(
trackPoint
);
if
(
type
==
PCB_VIA_T
&&
hitTest
==
true
)
{
bool
hitTest
=
(
*
iter
)
->
HitTest
(
trackPoint
);
if
(
(
type
==
PCB_VIA_T
)
&&
(
hitTest
==
true
)
)
{
item
=
*
iter
;
}
}
// Check for pads if via was not found on this end of the track
if
(
item
==
NULL
)
{
for
(
std
::
vector
<
D_PAD
*>::
iterator
iter
=
aTrack
.
m_PadsConnected
.
begin
();
iter
!=
aTrack
.
m_PadsConnected
.
end
();
++
iter
)
{
if
(
item
==
NULL
)
{
for
(
std
::
vector
<
D_PAD
*>::
iterator
iter
=
aTrack
.
m_PadsConnected
.
begin
();
iter
!=
aTrack
.
m_PadsConnected
.
end
();
++
iter
)
{
PAD_SHAPE_T
shape
=
(
*
iter
)
->
GetShape
();
bool
hitTest
=
(
*
iter
)
->
HitTest
(
trackPoint
);
if
(
shape
==
PAD_CIRCLE
&&
hitTest
==
true
)
{
bool
hitTest
=
(
*
iter
)
->
HitTest
(
trackPoint
);
if
(
shape
==
PAD_CIRCLE
&&
hitTest
==
true
)
{
item
=
*
iter
;
}
}
...
...
@@ -297,20 +377,28 @@ BOARD_CONNECTED_ITEM* TEARDROP::GetObjectOnEnd(TRACK &aTrack, ENDPOINT_T endPoin
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
dY
=
abs
((
segment
.
A
.
y
-
segment
.
B
.
y
)
/
splits
);
if
(
segment
.
A
.
x
>
segment
.
B
.
x
)
{
int
dX
=
abs
(
(
aSegment
.
A
.
x
-
aSegment
.
B
.
x
)
/
aSplits
);
int
dY
=
abs
(
(
aSegment
.
A
.
y
-
aSegment
.
B
.
y
)
/
aSplits
);
if
(
aSegment
.
A
.
x
>
aSegment
.
B
.
x
)
{
dX
=
-
dX
;
}
if
(
segment
.
A
.
y
>
segment
.
B
.
y
)
{
if
(
aSegment
.
A
.
y
>
aSegment
.
B
.
y
)
{
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
for
(
int
i
=
1
;
i
<
splits
-
1
;
i
++
)
{
points
.
push_back
(
points
.
back
()
+
delta
);
for
(
int
i
=
1
;
i
<
aSplits
-
1
;
i
++
)
{
aPoints
.
push_back
(
aPoints
.
back
()
+
delta
);
}
}
pcbnew/class_teardrop.h
View file @
c5973eb8
...
...
@@ -17,93 +17,130 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file class_teardrop.h
* @brief Definitions for teardrops.
*/
#ifndef CLASS_TEARDROP_H
#define CLASS_TEARDROP_H
#include "class_track.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
{
public
:
TEARDROP
();
/**
* @brief
D
efines the type of a teardrop.
* @brief
The TEARDROP_TYPE d
efines the type of a teardrop.
*/
typedef
enum
{
TEARDROP_NONE
,
///< The type is undefined
TEARDROP_STRAIGHT
,
///< The teardrop is created by two straight segments
TEARDROP_CURVED
///< The teardrop is created by several segments approximating a curve
typedef
enum
{
TEARDROP_NONE
,
///< The type is undefined
TEARDROP_STRAIGHT
,
///< The teardrop is created by two straight segments
TEARDROP_CURVED
///< The teardrop is created by several segments approximating a curve
}
TEARDROP_TYPE
;
/**
* @brief GetType returns the type of the teardrop.
* @return TEARDROP_TYPE
* @brief Function \a GetType
* 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
* @param aTrack
* @return \a true in case the teardrops were successfully built and \a false otherwise
* @brief Function \a Create
* creates a teardrop(s) for a given track.
* @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
:
///
>
Contains the type of teardrop
/// Contains the type of teardrop
TEARDROP_TYPE
m_type
;
///> \a m_upperSegment and \a m_lowerSegment contain coordinates of segments composing a teardrop
std
::
vector
<
VECTOR2I
>
m_upperSegment
;
std
::
vector
<
VECTOR2I
>
m_lowerSegment
;
/// Contains the actual coordinates of teardrop
std
::
vector
<
VECTOR2I
>
m_coordinates
;
/**
* @brief Function \a CurvedSegments computes several points on deltoid curve and moves
* these points along the vector defined by \a aTrack.
* @brief Function \a curvedSegments
* 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.
* 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] 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.
* @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] distance 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
* @param [in] aDistance is distance ratio (in percent) from circle center in respect to its diameter
* @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
*
@param aTrack is used to create a vector
* @param
startPoint is start point of resulting vector
* @param
endPoint is end point of resulting vector
* @
return \a true in case the vector is created successfully and \a false otherwise
* @brief Function
\a splitSegment
*
splits a segment into given number of subsegments.
* @param
[in] aSegment is a segment to be split
* @param
[i] aSplits is a number of splits
* @
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
);
inline
void
PointOnCurve
(
int
angle
,
double
radius
,
VECTOR2I
&
point
)
{
/**
* @brief Function \a pointOnCurve
* 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
;
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"
DIALOG_TEARDROPS
::
DIALOG_TEARDROPS
(
PCB_EDIT_FRAME
*
aParent
,
TEARDROPS_SETTINGS
*
settings
)
:
DIALOG_TEARDROPS_BASE
(
aParent
)
DIALOG_TEARDROPS
::
DIALOG_TEARDROPS
(
PCB_EDIT_FRAME
*
aParent
,
TEARDROPS_SETTINGS
*
aSettings
=
NULL
)
:
DIALOG_TEARDROPS_BASE
(
aParent
)
{
m_parent
=
aParent
;
m_settings
=
settings
;
if
(
m_settings
!=
NULL
)
{
InitDialogSettings
();
m_settings
=
aSettings
;
if
(
m_settings
!=
NULL
)
{
initDialogSettings
();
}
}
void
DIALOG_TEARDROPS
::
I
nitDialogSettings
()
void
DIALOG_TEARDROPS
::
i
nitDialogSettings
()
{
wxASSERT
(
m_settings
!=
NULL
);
if
(
m_modeRemove
->
GetValue
()
==
true
)
{
assert
(
m_settings
!=
NULL
);
if
(
m_modeRemove
->
GetValue
()
==
true
)
{
m_settings
->
m_mode
=
TEARDROPS_MODE_REMOVE
;
}
else
{
else
{
m_settings
->
m_mode
=
TEARDROPS_MODE_ADD
;
}
if
(
m_tracksAll
->
GetValue
()
==
true
)
{
if
(
m_tracksAll
->
GetValue
()
==
true
)
{
m_settings
->
m_track
=
TEARDROPS_TRACKS_ALL
;
}
else
{
else
{
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
;
if
(
m_scopeVias
->
IsChecked
()
==
true
)
{
m_settings
->
m_scope
=
static_cast
<
TEARDROPS_SCOPE
>
(
m_settings
->
m_scope
|
TEARDROPS_SCOPE_VIAS
);
if
(
m_scopeVias
->
IsChecked
()
==
true
)
{
m_settings
->
m_scope
=
static_cast
<
TEARDROPS_SCOPE
>
(
m_settings
->
m_scope
|
TEARDROPS_SCOPE_VIAS
);
}
if
(
m_scopePads
->
IsChecked
()
==
true
)
{
m_settings
->
m_scope
=
static_cast
<
TEARDROPS_SCOPE
>
(
m_settings
->
m_scope
|
TEARDROPS_SCOPE_PADS
);
if
(
m_scopePads
->
IsChecked
()
==
true
)
{
m_settings
->
m_scope
=
static_cast
<
TEARDROPS_SCOPE
>
(
m_settings
->
m_scope
|
TEARDROPS_SCOPE_PADS
);
}
if
(
m_scopeTracks
->
IsChecked
()
==
true
)
{
m_settings
->
m_scope
=
static_cast
<
TEARDROPS_SCOPE
>
(
m_settings
->
m_scope
|
TEARDROPS_SCOPE_TRACKS
);
if
(
m_scopeTracks
->
IsChecked
()
==
true
)
{
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_ignoreDrc
=
m_checkIgnore
->
IsChecked
();
}
void
DIALOG_TEARDROPS
::
OnModeAdd
(
wxCommandEvent
&
event
)
void
DIALOG_TEARDROPS
::
OnModeAdd
(
wxCommandEvent
&
aEvent
)
{
event
.
Skip
();
if
(
m_settings
!=
NULL
)
{
aEvent
.
Skip
();
if
(
m_settings
!=
NULL
)
{
m_settings
->
m_mode
=
TEARDROPS_MODE_ADD
;
LockOptionsControls
(
false
);
LockTracksControls
(
false
);
LockScopeControls
(
false
);
lockOptionsControls
(
false
);
lockTracksControls
(
false
);
lockScopeControls
(
false
);
}
}
void
DIALOG_TEARDROPS
::
OnModeRemove
(
wxCommandEvent
&
event
)
void
DIALOG_TEARDROPS
::
OnModeRemove
(
wxCommandEvent
&
aEvent
)
{
event
.
Skip
();
if
(
m_settings
!=
NULL
)
{
aEvent
.
Skip
();
if
(
m_settings
!=
NULL
)
{
m_settings
->
m_mode
=
TEARDROPS_MODE_REMOVE
;
LockOptionsControls
(
true
);
LockTracksControls
(
true
);
LockScopeControls
(
true
);
lockOptionsControls
(
true
);
lockTracksControls
(
true
);
lockScopeControls
(
true
);
}
}
void
DIALOG_TEARDROPS
::
OnTracksAll
(
wxCommandEvent
&
event
)
void
DIALOG_TEARDROPS
::
OnTracksAll
(
wxCommandEvent
&
aEvent
)
{
event
.
Skip
();
if
(
m_settings
!=
NULL
)
{
aEvent
.
Skip
();
if
(
m_settings
!=
NULL
)
{
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
();
if
(
m_settings
!=
NULL
)
{
aEvent
.
Skip
();
if
(
m_settings
!=
NULL
)
{
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
();
if
(
m_settings
!=
NULL
)
{
if
(
m_scopeVias
->
IsChecked
())
{
m_settings
->
m_scope
=
static_cast
<
TEARDROPS_SCOPE
>
(
m_settings
->
m_scope
|
TEARDROPS_SCOPE_VIAS
);
aEvent
.
Skip
();
if
(
m_settings
!=
NULL
)
{
if
(
m_scopeVias
->
IsChecked
()
)
{
m_settings
->
m_scope
=
static_cast
<
TEARDROPS_SCOPE
>
(
m_settings
->
m_scope
|
TEARDROPS_SCOPE_VIAS
);
}
else
{
m_settings
->
m_scope
=
static_cast
<
TEARDROPS_SCOPE
>
(
m_settings
->
m_scope
&
(
~
TEARDROPS_SCOPE_VIAS
));
else
{
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
();
if
(
m_settings
!=
NULL
)
{
if
(
m_scopePads
->
IsChecked
())
{
m_settings
->
m_scope
=
static_cast
<
TEARDROPS_SCOPE
>
(
m_settings
->
m_scope
|
TEARDROPS_SCOPE_PADS
);
aEvent
.
Skip
();
if
(
m_settings
!=
NULL
)
{
if
(
m_scopePads
->
IsChecked
()
)
{
m_settings
->
m_scope
=
static_cast
<
TEARDROPS_SCOPE
>
(
m_settings
->
m_scope
|
TEARDROPS_SCOPE_PADS
);
}
else
{
m_settings
->
m_scope
=
static_cast
<
TEARDROPS_SCOPE
>
(
m_settings
->
m_scope
&
(
~
TEARDROPS_SCOPE_PADS
));
else
{
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
();
if
(
m_settings
!=
NULL
)
{
m_settings
->
m_type
=
static_cast
<
TEARDROPS_TYPE
>
(
m_choiceStyle
->
GetSelection
());
aEvent
.
Skip
();
if
(
m_settings
!=
NULL
)
{
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
();
if
(
m_settings
!=
NULL
)
{
aEvent
.
Skip
();
if
(
m_settings
!=
NULL
)
{
m_settings
->
m_clearSelection
=
m_checkClear
->
IsChecked
();
}
}
void
DIALOG_TEARDROPS
::
OnIgnoreDrc
(
wxCommandEvent
&
event
)
void
DIALOG_TEARDROPS
::
OnIgnoreDrc
(
wxCommandEvent
&
aEvent
)
{
event
.
Skip
();
if
(
m_settings
!=
NULL
)
{
aEvent
.
Skip
();
if
(
m_settings
!=
NULL
)
{
m_settings
->
m_ignoreDrc
=
m_checkIgnore
->
IsChecked
();
}
}
void
DIALOG_TEARDROPS
::
LockOptionsControls
(
bool
state
)
void
DIALOG_TEARDROPS
::
lockOptionsControls
(
bool
state
)
{
if
(
state
==
true
)
{
if
(
m_tracksSelected
->
GetValue
()
==
false
)
{
m_checkClear
->
Enable
(
false
);
if
(
state
==
true
)
{
if
(
m_tracksSelected
->
GetValue
()
==
false
)
{
m_checkClear
->
Enable
(
false
);
}
m_checkIgnore
->
Enable
(
false
);
m_choiceStyle
->
Enable
(
false
);
}
else
{
if
(
m_tracksSelected
->
GetValue
()
==
true
)
{
m_checkClear
->
Enable
(
true
);
m_checkIgnore
->
Enable
(
false
);
m_choiceStyle
->
Enable
(
false
);
}
else
{
if
(
m_tracksSelected
->
GetValue
()
==
true
)
{
m_checkClear
->
Enable
(
true
);
}
m_checkIgnore
->
Enable
(
true
);
m_choiceStyle
->
Enable
(
true
);
m_checkIgnore
->
Enable
(
true
);
m_choiceStyle
->
Enable
(
true
);
}
}
void
DIALOG_TEARDROPS
::
LockTracksControls
(
bool
state
)
void
DIALOG_TEARDROPS
::
lockTracksControls
(
bool
state
)
{
if
(
state
==
true
)
{
m_tracksAll
->
Enable
(
false
);
m_tracksSelected
->
Enable
(
false
);
if
(
state
==
true
)
{
m_tracksAll
->
Enable
(
false
);
m_tracksSelected
->
Enable
(
false
);
}
else
{
m_tracksAll
->
Enable
(
true
);
m_tracksSelected
->
Enable
(
true
);
else
{
m_tracksAll
->
Enable
(
true
);
m_tracksSelected
->
Enable
(
true
);
}
}
void
DIALOG_TEARDROPS
::
LockScopeControls
(
bool
state
)
void
DIALOG_TEARDROPS
::
lockScopeControls
(
bool
state
)
{
if
(
state
==
true
)
{
m_scopePads
->
Enable
(
false
);
m_scopeVias
->
Enable
(
false
);
}
else
{
m_scopePads
->
Enable
(
true
);
m_scopeVias
->
Enable
(
true
);
if
(
state
==
true
)
{
m_scopePads
->
Enable
(
false
);
m_scopeVias
->
Enable
(
false
);
}
else
{
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
#define DIALOG_TEARDROPS_H
...
...
@@ -5,56 +24,108 @@
#include "dialog_teardrops_base.h"
#include "wxPcbStruct.h"
/**
* @brief The DIALOG_TEARDROPS class
* implements teardrop management dialog for current board.
*/
class
DIALOG_TEARDROPS
:
public
DIALOG_TEARDROPS_BASE
{
public
:
typedef
enum
{
/**
* @brief The TEARDROPS_MODE
* defines an action to be performed on teardrops.
*/
typedef
enum
{
/// Teardrops addition mode
TEARDROPS_MODE_ADD
,
/// Teardrops removal mode
TEARDROPS_MODE_REMOVE
}
TEARDROPS_MODE
;
typedef
enum
{
/**
* @brief The TEARDROPS_TRACKS
* determines selection processing.
*/
typedef
enum
{
/// Process all tracks
TEARDROPS_TRACKS_ALL
,
/// Process selected tracks only
TEARDROPS_TRACKS_SELECTED
}
TEARDROPS_TRACKS
;
typedef
enum
{
/**
* @brief The TEARDROPS_TYPE
* defines the shape of teardrops.
*/
typedef
enum
{
/// The shape is not defined
TEARDROPS_TYPE_NONE
=
-
1
,
/// The teardops have straight outlines
TEARDROPS_TYPE_STRAIGHT
,
/// The teardrops have curved outlines
TEARDROPS_TYPE_CURVED
}
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
,
/// Create teardrops for vias
TEARDROPS_SCOPE_VIAS
=
1
,
/// Create teardrops for pads
TEARDROPS_SCOPE_PADS
=
2
,
/// Create teardrops for tracks (not implemented yet)
TEARDROPS_SCOPE_TRACKS
=
4
}
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
;
/// Process selection
TEARDROPS_TRACKS
m_track
;
/// Objects scope
TEARDROPS_SCOPE
m_scope
;
/// Teardrops type
TEARDROPS_TYPE
m_type
;
/// Clear selection after the processing has finished
bool
m_clearSelection
;
/// Ignore DRC during processing
bool
m_ignoreDrc
;
}
TEARDROPS_SETTINGS
;
DIALOG_TEARDROPS
(
PCB_EDIT_FRAME
*
aParent
,
TEARDROPS_SETTINGS
*
settings
);
void
OnModeAdd
(
wxCommandEvent
&
event
);
void
OnModeRemove
(
wxCommandEvent
&
event
);
void
OnTracksAll
(
wxCommandEvent
&
event
);
void
OnTracksSelected
(
wxCommandEvent
&
event
);
void
OnStyleChanged
(
wxCommandEvent
&
event
);
void
OnClearSelection
(
wxCommandEvent
&
event
);
void
OnIgnoreDrc
(
wxCommandEvent
&
event
);
void
OnScopeVias
(
wxCommandEvent
&
event
);
void
OnScopePads
(
wxCommandEvent
&
event
);
DIALOG_TEARDROPS
(
PCB_EDIT_FRAME
*
aParent
,
TEARDROPS_SETTINGS
*
aSettings
);
void
OnModeAdd
(
wxCommandEvent
&
aEvent
);
void
OnModeRemove
(
wxCommandEvent
&
aEvent
);
void
OnTracksAll
(
wxCommandEvent
&
aEvent
);
void
OnTracksSelected
(
wxCommandEvent
&
aEvent
);
void
OnStyleChanged
(
wxCommandEvent
&
aEvent
);
void
OnClearSelection
(
wxCommandEvent
&
aEvent
);
void
OnIgnoreDrc
(
wxCommandEvent
&
aEvent
);
void
OnScopeVias
(
wxCommandEvent
&
aEvent
);
void
OnScopePads
(
wxCommandEvent
&
aEvent
);
private
:
PCB_EDIT_FRAME
*
m_parent
;
TEARDROPS_SETTINGS
*
m_settings
;
void
I
nitDialogSettings
();
void
LockOptionsControls
(
bool
state
);
void
LockTracksControls
(
bool
state
);
void
LockScopeControls
(
bool
state
);
void
i
nitDialogSettings
();
void
lockOptionsControls
(
bool
aState
);
void
lockTracksControls
(
bool
aState
);
void
lockScopeControls
(
bool
aState
);
};
#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 "class_board.h"
#include "class_module.h"
#include "ratsnest_data.h"
#include "view/view.h"
#include "common_actions.h"
#include "router/pns_utils.h"
#include "router/pns_router.h"
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_view
=
NULL
;
m_type
=
TEARDROP
::
TEARDROP_STRAIGHT
;
m_view
=
NULL
;
m_type
=
TEARDROP
::
TEARDROP_STRAIGHT
;
m_strategy
=
DRC_COMPLY
;
}
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_view
=
getView
();
m_type
=
TEARDROP
::
TEARDROP_STRAIGHT
;
m_view
=
getView
();
m_type
=
TEARDROP
::
TEARDROP_STRAIGHT
;
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
++
)
{
item
=
selection
.
items
.
GetPickedItem
(
i
);
if
((
item
!=
NULL
)
&&
(
item
->
Type
()
!=
PCB_TRACE_T
))
{
selection
.
items
.
RemovePicker
(
i
);
if
(
(
item
!=
NULL
)
&&
(
item
->
Type
()
!=
PCB_TRACE_T
)
)
{
aSelection
.
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
;
SELECTION
selection
=
GetManager
()
->
GetTool
<
SELECTION_TOOL
>
()
->
GetSelection
();
switch
(
settings
.
m_type
)
{
switch
(
aSettings
.
m_type
)
{
case
DIALOG_TEARDROPS
:
:
TEARDROPS_TYPE_CURVED
:
m_type
=
TEARDROP
::
TEARDROP_CURVED
;
break
;
default
:
m_type
=
TEARDROP
::
TEARDROP_STRAIGHT
;
}
if
(
settings
.
m_ignoreDrc
==
true
)
{
if
(
aSettings
.
m_ignoreDrc
==
true
)
{
m_strategy
=
DRC_IGNORE
;
}
else
{
else
{
m_strategy
=
DRC_COMPLY
;
}
FilterSelection
(
selection
);
if
(
settings
.
m_mode
==
DIALOG_TEARDROPS
::
TEARDROPS_MODE_ADD
)
{
if
(
settings
.
m_track
==
DIALOG_TEARDROPS
::
TEARDROPS_TRACKS_ALL
)
{
retVal
=
AddToAll
(
settings
);
filterSelection
(
selection
);
if
(
aSettings
.
m_mode
==
DIALOG_TEARDROPS
::
TEARDROPS_MODE_ADD
)
{
if
(
aSettings
.
m_track
==
DIALOG_TEARDROPS
::
TEARDROPS_TRACKS_ALL
)
{
retVal
=
addToAll
(
aSettings
);
}
else
if
(
settings
.
m_track
==
DIALOG_TEARDROPS
::
TEARDROPS_TRACKS_SELECTED
)
{
retVal
=
AddToSelected
(
selection
,
settings
);
else
if
(
aSettings
.
m_track
==
DIALOG_TEARDROPS
::
TEARDROPS_TRACKS_SELECTED
)
{
retVal
=
addToSelected
(
selection
,
aSettings
);
}
}
else
if
(
settings
.
m_mode
==
DIALOG_TEARDROPS
::
TEARDROPS_MODE_REMOVE
)
{
RemoveAll
();
else
if
(
aSettings
.
m_mode
==
DIALOG_TEARDROPS
::
TEARDROPS_MODE_REMOVE
)
{
removeAll
();
retVal
=
true
;
}
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
;
// Iterate through all vias and add teardrops to connected tracks
if
((
settings
.
m_scope
&
DIALOG_TEARDROPS
::
TEARDROPS_SCOPE_VIAS
)
==
DIALOG_TEARDROPS
::
TEARDROPS_SCOPE_VIAS
)
{
for
(
VIA
*
via
=
GetFirstVia
(
m_frame
->
GetBoard
()
->
m_Track
);
via
!=
NULL
;
via
=
GetFirstVia
(
via
->
Next
()))
{
if
(
IterateTracks
(
via
)
==
true
)
{
if
(
(
aSettings
.
m_scope
&
DIALOG_TEARDROPS
::
TEARDROPS_SCOPE_VIAS
)
==
DIALOG_TEARDROPS
::
TEARDROPS_SCOPE_VIAS
)
{
for
(
VIA
*
via
=
GetFirstVia
(
m_frame
->
GetBoard
()
->
m_Track
);
via
!=
NULL
;
via
=
GetFirstVia
(
via
->
Next
()
)
)
{
if
(
iterateTracks
(
via
)
==
true
)
{
added
=
true
;
}
}
}
// 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
)
{
for
(
MODULE
*
module
=
m_frame
->
GetBoard
()
->
m_Modules
.
GetFirst
();
module
!=
NULL
;
module
=
module
->
Next
())
{
D_PAD
*
pad
=
module
->
Pads
();
while
(
pad
!=
NULL
)
{
if
((
pad
->
GetShape
()
==
PAD_CIRCLE
)
&&
IterateTracks
(
pad
)
==
true
)
{
added
=
true
;
}
pad
=
pad
->
Next
();
}
if
(
(
aSettings
.
m_scope
&
DIALOG_TEARDROPS
::
TEARDROPS_SCOPE_PADS
)
==
DIALOG_TEARDROPS
::
TEARDROPS_SCOPE_PADS
)
{
for
(
MODULE
*
module
=
m_frame
->
GetBoard
()
->
m_Modules
.
GetFirst
();
module
!=
NULL
;
module
=
module
->
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
)
{
m_frame
->
SaveCopyInUndoList
(
m_undoListPicker
,
UR_NEW
);
if
(
added
==
true
)
{
m_frame
->
SaveCopyInUndoList
(
m_undoListPicker
,
UR_NEW
);
m_undoListPicker
.
ClearItemsList
();
}
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
added
=
false
;
int
addedNum
=
0
;
bool
retVal
=
false
;
bool
added
=
false
;
int
addedNum
=
0
;
for
(
size_t
i
=
0
;
i
<
selection
.
items
.
GetCount
();
i
++
)
{
TRACK
*
track
=
static_cast
<
TRACK
*>
(
selection
.
items
.
GetPickedItem
(
i
));
for
(
size_t
i
=
0
;
i
<
aSelection
.
items
.
GetCount
();
i
++
)
{
TRACK
*
track
=
static_cast
<
TRACK
*>
(
aSelection
.
items
.
GetPickedItem
(
i
)
);
TEARDROP
teardropEnd
;
retVal
=
teardropEnd
.
Create
(
*
track
,
ENDPOINT_END
,
m_type
);
if
(
retVal
==
true
)
{
added
=
DrawSegments
(
teardropEnd
,
*
track
);
if
(
added
==
true
)
{
retVal
=
teardropEnd
.
Create
(
*
track
,
ENDPOINT_END
,
m_type
);
if
(
retVal
==
true
)
{
added
=
drawSegments
(
teardropEnd
,
*
track
);
if
(
added
==
true
)
{
addedNum
++
;
}
}
TEARDROP
teardropStart
;
retVal
=
teardropStart
.
Create
(
*
track
,
ENDPOINT_START
,
m_type
);
if
(
retVal
==
true
)
{
added
=
DrawSegments
(
teardropStart
,
*
track
);
if
(
added
==
true
)
{
retVal
=
teardropStart
.
Create
(
*
track
,
ENDPOINT_START
,
m_type
);
if
(
retVal
==
true
)
{
added
=
drawSegments
(
teardropStart
,
*
track
);
if
(
added
==
true
)
{
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
)
{
m_frame
->
SaveCopyInUndoList
(
m_undoListPicker
,
UR_NEW
);
if
(
addedNum
>
0
)
{
m_frame
->
SaveCopyInUndoList
(
m_undoListPicker
,
UR_NEW
);
m_undoListPicker
.
ClearItemsList
();
}
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
flagAdded
=
false
;
for
(
size_t
i
=
0
;
i
<
aObject
->
m_TracksConnected
.
size
();
i
++
)
{
TRACK
*
track
=
aObject
->
m_TracksConnected
[
i
];
STATUS_FLAGS
objPosition
=
track
->
IsPointOnEnds
(
aObject
->
GetPosition
());
if
(
objPosition
==
STARTPOINT
||
objPosition
==
ENDPOINT
)
{
for
(
size_t
i
=
0
;
i
<
aObject
->
m_TracksConnected
.
size
();
i
++
)
{
TRACK
*
track
=
aObject
->
m_TracksConnected
[
i
];
STATUS_FLAGS
objPosition
=
track
->
IsPointOnEnds
(
aObject
->
GetPosition
()
);
if
(
objPosition
==
STARTPOINT
||
objPosition
==
ENDPOINT
)
{
ENDPOINT_T
endpoint
=
(
objPosition
==
STARTPOINT
?
ENDPOINT_START
:
ENDPOINT_END
);
TEARDROP
teardrop
;
retVal
=
teardrop
.
Create
(
*
track
,
endpoint
,
m_type
);
if
(
retVal
==
true
)
{
if
(
DrawSegments
(
teardrop
,
*
track
)
==
true
&&
flagAdded
==
false
)
{
retVal
=
teardrop
.
Create
(
*
track
,
endpoint
,
m_type
);
if
(
retVal
==
true
)
{
if
(
drawSegments
(
teardrop
,
*
track
)
==
true
&&
flagAdded
==
false
)
{
flagAdded
=
true
;
}
}
}
}
return
flagAdded
;
}
void
TEARDROPS_EDITOR
::
RemoveAll
()
void
TEARDROPS_EDITOR
::
removeAll
()
{
ITEM_PICKER
picker
(
NULL
,
UR_DELETED
);
TRACK
*
nextTrack
=
NULL
;
ITEM_PICKER
picker
(
NULL
,
UR_DELETED
);
TRACK
*
nextTrack
=
NULL
;
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
();
if
(
track
->
GetState
(
FLAG1
)
==
FLAG1
)
{
picker
.
SetItem
(
track
);
m_undoListPicker
.
PushItem
(
picker
);
if
(
track
->
GetState
(
FLAG1
)
==
FLAG1
)
{
picker
.
SetItem
(
track
);
m_undoListPicker
.
PushItem
(
picker
);
removed
=
true
;
m_view
->
Remove
(
track
);
m_frame
->
GetBoard
()
->
Remove
(
track
);
m_view
->
Remove
(
track
);
m_frame
->
GetBoard
()
->
Remove
(
track
);
}
track
=
nextTrack
;
}
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
();
}
}
bool
TEARDROPS_EDITOR
::
DrawSegments
(
TEARDROP
&
teardrop
,
TRACK
&
aTrack
)
bool
TEARDROPS_EDITOR
::
drawSegments
(
TEARDROP
&
aTeardrop
,
TRACK
&
aTrack
)
{
bool
tracksAdded
=
true
;
bool
proceedBuild
=
true
;
ITEM_PICKER
picker
(
NULL
,
UR_NEW
);
PNS_NODE
*
world
=
PNS_ROUTER
::
GetInstance
()
->
GetWorld
();
BOARD
*
board
=
aTrack
.
GetBoard
();
std
::
vector
<
TRACK
*>
tracks
;
ITEM_PICKER
picker
(
NULL
,
UR_NEW
);
PNS_NODE
*
world
=
PNS_ROUTER
::
GetInstance
()
->
GetWorld
();
BOARD
*
board
=
aTrack
.
GetBoard
();
std
::
vector
<
TRACK
*>
tracks
;
std
::
vector
<
VECTOR2I
>
coordinates
;
teardrop
.
GetCoordinates
(
coordinates
);
aTeardrop
.
GetCoordinates
(
coordinates
);
assert
(
coordinates
.
size
()
!=
0
);
assert
(
coordinates
.
size
()
!=
0
);
wxPoint
currentPoint
(
0
,
0
);
wxPoint
prevPoint
(
coordinates
[
0
].
x
,
coordinates
[
0
].
y
);
wxPoint
currentPoint
(
0
,
0
);
wxPoint
prevPoint
(
coordinates
[
0
].
x
,
coordinates
[
0
].
y
);
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
());
segment
.
SetWidth
(
aTrack
.
GetWidth
());
segment
.
SetLayers
(
PNS_LAYERSET
(
aTrack
.
GetLayer
()));
segment
.
SetParent
(
&
aTrack
);
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
()
);
segment
.
SetWidth
(
aTrack
.
GetWidth
()
);
segment
.
SetLayers
(
PNS_LAYERSET
(
aTrack
.
GetLayer
()
)
);
segment
.
SetParent
(
&
aTrack
);
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
;
proceedBuild
=
false
;
break
;
}
}
if
(
proceedBuild
==
true
)
{
TRACK
*
track
=
new
TRACK
(
aTrack
);
track
->
SetWidth
(
aTrack
.
GetWidth
());
track
->
SetLayer
(
aTrack
.
GetLayer
());
track
->
SetNetCode
(
aTrack
.
GetNetCode
());
currentPoint
=
wxPoint
(
coordinates
[
i
].
x
,
coordinates
[
i
].
y
);
track
->
SetStart
(
prevPoint
);
track
->
SetEnd
(
currentPoint
);
if
(
proceedBuild
==
true
)
{
TRACK
*
track
=
new
TRACK
(
aTrack
);
track
->
SetWidth
(
aTrack
.
GetWidth
()
);
track
->
SetLayer
(
aTrack
.
GetLayer
()
);
track
->
SetNetCode
(
aTrack
.
GetNetCode
()
);
currentPoint
=
wxPoint
(
coordinates
[
i
].
x
,
coordinates
[
i
].
y
);
track
->
SetStart
(
prevPoint
);
track
->
SetEnd
(
currentPoint
);
track
->
ClearFlags
();
track
->
SetState
(
FLAG1
,
true
);
tracks
.
push_back
(
track
);
track
->
SetState
(
FLAG1
,
true
);
tracks
.
push_back
(
track
);
prevPoint
=
currentPoint
;
picker
.
SetItem
(
track
);
m_undoListPicker
.
PushItem
(
picker
);
picker
.
SetItem
(
track
);
m_undoListPicker
.
PushItem
(
picker
);
}
prevPoint
=
currentPoint
;
}
if
(
tracksAdded
==
true
)
{
BOOST_FOREACH
(
TRACK
*
item
,
tracks
)
{
board
->
Add
(
item
);
m_view
->
Add
(
item
);
if
(
tracksAdded
==
true
)
{
// 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
// remove them from undo list
BOOST_FOREACH
(
TRACK
*
item
,
tracks
)
{
BOOST_FOREACH
(
TRACK
*
item
,
tracks
)
{
m_undoListPicker
.
PopItem
();
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
#define TEARDROPS_EDITOR_H
...
...
@@ -7,51 +26,99 @@
#include "class_teardrop.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
{
public
:
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
void
Reset
(
RESET_REASON
aReason
);
void
Reset
(
RESET_REASON
aReason
);
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
,
/// Ignore DRC and finish teardop
DRC_IGNORE
,
/// Try to adjust the outline or size of a teardop (not implemented)
DRC_ADJUST
}
DRC_STRATEGY
;
PCB_EDIT_FRAME
*
m_frame
;
KIGFX
::
VIEW
*
m_view
;
PCB_EDIT_FRAME
*
m_frame
;
KIGFX
::
VIEW
*
m_view
;
TEARDROP
::
TEARDROP_TYPE
m_type
;
PICKED_ITEMS_LIST
m_undoListPicker
;
DRC_STRATEGY
m_strategy
;
/**
* @brief FilterSelection filters selected objects and removes all objects except tracks.
* @param selection contains the list of currently selected objects
* @brief Function \a filterSelection
* 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
* @param aObject is a board object a which teardrops should be created. Currently such an object can
* @brief Function \a iterateTracks
* 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.
* @return \a true if at least one teardrop was successfully added and \a false otherwise
*/
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
);
bool
iterateTracks
(
const
BOARD_CONNECTED_ITEM
*
aObject
);
/**
* @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