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
5598acb6
Commit
5598acb6
authored
Sep 26, 2013
by
Maciej Sumiński
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Uncrustifying push&shove router
parent
87b3f2e4
Changes
37
Show whitespace changes
Inline
Side-by-side
Showing
37 changed files
with
6611 additions
and
6048 deletions
+6611
-6048
CMakeLists.txt
pcbnew/router/CMakeLists.txt
+47
-46
direction.h
pcbnew/router/direction.h
+298
-261
pns_index.h
pcbnew/router/pns_index.h
+181
-159
pns_item.cpp
pcbnew/router/pns_item.cpp
+53
-36
pns_item.h
pcbnew/router/pns_item.h
+111
-108
pns_itemset.cpp
pcbnew/router/pns_itemset.cpp
+43
-34
pns_itemset.h
pcbnew/router/pns_itemset.h
+20
-19
pns_joint.h
pcbnew/router/pns_joint.h
+157
-138
pns_layerset.h
pcbnew/router/pns_layerset.h
+90
-88
pns_line.cpp
pcbnew/router/pns_line.cpp
+657
-598
pns_line.h
pcbnew/router/pns_line.h
+217
-204
pns_line_placer.cpp
pcbnew/router/pns_line_placer.cpp
+543
-578
pns_line_placer.h
pcbnew/router/pns_line_placer.h
+213
-114
pns_node.cpp
pcbnew/router/pns_node.cpp
+781
-695
pns_node.h
pcbnew/router/pns_node.h
+190
-169
pns_optimizer.cpp
pcbnew/router/pns_optimizer.cpp
+621
-561
pns_optimizer.h
pcbnew/router/pns_optimizer.h
+98
-95
pns_router.cpp
pcbnew/router/pns_router.cpp
+624
-585
pns_router.h
pcbnew/router/pns_router.h
+103
-106
pns_routing_settings.h
pcbnew/router/pns_routing_settings.h
+25
-24
pns_segment.h
pcbnew/router/pns_segment.h
+89
-83
pns_shove.cpp
pcbnew/router/pns_shove.cpp
+412
-387
pns_shove.h
pcbnew/router/pns_shove.h
+43
-39
pns_solid.cpp
pcbnew/router/pns_solid.cpp
+30
-31
pns_solid.h
pcbnew/router/pns_solid.h
+32
-31
pns_utils.cpp
pcbnew/router/pns_utils.cpp
+20
-17
pns_utils.h
pcbnew/router/pns_utils.h
+6
-6
pns_via.cpp
pcbnew/router/pns_via.cpp
+111
-98
pns_via.h
pcbnew/router/pns_via.h
+92
-87
pns_walkaround.cpp
pcbnew/router/pns_walkaround.cpp
+185
-175
pns_walkaround.h
pcbnew/router/pns_walkaround.h
+72
-73
readme.txt
pcbnew/router/readme.txt
+0
-4
router_preview_item.cpp
pcbnew/router/router_preview_item.cpp
+167
-134
router_preview_item.h
pcbnew/router/router_preview_item.h
+58
-58
router_tool.cpp
pcbnew/router/router_tool.cpp
+187
-170
router_tool.h
pcbnew/router/router_tool.h
+23
-22
trace.h
pcbnew/router/trace.h
+12
-15
No files found.
pcbnew/router/CMakeLists.txt
View file @
5598acb6
include_directories
(
BEFORE
${
INC_BEFORE
}
)
include_directories
(
BEFORE
${
INC_BEFORE
}
)
include_directories
(
./
../
../../include
../../pcbnew
../../polygon
$
{
INC_AFTER
}
)
../../
include
../../
pcbnew
../../
polygon
$
{ INC_AFTER
}
)
set
(
PCBNEW_PNS_SRCS
set
(
PCBNEW_PNS_SRCS
direction.h
pns_via.h
pns_routing_settings.h
...
...
@@ -45,6 +45,7 @@ set(PCBNEW_PNS_SRCS
router_tool.h
router_preview_item.cpp
router_preview_item.h
)
)
add_library
(
pnsrouter STATIC
${
PCBNEW_PNS_SRCS
}
)
add_library
(
pnsrouter STATIC
${
PCBNEW_PNS_SRCS
}
)
pcbnew/router/direction.h
View file @
5598acb6
...
...
@@ -31,7 +31,6 @@
class
DIRECTION_45
{
public
:
/**
...
...
@@ -39,7 +38,8 @@ public:
* Represents available directions - there are 8 of them, as on a rectilinear map (north = up) +
* an extra undefined direction, reserved for traces that don't respect 45-degree routing regime.
*/
enum
Directions
{
enum
Directions
{
N
=
0
,
NE
=
1
,
E
=
2
,
...
...
@@ -55,31 +55,32 @@ public:
* Enum AngleType
* Represents kind of angle formed by vectors heading in two DIRECTION_45s.
*/
enum
AngleType
{
ANG_OBTUSE
=
0x1
,
ANG_RIGHT
=
0x2
,
ANG_ACUTE
=
0x4
,
ANG_STRAIGHT
=
0x8
,
enum
AngleType
{
ANG_OBTUSE
=
0x01
,
ANG_RIGHT
=
0x02
,
ANG_ACUTE
=
0x04
,
ANG_STRAIGHT
=
0x08
,
ANG_HALF_FULL
=
0x10
,
ANG_UNDEFINED
=
0x20
};
DIRECTION_45
(
Directions
aDir
=
UNDEFINED
)
:
m_dir
(
aDir
)
{};
DIRECTION_45
(
Directions
aDir
=
UNDEFINED
)
:
m_dir
(
aDir
)
{};
/**
* Constructor
* @param aVec vector, whose direction will be translated into a DIRECTION_45.
*/
DIRECTION_45
(
const
VECTOR2I
&
aVec
)
DIRECTION_45
(
const
VECTOR2I
&
aVec
)
{
construct
(
aVec
);
construct
(
aVec
);
}
/**
* Constructor
* @param aSeg segment, whose direction will be translated into a DIRECTION_45.
*/
DIRECTION_45
(
const
SEG
&
aSeg
)
DIRECTION_45
(
const
SEG
&
aSeg
)
{
construct
(
aSeg
.
b
-
aSeg
.
a
);
}
...
...
@@ -91,18 +92,37 @@ public:
*/
const
std
::
string
Format
()
const
{
switch
(
m_dir
)
switch
(
m_dir
)
{
case
N
:
return
"north"
;
case
NE
:
return
"north-east"
;
case
E
:
return
"east"
;
case
SE
:
return
"south-east"
;
case
S
:
return
"south"
;
case
SW
:
return
"south-west"
;
case
W
:
return
"west"
;
case
NW
:
return
"north-west"
;
case
UNDEFINED
:
return
"undefined"
;
default
:
return
"<Error>"
;
case
N
:
return
"north"
;
case
NE
:
return
"north-east"
;
case
E
:
return
"east"
;
case
SE
:
return
"south-east"
;
case
S
:
return
"south"
;
case
SW
:
return
"south-west"
;
case
W
:
return
"west"
;
case
NW
:
return
"north-west"
;
case
UNDEFINED
:
return
"undefined"
;
default
:
return
"<Error>"
;
}
}
...
...
@@ -113,9 +133,10 @@ public:
*/
DIRECTION_45
Opposite
()
const
{
if
(
m_dir
==
UNDEFINED
)
if
(
m_dir
==
UNDEFINED
)
return
UNDEFINED
;
const
Directions
OppositeMap
[]
=
{
S
,
SW
,
W
,
NW
,
N
,
NE
,
E
,
SE
}
;
const
Directions
OppositeMap
[]
=
{
S
,
SW
,
W
,
NW
,
N
,
NE
,
E
,
SE
};
return
OppositeMap
[
m_dir
];
}
...
...
@@ -124,20 +145,20 @@ public:
* Returns the type of angle between directions (this) and aOther.
* @param aOther direction to compare angle with
*/
AngleType
Angle
(
const
DIRECTION_45
&
aOther
)
const
AngleType
Angle
(
const
DIRECTION_45
&
aOther
)
const
{
if
(
m_dir
==
UNDEFINED
||
aOther
.
m_dir
==
UNDEFINED
)
if
(
m_dir
==
UNDEFINED
||
aOther
.
m_dir
==
UNDEFINED
)
return
ANG_UNDEFINED
;
int
d
=
std
::
abs
(
m_dir
-
aOther
.
m_dir
);
int
d
=
std
::
abs
(
m_dir
-
aOther
.
m_dir
);
if
(
d
==
1
||
d
==
7
)
if
(
d
==
1
||
d
==
7
)
return
ANG_OBTUSE
;
else
if
(
d
==
2
||
d
==
6
)
else
if
(
d
==
2
||
d
==
6
)
return
ANG_RIGHT
;
else
if
(
d
==
3
||
d
==
5
)
else
if
(
d
==
3
||
d
==
5
)
return
ANG_ACUTE
;
else
if
(
d
==
4
)
else
if
(
d
==
4
)
return
ANG_HALF_FULL
;
else
return
ANG_STRAIGHT
;
...
...
@@ -147,9 +168,9 @@ public:
* Function IsObtuse()
* @return true, when (this) forms an obtuse angle with aOther
*/
bool
IsObtuse
(
const
DIRECTION_45
&
aOther
)
const
bool
IsObtuse
(
const
DIRECTION_45
&
aOther
)
const
{
return
Angle
(
aOther
)
==
ANG_OBTUSE
;
return
Angle
(
aOther
)
==
ANG_OBTUSE
;
}
/**
...
...
@@ -159,7 +180,7 @@ public:
*/
bool
IsDiagonal
()
const
{
return
(
m_dir
%
2
)
==
1
;
return
(
m_dir
%
2
)
==
1
;
}
/**
...
...
@@ -172,51 +193,56 @@ public:
* @param aStartDiagonal whether the first segment has to be diagonal
* @return the trace
*/
const
SHAPE_LINE_CHAIN
BuildInitialTrace
(
const
VECTOR2I
&
aP0
,
const
VECTOR2I
&
aP1
,
bool
aStartDiagonal
=
false
)
const
const
SHAPE_LINE_CHAIN
BuildInitialTrace
(
const
VECTOR2I
&
aP0
,
const
VECTOR2I
&
aP1
,
bool
aStartDiagonal
=
false
)
const
{
int
w
=
abs
(
aP1
.
x
-
aP0
.
x
);
int
h
=
abs
(
aP1
.
y
-
aP0
.
y
);
int
sw
=
sign
(
aP1
.
x
-
aP0
.
x
);
int
sh
=
sign
(
aP1
.
y
-
aP0
.
y
);
int
w
=
abs
(
aP1
.
x
-
aP0
.
x
);
int
h
=
abs
(
aP1
.
y
-
aP0
.
y
);
int
sw
=
sign
(
aP1
.
x
-
aP0
.
x
);
int
sh
=
sign
(
aP1
.
y
-
aP0
.
y
);
VECTOR2I
mp0
,
mp1
;
// we are more horizontal than vertical?
if
(
w
>
h
)
if
(
w
>
h
)
{
mp0
=
VECTOR2I
(
(
w
-
h
)
*
sw
,
0
);
// direction: E
mp1
=
VECTOR2I
(
h
*
sw
,
h
*
sh
);
// direction: NE
}
else
{
mp0
=
VECTOR2I
((
w
-
h
)
*
sw
,
0
);
// direction: E
mp1
=
VECTOR2I
(
h
*
sw
,
h
*
sh
);
// direction: NE
}
else
{
mp0
=
VECTOR2I
(
0
,
sh
*
(
h
-
w
));
// direction: N
mp1
=
VECTOR2I
(
sw
*
w
,
sh
*
w
);
// direction: NE
mp0
=
VECTOR2I
(
0
,
sh
*
(
h
-
w
)
);
// direction: N
mp1
=
VECTOR2I
(
sw
*
w
,
sh
*
w
);
// direction: NE
}
bool
start_diagonal
;
if
(
m_dir
==
UNDEFINED
)
if
(
m_dir
==
UNDEFINED
)
start_diagonal
=
aStartDiagonal
;
else
start_diagonal
=
IsDiagonal
();
SHAPE_LINE_CHAIN
pl
;
pl
.
Append
(
aP0
);
if
(
start_diagonal
)
pl
.
Append
(
aP0
+
mp1
);
pl
.
Append
(
aP0
);
if
(
start_diagonal
)
pl
.
Append
(
aP0
+
mp1
);
else
pl
.
Append
(
aP0
+
mp0
);
pl
.
Append
(
aP0
+
mp0
);
pl
.
Append
(
aP1
);
pl
.
Append
(
aP1
);
pl
.
Simplify
();
return
pl
;
};
bool
operator
==
(
const
DIRECTION_45
&
aOther
)
const
bool
operator
==
(
const
DIRECTION_45
&
aOther
)
const
{
return
aOther
.
m_dir
==
m_dir
;
}
bool
operator
!=
(
const
DIRECTION_45
&
aOther
)
const
bool
operator
!=
(
const
DIRECTION_45
&
aOther
)
const
{
return
aOther
.
m_dir
!=
m_dir
;
}
...
...
@@ -224,16 +250,21 @@ public:
const
DIRECTION_45
Right
()
const
{
DIRECTION_45
r
;
r
.
m_dir
=
(
Directions
)
(
m_dir
+
1
);
if
(
r
.
m_dir
==
NW
)
if
(
r
.
m_dir
==
NW
)
r
.
m_dir
=
N
;
return
r
;
}
private
:
template
<
typename
T
>
int
sign
(
T
val
)
const
{
return
(
T
(
0
)
<
val
)
-
(
val
<
T
(
0
));
template
<
typename
T
>
int
sign
(
T
val
)
const
{
return
(
T
(
0
)
<
val
)
-
(
val
<
T
(
0
)
);
}
/**
...
...
@@ -242,47 +273,52 @@ private:
* degrees, the direction is rounded to the nearest octant.
* @param aVec our vector
*/
void
construct
(
const
VECTOR2I
&
aVec
)
void
construct
(
const
VECTOR2I
&
aVec
)
{
m_dir
=
UNDEFINED
;
if
(
aVec
.
x
==
0
&&
aVec
.
y
==
0
)
if
(
aVec
.
x
==
0
&&
aVec
.
y
==
0
)
return
;
double
mag
=
360
.
0
-
(
180
.
0
/
M_PI
*
atan2
((
double
)
aVec
.
y
,
(
double
)
aVec
.
x
))
+
90
.
0
;
if
(
mag
>=
360
.
0
)
double
mag
=
360
.
0
-
(
180
.
0
/
M_PI
*
atan2
(
(
double
)
aVec
.
y
,
(
double
)
aVec
.
x
)
)
+
90
.
0
;
if
(
mag
>=
360
.
0
)
mag
-=
360
.
0
;
if
(
mag
<
0
.
0
)
if
(
mag
<
0
.
0
)
mag
+=
360
.
0
;
m_dir
=
(
Directions
)
((
mag
+
22
.
5
)
/
45
.
0
);
m_dir
=
(
Directions
)(
(
mag
+
22
.
5
)
/
45
.
0
);
if
(
m_dir
>=
8
)
m_dir
=
(
Directions
)(
m_dir
-
8
);
if
(
m_dir
>=
8
)
m_dir
=
(
Directions
)
(
m_dir
-
8
);
if
(
m_dir
<
0
)
m_dir
=
(
Directions
)
(
m_dir
+
8
);
if
(
m_dir
<
0
)
m_dir
=
(
Directions
)(
m_dir
+
8
);
return
;
if
(
aVec
.
y
<
0
)
return
;
if
(
aVec
.
y
<
0
)
{
if
(
aVec
.
x
>
0
)
if
(
aVec
.
x
>
0
)
m_dir
=
NE
;
else
if
(
aVec
.
x
<
0
)
else
if
(
aVec
.
x
<
0
)
m_dir
=
NW
;
else
m_dir
=
N
;
}
else
if
(
aVec
.
y
==
0
)
else
if
(
aVec
.
y
==
0
)
{
if
(
aVec
.
x
>
0
)
if
(
aVec
.
x
>
0
)
m_dir
=
E
;
else
m_dir
=
W
;
}
else
// aVec.y>0
{
if
(
aVec
.
x
>
0
)
if
(
aVec
.
x
>
0
)
m_dir
=
SE
;
else
if
(
aVec
.
x
<
0
)
else
if
(
aVec
.
x
<
0
)
m_dir
=
SW
;
else
m_dir
=
S
;
...
...
@@ -293,3 +329,4 @@ private:
};
#endif // __DIRECTION_H
pcbnew/router/pns_index.h
View file @
5598acb6
...
...
@@ -37,42 +37,41 @@
* overlap and improving search time.
**/
class
PNS_INDEX
{
class
PNS_INDEX
{
public
:
typedef
std
::
list
<
PNS_ITEM
*>
NetItemsList
;
typedef
SHAPE_INDEX
<
PNS_ITEM
*>
ItemShapeIndex
;
typedef
boost
::
unordered_set
<
PNS_ITEM
*>
ItemSet
;
typedef
std
::
list
<
PNS_ITEM
*>
NetItemsList
;
typedef
SHAPE_INDEX
<
PNS_ITEM
*>
ItemShapeIndex
;
typedef
boost
::
unordered_set
<
PNS_ITEM
*>
ItemSet
;
PNS_INDEX
();
~
PNS_INDEX
();
void
Add
(
PNS_ITEM
*
aItem
);
void
Remove
(
PNS_ITEM
*
aItem
);
void
Replace
(
PNS_ITEM
*
aOldItem
,
PNS_ITEM
*
aNewItem
);
void
Add
(
PNS_ITEM
*
aItem
);
void
Remove
(
PNS_ITEM
*
aItem
);
void
Replace
(
PNS_ITEM
*
aOldItem
,
PNS_ITEM
*
aNewItem
);
template
<
class
Visitor
>
int
Query
(
const
PNS_ITEM
*
aItem
,
int
aMinDistance
,
Visitor
&
v
);
int
Query
(
const
PNS_ITEM
*
aItem
,
int
aMinDistance
,
Visitor
&
v
);
template
<
class
Visitor
>
int
Query
(
const
SHAPE
*
aShape
,
int
aMinDistance
,
Visitor
&
v
);
int
Query
(
const
SHAPE
*
aShape
,
int
aMinDistance
,
Visitor
&
v
);
void
Clear
();
NetItemsList
*
GetItemsForNet
(
int
aNet
)
;
NetItemsList
*
GetItemsForNet
(
int
aNet
)
;
ItemSet
::
iterator
begin
()
{
return
m_allItems
.
begin
();
}
ItemSet
::
iterator
end
()
{
return
m_allItems
.
end
();
}
bool
Contains
(
PNS_ITEM
*
aItem
)
const
{
return
m_allItems
.
find
(
aItem
)
!=
m_allItems
.
end
();
bool
Contains
(
PNS_ITEM
*
aItem
)
const
{
return
m_allItems
.
find
(
aItem
)
!=
m_allItems
.
end
();
}
int
Size
()
const
{
return
m_allItems
.
size
();
}
private
:
static
const
int
MaxSubIndices
=
64
;
static
const
int
SI_Multilayer
=
2
;
static
const
int
SI_SegDiagonal
=
0
;
...
...
@@ -81,161 +80,184 @@ private:
static
const
int
SI_PadsTop
=
0
;
static
const
int
SI_PadsBottom
=
1
;
template
<
class
Visitor
>
int
querySingle
(
int
index
,
const
SHAPE
*
aShape
,
int
aMinDistance
,
Visitor
&
v
);
template
<
class
Visitor
>
int
querySingle
(
int
index
,
const
SHAPE
*
aShape
,
int
aMinDistance
,
Visitor
&
v
);
ItemShapeIndex
*
getSubindex
(
const
PNS_ITEM
*
aItem
);
ItemShapeIndex
*
getSubindex
(
const
PNS_ITEM
*
aItem
);
ItemShapeIndex
*
m_subIndices
[
MaxSubIndices
];
ItemShapeIndex
*
m_subIndices
[
MaxSubIndices
];
std
::
map
<
int
,
NetItemsList
>
m_netMap
;
ItemSet
m_allItems
;
};
PNS_INDEX
::
PNS_INDEX
()
{
memset
(
m_subIndices
,
0
,
sizeof
(
m_subIndices
)
);
memset
(
m_subIndices
,
0
,
sizeof
(
m_subIndices
)
);
}
PNS_INDEX
::
ItemShapeIndex
*
PNS_INDEX
::
getSubindex
(
const
PNS_ITEM
*
aItem
)
PNS_INDEX
::
ItemShapeIndex
*
PNS_INDEX
::
getSubindex
(
const
PNS_ITEM
*
aItem
)
{
int
idx_n
=
-
1
;
const
PNS_LAYERSET
l
=
aItem
->
GetLayers
();
switch
(
aItem
->
GetKind
()
)
switch
(
aItem
->
GetKind
()
)
{
case
PNS_ITEM
:
:
VIA
:
idx_n
=
SI_Multilayer
;
break
;
case
PNS_ITEM
:
:
SOLID
:
{
if
(
l
.
IsMultilayer
()
)
idx_n
=
SI_Multilayer
;
else
if
(
l
.
Start
()
==
0
)
// fixme: use kicad layer codes
else
if
(
l
.
Start
()
==
0
)
// fixme: use kicad layer codes
idx_n
=
SI_PadsTop
;
else
if
(
l
.
Start
()
==
15
)
else
if
(
l
.
Start
()
==
15
)
idx_n
=
SI_PadsBottom
;
break
;
}
case
PNS_ITEM
:
:
SEGMENT
:
case
PNS_ITEM
:
:
LINE
:
idx_n
=
SI_Traces
+
2
*
l
.
Start
()
+
SI_SegStraight
;
break
;
default
:
break
;
}
assert
(
idx_n
>=
0
&&
idx_n
<
MaxSubIndices
);
if
(
!
m_subIndices
[
idx_n
])
assert
(
idx_n
>=
0
&&
idx_n
<
MaxSubIndices
);
if
(
!
m_subIndices
[
idx_n
]
)
m_subIndices
[
idx_n
]
=
new
ItemShapeIndex
;
return
m_subIndices
[
idx_n
];
}
void
PNS_INDEX
::
Add
(
PNS_ITEM
*
aItem
)
{
ItemShapeIndex
*
idx
=
getSubindex
(
aItem
);
void
PNS_INDEX
::
Add
(
PNS_ITEM
*
aItem
)
{
ItemShapeIndex
*
idx
=
getSubindex
(
aItem
);
idx
->
Add
(
aItem
);
m_allItems
.
insert
(
aItem
);
idx
->
Add
(
aItem
);
m_allItems
.
insert
(
aItem
);
int
net
=
aItem
->
GetNet
();
if
(
net
>=
0
)
if
(
net
>=
0
)
{
m_netMap
[
net
].
push_back
(
aItem
);
m_netMap
[
net
].
push_back
(
aItem
);
}
}
void
PNS_INDEX
::
Remove
(
PNS_ITEM
*
aItem
)
void
PNS_INDEX
::
Remove
(
PNS_ITEM
*
aItem
)
{
ItemShapeIndex
*
idx
=
getSubindex
(
aItem
);
idx
->
Remove
(
aItem
);
m_allItems
.
erase
(
aItem
);
ItemShapeIndex
*
idx
=
getSubindex
(
aItem
);
idx
->
Remove
(
aItem
);
m_allItems
.
erase
(
aItem
);
int
net
=
aItem
->
GetNet
();
if
(
net
>=
0
&&
m_netMap
.
find
(
net
)
!=
m_netMap
.
end
()
)
m_netMap
[
net
].
remove
(
aItem
);
if
(
net
>=
0
&&
m_netMap
.
find
(
net
)
!=
m_netMap
.
end
()
)
m_netMap
[
net
].
remove
(
aItem
);
}
void
PNS_INDEX
::
Replace
(
PNS_ITEM
*
aOldItem
,
PNS_ITEM
*
aNewItem
)
void
PNS_INDEX
::
Replace
(
PNS_ITEM
*
aOldItem
,
PNS_ITEM
*
aNewItem
)
{
Remove
(
aOldItem
);
Add
(
aNewItem
);
Remove
(
aOldItem
);
Add
(
aNewItem
);
}
template
<
class
Visitor
>
int
PNS_INDEX
::
querySingle
(
int
index
,
const
SHAPE
*
aShape
,
int
aMinDistance
,
Visitor
&
v
)
{
if
(
!
m_subIndices
[
index
]
)
int
PNS_INDEX
::
querySingle
(
int
index
,
const
SHAPE
*
aShape
,
int
aMinDistance
,
Visitor
&
v
)
{
if
(
!
m_subIndices
[
index
]
)
return
0
;
return
m_subIndices
[
index
]
->
Query
(
aShape
,
aMinDistance
,
v
,
false
);
}
return
m_subIndices
[
index
]
->
Query
(
aShape
,
aMinDistance
,
v
,
false
);
}
template
<
class
Visitor
>
int
PNS_INDEX
::
Query
(
const
PNS_ITEM
*
aItem
,
int
aMinDistance
,
Visitor
&
v
)
{
const
SHAPE
*
shape
=
aItem
->
GetShape
();
int
PNS_INDEX
::
Query
(
const
PNS_ITEM
*
aItem
,
int
aMinDistance
,
Visitor
&
v
)
{
const
SHAPE
*
shape
=
aItem
->
GetShape
();
int
total
=
0
;
total
+=
querySingle
(
SI_Multilayer
,
shape
,
aMinDistance
,
v
);
total
+=
querySingle
(
SI_Multilayer
,
shape
,
aMinDistance
,
v
);
const
PNS_LAYERSET
layers
=
aItem
->
GetLayers
();
if
(
layers
.
IsMultilayer
()
)
if
(
layers
.
IsMultilayer
()
)
{
total
+=
querySingle
(
SI_PadsTop
,
shape
,
aMinDistance
,
v
);
total
+=
querySingle
(
SI_PadsBottom
,
shape
,
aMinDistance
,
v
);
for
(
int
i
=
layers
.
Start
();
i
<=
layers
.
End
();
++
i
)
total
+=
querySingle
(
SI_Traces
+
2
*
i
+
SI_SegStraight
,
shape
,
aMinDistance
,
v
);
total
+=
querySingle
(
SI_PadsTop
,
shape
,
aMinDistance
,
v
);
total
+=
querySingle
(
SI_PadsBottom
,
shape
,
aMinDistance
,
v
);
}
else
{
for
(
int
i
=
layers
.
Start
();
i
<=
layers
.
End
();
++
i
)
total
+=
querySingle
(
SI_Traces
+
2
*
i
+
SI_SegStraight
,
shape
,
aMinDistance
,
v
);
}
else
{
int
l
=
layers
.
Start
();
if
(
l
==
0
)
total
+=
querySingle
(
SI_PadsTop
,
shape
,
aMinDistance
,
v
);
else
if
(
l
==
15
)
total
+=
querySingle
(
SI_PadsBottom
,
shape
,
aMinDistance
,
v
);
total
+=
querySingle
(
SI_Traces
+
2
*
l
+
SI_SegStraight
,
shape
,
aMinDistance
,
v
);
if
(
l
==
0
)
total
+=
querySingle
(
SI_PadsTop
,
shape
,
aMinDistance
,
v
);
else
if
(
l
==
15
)
total
+=
querySingle
(
SI_PadsBottom
,
shape
,
aMinDistance
,
v
);
total
+=
querySingle
(
SI_Traces
+
2
*
l
+
SI_SegStraight
,
shape
,
aMinDistance
,
v
);
}
return
total
;
}
}
template
<
class
Visitor
>
int
PNS_INDEX
::
Query
(
const
SHAPE
*
aShape
,
int
aMinDistance
,
Visitor
&
v
)
{
int
PNS_INDEX
::
Query
(
const
SHAPE
*
aShape
,
int
aMinDistance
,
Visitor
&
v
)
{
int
total
=
0
;
for
(
int
i
=
0
;
i
<
MaxSubIndices
;
i
++
)
total
+=
querySingle
(
i
,
aShape
,
aMinDistance
,
v
);
for
(
int
i
=
0
;
i
<
MaxSubIndices
;
i
++
)
total
+=
querySingle
(
i
,
aShape
,
aMinDistance
,
v
);
return
total
;
}
}
void
PNS_INDEX
::
Clear
()
{
for
(
int
i
=
0
;
i
<
MaxSubIndices
;
++
i
)
for
(
int
i
=
0
;
i
<
MaxSubIndices
;
++
i
)
{
ItemShapeIndex
*
idx
=
m_subIndices
[
i
];
if
(
idx
)
ItemShapeIndex
*
idx
=
m_subIndices
[
i
];
if
(
idx
)
delete
idx
;
m_subIndices
[
i
]
=
NULL
;
}
}
PNS_INDEX
::~
PNS_INDEX
()
{
Clear
();
}
PNS_INDEX
::
NetItemsList
*
PNS_INDEX
::
GetItemsForNet
(
int
aNet
)
PNS_INDEX
::
NetItemsList
*
PNS_INDEX
::
GetItemsForNet
(
int
aNet
)
{
if
(
m_netMap
.
find
(
aNet
)
==
m_netMap
.
end
()
)
if
(
m_netMap
.
find
(
aNet
)
==
m_netMap
.
end
()
)
return
NULL
;
return
&
m_netMap
[
aNet
];
}
#endif
pcbnew/router/pns_item.cpp
View file @
5598acb6
...
...
@@ -21,22 +21,25 @@
#include "pns_item.h"
#include "pns_line.h"
bool
PNS_ITEM
::
collideSimple
(
const
PNS_ITEM
*
aOther
,
int
aClearance
,
bool
aNeedMTV
,
VECTOR2I
&
aMTV
)
const
bool
PNS_ITEM
::
collideSimple
(
const
PNS_ITEM
*
aOther
,
int
aClearance
,
bool
aNeedMTV
,
VECTOR2I
&
aMTV
)
const
{
// same nets? no collision!
if
(
m_net
==
aOther
->
m_net
)
return
false
;
// check if we are not on completely different layers first
if
(
!
m_layers
.
Overlaps
(
aOther
->
m_layers
)
)
if
(
!
m_layers
.
Overlaps
(
aOther
->
m_layers
)
)
return
false
;
return
GetShape
()
->
Collide
(
aOther
->
GetShape
(),
aClearance
);
return
GetShape
()
->
Collide
(
aOther
->
GetShape
(),
aClearance
);
// fixme: MTV
}
bool
PNS_ITEM
::
Collide
(
const
PNS_ITEM
*
aOther
,
int
aClearance
,
bool
aNeedMTV
,
VECTOR2I
&
aMTV
)
const
bool
PNS_ITEM
::
Collide
(
const
PNS_ITEM
*
aOther
,
int
aClearance
,
bool
aNeedMTV
,
VECTOR2I
&
aMTV
)
const
{
if
(
collideSimple
(
aOther
,
aClearance
,
aNeedMTV
,
aMTV
)
)
return
true
;
...
...
@@ -44,29 +47,43 @@ bool PNS_ITEM::Collide( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, V
// special case for "head" line with a via attached at the end.
if
(
aOther
->
m_kind
==
LINE
)
{
const
PNS_LINE
*
line
=
static_cast
<
const
PNS_LINE
*>
(
aOther
);
if
(
line
->
EndsWithVia
())
return
collideSimple
(
&
line
->
GetVia
(),
aClearance
-
line
->
GetWidth
()
/
2
,
aNeedMTV
,
aMTV
);
const
PNS_LINE
*
line
=
static_cast
<
const
PNS_LINE
*>
(
aOther
);
if
(
line
->
EndsWithVia
()
)
return
collideSimple
(
&
line
->
GetVia
(),
aClearance
-
line
->
GetWidth
()
/
2
,
aNeedMTV
,
aMTV
);
}
return
false
;
}
const
std
::
string
PNS_ITEM
::
GetKindStr
()
const
{
switch
(
m_kind
)
switch
(
m_kind
)
{
case
LINE
:
return
"line"
;
case
SEGMENT
:
return
"segment"
;
case
VIA
:
return
"via"
;
case
JOINT
:
return
"joint"
;
case
SOLID
:
return
"solid"
;
default
:
return
"unknown"
;
case
LINE
:
return
"line"
;
case
SEGMENT
:
return
"segment"
;
case
VIA
:
return
"via"
;
case
JOINT
:
return
"joint"
;
case
SOLID
:
return
"solid"
;
default
:
return
"unknown"
;
}
}
PNS_ITEM
::~
PNS_ITEM
()
{
}
pcbnew/router/pns_item.h
View file @
5598acb6
...
...
@@ -41,11 +41,11 @@ class PNS_NODE;
class
PNS_ITEM
{
public
:
static
const
int
UnusedNet
=
INT_MAX
;
///> Supported item types
enum
PnsKind
{
enum
PnsKind
{
SOLID
=
1
,
LINE
=
2
,
JOINT
=
4
,
...
...
@@ -54,7 +54,7 @@ public:
ANY
=
0xff
};
PNS_ITEM
(
PnsKind
aKind
)
PNS_ITEM
(
PnsKind
aKind
)
{
m_net
=
UnusedNet
;
m_movable
=
true
;
...
...
@@ -77,79 +77,82 @@ public:
virtual
~
PNS_ITEM
();
virtual
PNS_ITEM
*
Clone
()
const
=
0
;
virtual
PNS_ITEM
*
Clone
()
const
=
0
;
///> Returns a convex polygon "hull" of a the item, that is used as the walkaround
/// path.
/// aClearance defines how far from the body of the item the hull should be,
/// aWalkaroundThickness is the width of the line that walks around this hull.
virtual
const
SHAPE_LINE_CHAIN
Hull
(
int
aClearance
=
0
,
int
aWalkaroundThickness
=
0
)
const
virtual
const
SHAPE_LINE_CHAIN
Hull
(
int
aClearance
=
0
,
int
aWalkaroundThickness
=
0
)
const
{
return
SHAPE_LINE_CHAIN
();
};
PnsKind
GetKind
()
const
{
return
m_kind
;
}
bool
OfKind
(
int
aKind
)
const
{
return
(
aKind
&
m_kind
)
!=
0
;
}
const
std
::
string
GetKindStr
()
const
;
///> Gets/Sets the corresponding parent object in the host application's model (pcbnew)
void
SetParent
(
BOARD_ITEM
*
aParent
)
{
m_parent
=
aParent
;
}
BOARD_ITEM
*
GetParent
()
const
{
return
m_parent
;
}
void
SetParent
(
BOARD_ITEM
*
aParent
)
{
m_parent
=
aParent
;
}
BOARD_ITEM
*
GetParent
()
const
{
return
m_parent
;
}
///> Net accessors
int
GetNet
()
const
{
return
m_net
;
}
void
SetNet
(
int
aNet
)
{
m_net
=
aNet
;
}
void
SetNet
(
int
aNet
)
{
m_net
=
aNet
;
}
///> Layers accessors
const
PNS_LAYERSET
&
GetLayers
()
const
{
return
m_layers
;
}
void
SetLayers
(
const
PNS_LAYERSET
&
aLayers
)
{
m_layers
=
aLayers
;
}
void
SetLayer
(
int
aLayer
)
{
m_layers
=
PNS_LAYERSET
(
aLayer
,
aLayer
);
}
void
SetLayers
(
const
PNS_LAYERSET
&
aLayers
)
{
m_layers
=
aLayers
;
}
void
SetLayer
(
int
aLayer
)
{
m_layers
=
PNS_LAYERSET
(
aLayer
,
aLayer
);
}
///> Ownership management. An item can belong to a single PNS_NODE or stay unowned.
void
SetOwner
(
PNS_NODE
*
aOwner
)
{
m_owner
=
aOwner
;
}
bool
BelongsTo
(
PNS_NODE
*
aNode
)
const
{
return
m_owner
==
aNode
;
}
PNS_NODE
*
GetOwner
()
const
{
return
m_owner
;
}
void
SetOwner
(
PNS_NODE
*
aOwner
)
{
m_owner
=
aOwner
;
}
bool
BelongsTo
(
PNS_NODE
*
aNode
)
const
{
return
m_owner
==
aNode
;
}
PNS_NODE
*
GetOwner
()
const
{
return
m_owner
;
}
///> Sets the world that is used for collision resolution.
void
SetWorld
(
PNS_NODE
*
aWorld
)
{
m_world
=
aWorld
;
}
PNS_NODE
*
GetWorld
()
const
{
return
m_world
;
}
void
SetWorld
(
PNS_NODE
*
aWorld
)
{
m_world
=
aWorld
;
}
PNS_NODE
*
GetWorld
()
const
{
return
m_world
;
}
///> Collision function. Checks if the item aOther is closer to us than
/// aClearance and returns true if so. It can also calculate a minimum translation vector that resolves the
/// collision if needed.
virtual
bool
Collide
(
const
PNS_ITEM
*
aOther
,
int
aClearance
,
bool
aNeedMTV
,
VECTOR2I
&
aMTV
)
const
;
/// aClearance and returns true if so. It can also calculate a minimum translation vector that
/// resolves the collision if needed.
virtual
bool
Collide
(
const
PNS_ITEM
*
aOther
,
int
aClearance
,
bool
aNeedMTV
,
VECTOR2I
&
aMTV
)
const
;
///> A shortcut without MTV calculation
bool
Collide
(
const
PNS_ITEM
*
aOther
,
int
aClearance
)
const
bool
Collide
(
const
PNS_ITEM
*
aOther
,
int
aClearance
)
const
{
VECTOR2I
dummy
;
return
Collide
(
aOther
,
aClearance
,
false
,
dummy
);
return
Collide
(
aOther
,
aClearance
,
false
,
dummy
);
}
///> Returns the geometric shape of the item
virtual
const
SHAPE
*
GetShape
()
const
{
virtual
const
SHAPE
*
GetShape
()
const
{
return
NULL
;
}
private
:
bool
collideSimple
(
const
PNS_ITEM
*
aOther
,
int
aClearance
,
bool
aNeedMTV
,
VECTOR2I
&
aMTV
)
const
;
bool
collideSimple
(
const
PNS_ITEM
*
aOther
,
int
aClearance
,
bool
aNeedMTV
,
VECTOR2I
&
aMTV
)
const
;
protected
:
PnsKind
m_kind
;
BOARD_ITEM
*
m_parent
;
PNS_NODE
*
m_world
;
PNS_NODE
*
m_owner
;
BOARD_ITEM
*
m_parent
;
PNS_NODE
*
m_world
;
PNS_NODE
*
m_owner
;
PNS_LAYERSET
m_layers
;
bool
m_movable
;
int
m_net
;
};
#endif
// __PNS_ITEM_H
#endif
// __PNS_ITEM_Ha
pcbnew/router/pns_itemset.cpp
View file @
5598acb6
...
...
@@ -25,48 +25,57 @@
PNS_ITEMSET
::
PNS_ITEMSET
()
{
}
PNS_ITEMSET
::~
PNS_ITEMSET
()
{
}
PNS_ITEMSET
&
PNS_ITEMSET
::
FilterLayers
(
int
aStart
,
int
aEnd
)
PNS_ITEMSET
&
PNS_ITEMSET
::
FilterLayers
(
int
aStart
,
int
aEnd
)
{
ItemVector
newItems
;
PNS_LAYERSET
l
;
if
(
aEnd
<
0
)
l
=
PNS_LAYERSET
(
aStart
);
if
(
aEnd
<
0
)
l
=
PNS_LAYERSET
(
aStart
);
else
l
=
PNS_LAYERSET
(
aStart
,
aEnd
);
l
=
PNS_LAYERSET
(
aStart
,
aEnd
);
BOOST_FOREACH
(
PNS_ITEM
*
item
,
m_items
)
if
(
item
->
GetLayers
().
Overlaps
(
l
)
)
newItems
.
push_back
(
item
);
BOOST_FOREACH
(
PNS_ITEM
*
item
,
m_items
)
if
(
item
->
GetLayers
().
Overlaps
(
l
))
newItems
.
push_back
(
item
);
m_items
=
newItems
;
return
*
this
;
}
PNS_ITEMSET
&
PNS_ITEMSET
::
FilterKinds
(
int
aKindMask
)
PNS_ITEMSET
&
PNS_ITEMSET
::
FilterKinds
(
int
aKindMask
)
{
ItemVector
newItems
;
BOOST_FOREACH
(
PNS_ITEM
*
item
,
m_items
)
if
(
item
->
GetKind
()
&
aKindMask
)
newItems
.
push_back
(
item
);
BOOST_FOREACH
(
PNS_ITEM
*
item
,
m_items
)
if
(
item
->
GetKind
()
&
aKindMask
)
newItems
.
push_back
(
item
);
m_items
=
newItems
;
return
*
this
;
}
PNS_ITEMSET
&
PNS_ITEMSET
::
FilterNet
(
int
aNet
)
PNS_ITEMSET
&
PNS_ITEMSET
::
FilterNet
(
int
aNet
)
{
ItemVector
newItems
;
BOOST_FOREACH
(
PNS_ITEM
*
item
,
m_items
)
if
(
item
->
GetNet
()
==
aNet
)
newItems
.
push_back
(
item
);
BOOST_FOREACH
(
PNS_ITEM
*
item
,
m_items
)
if
(
item
->
GetNet
()
==
aNet
)
newItems
.
push_back
(
item
);
m_items
=
newItems
;
return
*
this
;
}
...
...
pcbnew/router/pns_itemset.h
View file @
5598acb6
...
...
@@ -28,35 +28,36 @@
/**
* Class PNS_ITEMSET
*
* Holds a list of board items, that can be filtered against net, kinds, layers, etc.
* Holds a list of board items, that can be filtered against net, kinds,
* layers, etc.
**/
class
PNS_ITEMSET
{
public
:
typedef
std
::
vector
<
PNS_ITEM
*>
ItemVector
;
typedef
std
::
vector
<
PNS_ITEM
*>
ItemVector
;
PNS_ITEMSET
();
~
PNS_ITEMSET
();
ItemVector
&
Items
()
{
return
m_items
;
}
PNS_ITEMSET
&
FilterLayers
(
int
aStart
,
int
aEnd
=
-
1
);
PNS_ITEMSET
&
FilterKinds
(
int
aKindMask
);
PNS_ITEMSET
&
FilterNet
(
int
aNet
);
PNS_ITEMSET
&
FilterLayers
(
int
aStart
,
int
aEnd
=
-
1
);
PNS_ITEMSET
&
FilterKinds
(
int
aKindMask
);
PNS_ITEMSET
&
FilterNet
(
int
aNet
);
int
Size
()
{
return
m_items
.
size
();
}
void
Add
(
PNS_ITEM
*
item
)
void
Add
(
PNS_ITEM
*
item
)
{
m_items
.
push_back
(
item
);
m_items
.
push_back
(
item
);
}
PNS_ITEM
*
Get
(
int
index
)
const
{
return
m_items
[
index
];
}
PNS_ITEM
*
Get
(
int
index
)
const
{
return
m_items
[
index
];
}
private
:
ItemVector
m_items
;
};
#endif
pcbnew/router/pns_joint.h
View file @
5598acb6
...
...
@@ -32,35 +32,38 @@
/**
* Class PNS_JOINT
*
* Represents a 2D point on a given set of layers and belonging to a certain net,
* that links together a number of board items.
* A hash table of joints is used by the router to follow connectivity between the items.
* Represents a 2D point on a given set of layers and belonging to a certain
* net, that links together a number of board items.
* A hash table of joints is used by the router to follow connectivity between
* the items.
**/
class
PNS_JOINT
:
public
PNS_ITEM
{
public
:
typedef
std
::
vector
<
PNS_ITEM
*>
LinkedItems
;
typedef
std
::
vector
<
PNS_ITEM
*>
LinkedItems
;
///> joints are hashed by their position, layers and net. Linked items are, obviously, not hashed
struct
HashTag
{
///> Joints are hashed by their position, layers and net.
/// Linked items are, obviously, not hashed
struct
HashTag
{
VECTOR2I
pos
;
int
net
;
};
PNS_JOINT
()
:
PNS_ITEM
(
JOINT
)
{}
PNS_JOINT
()
:
PNS_ITEM
(
JOINT
)
{}
PNS_JOINT
(
const
VECTOR2I
&
aPos
,
const
PNS_LAYERSET
&
aLayers
,
int
aNet
=
-
1
)
:
PNS_ITEM
(
JOINT
)
PNS_JOINT
(
const
VECTOR2I
&
aPos
,
const
PNS_LAYERSET
&
aLayers
,
int
aNet
=
-
1
)
:
PNS_ITEM
(
JOINT
)
{
m_tag
.
pos
=
aPos
;
m_tag
.
net
=
aNet
;
m_layers
=
aLayers
;
}
PNS_JOINT
(
const
PNS_JOINT
&
b
)
:
PNS_ITEM
(
JOINT
)
PNS_JOINT
(
const
PNS_JOINT
&
b
)
:
PNS_ITEM
(
JOINT
)
{
m_layers
=
b
.
m_layers
;
m_tag
.
pos
=
b
.
m_tag
.
pos
;
...
...
@@ -69,99 +72,111 @@ public:
m_layers
=
b
.
m_layers
;
}
PNS_ITEM
*
Clone
()
const
PNS_ITEM
*
Clone
()
const
{
assert
(
false
);
assert
(
false
);
return
NULL
;
}
///> returns true if the joint is a trivial line corner, connecting two segments of the same net, on the same layer.
///> Returns true if the joint is a trivial line corner, connecting two
/// segments of the same net, on the same layer.
bool
IsLineCorner
()
const
{
if
(
m_linkedItems
.
size
()
!=
2
)
if
(
m_linkedItems
.
size
()
!=
2
)
return
false
;
if
(
m_linkedItems
[
0
]
->
GetKind
()
!=
SEGMENT
||
m_linkedItems
[
1
]
->
GetKind
()
!=
SEGMENT
)
if
(
m_linkedItems
[
0
]
->
GetKind
()
!=
SEGMENT
||
m_linkedItems
[
1
]
->
GetKind
()
!=
SEGMENT
)
return
false
;
PNS_SEGMENT
*
seg1
=
static_cast
<
PNS_SEGMENT
*>
(
m_linkedItems
[
0
]);
PNS_SEGMENT
*
seg2
=
static_cast
<
PNS_SEGMENT
*>
(
m_linkedItems
[
1
]);
PNS_SEGMENT
*
seg1
=
static_cast
<
PNS_SEGMENT
*>
(
m_linkedItems
[
0
]);
PNS_SEGMENT
*
seg2
=
static_cast
<
PNS_SEGMENT
*>
(
m_linkedItems
[
1
]);
// joints between segments of different widths are not trivial.
return
(
seg1
->
GetWidth
()
==
seg2
->
GetWidth
()
);
return
seg1
->
GetWidth
()
==
seg2
->
GetWidth
(
);
}
///> Links the joint to a given board item (when it's added to the PNS_NODE)
void
Link
(
PNS_ITEM
*
aItem
)
void
Link
(
PNS_ITEM
*
aItem
)
{
LinkedItems
::
iterator
f
=
std
::
find
(
m_linkedItems
.
begin
(),
m_linkedItems
.
end
(),
aItem
);
if
(
f
!=
m_linkedItems
.
end
())
LinkedItems
::
iterator
f
=
std
::
find
(
m_linkedItems
.
begin
(),
m_linkedItems
.
end
(),
aItem
);
if
(
f
!=
m_linkedItems
.
end
()
)
return
;
m_linkedItems
.
push_back
(
aItem
);
m_linkedItems
.
push_back
(
aItem
);
}
///> Unlinks a given board item from the joint (upon its removal from a PNS_NODE)
///> Returns true if the joint became dangling after unlinking.
bool
Unlink
(
PNS_ITEM
*
aItem
)
bool
Unlink
(
PNS_ITEM
*
aItem
)
{
LinkedItems
::
iterator
f
=
std
::
find
(
m_linkedItems
.
begin
(),
m_linkedItems
.
end
(),
aItem
);
if
(
f
!=
m_linkedItems
.
end
())
m_linkedItems
.
erase
(
f
);
return
(
m_linkedItems
.
size
()
==
0
);
LinkedItems
::
iterator
f
=
std
::
find
(
m_linkedItems
.
begin
(),
m_linkedItems
.
end
(),
aItem
);
if
(
f
!=
m_linkedItems
.
end
()
)
m_linkedItems
.
erase
(
f
);
return
m_linkedItems
.
size
()
==
0
;
}
///> For trivial joints, returns the segment adjacent to (aCurrent). For non-trival ones, returns
///> NULL, indicating the end of line.
PNS_SEGMENT
*
NextSegment
(
PNS_SEGMENT
*
aCurrent
)
const
PNS_SEGMENT
*
NextSegment
(
PNS_SEGMENT
*
aCurrent
)
const
{
if
(
!
IsLineCorner
()
)
if
(
!
IsLineCorner
()
)
return
NULL
;
return
static_cast
<
PNS_SEGMENT
*>
(
m_linkedItems
[
m_linkedItems
[
0
]
==
aCurrent
?
1
:
0
]
);
return
static_cast
<
PNS_SEGMENT
*>
(
m_linkedItems
[
m_linkedItems
[
0
]
==
aCurrent
?
1
:
0
]
);
}
/// trivial accessors
const
HashTag
&
GetTag
()
const
{
return
m_tag
;
}
const
VECTOR2I
&
GetPos
()
const
{
return
m_tag
.
pos
;
}
int
GetNet
()
const
{
return
m_tag
.
net
;
}
LinkedItems
&
GetLinkList
()
{
return
m_linkedItems
;
};
LinkedItems
&
GetLinkList
()
{
return
m_linkedItems
;
};
///> Returns the number of linked items of types listed in aMask.
int
LinkCount
(
int
aMask
=
-
1
)
const
{
int
n
=
0
;
for
(
LinkedItems
::
const_iterator
i
=
m_linkedItems
.
begin
();
i
!=
m_linkedItems
.
end
();
++
i
)
for
(
LinkedItems
::
const_iterator
i
=
m_linkedItems
.
begin
();
i
!=
m_linkedItems
.
end
();
++
i
)
if
(
(
*
i
)
->
GetKind
()
&
aMask
)
n
++
;
return
n
;
}
void
Dump
()
const
;
bool
operator
==
(
const
PNS_JOINT
&
rhs
)
const
bool
operator
==
(
const
PNS_JOINT
&
rhs
)
const
{
return
m_tag
.
pos
==
rhs
.
m_tag
.
pos
&&
m_tag
.
net
==
rhs
.
m_tag
.
net
;
}
void
Merge
(
const
PNS_JOINT
&
aJoint
)
{
if
(
!
Overlaps
(
aJoint
)
)
if
(
!
Overlaps
(
aJoint
)
)
return
;
m_layers
.
Merge
(
aJoint
.
m_layers
);
m_layers
.
Merge
(
aJoint
.
m_layers
);
// fixme: duplicate links (?)
for
(
LinkedItems
::
const_iterator
i
=
aJoint
.
m_linkedItems
.
begin
();
i
!=
aJoint
.
m_linkedItems
.
end
();
++
i
)
m_linkedItems
.
push_back
(
*
i
);
for
(
LinkedItems
::
const_iterator
i
=
aJoint
.
m_linkedItems
.
begin
();
i
!=
aJoint
.
m_linkedItems
.
end
();
++
i
)
m_linkedItems
.
push_back
(
*
i
);
}
bool
Overlaps
(
const
PNS_JOINT
&
rhs
)
const
bool
Overlaps
(
const
PNS_JOINT
&
rhs
)
const
{
return
m_tag
.
pos
==
rhs
.
m_tag
.
pos
&&
m_tag
.
net
==
rhs
.
m_tag
.
net
&&
m_layers
.
Overlaps
(
rhs
.
m_layers
);
return
m_tag
.
pos
==
rhs
.
m_tag
.
pos
&&
m_tag
.
net
==
rhs
.
m_tag
.
net
&&
m_layers
.
Overlaps
(
rhs
.
m_layers
);
}
private
:
///> hash tag for unordered_multimap
HashTag
m_tag
;
...
...
@@ -171,18 +186,22 @@ private:
// hash function & comparison operator for boost::unordered_map<>
inline
bool
operator
==
(
PNS_JOINT
::
HashTag
const
&
p1
,
PNS_JOINT
::
HashTag
const
&
p2
)
inline
bool
operator
==
(
PNS_JOINT
::
HashTag
const
&
p1
,
PNS_JOINT
::
HashTag
const
&
p2
)
{
return
p1
.
pos
==
p2
.
pos
&&
p1
.
net
==
p2
.
net
;
}
inline
std
::
size_t
hash_value
(
PNS_JOINT
::
HashTag
const
&
p
)
inline
std
::
size_t
hash_value
(
PNS_JOINT
::
HashTag
const
&
p
)
{
std
::
size_t
seed
=
0
;
boost
::
hash_combine
(
seed
,
p
.
pos
.
x
);
boost
::
hash_combine
(
seed
,
p
.
pos
.
y
);
boost
::
hash_combine
(
seed
,
p
.
net
);
boost
::
hash_combine
(
seed
,
p
.
pos
.
x
);
boost
::
hash_combine
(
seed
,
p
.
pos
.
y
);
boost
::
hash_combine
(
seed
,
p
.
net
);
return
seed
;
}
#endif // __PNS_JOINT_H
pcbnew/router/pns_layerset.h
View file @
5598acb6
...
...
@@ -28,91 +28,93 @@
*
* Represents a contiguous set of PCB layers.
*/
class
PNS_LAYERSET
{
public
:
PNS_LAYERSET
()
:
m_start
(
-
1
),
m_end
(
-
1
)
public
:
PNS_LAYERSET
()
:
m_start
(
-
1
),
m_end
(
-
1
)
{};
PNS_LAYERSET
(
int
aStart
,
int
aEnd
)
PNS_LAYERSET
(
int
aStart
,
int
aEnd
)
{
if
(
aStart
>
aEnd
)
std
::
swap
(
aStart
,
aEnd
);
if
(
aStart
>
aEnd
)
std
::
swap
(
aStart
,
aEnd
);
m_start
=
aStart
;
m_end
=
aEnd
;
}
PNS_LAYERSET
(
int
aLayer
)
PNS_LAYERSET
(
int
aLayer
)
{
m_start
=
m_end
=
aLayer
;
}
PNS_LAYERSET
(
const
PNS_LAYERSET
&
b
)
:
m_start
(
b
.
m_start
),
m_end
(
b
.
m_end
)
PNS_LAYERSET
(
const
PNS_LAYERSET
&
b
)
:
m_start
(
b
.
m_start
),
m_end
(
b
.
m_end
)
{}
~
PNS_LAYERSET
()
{};
~
PNS_LAYERSET
()
{};
const
PNS_LAYERSET
&
operator
=
(
const
PNS_LAYERSET
&
b
)
const
PNS_LAYERSET
&
operator
=
(
const
PNS_LAYERSET
&
b
)
{
m_start
=
b
.
m_start
;
m_end
=
b
.
m_end
;
return
*
this
;
}
bool
Overlaps
(
const
PNS_LAYERSET
&
aOther
)
const
bool
Overlaps
(
const
PNS_LAYERSET
&
aOther
)
const
{
return
m_end
>=
aOther
.
m_start
&&
m_start
<=
aOther
.
m_end
;
}
bool
Overlaps
(
const
int
aLayer
)
const
bool
Overlaps
(
const
int
aLayer
)
const
{
return
aLayer
>=
m_start
&&
aLayer
<=
m_end
;
}
bool
IsMultilayer
(
)
const
bool
IsMultilayer
(
)
const
{
return
m_start
!=
m_end
;
}
int
Start
()
const
{
int
Start
()
const
{
return
m_start
;
}
int
End
()
const
{
int
End
()
const
{
return
m_end
;
}
void
Merge
(
const
PNS_LAYERSET
&
aOther
)
void
Merge
(
const
PNS_LAYERSET
&
aOther
)
{
if
(
m_start
<
0
||
m_end
<
0
)
if
(
m_start
<
0
||
m_end
<
0
)
{
m_start
=
aOther
.
m_start
;
m_end
=
aOther
.
m_end
;
return
;
}
if
(
aOther
.
m_start
<
m_start
)
if
(
aOther
.
m_start
<
m_start
)
m_start
=
aOther
.
m_start
;
if
(
aOther
.
m_end
>
m_end
)
if
(
aOther
.
m_end
>
m_end
)
m_end
=
aOther
.
m_end
;
}
///> Shortcut for comparisons/overlap tests
static
PNS_LAYERSET
All
()
{
return
PNS_LAYERSET
(
0
,
256
);
return
PNS_LAYERSET
(
0
,
256
);
}
private
:
private
:
int
m_start
;
int
m_end
;
};
#endif // __PNS_LAYERSET_H
pcbnew/router/pns_line.cpp
View file @
5598acb6
...
...
@@ -23,7 +23,6 @@
#include <math/vector2d.h>
#include "pns_line.h"
#include "pns_node.h"
#include "pns_via.h"
...
...
@@ -33,9 +32,9 @@
using
namespace
std
;
using
boost
::
optional
;
PNS_LINE
*
PNS_LINE
::
Clone
()
const
PNS_LINE
*
PNS_LINE
::
Clone
()
const
{
PNS_LINE
*
l
=
new
PNS_LINE
();
PNS_LINE
*
l
=
new
PNS_LINE
();
l
->
m_line
=
m_line
;
l
->
m_width
=
m_width
;
...
...
@@ -49,9 +48,10 @@ PNS_LINE *PNS_LINE::Clone() const
return
l
;
}
PNS_LINE
*
PNS_LINE
::
CloneProperties
()
const
PNS_LINE
*
PNS_LINE
::
CloneProperties
()
const
{
PNS_LINE
*
l
=
new
PNS_LINE
();
PNS_LINE
*
l
=
new
PNS_LINE
();
l
->
m_width
=
m_width
;
l
->
m_layers
=
m_layers
;
...
...
@@ -61,39 +61,43 @@ PNS_LINE *PNS_LINE::CloneProperties() const
return
l
;
}
PNS_SEGMENT
*
PNS_SEGMENT
::
Clone
()
const
PNS_SEGMENT
*
PNS_SEGMENT
::
Clone
()
const
{
PNS_SEGMENT
*
s
=
new
PNS_SEGMENT
;
PNS_SEGMENT
*
s
=
new
PNS_SEGMENT
;
s
->
m_width
=
m_width
;
s
->
m_net
=
m_net
;
s
->
m_shape
=
m_shape
;
s
->
m_layers
=
m_layers
;
return
s
;
//
assert(false);
return
s
;
//
assert(false);
}
#if 1
bool
PNS_LINE
::
MergeObtuseSegments
(
)
bool
PNS_LINE
::
MergeObtuseSegments
(
)
{
int
step
=
m_line
.
PointCount
()
-
3
;
int
iter
=
0
;
int
segs_pre
=
m_line
.
SegmentCount
();
if
(
step
<
0
)
if
(
step
<
0
)
return
false
;
SHAPE_LINE_CHAIN
current_path
(
m_line
);
SHAPE_LINE_CHAIN
current_path
(
m_line
);
while
(
1
)
while
(
1
)
{
iter
++
;
int
n_segs
=
current_path
.
SegmentCount
();
int
max_step
=
n_segs
-
2
;
if
(
step
>
max_step
)
if
(
step
>
max_step
)
step
=
max_step
;
if
(
step
<
2
)
if
(
step
<
2
)
{
m_line
=
current_path
;
return
current_path
.
SegmentCount
()
<
segs_pre
;
...
...
@@ -102,81 +106,88 @@ bool PNS_LINE::MergeObtuseSegments( )
bool
found_anything
=
false
;
int
n
=
0
;
while
(
n
<
n_segs
-
step
)
while
(
n
<
n_segs
-
step
)
{
const
SEG
s1
=
current_path
.
CSegment
(
n
);
const
SEG
s2
=
current_path
.
CSegment
(
n
+
step
);
const
SEG
s1
=
current_path
.
CSegment
(
n
);
const
SEG
s2
=
current_path
.
CSegment
(
n
+
step
);
SEG
s1opt
,
s2opt
;
if
(
DIRECTION_45
(
s1
).
IsObtuse
(
DIRECTION_45
(
s2
))
)
if
(
DIRECTION_45
(
s1
).
IsObtuse
(
DIRECTION_45
(
s2
)
)
)
{
VECTOR2I
ip
=
*
s1
.
IntersectLines
(
s2
);
VECTOR2I
ip
=
*
s1
.
IntersectLines
(
s2
);
if
(
s1
.
Distance
(
ip
)
<=
1
||
s2
.
Distance
(
ip
)
<=
1
)
if
(
s1
.
Distance
(
ip
)
<=
1
||
s2
.
Distance
(
ip
)
<=
1
)
{
s1opt
=
SEG
(
s1
.
a
,
ip
);
s2opt
=
SEG
(
ip
,
s2
.
b
);
}
else
{
s1opt
=
SEG
(
s1
.
a
,
ip
);
s2opt
=
SEG
(
ip
,
s2
.
b
);
s1opt
=
SEG
(
s1
.
a
,
ip
);
s2opt
=
SEG
(
ip
,
s2
.
b
);
}
else
{
s1opt
=
SEG
(
s1
.
a
,
ip
);
s2opt
=
SEG
(
ip
,
s2
.
b
);
}
if
(
DIRECTION_45
(
s1opt
).
IsObtuse
(
DIRECTION_45
(
s2opt
))
)
if
(
DIRECTION_45
(
s1opt
).
IsObtuse
(
DIRECTION_45
(
s2opt
)
)
)
{
SHAPE_LINE_CHAIN
opt_path
;
opt_path
.
Append
(
s1opt
.
a
);
opt_path
.
Append
(
s1opt
.
b
);
opt_path
.
Append
(
s2opt
.
b
);
opt_path
.
Append
(
s1opt
.
a
);
opt_path
.
Append
(
s1opt
.
b
);
opt_path
.
Append
(
s2opt
.
b
);
PNS_LINE
opt_track
(
*
this
,
opt_path
);
PNS_LINE
opt_track
(
*
this
,
opt_path
);
if
(
!
m_world
->
CheckColliding
(
&
opt_track
,
PNS_ITEM
::
ANY
)
)
if
(
!
m_world
->
CheckColliding
(
&
opt_track
,
PNS_ITEM
::
ANY
)
)
{
current_path
.
Replace
(
s1
.
Index
()
+
1
,
s2
.
Index
(),
ip
);
current_path
.
Replace
(
s1
.
Index
()
+
1
,
s2
.
Index
(),
ip
);
n_segs
=
current_path
.
SegmentCount
();
found_anything
=
true
;
break
;
}
}
}
n
++
;
}
if
(
!
found_anything
)
if
(
!
found_anything
)
{
if
(
step
<=
2
)
{
m_line
=
current_path
;
return
m_line
.
SegmentCount
()
<
segs_pre
;
}
step
--
;
step
--
;
}
}
return
m_line
.
SegmentCount
()
<
segs_pre
;
}
bool
PNS_LINE
::
MergeSegments
(
)
bool
PNS_LINE
::
MergeSegments
()
{
int
step
=
m_line
.
PointCount
()
-
3
;
int
iter
=
0
;
int
segs_pre
=
m_line
.
SegmentCount
();
if
(
step
<
0
)
if
(
step
<
0
)
return
false
;
SHAPE_LINE_CHAIN
current_path
(
m_line
);
SHAPE_LINE_CHAIN
current_path
(
m_line
);
while
(
1
)
while
(
1
)
{
iter
++
;
int
n_segs
=
current_path
.
SegmentCount
();
int
max_step
=
n_segs
-
2
;
if
(
step
>
max_step
)
if
(
step
>
max_step
)
step
=
max_step
;
if
(
step
<
2
)
if
(
step
<
2
)
{
m_line
=
current_path
;
return
current_path
.
SegmentCount
()
<
segs_pre
;
...
...
@@ -185,116 +196,121 @@ bool PNS_LINE::MergeSegments( )
bool
found_anything
=
false
;
int
n
=
0
;
while
(
n
<
n_segs
-
step
)
while
(
n
<
n_segs
-
step
)
{
const
SEG
s1
=
current_path
.
CSegment
(
n
);
const
SEG
s2
=
current_path
.
CSegment
(
n
+
step
);
const
SEG
s1
=
current_path
.
CSegment
(
n
);
const
SEG
s2
=
current_path
.
CSegment
(
n
+
step
);
SEG
s1opt
,
s2opt
;
if
(
n
>
0
)
if
(
n
>
0
)
{
SHAPE_LINE_CHAIN
path_straight
=
DIRECTION_45
().
BuildInitialTrace
(
s1
.
a
,
s2
.
a
,
false
);
SHAPE_LINE_CHAIN
path_diagonal
=
DIRECTION_45
().
BuildInitialTrace
(
s1
.
a
,
s2
.
a
,
true
);
SHAPE_LINE_CHAIN
path_straight
=
DIRECTION_45
().
BuildInitialTrace
(
s1
.
a
,
s2
.
a
,
false
);
SHAPE_LINE_CHAIN
path_diagonal
=
DIRECTION_45
().
BuildInitialTrace
(
s1
.
a
,
s2
.
a
,
true
);
}
if
(
DIRECTION_45
(
s1
)
==
DIRECTION_45
(
s2
)
)
if
(
DIRECTION_45
(
s1
)
==
DIRECTION_45
(
s2
)
)
{
if
(
s1
.
Collinear
(
s2
)
)
if
(
s1
.
Collinear
(
s2
)
)
{
//
printf("Colinear: np %d step %d n1 %d n2 %d\n", n_segs, step, n, n+step);
//
printf("Colinear: np %d step %d n1 %d n2 %d\n", n_segs, step, n, n+step);
SHAPE_LINE_CHAIN
opt_path
;
opt_path
.
Append
(
s1
.
a
);
opt_path
.
Append
(
s2
.
b
);
opt_path
.
Append
(
s1
.
a
);
opt_path
.
Append
(
s2
.
b
);
PNS_LINE
tmp
(
*
this
,
opt_path
);
PNS_LINE
tmp
(
*
this
,
opt_path
);
if
(
!
m_world
->
CheckColliding
(
&
tmp
,
PNS_ITEM
::
ANY
)
)
if
(
!
m_world
->
CheckColliding
(
&
tmp
,
PNS_ITEM
::
ANY
)
)
{
current_path
.
Remove
(
s1
.
Index
()
+
1
,
s2
.
Index
()
);
current_path
.
Remove
(
s1
.
Index
()
+
1
,
s2
.
Index
()
);
n_segs
=
current_path
.
SegmentCount
();
found_anything
=
true
;
break
;
}
}
}
else
if
(
DIRECTION_45
(
s1
).
IsObtuse
(
DIRECTION_45
(
s2
))
)
else
if
(
DIRECTION_45
(
s1
).
IsObtuse
(
DIRECTION_45
(
s2
)
)
)
{
VECTOR2I
ip
=
*
s1
.
IntersectLines
(
s2
);
VECTOR2I
ip
=
*
s1
.
IntersectLines
(
s2
);
if
(
s1
.
Distance
(
ip
)
<=
1
||
s2
.
Distance
(
ip
)
<=
1
)
if
(
s1
.
Distance
(
ip
)
<=
1
||
s2
.
Distance
(
ip
)
<=
1
)
{
s1opt
=
SEG
(
s1
.
a
,
ip
);
s2opt
=
SEG
(
ip
,
s2
.
b
);
}
else
{
s1opt
=
SEG
(
s1
.
a
,
ip
);
s2opt
=
SEG
(
ip
,
s2
.
b
);
s1opt
=
SEG
(
s1
.
a
,
ip
);
s2opt
=
SEG
(
ip
,
s2
.
b
);
}
else
{
s1opt
=
SEG
(
s1
.
a
,
ip
);
s2opt
=
SEG
(
ip
,
s2
.
b
);
}
if
(
DIRECTION_45
(
s1opt
).
IsObtuse
(
DIRECTION_45
(
s2opt
))
)
if
(
DIRECTION_45
(
s1opt
).
IsObtuse
(
DIRECTION_45
(
s2opt
)
)
)
{
SHAPE_LINE_CHAIN
opt_path
;
opt_path
.
Append
(
s1opt
.
a
);
opt_path
.
Append
(
s1opt
.
b
);
opt_path
.
Append
(
s2opt
.
b
);
opt_path
.
Append
(
s1opt
.
a
);
opt_path
.
Append
(
s1opt
.
b
);
opt_path
.
Append
(
s2opt
.
b
);
PNS_LINE
opt_track
(
*
this
,
opt_path
);
PNS_LINE
opt_track
(
*
this
,
opt_path
);
if
(
!
m_world
->
CheckColliding
(
&
opt_track
,
PNS_ITEM
::
ANY
)
)
if
(
!
m_world
->
CheckColliding
(
&
opt_track
,
PNS_ITEM
::
ANY
)
)
{
current_path
.
Replace
(
s1
.
Index
()
+
1
,
s2
.
Index
(),
ip
);
current_path
.
Replace
(
s1
.
Index
()
+
1
,
s2
.
Index
(),
ip
);
n_segs
=
current_path
.
SegmentCount
();
found_anything
=
true
;
break
;
}
}
}
n
++
;
}
if
(
!
found_anything
)
if
(
!
found_anything
)
{
if
(
step
<=
2
)
{
m_line
=
current_path
;
return
m_line
.
SegmentCount
()
<
segs_pre
;
}
step
--
;
step
--
;
}
}
return
m_line
.
SegmentCount
()
<
segs_pre
;
}
#endif
int
PNS_LINE
::
CountCorners
(
int
aAngles
)
int
PNS_LINE
::
CountCorners
(
int
aAngles
)
{
int
count
=
0
;
for
(
int
i
=
0
;
i
<
m_line
.
SegmentCount
()
-
1
;
i
++
)
for
(
int
i
=
0
;
i
<
m_line
.
SegmentCount
()
-
1
;
i
++
)
{
const
SEG
seg1
=
m_line
.
CSegment
(
i
);
const
SEG
seg2
=
m_line
.
CSegment
(
i
+
1
);
const
SEG
seg1
=
m_line
.
CSegment
(
i
);
const
SEG
seg2
=
m_line
.
CSegment
(
i
+
1
);
const
DIRECTION_45
dir1
(
seg1
);
const
DIRECTION_45
dir2
(
seg2
);
const
DIRECTION_45
dir1
(
seg1
);
const
DIRECTION_45
dir2
(
seg2
);
DIRECTION_45
::
AngleType
a
=
dir1
.
Angle
(
dir2
);
DIRECTION_45
::
AngleType
a
=
dir1
.
Angle
(
dir2
);
if
(
a
&
aAngles
)
if
(
a
&
aAngles
)
count
++
;
}
return
count
;
}
//#define DUMP_TEST_CASES
// #define DUMP_TEST_CASES
// fixme: damn f*****g inefficient and incredibly crappily written
void
PNS_LINE
::
NewWalkaround
(
const
SHAPE_LINE_CHAIN
&
aObstacle
,
...
...
@@ -303,10 +319,9 @@ void PNS_LINE::NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle,
SHAPE_LINE_CHAIN
&
aPostPath
,
bool
aCw
)
const
{
typedef
SHAPE_LINE_CHAIN
::
Intersection
Intersection
;
SHAPE_LINE_CHAIN
l_orig
(
m_line
);
SHAPE_LINE_CHAIN
l_orig
(
m_line
);
SHAPE_LINE_CHAIN
l_hull
;
vector
<
bool
>
outside
,
on_edge
,
inside
;
SHAPE_LINE_CHAIN
path
;
...
...
@@ -314,46 +329,46 @@ void PNS_LINE::NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle,
vector
<
Intersection
>
isects
;
// don't calculate walkaround for empty lines
if
(
m_line
.
PointCount
()
<
2
)
if
(
m_line
.
PointCount
()
<
2
)
return
;
#ifdef DUMP_TEST_CASES
printf
(
"%s
\n
"
,
m_line
.
Format
().
c_str
()
);
printf
(
"%s
\n
"
,
aObstacle
.
Format
().
c_str
()
);
printf
(
"%s
\n
"
,
m_line
.
Format
().
c_str
()
);
printf
(
"%s
\n
"
,
aObstacle
.
Format
().
c_str
()
);
#endif
aObstacle
.
Intersect
(
m_line
,
isects
);
//printf("NewWalk intersectiosn :%d\n" ,isects.size());
aObstacle
.
Intersect
(
m_line
,
isects
);
// printf("NewWalk intersectiosn :%d\n" ,isects.size());
if
(
!
aCw
)
l_hull
=
aObstacle
.
Reverse
();
else
l_hull
=
aObstacle
;
BOOST_FOREACH
(
Intersection
isect
,
isects
)
{
l_orig
.
Split
(
isect
.
p
);
l_hull
.
Split
(
isect
.
p
);
BOOST_FOREACH
(
Intersection
isect
,
isects
)
{
l_orig
.
Split
(
isect
.
p
);
l_hull
.
Split
(
isect
.
p
);
}
#ifdef DUMP_TEST_CASES
printf
(
"%s
\n
"
,
m_line
.
Format
().
c_str
()
);
printf
(
"%s
\n
"
,
aObstacle
.
Format
().
c_str
()
);
printf
(
"%s
\n
"
,
l_orig
.
Format
().
c_str
()
);
printf
(
"%s
\n
"
,
l_hull
.
Format
().
c_str
()
);
printf
(
"%s
\n
"
,
m_line
.
Format
().
c_str
()
);
printf
(
"%s
\n
"
,
aObstacle
.
Format
().
c_str
()
);
printf
(
"%s
\n
"
,
l_orig
.
Format
().
c_str
()
);
printf
(
"%s
\n
"
,
l_hull
.
Format
().
c_str
()
);
#endif
//
printf("Pts: line %d hull %d\n", l_orig.PointCount(), l_hull.PointCount());
//
printf("Pts: line %d hull %d\n", l_orig.PointCount(), l_hull.PointCount());
int
first_post
=
-
1
;
int
last_pre
=
-
1
;
for
(
int
i
=
0
;
i
<
l_orig
.
PointCount
();
i
++
)
for
(
int
i
=
0
;
i
<
l_orig
.
PointCount
();
i
++
)
{
int
ei
=
l_hull
.
Find
(
l_orig
.
CPoint
(
i
))
;
int
ei
=
l_hull
.
Find
(
l_orig
.
CPoint
(
i
)
)
;
bool
edge
=
ei
>=
0
;
bool
in
=
l_hull
.
PointInside
(
l_orig
.
CPoint
(
i
)
)
&&
!
edge
;
bool
in
=
l_hull
.
PointInside
(
l_orig
.
CPoint
(
i
)
)
&&
!
edge
;
bool
out
=
!
(
in
||
edge
);
outside
.
push_back
(
out
);
...
...
@@ -361,97 +376,107 @@ void PNS_LINE::NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle,
inside
.
push_back
(
in
);
}
for
(
int
i
=
l_orig
.
PointCount
()
-
1
;
i
>=
1
;
i
--
)
if
(
inside
[
i
]
&&
outside
[
i
-
1
])
for
(
int
i
=
l_orig
.
PointCount
()
-
1
;
i
>=
1
;
i
--
)
if
(
inside
[
i
]
&&
outside
[
i
-
1
]
)
{
SHAPE_LINE_CHAIN
::
Intersections
ips
;
l_hull
.
Intersect
(
SEG
(
l_orig
.
CPoint
(
i
),
l_orig
.
CPoint
(
i
-
1
)
),
ips
);
l_orig
.
Remove
(
i
,
-
1
);
l_orig
.
Append
(
ips
[
0
].
p
);
l_hull
.
Intersect
(
SEG
(
l_orig
.
CPoint
(
i
),
l_orig
.
CPoint
(
i
-
1
)
),
ips
);
l_orig
.
Remove
(
i
,
-
1
);
l_orig
.
Append
(
ips
[
0
].
p
);
break
;
}
else
if
(
inside
[
i
]
&&
on_edge
[
i
-
1
]
)
else
if
(
inside
[
i
]
&&
on_edge
[
i
-
1
]
)
{
l_orig
.
Remove
(
i
,
-
1
);
//n = i;
}
else
if
(
!
inside
[
i
])
l_orig
.
Remove
(
i
,
-
1
);
// n = i;
}
else
if
(
!
inside
[
i
]
)
break
;
if
(
!
outside
.
size
()
&&
on_edge
.
size
()
<
2
)
if
(
!
outside
.
size
()
&&
on_edge
.
size
()
<
2
)
return
;
for
(
int
i
=
0
;
i
<
l_orig
.
PointCount
();
i
++
)
for
(
int
i
=
0
;
i
<
l_orig
.
PointCount
();
i
++
)
{
const
VECTOR2I
p
=
l_orig
.
Point
(
i
);
const
VECTOR2I
p
=
l_orig
.
Point
(
i
);
if
(
outside
[
i
]
||
(
on_edge
[
i
]
&&
i
==
(
l_orig
.
PointCount
()
-
1
))
)
if
(
outside
[
i
]
||
(
on_edge
[
i
]
&&
i
==
(
l_orig
.
PointCount
()
-
1
)
)
)
{
if
(
last_pre
<
0
)
aPrePath
.
Append
(
p
);
path
.
Append
(
p
);
if
(
last_pre
<
0
)
aPrePath
.
Append
(
p
);
path
.
Append
(
p
);
}
else
if
(
on_edge
[
i
]
)
else
if
(
on_edge
[
i
]
)
{
int
li
=
-
1
;
if
(
last_pre
<
0
)
if
(
last_pre
<
0
)
{
aPrePath
.
Append
(
p
);
aPrePath
.
Append
(
p
);
last_pre
=
path
.
PointCount
();
}
if
(
i
==
l_orig
.
PointCount
()
-
1
||
outside
[
i
+
1
])
if
(
i
==
l_orig
.
PointCount
()
-
1
||
outside
[
i
+
1
]
)
{
path
.
Append
(
p
);
path
.
Append
(
p
);
}
else
{
int
vi2
=
l_hull
.
Find
(
l_orig
.
CPoint
(
i
)
);
int
vi2
=
l_hull
.
Find
(
l_orig
.
CPoint
(
i
)
);
path
.
Append
(
l_hull
.
CPoint
(
vi2
)
);
path
.
Append
(
l_hull
.
CPoint
(
vi2
));
for
(
int
j
=
(
vi2
+
1
)
%
l_hull
.
PointCount
();
j
!=
vi2
;
j
=
(
j
+
1
)
%
l_hull
.
PointCount
())
for
(
int
j
=
(
vi2
+
1
)
%
l_hull
.
PointCount
();
j
!=
vi2
;
j
=
(
j
+
1
)
%
l_hull
.
PointCount
()
)
{
path
.
Append
(
l_hull
.
CPoint
(
j
));
li
=
l_orig
.
Find
(
l_hull
.
CPoint
(
j
));
if
(
li
>=
0
&&
(
li
==
(
l_orig
.
PointCount
()
-
1
)
||
outside
[
li
+
1
]))
path
.
Append
(
l_hull
.
CPoint
(
j
)
);
li
=
l_orig
.
Find
(
l_hull
.
CPoint
(
j
)
);
if
(
li
>=
0
&&
(
li
==
(
l_orig
.
PointCount
()
-
1
)
||
outside
[
li
+
1
])
)
break
;
}
if
(
li
>=
0
)
{
if
(
i
>=
li
)
if
(
li
>=
0
)
{
if
(
i
>=
li
)
break
;
else
{
else
i
=
li
;
}
}
}
first_post
=
path
.
PointCount
()
-
1
;
}
}
if
(
last_pre
<
0
&&
first_post
<
0
)
if
(
last_pre
<
0
&&
first_post
<
0
)
return
;
aWalkaroundPath
=
path
.
Slice
(
last_pre
,
first_post
);
if
(
first_post
>=
0
)
aPostPath
=
path
.
Slice
(
first_post
,
-
1
);
if
(
first_post
>=
0
)
aPostPath
=
path
.
Slice
(
first_post
,
-
1
);
}
bool
PNS_LINE
::
onEdge
(
const
SHAPE_LINE_CHAIN
&
obstacle
,
VECTOR2I
p
,
int
&
ei
,
bool
&
is_vertex
)
const
bool
PNS_LINE
::
onEdge
(
const
SHAPE_LINE_CHAIN
&
obstacle
,
VECTOR2I
p
,
int
&
ei
,
bool
&
is_vertex
)
const
{
int
vtx
=
obstacle
.
Find
(
p
);
int
vtx
=
obstacle
.
Find
(
p
);
if
(
vtx
>=
0
)
if
(
vtx
>=
0
)
{
ei
=
vtx
;
is_vertex
=
true
;
is_vertex
=
true
;
return
true
;
}
for
(
int
s
=
0
;
s
<
obstacle
.
SegmentCount
();
s
++
)
for
(
int
s
=
0
;
s
<
obstacle
.
SegmentCount
();
s
++
)
{
if
(
obstacle
.
CSegment
(
s
).
Contains
(
p
)
)
if
(
obstacle
.
CSegment
(
s
).
Contains
(
p
)
)
{
ei
=
s
;
is_vertex
=
false
;
...
...
@@ -462,55 +487,71 @@ bool PNS_LINE::onEdge(const SHAPE_LINE_CHAIN &obstacle, VECTOR2I p, int& ei, boo
return
false
;
}
bool
PNS_LINE
::
walkScan
(
const
SHAPE_LINE_CHAIN
&
line
,
const
SHAPE_LINE_CHAIN
&
obstacle
,
bool
reverse
,
VECTOR2I
&
ip
,
int
&
index_o
,
int
&
index_l
,
bool
&
is_vertex
)
const
bool
PNS_LINE
::
walkScan
(
const
SHAPE_LINE_CHAIN
&
line
,
const
SHAPE_LINE_CHAIN
&
obstacle
,
bool
reverse
,
VECTOR2I
&
ip
,
int
&
index_o
,
int
&
index_l
,
bool
&
is_vertex
)
const
{
int
sc
=
line
.
SegmentCount
();
for
(
int
i
=
0
;
i
<
line
.
SegmentCount
();
i
++
)
for
(
int
i
=
0
;
i
<
line
.
SegmentCount
();
i
++
)
{
printf
(
"check-seg rev %d %d/%d %d
\n
"
,
reverse
,
i
,
sc
,
sc
-
1
-
i
);
SEG
tmp
=
line
.
CSegment
(
reverse
?
sc
-
1
-
i
:
i
);
SEG
s
(
tmp
.
a
,
tmp
.
b
);
printf
(
"check-seg rev %d %d/%d %d
\n
"
,
reverse
,
i
,
sc
,
sc
-
1
-
i
);
SEG
tmp
=
line
.
CSegment
(
reverse
?
sc
-
1
-
i
:
i
);
SEG
s
(
tmp
.
a
,
tmp
.
b
);
if
(
reverse
)
if
(
reverse
)
{
s
.
a
=
tmp
.
b
;
s
.
b
=
tmp
.
a
;
}
if
(
onEdge
(
obstacle
,
s
.
a
,
index_o
,
is_vertex
)
)
if
(
onEdge
(
obstacle
,
s
.
a
,
index_o
,
is_vertex
)
)
{
index_l
=
(
reverse
?
sc
-
1
-
i
:
i
);
index_l
=
(
reverse
?
sc
-
1
-
i
:
i
);
ip
=
s
.
a
;
printf
(
"vertex %d on-%s %d
\n
"
,
index_l
,
is_vertex
?
"vertex"
:
"edge"
,
index_o
);
printf
(
"vertex %d on-%s %d
\n
"
,
index_l
,
is_vertex
?
"vertex"
:
"edge"
,
index_o
);
return
true
;
}
if
(
onEdge
(
obstacle
,
s
.
b
,
index_o
,
is_vertex
)
)
if
(
onEdge
(
obstacle
,
s
.
b
,
index_o
,
is_vertex
)
)
{
index_l
=
(
reverse
?
sc
-
1
-
i
-
1
:
i
+
1
);
index_l
=
(
reverse
?
sc
-
1
-
i
-
1
:
i
+
1
);
ip
=
s
.
b
;
printf
(
"vertex %d on-%s %d
\n
"
,
index_l
,
is_vertex
?
"vertex"
:
"edge"
,
index_o
);
printf
(
"vertex %d on-%s %d
\n
"
,
index_l
,
is_vertex
?
"vertex"
:
"edge"
,
index_o
);
return
true
;
}
SHAPE_LINE_CHAIN
::
Intersections
ips
;
int
n_is
=
obstacle
.
Intersect
(
s
,
ips
);
int
n_is
=
obstacle
.
Intersect
(
s
,
ips
);
if
(
n_is
>
0
)
if
(
n_is
>
0
)
{
index_o
=
ips
[
0
].
our
.
Index
();
index_l
=
reverse
?
sc
-
1
-
i
:
i
;
printf
(
"segment-%d intersects edge-%d
\n
"
,
index_l
,
index_o
);
index_l
=
reverse
?
sc
-
1
-
i
:
i
;
printf
(
"segment-%d intersects edge-%d
\n
"
,
index_l
,
index_o
);
ip
=
ips
[
0
].
p
;
return
true
;
}
}
return
false
;
}
bool
PNS_LINE
::
Walkaround
(
SHAPE_LINE_CHAIN
obstacle
,
SHAPE_LINE_CHAIN
&
pre
,
SHAPE_LINE_CHAIN
&
walk
,
SHAPE_LINE_CHAIN
&
post
,
bool
cw
)
const
bool
PNS_LINE
::
Walkaround
(
SHAPE_LINE_CHAIN
obstacle
,
SHAPE_LINE_CHAIN
&
pre
,
SHAPE_LINE_CHAIN
&
walk
,
SHAPE_LINE_CHAIN
&
post
,
bool
cw
)
const
{
const
SHAPE_LINE_CHAIN
&
line
=
GetCLine
();
const
SHAPE_LINE_CHAIN
&
line
=
GetCLine
();
VECTOR2I
ip_start
;
int
index_o_start
,
index_l_start
;
VECTOR2I
ip_end
;
...
...
@@ -518,187 +559,205 @@ bool PNS_LINE::Walkaround(SHAPE_LINE_CHAIN obstacle, SHAPE_LINE_CHAIN &pre, SHAP
bool
is_vertex_start
,
is_vertex_end
;
if
(
line
.
SegmentCount
()
<
1
)
if
(
line
.
SegmentCount
()
<
1
)
return
false
;
if
(
obstacle
.
PointInside
(
line
.
CPoint
(
0
))
||
obstacle
.
PointInside
(
line
.
CPoint
(
-
1
)))
if
(
obstacle
.
PointInside
(
line
.
CPoint
(
0
)
)
||
obstacle
.
PointInside
(
line
.
CPoint
(
-
1
)
)
)
return
false
;
// printf("forward:\n");
bool
found
=
walkScan
(
line
,
obstacle
,
false
,
ip_start
,
index_o_start
,
index_l_start
,
is_vertex_start
);
//printf("reverse:\n");
found
|=
walkScan
(
line
,
obstacle
,
true
,
ip_end
,
index_o_end
,
index_l_end
,
is_vertex_end
);
if
(
!
found
||
ip_start
==
ip_end
)
bool
found
=
walkScan
(
line
,
obstacle
,
false
,
ip_start
,
index_o_start
,
index_l_start
,
is_vertex_start
);
// printf("reverse:\n");
found
|=
walkScan
(
line
,
obstacle
,
true
,
ip_end
,
index_o_end
,
index_l_end
,
is_vertex_end
);
if
(
!
found
||
ip_start
==
ip_end
)
{
pre
=
line
;
return
true
;
}
pre
=
line
.
Slice
(
0
,
index_l_start
);
pre
.
Append
(
ip_start
);
pre
=
line
.
Slice
(
0
,
index_l_start
);
pre
.
Append
(
ip_start
);
walk
.
Clear
();
walk
.
Append
(
ip_start
);
walk
.
Append
(
ip_start
);
if
(
cw
)
if
(
cw
)
{
int
is
=
(
index_o_start
+
1
)
%
obstacle
.
PointCount
();
int
ie
=
(
is_vertex_end
?
index_o_end
:
index_o_end
+
1
)
%
obstacle
.
PointCount
();
int
is
=
(
index_o_start
+
1
)
%
obstacle
.
PointCount
();
int
ie
=
(
is_vertex_end
?
index_o_end
:
index_o_end
+
1
)
%
obstacle
.
PointCount
();
while
(
1
)
while
(
1
)
{
printf
(
"is %d
\n
"
,
is
);
walk
.
Append
(
obstacle
.
CPoint
(
is
));
printf
(
"is %d
\n
"
,
is
);
walk
.
Append
(
obstacle
.
CPoint
(
is
)
);
if
(
is
==
ie
)
if
(
is
==
ie
)
break
;
is
++
;
if
(
is
==
obstacle
.
PointCount
()
)
is
++
;
if
(
is
==
obstacle
.
PointCount
()
)
is
=
0
;
}
}
else
{
}
else
{
int
is
=
index_o_start
;
int
ie
=
(
is_vertex_end
?
index_o_end
:
index_o_end
)
%
obstacle
.
PointCount
();
int
ie
=
(
is_vertex_end
?
index_o_end
:
index_o_end
)
%
obstacle
.
PointCount
();
while
(
1
)
while
(
1
)
{
printf
(
"is %d
\n
"
,
is
);
walk
.
Append
(
obstacle
.
CPoint
(
is
));
if
(
is
==
ie
)
printf
(
"is %d
\n
"
,
is
);
walk
.
Append
(
obstacle
.
CPoint
(
is
)
);
if
(
is
==
ie
)
break
;
is
--
;
if
(
is
<
0
)
is
--
;
if
(
is
<
0
)
is
=
obstacle
.
PointCount
()
-
1
;
}
}
walk
.
Append
(
ip_end
);
walk
.
Append
(
ip_end
);
post
.
Clear
();
post
.
Append
(
ip_end
);
post
.
Append
(
line
.
Slice
(
is_vertex_end
?
index_l_end
:
index_l_end
+
1
,
-
1
)
);
post
.
Append
(
ip_end
);
post
.
Append
(
line
.
Slice
(
is_vertex_end
?
index_l_end
:
index_l_end
+
1
,
-
1
)
);
//
for(int i = (index_o_start + 1) % obstacle.PointCount();
//
for(int i = (index_o_start + 1) % obstacle.PointCount();
// i != (index_o_end + 1) % obstacle.PointCount(); i=(i+1) % obstacle.PointCount())
//
{
//
printf("append %d\n", i);
//
walk.Append(obstacle.CPoint(i));
//
}
//
{
//
printf("append %d\n", i);
//
walk.Append(obstacle.CPoint(i));
//
}
return
true
;
}
void
PNS_LINE
::
NewWalkaround
(
const
SHAPE_LINE_CHAIN
&
aObstacle
,
SHAPE_LINE_CHAIN
&
aPath
,
bool
aCw
)
const
{
SHAPE_LINE_CHAIN
walk
,
post
;
NewWalkaround
(
aObstacle
,
aPath
,
walk
,
post
,
aCw
);
aPath
.
Append
(
walk
);
aPath
.
Append
(
post
);
NewWalkaround
(
aObstacle
,
aPath
,
walk
,
post
,
aCw
);
aPath
.
Append
(
walk
);
aPath
.
Append
(
post
);
aPath
.
Simplify
();
}
void
PNS_LINE
::
Walkaround
(
const
SHAPE_LINE_CHAIN
&
aObstacle
,
SHAPE_LINE_CHAIN
&
aPath
,
bool
aCw
)
const
{
SHAPE_LINE_CHAIN
walk
,
post
;
Walkaround
(
aObstacle
,
aPath
,
walk
,
post
,
aCw
);
aPath
.
Append
(
walk
);
aPath
.
Append
(
post
);
Walkaround
(
aObstacle
,
aPath
,
walk
,
post
,
aCw
);
aPath
.
Append
(
walk
);
aPath
.
Append
(
post
);
aPath
.
Simplify
();
}
const
SHAPE_LINE_CHAIN
PNS_SEGMENT
::
Hull
(
int
aClearance
,
int
aWalkaroundThickness
)
const
const
SHAPE_LINE_CHAIN
PNS_SEGMENT
::
Hull
(
int
aClearance
,
int
aWalkaroundThickness
)
const
{
int
d
=
aClearance
+
10
;
int
x
=
(
int
)
(
2.0
/
(
1.0
+
M_SQRT2
)
*
d
)
+
2
;
int
x
=
(
int
)(
2.0
/
(
1.0
+
M_SQRT2
)
*
d
)
+
2
;
const
VECTOR2I
a
=
m_shape
.
CPoint
(
0
);
const
VECTOR2I
b
=
m_shape
.
CPoint
(
1
);
const
VECTOR2I
a
=
m_shape
.
CPoint
(
0
);
const
VECTOR2I
b
=
m_shape
.
CPoint
(
1
);
VECTOR2I
dir
=
b
-
a
;
VECTOR2I
p0
=
dir
.
Perpendicular
().
Resize
(
d
);
VECTOR2I
ds
=
dir
.
Perpendicular
().
Resize
(
x
/
2
);
VECTOR2I
pd
=
dir
.
Resize
(
x
/
2
);
VECTOR2I
dp
=
dir
.
Resize
(
d
);
VECTOR2I
p0
=
dir
.
Perpendicular
().
Resize
(
d
);
VECTOR2I
ds
=
dir
.
Perpendicular
().
Resize
(
x
/
2
);
VECTOR2I
pd
=
dir
.
Resize
(
x
/
2
);
VECTOR2I
dp
=
dir
.
Resize
(
d
);
SHAPE_LINE_CHAIN
s
;
s
.
SetClosed
(
true
);
s
.
Append
(
b
+
p0
+
pd
);
s
.
Append
(
b
+
dp
+
ds
);
s
.
Append
(
b
+
dp
-
ds
);
s
.
Append
(
b
-
p0
+
pd
);
s
.
Append
(
a
-
p0
-
pd
);
s
.
Append
(
a
-
dp
-
ds
);
s
.
Append
(
a
-
dp
+
ds
);
s
.
Append
(
a
+
p0
-
pd
);
s
.
Append
(
b
+
p0
+
pd
);
s
.
Append
(
b
+
dp
+
ds
);
s
.
Append
(
b
+
dp
-
ds
);
s
.
Append
(
b
-
p0
+
pd
);
s
.
Append
(
a
-
p0
-
pd
);
s
.
Append
(
a
-
dp
-
ds
);
s
.
Append
(
a
-
dp
+
ds
);
s
.
Append
(
a
+
p0
-
pd
);
// make sure the hull outline is always clockwise
if
(
s
.
CSegment
(
0
).
Side
(
a
)
<
0
)
if
(
s
.
CSegment
(
0
).
Side
(
a
)
<
0
)
return
s
.
Reverse
();
else
return
s
;
}
bool
PNS_LINE
::
Is45Degree
()
{
for
(
int
i
=
0
;
i
<
m_line
.
SegmentCount
();
i
++
)
for
(
int
i
=
0
;
i
<
m_line
.
SegmentCount
();
i
++
)
{
const
SEG
&
s
=
m_line
.
CSegment
(
i
);
const
SEG
&
s
=
m_line
.
CSegment
(
i
);
double
angle
=
180.0
/
M_PI
*
atan2
((
double
)
s
.
b
.
y
-
(
double
)
s
.
a
.
y
,
(
double
)
s
.
b
.
x
-
(
double
)
s
.
a
.
x
);
double
angle
=
180.0
/
M_PI
*
atan2
(
(
double
)
s
.
b
.
y
-
(
double
)
s
.
a
.
y
,
(
double
)
s
.
b
.
x
-
(
double
)
s
.
a
.
x
);
if
(
angle
<
0
)
angle
+=
360.0
;
if
(
angle
<
0
)
angle
+=
360.0
;
double
angle_a
=
fabs
(
fmod
(
angle
,
45.0
));
if
(
angle_a
>
1.0
&&
angle_a
<
44.0
)
double
angle_a
=
fabs
(
fmod
(
angle
,
45.0
)
);
if
(
angle_a
>
1.0
&&
angle_a
<
44.0
)
return
false
;
}
return
true
;
}
const
PNS_LINE
PNS_LINE
::
ClipToNearestObstacle
(
PNS_NODE
*
aNode
)
const
const
PNS_LINE
PNS_LINE
::
ClipToNearestObstacle
(
PNS_NODE
*
aNode
)
const
{
PNS_LINE
l
(
*
this
);
PNS_LINE
l
(
*
this
);
PNS_NODE
::
OptObstacle
obs
=
aNode
->
NearestObstacle
(
&
l
);
PNS_NODE
::
OptObstacle
obs
=
aNode
->
NearestObstacle
(
&
l
);
if
(
obs
)
if
(
obs
)
{
l
.
RemoveVia
();
int
p
=
l
.
GetLine
().
Split
(
obs
->
ip_first
);
l
.
GetLine
().
Remove
(
p
+
1
,
-
1
);
int
p
=
l
.
GetLine
().
Split
(
obs
->
ip_first
);
l
.
GetLine
().
Remove
(
p
+
1
,
-
1
);
}
return
l
;
}
void
PNS_LINE
::
ShowLinks
()
{
if
(
!
m_segmentRefs
)
if
(
!
m_segmentRefs
)
{
printf
(
"line %p: no links
\n
"
,
this
);
printf
(
"line %p: no links
\n
"
,
this
);
return
;
}
printf
(
"line %p: %d linked segs
\n
"
,
this
,
m_segmentRefs
->
size
());
for
(
int
i
=
0
;
i
<
(
int
)
m_segmentRefs
->
size
();
i
++
)
printf
(
"seg %d: %p
\n
"
,
i
,
(
*
m_segmentRefs
)[
i
])
;
printf
(
"line %p: %d linked segs
\n
"
,
this
,
m_segmentRefs
->
size
()
);
for
(
int
i
=
0
;
i
<
(
int
)
m_segmentRefs
->
size
();
i
++
)
printf
(
"seg %d: %p
\n
"
,
i
,
(
*
m_segmentRefs
)[
i
]
);
}
pcbnew/router/pns_line.h
View file @
5598acb6
...
...
@@ -38,46 +38,48 @@ class PNS_VIA;
/**
* Class PNS_LINE
*
* Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,
* junctions between multiple traces or two traces different widths and combinations of these).
* PNS_LINEs are NOT stored in the model (PNS_NODE) - instead, they are assembled on-the-fly, based on
* a via/pad/segment that belongs/begins them.
* Represents a track on a PCB, connecting two non-trivial joints (that is,
* vias, pads, junctions between multiple traces or two traces different widths
* and combinations of these). PNS_LINEs are NOT stored in the model (PNS_NODE).
* Instead, they are assembled on-the-fly, based on a via/pad/segment that
* belongs/begins them.
*
* PNS_LINEs can be either loose (consisting of segments that do not belong to any PNS_NODE) or owned (with segments
* taken from a PNS_NODE) - these are returned by PNS_NODE::AssembleLine and friends.
* PNS_LINEs can be either loose (consisting of segments that do not belong to
* any PNS_NODE) or owned (with segments taken from a PNS_NODE) - these are
* returned by PNS_NODE::AssembleLine and friends.
*
* A PNS_LINE may have a PNS_VIA attached at its and - this is used by via dragging/force propagation stuff.
* A PNS_LINE may have a PNS_VIA attached at its and - this is used by via
* dragging/force propagation stuff.
*/
class
PNS_LINE
:
public
PNS_ITEM
{
public
:
typedef
std
::
vector
<
PNS_SEGMENT
*>
LinkedSegments
;
typedef
std
::
vector
<
PNS_SEGMENT
*>
LinkedSegments
;
PNS_LINE
()
:
PNS_ITEM
(
LINE
)
PNS_LINE
()
:
PNS_ITEM
(
LINE
)
{
m_segmentRefs
=
NULL
;
m_hasVia
=
false
;
m_affectedRangeStart
=
-
1
;
};
PNS_LINE
(
int
aLayer
,
int
aWidth
,
const
SHAPE_LINE_CHAIN
&
aLine
)
:
PNS_ITEM
(
LINE
)
PNS_LINE
(
int
aLayer
,
int
aWidth
,
const
SHAPE_LINE_CHAIN
&
aLine
)
:
PNS_ITEM
(
LINE
)
{
m_line
=
aLine
;
m_width
=
aWidth
;
m_segmentRefs
=
NULL
;
m_hasVia
=
false
;
m_affectedRangeStart
=
-
1
;
SetLayer
(
aLayer
);
SetLayer
(
aLayer
);
}
PNS_LINE
(
const
PNS_LINE
&
aOther
)
:
PNS_ITEM
(
aOther
),
m_line
(
aOther
.
m_line
),
m_width
(
aOther
.
m_width
)
PNS_LINE
(
const
PNS_LINE
&
aOther
)
:
PNS_ITEM
(
aOther
),
m_line
(
aOther
.
m_line
),
m_width
(
aOther
.
m_width
)
{
m_net
=
aOther
.
m_net
;
m_movable
=
aOther
.
m_movable
;
...
...
@@ -94,10 +96,10 @@ public:
* copies properties (net, layers from a base line), and replaces the shape
* by aLine
**/
PNS_LINE
(
const
PNS_LINE
&
aBase
,
const
SHAPE_LINE_CHAIN
&
aLine
)
:
PNS_ITEM
(
aBase
),
m_line
(
aLine
),
m_width
(
aBase
.
m_width
)
PNS_LINE
(
const
PNS_LINE
&
aBase
,
const
SHAPE_LINE_CHAIN
&
aLine
)
:
PNS_ITEM
(
aBase
),
m_line
(
aLine
),
m_width
(
aBase
.
m_width
)
{
m_net
=
aBase
.
m_net
;
m_layers
=
aBase
.
m_layers
;
...
...
@@ -106,64 +108,68 @@ public:
m_affectedRangeStart
=
-
1
;
}
~
PNS_LINE
()
~
PNS_LINE
()
{
if
(
m_segmentRefs
)
if
(
m_segmentRefs
)
delete
m_segmentRefs
;
};
virtual
PNS_LINE
*
Clone
()
const
;
virtual
PNS_LINE
*
Clone
()
const
;
///> clones the line without cloning the shape (just the properties - net, width, layers, etc.)
PNS_LINE
*
CloneProperties
()
const
;
///> clones the line without cloning the shape
///> (just the properties - net, width, layers, etc.)
PNS_LINE
*
CloneProperties
()
const
;
int
GetLayer
()
const
{
return
GetLayers
().
Start
();
}
///> Geometry accessors
void
SetShape
(
const
SHAPE_LINE_CHAIN
&
aLine
)
{
m_line
=
aLine
;
}
void
SetShape
(
const
SHAPE_LINE_CHAIN
&
aLine
)
{
m_line
=
aLine
;
}
const
SHAPE
*
GetShape
()
const
{
return
&
m_line
;
}
SHAPE_LINE_CHAIN
&
GetLine
()
{
return
m_line
;
}
const
SHAPE_LINE_CHAIN
&
GetCLine
()
const
{
return
m_line
;
}
///> Width accessors
void
SetWidth
(
int
aWidth
)
{
m_width
=
aWidth
;
}
int
GetWidth
()
const
{
return
m_width
;
}
int
GetWidth
()
const
{
return
m_width
;
}
///> Links a segment from a PNS_NODE to this line, making it owned by the node
void
LinkSegment
(
PNS_SEGMENT
*
aSeg
)
void
LinkSegment
(
PNS_SEGMENT
*
aSeg
)
{
if
(
!
m_segmentRefs
)
m_segmentRefs
=
new
std
::
vector
<
PNS_SEGMENT
*>
();
m_segmentRefs
->
push_back
(
aSeg
);
if
(
!
m_segmentRefs
)
m_segmentRefs
=
new
std
::
vector
<
PNS_SEGMENT
*>
();
m_segmentRefs
->
push_back
(
aSeg
);
}
///> Returns a list of segments from the owning node that constitute this line (or NULL if
///>
the line is loose)
///> Returns a list of segments from the owning node that constitute this
///> line (or NULL if
the line is loose)
LinkedSegments
*
GetLinkedSegments
()
{
return
m_segmentRefs
;
}
bool
ContainsSegment
(
PNS_SEGMENT
*
aSeg
)
const
bool
ContainsSegment
(
PNS_SEGMENT
*
aSeg
)
const
{
if
(
!
m_segmentRefs
)
if
(
!
m_segmentRefs
)
return
false
;
return
std
::
find
(
m_segmentRefs
->
begin
(),
m_segmentRefs
->
end
(),
aSeg
)
!=
m_segmentRefs
->
end
();
return
std
::
find
(
m_segmentRefs
->
begin
(),
m_segmentRefs
->
end
(),
aSeg
)
!=
m_segmentRefs
->
end
();
}
///> Returns this line, but clipped to the nearest obstacle along, to avoid collision.
const
PNS_LINE
ClipToNearestObstacle
(
PNS_NODE
*
aNode
)
const
;
///> Returns this line, but clipped to the nearest obstacle
///> along, to avoid collision.
const
PNS_LINE
ClipToNearestObstacle
(
PNS_NODE
*
aNode
)
const
;
///> DEPRECATED optimization functions (moved to PNS_OPTIMIZER)
bool
MergeObtuseSegments
();
bool
MergeSegments
();
///> Returns the number of corners of angles specified by mask aAngles.
int
CountCorners
(
int
aAngles
);
int
CountCorners
(
int
aAngles
);
///> Calculates a line thightly wrapping a convex hull of an obstacle object (aObstacle).
///> Calculates a line thightly wrapping a convex hull
///> of an obstacle object (aObstacle).
///> aPrePath = path from origin to the obstacle
///> aWalkaroundPath = path around the obstacle
///> aPostPath = past from obstacle till the end
...
...
@@ -179,13 +185,16 @@ public:
bool
aCw
)
const
;
bool
Walkaround
(
SHAPE_LINE_CHAIN
obstacle
,
SHAPE_LINE_CHAIN
&
pre
,
SHAPE_LINE_CHAIN
&
walk
,
SHAPE_LINE_CHAIN
&
post
,
bool
cw
)
const
;
bool
Walkaround
(
SHAPE_LINE_CHAIN
obstacle
,
SHAPE_LINE_CHAIN
&
pre
,
SHAPE_LINE_CHAIN
&
walk
,
SHAPE_LINE_CHAIN
&
post
,
bool
cw
)
const
;
void
Walkaround
(
const
SHAPE_LINE_CHAIN
&
aObstacle
,
SHAPE_LINE_CHAIN
&
aPath
,
bool
aCw
)
const
;
bool
Is45Degree
();
///> Prints out all linked segments
...
...
@@ -193,34 +202,37 @@ public:
bool
EndsWithVia
()
const
{
return
m_hasVia
;
}
void
AppendVia
(
const
PNS_VIA
&
aVia
)
{
void
AppendVia
(
const
PNS_VIA
&
aVia
)
{
m_hasVia
=
true
;
m_via
=
aVia
;
m_via
.
SetNet
(
m_net
)
;
m_via
.
SetNet
(
m_net
)
;
}
void
RemoveVia
()
{
m_hasVia
=
false
;
}
const
PNS_VIA
&
GetVia
()
const
{
return
m_via
;
}
void
SetAffectedRange
(
int
aStart
,
int
aEnd
)
void
SetAffectedRange
(
int
aStart
,
int
aEnd
)
{
m_affectedRangeStart
=
aStart
;
m_affectedRangeEnd
=
aEnd
;
}
void
ClearAffectedRange
(
)
void
ClearAffectedRange
(
)
{
m_affectedRangeStart
=
-
1
;
}
bool
GetAffectedRange
(
int
&
aStart
,
int
&
aEnd
)
bool
GetAffectedRange
(
int
&
aStart
,
int
&
aEnd
)
{
if
(
m_affectedRangeStart
>=
0
)
if
(
m_affectedRangeStart
>=
0
)
{
aStart
=
m_affectedRangeStart
;
aEnd
=
m_affectedRangeEnd
;
return
true
;
}
else
{
}
else
{
aStart
=
0
;
aEnd
=
m_line
.
PointCount
();
return
false
;
...
...
@@ -228,8 +240,9 @@ public:
}
private
:
bool
onEdge
(
const
SHAPE_LINE_CHAIN
&
obstacle
,
VECTOR2I
p
,
int
&
ei
,
bool
&
is_vertex
)
const
;
bool
walkScan
(
const
SHAPE_LINE_CHAIN
&
line
,
const
SHAPE_LINE_CHAIN
&
obstacle
,
bool
reverse
,
VECTOR2I
&
ip
,
int
&
index_o
,
int
&
index_l
,
bool
&
is_vertex
)
const
;
bool
onEdge
(
const
SHAPE_LINE_CHAIN
&
obstacle
,
VECTOR2I
p
,
int
&
ei
,
bool
&
is_vertex
)
const
;
bool
walkScan
(
const
SHAPE_LINE_CHAIN
&
line
,
const
SHAPE_LINE_CHAIN
&
obstacle
,
bool
reverse
,
VECTOR2I
&
ip
,
int
&
index_o
,
int
&
index_l
,
bool
&
is_vertex
)
const
;
///> List of semgments in a PNS_NODE (PNS_ITEM::m_owner) that constitute this line.
LinkedSegments
*
m_segmentRefs
;
...
...
@@ -238,6 +251,7 @@ private:
SHAPE_LINE_CHAIN
m_line
;
int
m_width
;
///> Via at the end and a flag indicating if it's enabled.
PNS_VIA
m_via
;
bool
m_hasVia
;
...
...
@@ -246,6 +260,5 @@ private:
int
m_affectedRangeEnd
;
};
#endif // __PNS_LINE_H
pcbnew/router/pns_line_placer.cpp
View file @
5598acb6
...
...
@@ -33,9 +33,9 @@
using
namespace
std
;
using
boost
::
optional
;
PNS_LINE_PLACER
::
PNS_LINE_PLACER
(
PNS_NODE
*
aWorld
)
PNS_LINE_PLACER
::
PNS_LINE_PLACER
(
PNS_NODE
*
aWorld
)
{
m_initial_direction
=
DIRECTION_45
(
DIRECTION_45
::
N
);
m_initial_direction
=
DIRECTION_45
(
DIRECTION_45
::
N
);
m_follow_mouse
=
false
;
m_smoothing_step
=
100000
;
m_smooth_mouse
=
false
;
...
...
@@ -46,13 +46,15 @@ PNS_LINE_PLACER::PNS_LINE_PLACER( PNS_NODE *aWorld )
m_shove
=
NULL
;
};
PNS_LINE_PLACER
::~
PNS_LINE_PLACER
()
{
if
(
m_shove
)
if
(
m_shove
)
delete
m_shove
;
}
void
PNS_LINE_PLACER
::
ApplySettings
(
const
PNS_ROUTING_SETTINGS
&
aSettings
)
void
PNS_LINE_PLACER
::
ApplySettings
(
const
PNS_ROUTING_SETTINGS
&
aSettings
)
{
m_follow_mouse
=
aSettings
.
m_followMouse
;
m_mode
=
aSettings
.
m_routingMode
;
...
...
@@ -60,44 +62,42 @@ void PNS_LINE_PLACER::ApplySettings ( const PNS_ROUTING_SETTINGS& aSettings )
m_smartPads
=
aSettings
.
m_smartPads
;
}
void
PNS_LINE_PLACER
::
StartPlacement
(
const
VECTOR2I
&
aStart
,
int
aNet
,
int
aWidth
,
int
aLayer
)
void
PNS_LINE_PLACER
::
StartPlacement
(
const
VECTOR2I
&
aStart
,
int
aNet
,
int
aWidth
,
int
aLayer
)
{
m_direction
=
m_initial_direction
;
TRACE
(
1
,
"world %p, intitial-direction %s layer %d
\n
"
,
m_world
%
m_direction
.
Format
().
c_str
()
%
aLayer
);
m_head
.
SetNet
(
aNet
);
m_tail
.
SetNet
(
aNet
);
m_head
.
SetWidth
(
aWidth
);
m_tail
.
SetWidth
(
aWidth
);
TRACE
(
1
,
"world %p, intitial-direction %s layer %d
\n
"
,
m_world
%
m_direction
.
Format
().
c_str
()
%
aLayer
);
m_head
.
SetNet
(
aNet
);
m_tail
.
SetNet
(
aNet
);
m_head
.
SetWidth
(
aWidth
);
m_tail
.
SetWidth
(
aWidth
);
m_head
.
GetLine
().
Clear
();
m_tail
.
GetLine
().
Clear
();
m_head
.
SetLayer
(
aLayer
);
m_tail
.
SetLayer
(
aLayer
);
m_head
.
SetLayer
(
aLayer
);
m_tail
.
SetLayer
(
aLayer
);
m_iteration
=
0
;
m_p_start
=
aStart
;
m_currentNode
=
m_world
->
Branch
();
m_head
.
SetWorld
(
m_currentNode
);
m_tail
.
SetWorld
(
m_currentNode
);
//
if(m_shove)
m_head
.
SetWorld
(
m_currentNode
);
m_tail
.
SetWorld
(
m_currentNode
);
//
if(m_shove)
// delete m_shove;
m_shove
=
new
PNS_SHOVE
(
m_currentNode
);
m_shove
=
new
PNS_SHOVE
(
m_currentNode
);
m_placingVia
=
false
;
}
void
PNS_LINE_PLACER
::
SetInitialDirection
(
const
DIRECTION_45
&
aDirection
)
void
PNS_LINE_PLACER
::
SetInitialDirection
(
const
DIRECTION_45
&
aDirection
)
{
m_initial_direction
=
aDirection
;
if
(
m_tail
.
GetCLine
().
SegmentCount
()
==
0
)
if
(
m_tail
.
GetCLine
().
SegmentCount
()
==
0
)
m_direction
=
aDirection
;
}
/**
* Function handleSelfIntersections()
*
* Checks if the head of the track intersects its tail. If so, cuts the tail up to the
* intersecting segment and fixes the head direction to match the last segment before the cut.
* @return true if the line has been changed.
*/
bool
PNS_LINE_PLACER
::
handleSelfIntersections
()
{
SHAPE_LINE_CHAIN
::
Intersections
ips
;
...
...
@@ -105,13 +105,13 @@ bool PNS_LINE_PLACER::handleSelfIntersections()
SHAPE_LINE_CHAIN
&
tail
=
m_tail
.
GetLine
();
// if there is no tail, there is nothing to intersect with
if
(
tail
.
PointCount
()
<
2
)
if
(
tail
.
PointCount
()
<
2
)
return
false
;
tail
.
Intersect
(
head
,
ips
);
tail
.
Intersect
(
head
,
ips
);
// no intesection points - nothing to reduce
if
(
ips
.
empty
()
)
if
(
ips
.
empty
()
)
return
false
;
int
n
=
INT_MAX
;
...
...
@@ -119,9 +119,9 @@ bool PNS_LINE_PLACER::handleSelfIntersections()
// if there is more than one intersection, find the one that is
// closest to the beginning of the tail.
BOOST_FOREACH
(
SHAPE_LINE_CHAIN
::
Intersection
i
,
ips
)
BOOST_FOREACH
(
SHAPE_LINE_CHAIN
::
Intersection
i
,
ips
)
{
if
(
i
.
our
.
Index
()
<
n
)
if
(
i
.
our
.
Index
()
<
n
)
{
n
=
i
.
our
.
Index
();
ipoint
=
i
.
p
;
...
...
@@ -129,37 +129,34 @@ bool PNS_LINE_PLACER::handleSelfIntersections()
}
// ignore the point where head and tail meet
if
(
ipoint
==
head
.
CPoint
(
0
)
||
ipoint
==
tail
.
CPoint
(
-
1
)
)
if
(
ipoint
==
head
.
CPoint
(
0
)
||
ipoint
==
tail
.
CPoint
(
-
1
)
)
return
false
;
// Intersection point is on the first or the second segment: just start routing
// from the beginning
if
(
n
<
2
)
if
(
n
<
2
)
{
m_p_start
=
tail
.
Point
(
0
);
m_p_start
=
tail
.
Point
(
0
);
m_direction
=
m_initial_direction
;
tail
.
Clear
();
head
.
Clear
();
return
true
;
}
else
{
}
else
{
// Clip till the last tail segment before intersection.
// Set the direction to the one of this segment.
const
SEG
last
=
tail
.
CSegment
(
n
-
1
);
const
SEG
last
=
tail
.
CSegment
(
n
-
1
);
m_p_start
=
last
.
a
;
m_direction
=
DIRECTION_45
(
last
);
tail
.
Remove
(
n
,
-
1
);
m_direction
=
DIRECTION_45
(
last
);
tail
.
Remove
(
n
,
-
1
);
return
true
;
}
return
false
;
}
/**
* Function handlePullback()
*
* Deals with pull-back: reduces the tail if head trace is moved backwards wrs
* to the current tail direction.
* @return true if the line has been changed.
*/
bool
PNS_LINE_PLACER
::
handlePullback
()
{
SHAPE_LINE_CHAIN
&
head
=
m_head
.
GetLine
();
...
...
@@ -167,43 +164,45 @@ bool PNS_LINE_PLACER::handlePullback()
int
n
=
tail
.
PointCount
();
if
(
n
==
0
)
if
(
n
==
0
)
return
false
;
else
if
(
n
==
1
)
else
if
(
n
==
1
)
{
m_p_start
=
tail
.
CPoint
(
0
);
m_p_start
=
tail
.
CPoint
(
0
);
tail
.
Clear
();
return
true
;
}
DIRECTION_45
first_head
(
head
.
Segment
(
0
)
);
DIRECTION_45
last_tail
(
tail
.
Segment
(
-
1
)
);
DIRECTION_45
::
AngleType
angle
=
first_head
.
Angle
(
last_tail
);
DIRECTION_45
first_head
(
head
.
Segment
(
0
)
);
DIRECTION_45
last_tail
(
tail
.
Segment
(
-
1
)
);
DIRECTION_45
::
AngleType
angle
=
first_head
.
Angle
(
last_tail
);
// case 1: we have a defined routing direction, and the currently computed head
// goes in different one.
bool
pullback_1
=
false
;
//
(m_direction != DIRECTION_45::UNDEFINED && m_direction != first_head);
// case 1: we have a defined routing direction, and the currently computed
// head goes in different one.
bool
pullback_1
=
false
;
//
(m_direction != DIRECTION_45::UNDEFINED && m_direction != first_head);
// case 2: regardless of the current routing direction, if the tail/head extremities form
// an acute or right angle, reduce the tail by one segment (and hope that further iterations)
// will result with a cleaner trace
bool
pullback_2
=
(
angle
==
DIRECTION_45
::
ANG_RIGHT
||
angle
==
DIRECTION_45
::
ANG_ACUTE
);
// case 2: regardless of the current routing direction, if the tail/head
// extremities form an acute or right angle, reduce the tail by one segment
// (and hope that further iterations) will result with a cleaner trace
bool
pullback_2
=
(
angle
==
DIRECTION_45
::
ANG_RIGHT
||
angle
==
DIRECTION_45
::
ANG_ACUTE
);
if
(
pullback_1
||
pullback_2
)
if
(
pullback_1
||
pullback_2
)
{
const
SEG
last
=
tail
.
CSegment
(
-
1
);
m_direction
=
DIRECTION_45
(
last
);
const
SEG
last
=
tail
.
CSegment
(
-
1
);
m_direction
=
DIRECTION_45
(
last
);
m_p_start
=
last
.
a
;
TRACE
(
0
,
"Placer: pullback triggered [%d] [%s %s]"
,
n
%
last_tail
.
Format
().
c_str
()
%
first_head
.
Format
().
c_str
()
);
TRACE
(
0
,
"Placer: pullback triggered [%d] [%s %s]"
,
n
%
last_tail
.
Format
().
c_str
()
%
first_head
.
Format
().
c_str
());
// erase the last point in the tail, hoping that the next iteration will result with a head
// trace that starts with a segment following our current direction.
if
(
n
<
2
)
// erase the last point in the tail, hoping that the next iteration will
// result with a head trace that starts with a segment following our
// current direction.
if
(
n
<
2
)
tail
.
Clear
();
// don't leave a single-point tail
else
tail
.
Remove
(
-
1
,
-
1
);
tail
.
Remove
(
-
1
,
-
1
);
if
(
!
tail
.
SegmentCount
()
)
m_direction
=
m_initial_direction
;
...
...
@@ -214,15 +213,8 @@ bool PNS_LINE_PLACER::handlePullback()
return
false
;
}
/**
* Function reduceTail()
*
* Attempts to reduce the numer of segments in the tail by trying to replace a certain number
* of latest tail segments with a direct trace leading to aEnd that does not collide with anything.
* @param aEnd: current routing destination point.
* @return true if the line has been changed.
*/
bool
PNS_LINE_PLACER
::
reduceTail
(
const
VECTOR2I
&
aEnd
)
bool
PNS_LINE_PLACER
::
reduceTail
(
const
VECTOR2I
&
aEnd
)
{
SHAPE_LINE_CHAIN
&
head
=
m_head
.
GetLine
();
SHAPE_LINE_CHAIN
&
tail
=
m_tail
.
GetLine
();
...
...
@@ -230,32 +222,33 @@ bool PNS_LINE_PLACER::reduceTail(const VECTOR2I& aEnd)
int
n
=
tail
.
SegmentCount
();
// Don't attempt this for too short tails
if
(
n
<
2
)
if
(
n
<
2
)
return
false
;
// Start from the segment farthest from the end of the tail
//int start_index = std::max(n - 1 - ReductionDepth, 0);
// int start_index = std::max(n - 1 - ReductionDepth, 0);
DIRECTION_45
new_direction
;
VECTOR2I
new_start
;
int
reduce_index
=
-
1
;
DIRECTION_45
head_dir
(
head
.
Segment
(
0
)
);
DIRECTION_45
head_dir
(
head
.
Segment
(
0
)
);
for
(
int
i
=
tail
.
SegmentCount
()
-
1
;
i
>=
0
;
i
--
)
for
(
int
i
=
tail
.
SegmentCount
()
-
1
;
i
>=
0
;
i
--
)
{
const
SEG
s
=
tail
.
CSegment
(
i
);
DIRECTION_45
dir
(
s
);
const
SEG
s
=
tail
.
CSegment
(
i
);
DIRECTION_45
dir
(
s
);
// calculate a replacement route and check if it matches the direction of the segment to be replaced
SHAPE_LINE_CHAIN
replacement
=
dir
.
BuildInitialTrace
(
s
.
a
,
aEnd
);
// calculate a replacement route and check if it matches
// the direction of the segment to be replaced
SHAPE_LINE_CHAIN
replacement
=
dir
.
BuildInitialTrace
(
s
.
a
,
aEnd
);
PNS_LINE
tmp
(
m_tail
,
replacement
);
PNS_LINE
tmp
(
m_tail
,
replacement
);
if
(
m_currentNode
->
CheckColliding
(
&
tmp
,
PNS_ITEM
::
ANY
)
)
if
(
m_currentNode
->
CheckColliding
(
&
tmp
,
PNS_ITEM
::
ANY
)
)
break
;
if
(
DIRECTION_45
(
replacement
.
Segment
(
0
))
==
dir
)
if
(
DIRECTION_45
(
replacement
.
Segment
(
0
)
)
==
dir
)
{
new_start
=
s
.
a
;
new_direction
=
dir
;
...
...
@@ -263,15 +256,14 @@ bool PNS_LINE_PLACER::reduceTail(const VECTOR2I& aEnd)
}
}
if
(
reduce_index
>=
0
)
if
(
reduce_index
>=
0
)
{
TRACE
(
0
,
"Placer: reducing tail: %d"
,
reduce_index
);
SHAPE_LINE_CHAIN
reducedLine
=
new_direction
.
BuildInitialTrace
(
new_start
,
aEnd
);
TRACE
(
0
,
"Placer: reducing tail: %d"
,
reduce_index
);
SHAPE_LINE_CHAIN
reducedLine
=
new_direction
.
BuildInitialTrace
(
new_start
,
aEnd
);
m_p_start
=
new_start
;
m_direction
=
new_direction
;
tail
.
Remove
(
reduce_index
+
1
,
-
1
);
tail
.
Remove
(
reduce_index
+
1
,
-
1
);
head
.
Clear
();
return
true
;
}
...
...
@@ -283,32 +275,23 @@ bool PNS_LINE_PLACER::reduceTail(const VECTOR2I& aEnd)
}
/**
* Function checkObtusity()
*
* Helper that checks if segments a and b form an obtuse angle (in 45-degree regime).
* @return true, if angle (a, b) is obtuse
*/
bool
PNS_LINE_PLACER
::
checkObtusity
(
const
SEG
&
a
,
const
SEG
&
b
)
const
bool
PNS_LINE_PLACER
::
checkObtusity
(
const
SEG
&
a
,
const
SEG
&
b
)
const
{
const
DIRECTION_45
dir_a
(
a
);
const
DIRECTION_45
dir_b
(
b
);
return
dir_a
.
IsObtuse
(
dir_b
)
||
dir_a
==
dir_b
;
const
DIRECTION_45
dir_a
(
a
);
const
DIRECTION_45
dir_b
(
b
);
return
dir_a
.
IsObtuse
(
dir_b
)
||
dir_a
==
dir_b
;
}
/**
* Function mergeHead()
*
* Moves "estabished" segments from the head to the tail if certain conditions are met.
* @return true, if the line has been changed.
*/
bool
PNS_LINE_PLACER
::
mergeHead
()
{
SHAPE_LINE_CHAIN
&
head
=
m_head
.
GetLine
();
SHAPE_LINE_CHAIN
&
tail
=
m_tail
.
GetLine
();
const
int
ForbiddenAngles
=
DIRECTION_45
::
ANG_ACUTE
|
DIRECTION_45
::
ANG_HALF_FULL
|
DIRECTION_45
::
ANG_UNDEFINED
;
const
int
ForbiddenAngles
=
DIRECTION_45
::
ANG_ACUTE
|
DIRECTION_45
::
ANG_HALF_FULL
|
DIRECTION_45
::
ANG_UNDEFINED
;
head
.
Simplify
();
tail
.
Simplify
();
...
...
@@ -318,50 +301,49 @@ bool PNS_LINE_PLACER::mergeHead()
if
(
n_head
<
3
)
{
TRACEn
(
4
,
"Merge failed: not enough head segs."
);
TRACEn
(
4
,
"Merge failed: not enough head segs."
);
return
false
;
}
if
(
n_tail
&&
head
.
CPoint
(
0
)
!=
tail
.
CPoint
(
-
1
)
)
if
(
n_tail
&&
head
.
CPoint
(
0
)
!=
tail
.
CPoint
(
-
1
)
)
{
TRACEn
(
4
,
"Merge failed: head and tail discontinuous."
);
TRACEn
(
4
,
"Merge failed: head and tail discontinuous."
);
return
false
;
}
if
(
m_head
.
CountCorners
(
ForbiddenAngles
)
!=
0
)
if
(
m_head
.
CountCorners
(
ForbiddenAngles
)
!=
0
)
return
false
;
DIRECTION_45
dir_tail
,
dir_head
;
dir_head
=
DIRECTION_45
(
head
.
CSegment
(
0
)
);
dir_head
=
DIRECTION_45
(
head
.
CSegment
(
0
)
);
if
(
n_tail
)
if
(
n_tail
)
{
dir_tail
=
DIRECTION_45
(
tail
.
CSegment
(
-
1
));
if
(
dir_head
.
Angle
(
dir_tail
)
&
ForbiddenAngles
)
dir_tail
=
DIRECTION_45
(
tail
.
CSegment
(
-
1
)
);
if
(
dir_head
.
Angle
(
dir_tail
)
&
ForbiddenAngles
)
return
false
;
}
if
(
!
n_tail
)
tail
.
Append
(
head
.
CSegment
(
0
).
a
);
if
(
!
n_tail
)
tail
.
Append
(
head
.
CSegment
(
0
).
a
);
for
(
int
i
=
0
;
i
<
n_head
-
2
;
i
++
)
for
(
int
i
=
0
;
i
<
n_head
-
2
;
i
++
)
{
tail
.
Append
(
head
.
CSegment
(
i
).
b
);
tail
.
Append
(
head
.
CSegment
(
i
).
b
);
}
tail
.
Simplify
();
SEG
last
=
tail
.
CSegment
(
-
1
);
SEG
last
=
tail
.
CSegment
(
-
1
);
m_p_start
=
last
.
b
;
m_direction
=
DIRECTION_45
(
last
).
Right
();
head
.
Remove
(
0
,
n_head
-
2
);
m_direction
=
DIRECTION_45
(
last
).
Right
();
TRACE
(
0
,
"Placer: merge %d, new direction: %s"
,
n_head
%
m_direction
.
Format
().
c_str
()
);
head
.
Remove
(
0
,
n_head
-
2
);
TRACE
(
0
,
"Placer: merge %d, new direction: %s"
,
n_head
%
m_direction
.
Format
().
c_str
()
);
head
.
Simplify
();
tail
.
Simplify
();
...
...
@@ -369,185 +351,177 @@ bool PNS_LINE_PLACER::mergeHead()
return
true
;
}
bool
PNS_LINE_PLACER
::
handleViaPlacement
(
PNS_LINE
&
aHead
)
bool
PNS_LINE_PLACER
::
handleViaPlacement
(
PNS_LINE
&
aHead
)
{
if
(
!
m_placingVia
)
if
(
!
m_placingVia
)
return
true
;
PNS_LAYERSET
allLayers
(
0
,
15
);
PNS_VIA
v
(
aHead
.
GetCLine
().
CPoint
(
-
1
),
allLayers
,
m_viaDiameter
,
aHead
.
GetNet
()
);
v
.
SetDrill
(
m_viaDrill
);
PNS_LAYERSET
allLayers
(
0
,
15
);
PNS_VIA
v
(
aHead
.
GetCLine
().
CPoint
(
-
1
),
allLayers
,
m_viaDiameter
,
aHead
.
GetNet
()
);
v
.
SetDrill
(
m_viaDrill
);
VECTOR2I
force
;
VECTOR2I
lead
=
aHead
.
GetCLine
().
CPoint
(
-
1
)
-
aHead
.
GetCLine
().
CPoint
(
0
);
VECTOR2I
lead
=
aHead
.
GetCLine
().
CPoint
(
-
1
)
-
aHead
.
GetCLine
().
CPoint
(
0
);
if
(
v
.
PushoutForce
(
m_shove
->
GetCurrentNode
(),
lead
,
force
,
true
,
20
)
)
if
(
v
.
PushoutForce
(
m_shove
->
GetCurrentNode
(),
lead
,
force
,
true
,
20
)
)
{
SHAPE_LINE_CHAIN
line
=
m_direction
.
BuildInitialTrace
(
aHead
.
GetCLine
().
CPoint
(
0
),
aHead
.
GetCLine
().
CPoint
(
-
1
)
+
force
);
aHead
=
PNS_LINE
(
aHead
,
line
);
SHAPE_LINE_CHAIN
line
=
m_direction
.
BuildInitialTrace
(
aHead
.
GetCLine
().
CPoint
(
0
),
aHead
.
GetCLine
().
CPoint
(
-
1
)
+
force
);
aHead
=
PNS_LINE
(
aHead
,
line
);
v
.
SetPos
(
v
.
GetPos
()
+
force
);
v
.
SetPos
(
v
.
GetPos
()
+
force
);
return
true
;
}
return
false
;
}
/**
* Function routeHead()
*
* Computes the head trace between the current start point (m_p_start) and point aP,
* starting with direction defined in m_direction. The trace walks around all
* colliding solid or non-movable items. Movable segments are ignored, as they'll be handled
* later by the shove algorithm.
*/
bool
PNS_LINE_PLACER
::
routeHead
(
const
VECTOR2I
&
aP
,
PNS_LINE
&
aNewHead
,
bool
aCwWalkaround
)
bool
PNS_LINE_PLACER
::
routeHead
(
const
VECTOR2I
&
aP
,
PNS_LINE
&
aNewHead
,
bool
aCwWalkaround
)
{
// STAGE 1: route a simple two-segment trace between m_p_start and aP...
SHAPE_LINE_CHAIN
line
=
m_direction
.
BuildInitialTrace
(
m_p_start
,
aP
);
SHAPE_LINE_CHAIN
line
=
m_direction
.
BuildInitialTrace
(
m_p_start
,
aP
);
PNS_LINE
initTrack
(
m_head
,
line
);
PNS_LINE
initTrack
(
m_head
,
line
);
PNS_LINE
walkFull
,
walkSolids
;
if
(
m_mode
==
RM_Ignore
)
if
(
m_mode
==
RM_Ignore
)
{
aNewHead
=
initTrack
;
return
true
;
}
handleViaPlacement
(
initTrack
);
handleViaPlacement
(
initTrack
);
m_currentNode
=
m_shove
->
GetCurrentNode
();
PNS_OPTIMIZER
optimizer
(
m_currentNode
);
PNS_OPTIMIZER
optimizer
(
m_currentNode
);
PNS_WALKAROUND
walkaround
(
m_currentNode
);
walkaround
.
SetSolidsOnly
(
false
);
walkaround
.
SetIterationLimit
(
m_mode
==
RM_Walkaround
?
8
:
5
);
//
walkaround.SetApproachCursor(true, aP);
walkaround
.
SetSolidsOnly
(
false
);
walkaround
.
SetIterationLimit
(
m_mode
==
RM_Walkaround
?
8
:
5
);
//
walkaround.SetApproachCursor(true, aP);
PNS_WALKAROUND
::
WalkaroundStatus
wf
=
walkaround
.
Route
(
initTrack
,
walkFull
);
PNS_WALKAROUND
::
WalkaroundStatus
wf
=
walkaround
.
Route
(
initTrack
,
walkFull
);
#if 0
if(m_mode == RM_Walkaround
)
if( m_mode == RM_Walkaround
)
{
// walkaround.
// PNSDisplayDebugLine (walkFull.GetCLine(), 4);
if(wf == PNS_WALKAROUND::STUCK
)
if( wf == PNS_WALKAROUND::STUCK
)
{
aNewHead = m_head;
aNewHead.SetShape(walkFull.GetCLine()
);
aNewHead = aNewHead.ClipToNearestObstacle(m_currentNode
);
aNewHead.SetShape( walkFull.GetCLine()
);
aNewHead = aNewHead.ClipToNearestObstacle( m_currentNode
);
return false;
}
aNewHead = m_head;
aNewHead.SetShape(walkFull.GetCLine()
);
aNewHead.SetShape( walkFull.GetCLine()
);
// printf("nh w %d l %d\n", aNewHead.GetWidth(), aNewHead.GetLayers().Start());
return true;
}
#endif
PNS_COST_ESTIMATOR
cost_walk
,
cost_orig
;
walkaround
.
SetApproachCursor
(
false
,
aP
);
walkaround
.
SetSolidsOnly
(
true
);
walkaround
.
SetApproachCursor
(
false
,
aP
);
walkaround
.
SetSolidsOnly
(
true
);
walkaround
.
SetIterationLimit
(
10
);
PNS_WALKAROUND
::
WalkaroundStatus
stat_solids
=
walkaround
.
Route
(
initTrack
,
walkSolids
);
PNS_WALKAROUND
::
WalkaroundStatus
stat_solids
=
walkaround
.
Route
(
initTrack
,
walkSolids
);
optimizer
.
SetEffortLevel
(
PNS_OPTIMIZER
::
MERGE_SEGMENTS
);
optimizer
.
SetCollisionMask
(
PNS_ITEM
::
SOLID
);
optimizer
.
Optimize
(
&
walkSolids
);
optimizer
.
SetEffortLevel
(
PNS_OPTIMIZER
::
MERGE_SEGMENTS
);
optimizer
.
SetCollisionMask
(
PNS_ITEM
::
SOLID
);
optimizer
.
Optimize
(
&
walkSolids
);
#if 0
optimizer.SetCollisionMask (-1
);
optimizer.Optimize(&walkFull
);
optimizer.SetCollisionMask( -1
);
optimizer.Optimize( &walkFull
);
#endif
cost_orig
.
Add
(
initTrack
);
cost_walk
.
Add
(
walkFull
);
cost_orig
.
Add
(
initTrack
);
cost_walk
.
Add
(
walkFull
);
if
(
m_mode
==
RM_Smart
||
m_mode
==
RM_Shove
)
if
(
m_mode
==
RM_Smart
||
m_mode
==
RM_Shove
)
{
PNS_LINE
l2
;
bool
walk_better
=
cost_orig
.
IsBetter
(
cost_walk
,
1.5
,
10.0
);
bool
walk_better
=
cost_orig
.
IsBetter
(
cost_walk
,
1.5
,
10.0
);
walk_better
=
false
;
#if 0
printf("RtTrk width %d %d %d", initTrack.GetWidth(), walkFull.GetWidth(), walkSolids.GetWidth());
printf("init-coll %d\n", m_currentNode->CheckColliding(&initTrack)? 1: 0);
printf("total cost: walk cor %.0f len %.0f orig cor %.0f len %.0f walk-better %d\n",
printf( "RtTrk width %d %d %d", initTrack.GetWidth(),
walkFull.GetWidth(), walkSolids.GetWidth() );
printf( "init-coll %d\n", m_currentNode->CheckColliding( &initTrack ) ? 1 : 0 );
printf( "total cost: walk cor %.0f len %.0f orig cor %.0f len %.0f walk-better %d\n",
cost_walk.GetCornerCost(), cost_walk.GetLengthCost(),
cost_orig.GetCornerCost(), cost_orig.GetLengthCost(),
walk_better );
#endif
if
(
m_mode
==
RM_Smart
&&
wf
==
PNS_WALKAROUND
::
DONE
&&
walk_better
&&
walkFull
.
GetCLine
().
CPoint
(
-
1
)
==
initTrack
.
GetCLine
().
CPoint
(
-
1
))
if
(
m_mode
==
RM_Smart
&&
wf
==
PNS_WALKAROUND
::
DONE
&&
walk_better
&&
walkFull
.
GetCLine
().
CPoint
(
-
1
)
==
initTrack
.
GetCLine
().
CPoint
(
-
1
)
)
l2
=
walkFull
;
else
if
(
stat_solids
==
PNS_WALKAROUND
::
DONE
)
else
if
(
stat_solids
==
PNS_WALKAROUND
::
DONE
)
l2
=
walkSolids
;
else
l2
=
initTrack
.
ClipToNearestObstacle
(
m_shove
->
GetCurrentNode
()
);
l2
=
initTrack
.
ClipToNearestObstacle
(
m_shove
->
GetCurrentNode
()
);
PNS_LINE
l
(
m_tail
);
PNS_LINE
l
(
m_tail
);
l
.
GetLine
().
Append
(
l2
.
GetCLine
()
);
l
.
GetLine
().
Simplify
();
if
(
m_placingVia
)
if
(
m_placingVia
)
{
PNS_LAYERSET
allLayers
(
0
,
15
);
PNS_VIA
v1
(
l
.
GetCLine
().
CPoint
(
-
1
),
allLayers
,
m_viaDiameter
);
PNS_VIA
v2
(
l2
.
GetCLine
().
CPoint
(
-
1
),
allLayers
,
m_viaDiameter
);
v1
.
SetDrill
(
m_viaDrill
);
v2
.
SetDrill
(
m_viaDrill
);
l
.
AppendVia
(
v1
);
l2
.
AppendVia
(
v2
);
PNS_LAYERSET
allLayers
(
0
,
15
);
PNS_VIA
v1
(
l
.
GetCLine
().
CPoint
(
-
1
),
allLayers
,
m_viaDiameter
);
PNS_VIA
v2
(
l2
.
GetCLine
().
CPoint
(
-
1
),
allLayers
,
m_viaDiameter
);
v1
.
SetDrill
(
m_viaDrill
);
v2
.
SetDrill
(
m_viaDrill
);
l
.
AppendVia
(
v1
);
l2
.
AppendVia
(
v2
);
}
PNS_SHOVE
::
ShoveStatus
status
=
m_shove
->
ShoveLines
(
&
l
);
PNS_SHOVE
::
ShoveStatus
status
=
m_shove
->
ShoveLines
(
&
l
);
m_currentNode
=
m_shove
->
GetCurrentNode
();
if
(
status
==
PNS_SHOVE
::
SH_OK
)
if
(
status
==
PNS_SHOVE
::
SH_OK
)
{
optimizer
.
SetWorld
(
m_currentNode
);
optimizer
.
SetWorld
(
m_currentNode
);
optimizer
.
ClearCache
();
optimizer
.
SetEffortLevel
(
PNS_OPTIMIZER
::
MERGE_OBTUSE
|
PNS_OPTIMIZER
::
SMART_PADS
);
optimizer
.
SetCollisionMask
(
-
1
);
optimizer
.
Optimize
(
&
l2
);
optimizer
.
SetCollisionMask
(
-
1
);
optimizer
.
Optimize
(
&
l2
);
aNewHead
=
l2
;
return
true
;
}
else
{
}
else
{
walkaround
.
SetWorld
(
m_currentNode
);
walkaround
.
SetSolidsOnly
(
false
);
walkaround
.
SetSolidsOnly
(
false
);
walkaround
.
SetIterationLimit
(
10
);
walkaround
.
SetApproachCursor
(
true
,
aP
);
walkaround
.
Route
(
initTrack
,
l2
);
aNewHead
=
l2
.
ClipToNearestObstacle
(
m_shove
->
GetCurrentNode
()
);
//
aNewHead = l2;
walkaround
.
SetApproachCursor
(
true
,
aP
);
walkaround
.
Route
(
initTrack
,
l2
);
aNewHead
=
l2
.
ClipToNearestObstacle
(
m_shove
->
GetCurrentNode
()
);
//
aNewHead = l2;
return
false
;
}
}
return
false
;
}
/**
* Function optimizeTailHeadTransition()
*
* Tries to reduce the corner count of the most recent part of tail/head by merging
* obtuse/collinear segments.
* @return true, if the line has been changed.
*/
bool
PNS_LINE_PLACER
::
optimizeTailHeadTransition
()
{
SHAPE_LINE_CHAIN
&
head
=
m_head
.
GetLine
();
...
...
@@ -555,37 +529,37 @@ bool PNS_LINE_PLACER::optimizeTailHeadTransition()
const
int
TailLookbackSegments
=
5
;
int
threshold
=
min
(
tail
.
PointCount
(),
TailLookbackSegments
+
1
);
int
threshold
=
min
(
tail
.
PointCount
(),
TailLookbackSegments
+
1
);
if
(
tail
.
SegmentCount
()
<
3
)
if
(
tail
.
SegmentCount
()
<
3
)
return
false
;
// assemble TailLookbackSegments tail segments with the current head
SHAPE_LINE_CHAIN
opt_line
=
tail
.
Slice
(
-
threshold
,
-
1
);
SHAPE_LINE_CHAIN
opt_line
=
tail
.
Slice
(
-
threshold
,
-
1
);
opt_line
.
Append
(
head
);
opt_line
.
Append
(
head
);
// opt_line.Simplify();
PNS_LINE
new_head
(
m_tail
,
opt_line
);
PNS_LINE
new_head
(
m_tail
,
opt_line
);
// and see if it could be made simpler by merging obtuse/collnear segments. If so,
// replace the (threshold) last tail points and the head with the optimized line
// and see if it could be made simpler by merging obtuse/collnear segments.
// If so, replace the (threshold) last tail points and the head with
// the optimized line
//
if(PNS_OPTIMIZER::Optimize(&new_head, PNS_OPTIMIZER::MERGE_SEGMENTS))
//
if(PNS_OPTIMIZER::Optimize(&new_head, PNS_OPTIMIZER::MERGE_SEGMENTS))
if
(
new_head
.
MergeSegments
())
if
(
new_head
.
MergeSegments
()
)
{
PNS_LINE
tmp
(
m_tail
,
opt_line
);
PNS_LINE
tmp
(
m_tail
,
opt_line
);
TRACE
(
0
,
"Placer: optimize tail-head [%d]"
,
threshold
);
TRACE
(
0
,
"Placer: optimize tail-head [%d]"
,
threshold
);
head
.
Clear
();
tail
.
Replace
(
-
threshold
,
-
1
,
new_head
.
GetCLine
()
);
tail
.
Replace
(
-
threshold
,
-
1
,
new_head
.
GetCLine
()
);
tail
.
Simplify
();
m_p_start
=
new_head
.
GetCLine
().
CPoint
(
-
1
);
m_direction
=
DIRECTION_45
(
new_head
.
GetCLine
().
CSegment
(
-
1
)
);
m_p_start
=
new_head
.
GetCLine
().
CPoint
(
-
1
);
m_direction
=
DIRECTION_45
(
new_head
.
GetCLine
().
CSegment
(
-
1
)
);
return
true
;
}
...
...
@@ -593,16 +567,8 @@ bool PNS_LINE_PLACER::optimizeTailHeadTransition()
return
false
;
}
/**
* Function routeStep()
*
* Performs a single routing alorithm step, for the end point aP.
* @param aP ending point of current route
* @return true, if the line has been changed.
*/
void
PNS_LINE_PLACER
::
routeStep
(
const
VECTOR2I
&
aP
)
void
PNS_LINE_PLACER
::
routeStep
(
const
VECTOR2I
&
aP
)
{
bool
fail
=
false
;
bool
go_back
=
false
;
...
...
@@ -613,77 +579,70 @@ void PNS_LINE_PLACER::routeStep(const VECTOR2I& aP)
m_follow_mouse
=
true
;
TRACE
(
2
,
"INIT-DIR: %s head: %d, tail: %d segs
\n
"
,
m_initial_direction
.
Format
().
c_str
()
%
m_head
.
GetCLine
().
SegmentCount
()
%
m_tail
.
GetCLine
().
SegmentCount
());
TRACE
(
2
,
"INIT-DIR: %s head: %d, tail: %d segs
\n
"
,
m_initial_direction
.
Format
().
c_str
()
%
m_head
.
GetCLine
().
SegmentCount
()
%
m_tail
.
GetCLine
().
SegmentCount
()
);
for
(
i
=
0
;
i
<
n_iter
;
i
++
)
for
(
i
=
0
;
i
<
n_iter
;
i
++
)
{
if
(
!
go_back
&&
m_follow_mouse
)
reduceTail
(
aP
);
if
(
!
go_back
&&
m_follow_mouse
)
reduceTail
(
aP
);
go_back
=
false
;
if
(
!
routeHead
(
aP
,
new_head
,
true
)
)
if
(
!
routeHead
(
aP
,
new_head
,
true
)
)
fail
=
true
;
if
(
!
new_head
.
Is45Degree
()
)
if
(
!
new_head
.
Is45Degree
()
)
fail
=
true
;
if
(
!
m_follow_mouse
)
if
(
!
m_follow_mouse
)
return
;
m_head
=
new_head
;
if
(
handleSelfIntersections
()
)
if
(
handleSelfIntersections
()
)
{
n_iter
++
;
go_back
=
true
;
}
if
(
!
go_back
&&
handlePullback
()
)
if
(
!
go_back
&&
handlePullback
()
)
{
n_iter
++
;
go_back
=
true
;
}
}
if
(
!
fail
)
if
(
!
fail
)
{
if
(
optimizeTailHeadTransition
()
)
if
(
optimizeTailHeadTransition
()
)
return
;
mergeHead
();
}
}
/**
* Function Route()
*
* Re-routes the current track to point aP. Returns true, when routing has completed
* successfully (i.e. the trace end has reached point aP), and false if the trace was stuck somewhere
* on the way. May call routeStep() repetitively due to mouse smoothing.
* @param aP ending point of current route.
* @return true, if the routing is complete.
*/
bool
PNS_LINE_PLACER
::
Route
(
const
VECTOR2I
&
aP
)
bool
PNS_LINE_PLACER
::
Route
(
const
VECTOR2I
&
aP
)
{
if
(
m_smooth_mouse
)
if
(
m_smooth_mouse
)
{
VECTOR2I
p_cur
=
m_p_start
;
VECTOR2I
step
=
(
aP
-
m_p_start
).
Resize
(
m_smoothing_step
);
VECTOR2I
step
=
(
aP
-
m_p_start
).
Resize
(
m_smoothing_step
);
do
{
if
((
p_cur
-
aP
).
EuclideanNorm
()
<=
m_smoothing_step
)
if
(
(
p_cur
-
aP
).
EuclideanNorm
()
<=
m_smoothing_step
)
p_cur
=
aP
;
else
p_cur
+=
step
;
routeStep
(
p_cur
);
}
while
(
p_cur
!=
aP
);
}
else
routeStep
(
aP
);
routeStep
(
p_cur
);
}
while
(
p_cur
!=
aP
);
}
else
routeStep
(
aP
);
return
CurrentEnd
()
==
aP
;
}
...
...
@@ -691,25 +650,31 @@ bool PNS_LINE_PLACER::Route(const VECTOR2I& aP)
const
PNS_LINE
PNS_LINE_PLACER
::
GetTrace
()
const
{
PNS_LINE
tmp
(
m_head
);
PNS_LINE
tmp
(
m_head
);
tmp
.
SetShape
(
m_tail
.
GetCLine
()
);
tmp
.
GetLine
().
Append
(
m_head
.
GetCLine
()
);
tmp
.
GetLine
().
Simplify
();
return
tmp
;
}
void
PNS_LINE_PLACER
::
FlipPosture
()
{
m_initial_direction
=
m_initial_direction
.
Right
();
m_direction
=
m_direction
.
Right
();
}
void
PNS_LINE_PLACER
::
GetUpdatedItems
(
PNS_NODE
::
ItemVector
&
aRemoved
,
PNS_NODE
::
ItemVector
&
aAdded
)
void
PNS_LINE_PLACER
::
GetUpdatedItems
(
PNS_NODE
::
ItemVector
&
aRemoved
,
PNS_NODE
::
ItemVector
&
aAdded
)
{
return
m_shove
->
GetCurrentNode
()
->
GetUpdatedItems
(
aRemoved
,
aAdded
);
return
m_shove
->
GetCurrentNode
()
->
GetUpdatedItems
(
aRemoved
,
aAdded
);
}
PNS_NODE
*
PNS_LINE_PLACER
::
GetCurrentNode
()
const
PNS_NODE
*
PNS_LINE_PLACER
::
GetCurrentNode
()
const
{
return
m_shove
->
GetCurrentNode
();
}
pcbnew/router/pns_line_placer.h
View file @
5598acb6
...
...
@@ -39,17 +39,18 @@ class PNS_ROUTER_BASE;
/**
* Class PNS_LINE_PLACER
*
* Interactively routes a single track. Runs shove and walkaround algorithms when needed.
* Interactively routes a single track. Runs shove and walkaround
* algorithms when needed.
*/
class
PNS_LINE_PLACER
{
public
:
PNS_LINE_PLACER
(
PNS_NODE
*
aWorld
);
public
:
PNS_LINE_PLACER
(
PNS_NODE
*
aWorld
);
~
PNS_LINE_PLACER
();
///> Appends a via at the end of currently placed line.
void
AddVia
(
bool
aEnabled
,
int
aDiameter
,
int
aDrill
)
void
AddVia
(
bool
aEnabled
,
int
aDiameter
,
int
aDrill
)
{
m_viaDiameter
=
aDiameter
;
m_viaDrill
=
aDrill
;
...
...
@@ -57,100 +58,198 @@ class PNS_LINE_PLACER
}
///> Starts placement of a line at point aStart.
void
StartPlacement
(
const
VECTOR2I
&
aStart
,
int
aNet
,
int
aWidth
,
int
aLayer
);
void
StartPlacement
(
const
VECTOR2I
&
aStart
,
int
aNet
,
int
aWidth
,
int
aLayer
);
///> Updates the routed line with a new ending point.
bool
Route
(
const
VECTOR2I
&
aP
);
/**
* Function Route()
*
* Re-routes the current track to point aP. Returns true, when routing has
* completed successfully (i.e. the trace end has reached point aP), and false
* if the trace was stuck somewhere on the way. May call routeStep()
* repetitively due to mouse smoothing.
* @param aP ending point of current route.
* @return true, if the routing is complete.
*/
bool
Route
(
const
VECTOR2I
&
aP
);
///> Sets initial routing direction/posture
void
SetInitialDirection
(
const
DIRECTION_45
&
aDirection
);
void
SetInitialDirection
(
const
DIRECTION_45
&
aDirection
);
void
ApplySettings
(
const
PNS_ROUTING_SETTINGS
&
aSettings
);
void
ApplySettings
(
const
PNS_ROUTING_SETTINGS
&
aSettings
);
///> Returns the "head" of the line being placed, that is the volatile part that has not been settled yet
///> Returns the "head" of the line being placed, that is the volatile part
///> that has not been settled yet
const
PNS_LINE
&
GetHead
()
const
{
return
m_head
;
}
///> Returns the "tail" of the line being placed the part that has been fixed already (follow mouse mode only)
///> Returns the "tail" of the line being placed the part that has been
///> fixed already (follow mouse mode only)
const
PNS_LINE
&
GetTail
()
const
{
return
m_tail
;
}
///> Returns the whole routed line
const
PNS_LINE
GetTrace
()
const
;
///> Returns the current end of the line being placed. It may not be equal to the cursor position due to collisions.
///> Returns the current end of the line being placed. It may not be equal
///> to the cursor position due to collisions.
const
VECTOR2I
&
CurrentEnd
()
const
{
if
(
m_head
.
GetCLine
().
PointCount
()
>
0
)
return
m_head
.
GetCLine
().
CPoint
(
-
1
);
else
if
(
m_tail
.
GetCLine
().
PointCount
()
>
0
)
return
m_tail
.
GetCLine
().
CPoint
(
-
1
);
if
(
m_head
.
GetCLine
().
PointCount
()
>
0
)
return
m_head
.
GetCLine
().
CPoint
(
-
1
);
else
if
(
m_tail
.
GetCLine
().
PointCount
()
>
0
)
return
m_tail
.
GetCLine
().
CPoint
(
-
1
);
else
return
m_p_start
;
}
///> Returns all items in the world that have been affected by the routing operation. Used
/// to update data structures of the host application
void
GetUpdatedItems
(
PNS_NODE
::
ItemVector
&
aRemoved
,
PNS_NODE
::
ItemVector
&
aAdded
);
///> Returns all items in the world that have been affected by the routing
///> operation. Used to update data structures of the host application
void
GetUpdatedItems
(
PNS_NODE
::
ItemVector
&
aRemoved
,
PNS_NODE
::
ItemVector
&
aAdded
);
///> Toggles the current posture (straight/diagonal) of the trace head.
void
FlipPosture
();
///> Returns the most recent world state
PNS_NODE
*
GetCurrentNode
()
const
;
private
:
PNS_NODE
*
GetCurrentNode
()
const
;
private
:
static
const
double
m_shoveLengthThreshold
=
1
.
7
;
bool
handleViaPlacement
(
PNS_LINE
&
aHead
);
bool
handleViaPlacement
(
PNS_LINE
&
aHead
);
/**
* Function checkObtusity()
*
* Helper that checks if segments a and b form an obtuse angle
* (in 45-degree regime).
* @return true, if angle (a, b) is obtuse
*/
bool
checkObtusity
(
const
SEG
&
a
,
const
SEG
&
b
)
const
;
bool
checkObtusity
(
const
SEG
&
a
,
const
SEG
&
b
)
const
;
/**
* Function handleSelfIntersections()
*
* Checks if the head of the track intersects its tail. If so, cuts the
* tail up to the intersecting segment and fixes the head direction to match
* the last segment before the cut.
* @return true if the line has been changed.
*/
bool
handleSelfIntersections
();
/**
* Function handlePullback()
*
* Deals with pull-back: reduces the tail if head trace is moved backwards
* wrs to the current tail direction.
* @return true if the line has been changed.
*/
bool
handlePullback
();
/**
* Function mergeHead()
*
* Moves "estabished" segments from the head to the tail if certain
* conditions are met.
* @return true, if the line has been changed.
*/
bool
mergeHead
();
bool
reduceTail
(
const
VECTOR2I
&
aEnd
);
/**
* Function reduceTail()
*
* Attempts to reduce the numer of segments in the tail by trying to replace a
* certain number of latest tail segments with a direct trace leading to aEnd
* that does not collide with anything.
* @param aEnd: current routing destination point.
* @return true if the line has been changed.
*/
bool
reduceTail
(
const
VECTOR2I
&
aEnd
);
void
fixHeadPosture
();
/**
* Function optimizeTailHeadTransition()
*
* Tries to reduce the corner count of the most recent part of tail/head by
* merging obtuse/collinear segments.
* @return true, if the line has been changed.
*/
bool
optimizeTailHeadTransition
();
bool
routeHead
(
const
VECTOR2I
&
aP
,
PNS_LINE
&
aNewHead
,
bool
aCwWalkaround
=
true
);
void
routeStep
(
const
VECTOR2I
&
aP
);
/**
* Function routeHead()
*
* Computes the head trace between the current start point (m_p_start) and
* point aP, starting with direction defined in m_direction. The trace walks
* around all colliding solid or non-movable items. Movable segments are
* ignored, as they'll be handled later by the shove algorithm.
*/
bool
routeHead
(
const
VECTOR2I
&
aP
,
PNS_LINE
&
aNewHead
,
bool
aCwWalkaround
=
true
);
/**
* Function routeStep()
*
* Performs a single routing alorithm step, for the end point aP.
* @param aP ending point of current route
* @return true, if the line has been changed.
*/
void
routeStep
(
const
VECTOR2I
&
aP
);
///> routing mode (walkaround, shove, etc.)
PNS_MODE
m_mode
;
///> follow mouse trail by attaching new segments to the head as the cursor moves
///> follow mouse trail by attaching new segments to the head
///> as the cursor moves
bool
m_follow_mouse
;
///> mouse smoothing active
bool
m_smooth_mouse
;
///> mouse smoothing step (in world units)
int
m_smoothing_step
;
///> current routing direction
DIRECTION_45
m_direction
;
///> routing direction for new traces
DIRECTION_45
m_initial_direction
;
///> routing "head": volatile part of the track from the previously
/// analyzed point to the current routing destination
PNS_LINE
m_head
;
///> routing "tail": part of the track that has been already fixed due to collisions with obstacles
PNS_LINE
m_tail
;
///> current algorithm iteration
int
m_iteration
;
///> pointer to world to search colliding items
PNS_NODE
*
m_world
;
PNS_NODE
*
m_world
;
///> current routing start point (end of tail, beginning of head)
VECTOR2I
m_p_start
;
///> The shove engine
PNS_SHOVE
*
m_shove
;
PNS_SHOVE
*
m_shove
;
///> Current world state
PNS_NODE
*
m_currentNode
;
PNS_NODE
*
m_currentNode
;
///> Are we placing a via?
bool
m_placingVia
;
///> current via diameter
int
m_viaDiameter
;
///> current via drill
int
m_viaDrill
;
///> walkaround algorithm iteration limit
int
m_walkaroundIterationLimit
;
///> smart pads optimizer enabled.
bool
m_smartPads
;
};
#endif // __PNS_LINE_PLACER_H
pcbnew/router/pns_node.cpp
View file @
5598acb6
...
...
@@ -42,36 +42,38 @@ using namespace std;
using
boost
::
unordered_set
;
using
boost
::
unordered_map
;
static
boost
::
unordered_set
<
PNS_NODE
*>
allocNodes
;
static
boost
::
unordered_set
<
PNS_NODE
*>
allocNodes
;
PNS_NODE
::
PNS_NODE
()
{
//
printf("MakeNode [%p, total = %d]\n", this, allocNodes.size());
//
printf("MakeNode [%p, total = %d]\n", this, allocNodes.size());
m_root
=
this
;
m_parent
=
NULL
;
m_maxClearance
=
800000
;
// fixme: depends on how thick traces are.
m_index
=
new
PNS_INDEX
;
allocNodes
.
insert
(
this
);
allocNodes
.
insert
(
this
);
}
PNS_NODE
::~
PNS_NODE
()
{
if
(
!
m_children
.
empty
()
)
if
(
!
m_children
.
empty
()
)
{
TRACEn
(
0
,
"attempting to free a node that has kids.
\n
"
);
assert
(
false
);
TRACEn
(
0
,
"attempting to free a node that has kids.
\n
"
);
assert
(
false
);
}
if
(
allocNodes
.
find
(
this
)
==
allocNodes
.
end
()
)
if
(
allocNodes
.
find
(
this
)
==
allocNodes
.
end
()
)
{
TRACEn
(
0
,
"attempting to free an already-free'd node.
\n
"
);
assert
(
false
);
TRACEn
(
0
,
"attempting to free an already-free'd node.
\n
"
);
assert
(
false
);
}
allocNodes
.
erase
(
this
);
allocNodes
.
erase
(
this
);
for
(
PNS_INDEX
::
ItemSet
::
iterator
i
=
m_index
->
begin
();
i
!=
m_index
->
end
();
++
i
)
if
(
(
*
i
)
->
BelongsTo
(
this
))
for
(
PNS_INDEX
::
ItemSet
::
iterator
i
=
m_index
->
begin
();
i
!=
m_index
->
end
();
++
i
)
if
(
(
*
i
)
->
BelongsTo
(
this
)
)
delete
*
i
;
unlinkParent
();
...
...
@@ -79,174 +81,196 @@ PNS_NODE::~PNS_NODE()
}
int
PNS_NODE
::
GetClearance
(
const
PNS_ITEM
*
a
,
const
PNS_ITEM
*
b
)
const
int
PNS_NODE
::
GetClearance
(
const
PNS_ITEM
*
a
,
const
PNS_ITEM
*
b
)
const
{
int
clearance
=
(
*
m_clearanceFunctor
)
(
a
,
b
);
int
clearance
=
(
*
m_clearanceFunctor
)(
a
,
b
);
if
(
a
->
OfKind
(
PNS_ITEM
::
SEGMENT
)
)
clearance
+=
static_cast
<
const
PNS_SEGMENT
*>
(
a
)
->
GetWidth
()
/
2
;
if
(
a
->
OfKind
(
PNS_ITEM
::
SEGMENT
)
)
clearance
+=
static_cast
<
const
PNS_SEGMENT
*>
(
a
)
->
GetWidth
()
/
2
;
if
(
a
->
OfKind
(
PNS_ITEM
::
LINE
)
)
clearance
+=
static_cast
<
const
PNS_LINE
*>
(
a
)
->
GetWidth
()
/
2
;
if
(
a
->
OfKind
(
PNS_ITEM
::
LINE
)
)
clearance
+=
static_cast
<
const
PNS_LINE
*>
(
a
)
->
GetWidth
()
/
2
;
if
(
b
->
OfKind
(
PNS_ITEM
::
SEGMENT
)
)
clearance
+=
static_cast
<
const
PNS_SEGMENT
*>
(
b
)
->
GetWidth
()
/
2
;
if
(
b
->
OfKind
(
PNS_ITEM
::
SEGMENT
)
)
clearance
+=
static_cast
<
const
PNS_SEGMENT
*>
(
b
)
->
GetWidth
()
/
2
;
if
(
b
->
OfKind
(
PNS_ITEM
::
LINE
)
)
clearance
+=
static_cast
<
const
PNS_LINE
*>
(
b
)
->
GetWidth
()
/
2
;
if
(
b
->
OfKind
(
PNS_ITEM
::
LINE
)
)
clearance
+=
static_cast
<
const
PNS_LINE
*>
(
b
)
->
GetWidth
()
/
2
;
return
clearance
;
}
PNS_NODE
*
PNS_NODE
::
Branch
()
{
PNS_NODE
*
child
=
new
PNS_NODE
;
m_children
.
push_back
(
child
);
PNS_NODE
*
child
=
new
PNS_NODE
;
m_children
.
push_back
(
child
);
child
->
m_parent
=
this
;
child
->
m_clearanceFunctor
=
m_clearanceFunctor
;
child
->
m_root
=
isRoot
()
?
this
:
m_root
;
// immmediate offspring of the root branch needs not copy anything. For the rest,
// deep-copy joints, overridden item map and pointers to stored items.
if
(
!
isRoot
())
// immmediate offspring of the root branch needs not copy anything.
// For the rest, deep-copy joints, overridden item map and pointers
// to stored items.
if
(
!
isRoot
()
)
{
JointMap
::
iterator
j
;
for
(
PNS_INDEX
::
ItemSet
::
iterator
i
=
m_index
->
begin
();
i
!=
m_index
->
end
();
++
i
)
child
->
m_index
->
Add
(
*
i
);
for
(
PNS_INDEX
::
ItemSet
::
iterator
i
=
m_index
->
begin
();
i
!=
m_index
->
end
();
++
i
)
child
->
m_index
->
Add
(
*
i
);
child
->
m_joints
=
m_joints
;
child
->
m_override
=
m_override
;
}
TRACE
(
2
,
"%d items, %d joints, %d overrides"
,
child
->
m_index
->
Size
()
%
child
->
m_joints
.
size
()
%
child
->
m_override
.
size
());
TRACE
(
2
,
"%d items, %d joints, %d overrides"
,
child
->
m_index
->
Size
()
%
child
->
m_joints
.
size
()
%
child
->
m_override
.
size
()
);
return
child
;
}
void
PNS_NODE
::
unlinkParent
(
)
void
PNS_NODE
::
unlinkParent
()
{
if
(
isRoot
()
)
return
;
for
(
vector
<
PNS_NODE
*>::
iterator
i
=
m_parent
->
m_children
.
begin
();
i
!=
m_parent
->
m_children
.
end
();
++
i
)
for
(
vector
<
PNS_NODE
*>::
iterator
i
=
m_parent
->
m_children
.
begin
();
i
!=
m_parent
->
m_children
.
end
();
++
i
)
{
if
(
*
i
==
this
)
if
(
*
i
==
this
)
{
m_parent
->
m_children
.
erase
(
i
);
m_parent
->
m_children
.
erase
(
i
);
return
;
}
}
}
// function object that visits potential obstacles and performs the actual collision refining
struct
PNS_NODE
::
obstacleVisitor
{
///> node we are searching in (either root or a branch)
PNS_NODE
*
m_node
;
///> node that overrides root entries
PNS_NODE
*
m_override
;
///> list of encountered obstacles
// function object that visits potential obstacles and performs
// the actual collision refining
struct
PNS_NODE
::
obstacleVisitor
{
///> node we are searching in (either root or a branch)
PNS_NODE
*
m_node
;
///> node that overrides root entries
PNS_NODE
*
m_override
;
///> list of encountered obstacles
Obstacles
&
m_tab
;
///> the item we are looking for collisions with
///> the item we are looking for collisions with
const
PNS_ITEM
*
m_item
;
///> acccepted kinds of colliding items (solids, vias, segments, etc...)
///> acccepted kinds of colliding items (solids, vias, segments, etc...)
int
m_kindMask
;
///> max number of hits
///> max number of hits
int
m_limitCount
;
///> number of items found so far
///> number of items found so far
int
m_matchCount
;
obstacleVisitor
(
PNS_NODE
::
Obstacles
&
aTab
,
const
PNS_ITEM
*
aItem
,
int
aKindMask
)
:
m_tab
(
aTab
),
m_item
(
aItem
),
m_kindMask
(
aKindMask
),
m_limitCount
(
-
1
),
m_matchCount
(
0
)
{
};
obstacleVisitor
(
PNS_NODE
::
Obstacles
&
aTab
,
const
PNS_ITEM
*
aItem
,
int
aKindMask
)
:
m_tab
(
aTab
),
m_item
(
aItem
),
m_kindMask
(
aKindMask
),
m_limitCount
(
-
1
),
m_matchCount
(
0
)
{};
void
SetCountLimit
(
int
aLimit
)
void
SetCountLimit
(
int
aLimit
)
{
m_limitCount
=
aLimit
;
}
void
SetWorld
(
PNS_NODE
*
aNode
,
PNS_NODE
*
aOverride
=
NULL
)
void
SetWorld
(
PNS_NODE
*
aNode
,
PNS_NODE
*
aOverride
=
NULL
)
{
m_node
=
aNode
;
m_override
=
aOverride
;
}
bool
operator
()(
PNS_ITEM
*
aItem
)
bool
operator
()(
PNS_ITEM
*
aItem
)
{
if
(
!
aItem
->
OfKind
(
m_kindMask
))
if
(
!
aItem
->
OfKind
(
m_kindMask
)
)
return
true
;
// check if there is a more recent branch with a newer (possibily modified) version of this item.
if
(
m_override
&&
m_override
->
overrides
(
aItem
)
)
// check if there is a more recent branch with a newer
// (possibily modified) version of this item.
if
(
m_override
&&
m_override
->
overrides
(
aItem
)
)
return
true
;
int
clearance
=
m_node
->
GetClearance
(
aItem
,
m_item
);
if
(
!
aItem
->
Collide
(
m_item
,
clearance
))
int
clearance
=
m_node
->
GetClearance
(
aItem
,
m_item
);
if
(
!
aItem
->
Collide
(
m_item
,
clearance
)
)
return
true
;
PNS_OBSTACLE
obs
;
obs
.
item
=
aItem
;
m_tab
.
push_back
(
obs
);
m_tab
.
push_back
(
obs
);
m_matchCount
++
;
m_matchCount
++
;
if
(
m_limitCount
>
0
&&
m_matchCount
>=
m_limitCount
)
if
(
m_limitCount
>
0
&&
m_matchCount
>=
m_limitCount
)
return
false
;
return
true
;
};
};
int
PNS_NODE
::
QueryColliding
(
const
PNS_ITEM
*
aItem
,
PNS_NODE
::
Obstacles
&
aObstacles
,
int
aKindMask
,
int
aLimitCount
)
int
PNS_NODE
::
QueryColliding
(
const
PNS_ITEM
*
aItem
,
PNS_NODE
::
Obstacles
&
aObstacles
,
int
aKindMask
,
int
aLimitCount
)
{
obstacleVisitor
visitor
(
aObstacles
,
aItem
,
aKindMask
);
obstacleVisitor
visitor
(
aObstacles
,
aItem
,
aKindMask
);
assert
(
allocNodes
.
find
(
this
)
!=
allocNodes
.
end
()
);
assert
(
allocNodes
.
find
(
this
)
!=
allocNodes
.
end
()
);
visitor
.
SetCountLimit
(
aLimitCount
);
visitor
.
SetCountLimit
(
aLimitCount
);
visitor
.
SetWorld
(
this
,
NULL
);
// first, look for colliding items ourselves
m_index
->
Query
(
aItem
,
m_maxClearance
,
visitor
);
m_index
->
Query
(
aItem
,
m_maxClearance
,
visitor
);
// if we haven't found enough items, look in the root branch as well.
if
(
!
isRoot
()
&&
(
visitor
.
m_matchCount
<
aLimitCount
||
aLimitCount
<
0
)
)
if
(
!
isRoot
()
&&
(
visitor
.
m_matchCount
<
aLimitCount
||
aLimitCount
<
0
)
)
{
visitor
.
SetWorld
(
m_root
,
this
);
m_root
->
m_index
->
Query
(
aItem
,
m_maxClearance
,
visitor
);
visitor
.
SetWorld
(
m_root
,
this
);
m_root
->
m_index
->
Query
(
aItem
,
m_maxClearance
,
visitor
);
}
return
aObstacles
.
size
();
}
PNS_NODE
::
OptObstacle
PNS_NODE
::
NearestObstacle
(
const
PNS_LINE
*
aItem
,
int
aKindMask
)
PNS_NODE
::
OptObstacle
PNS_NODE
::
NearestObstacle
(
const
PNS_LINE
*
aItem
,
int
aKindMask
)
{
Obstacles
obs_list
;
bool
found_isects
=
false
;
const
SHAPE_LINE_CHAIN
&
line
=
aItem
->
GetCLine
();
const
SHAPE_LINE_CHAIN
&
line
=
aItem
->
GetCLine
();
obs_list
.
reserve
(
100
);
obs_list
.
reserve
(
100
);
int
n
=
0
;
for
(
int
i
=
0
;
i
<
line
.
SegmentCount
();
i
++
)
for
(
int
i
=
0
;
i
<
line
.
SegmentCount
();
i
++
)
{
const
PNS_SEGMENT
s
(
*
aItem
,
line
.
CSegment
(
i
)
);
n
+=
QueryColliding
(
&
s
,
obs_list
,
aKindMask
);
const
PNS_SEGMENT
s
(
*
aItem
,
line
.
CSegment
(
i
)
);
n
+=
QueryColliding
(
&
s
,
obs_list
,
aKindMask
);
}
if
(
aItem
->
EndsWithVia
()
)
n
+=
QueryColliding
(
&
aItem
->
GetVia
(),
obs_list
,
aKindMask
);
if
(
aItem
->
EndsWithVia
()
)
n
+=
QueryColliding
(
&
aItem
->
GetVia
(),
obs_list
,
aKindMask
);
//
if(! QueryColliding ( aItem, obs_list, aKindMask ))
if
(
!
n
)
//
if(! QueryColliding ( aItem, obs_list, aKindMask ))
if
(
!
n
)
return
OptObstacle
();
PNS_LINE
&
aLine
=
(
PNS_LINE
&
)
*
aItem
;
...
...
@@ -255,31 +279,31 @@ PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE *aItem, int aKin
nearest
.
item
=
NULL
;
nearest
.
dist_first
=
INT_MAX
;
BOOST_FOREACH
(
PNS_OBSTACLE
obs
,
obs_list
)
BOOST_FOREACH
(
PNS_OBSTACLE
obs
,
obs_list
)
{
VECTOR2I
ip_first
,
ip_last
;
int
dist_max
=
INT_MIN
;
vector
<
SHAPE_LINE_CHAIN
::
Intersection
>
isect_list
;
int
clearance
=
GetClearance
(
obs
.
item
,
&
aLine
);
int
clearance
=
GetClearance
(
obs
.
item
,
&
aLine
);
SHAPE_LINE_CHAIN
hull
=
obs
.
item
->
Hull
(
clearance
);
SHAPE_LINE_CHAIN
hull
=
obs
.
item
->
Hull
(
clearance
);
if
(
aLine
.
EndsWithVia
()
)
if
(
aLine
.
EndsWithVia
()
)
{
int
clearance
=
GetClearance
(
obs
.
item
,
&
aLine
.
GetVia
()
);
int
clearance
=
GetClearance
(
obs
.
item
,
&
aLine
.
GetVia
()
);
SHAPE_LINE_CHAIN
viaHull
=
aLine
.
GetVia
().
Hull
(
clearance
);
SHAPE_LINE_CHAIN
viaHull
=
aLine
.
GetVia
().
Hull
(
clearance
);
viaHull
.
Intersect
(
hull
,
isect_list
);
viaHull
.
Intersect
(
hull
,
isect_list
);
BOOST_FOREACH
(
SHAPE_LINE_CHAIN
::
Intersection
isect
,
isect_list
)
BOOST_FOREACH
(
SHAPE_LINE_CHAIN
::
Intersection
isect
,
isect_list
)
{
int
dist
=
aLine
.
GetCLine
().
Length
()
+
(
isect
.
p
-
aLine
.
GetVia
().
GetPos
()
).
EuclideanNorm
();
int
dist
=
aLine
.
GetCLine
().
Length
()
+
(
isect
.
p
-
aLine
.
GetVia
().
GetPos
()).
EuclideanNorm
();
if
(
dist
<
nearest
.
dist_first
)
if
(
dist
<
nearest
.
dist_first
)
{
found_isects
=
true
;
nearest
.
dist_first
=
dist
;
...
...
@@ -288,7 +312,7 @@ PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE *aItem, int aKin
nearest
.
hull
=
hull
;
}
if
(
dist
>
dist_max
)
if
(
dist
>
dist_max
)
{
dist_max
=
dist
;
ip_last
=
isect
.
p
;
...
...
@@ -298,14 +322,13 @@ PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE *aItem, int aKin
isect_list
.
clear
();
hull
.
Intersect
(
aLine
.
GetCLine
(),
isect_list
);
hull
.
Intersect
(
aLine
.
GetCLine
(),
isect_list
);
BOOST_FOREACH
(
SHAPE_LINE_CHAIN
::
Intersection
isect
,
isect_list
)
BOOST_FOREACH
(
SHAPE_LINE_CHAIN
::
Intersection
isect
,
isect_list
)
{
int
dist
=
aLine
.
GetCLine
().
PathLength
(
isect
.
p
);
int
dist
=
aLine
.
GetCLine
().
PathLength
(
isect
.
p
);
if
(
dist
<
nearest
.
dist_first
)
if
(
dist
<
nearest
.
dist_first
)
{
found_isects
=
true
;
nearest
.
dist_first
=
dist
;
...
...
@@ -314,12 +337,11 @@ PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE *aItem, int aKin
nearest
.
hull
=
hull
;
}
if
(
dist
>
dist_max
)
if
(
dist
>
dist_max
)
{
dist_max
=
dist
;
ip_last
=
isect
.
p
;
}
}
nearest
.
ip_last
=
ip_last
;
...
...
@@ -329,244 +351,268 @@ PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE *aItem, int aKin
return
found_isects
?
nearest
:
OptObstacle
();
}
PNS_NODE
::
OptObstacle
PNS_NODE
::
CheckColliding
(
const
PNS_ITEM
*
aItemA
,
int
aKindMask
)
PNS_NODE
::
OptObstacle
PNS_NODE
::
CheckColliding
(
const
PNS_ITEM
*
aItemA
,
int
aKindMask
)
{
Obstacles
obs
;
obs
.
reserve
(
100
);
if
(
aItemA
->
GetKind
()
==
PNS_ITEM
::
LINE
)
obs
.
reserve
(
100
);
if
(
aItemA
->
GetKind
()
==
PNS_ITEM
::
LINE
)
{
int
n
=
0
;
const
PNS_LINE
*
line
=
static_cast
<
const
PNS_LINE
*>
(
aItemA
);
const
SHAPE_LINE_CHAIN
&
l
=
line
->
GetCLine
();
const
PNS_LINE
*
line
=
static_cast
<
const
PNS_LINE
*>
(
aItemA
);
const
SHAPE_LINE_CHAIN
&
l
=
line
->
GetCLine
();
for
(
int
i
=
0
;
i
<
l
.
SegmentCount
();
i
++
)
for
(
int
i
=
0
;
i
<
l
.
SegmentCount
();
i
++
)
{
const
PNS_SEGMENT
s
(
*
line
,
l
.
CSegment
(
i
));
n
+=
QueryColliding
(
&
s
,
obs
,
aKindMask
,
1
);
if
(
n
)
return
OptObstacle
(
obs
[
0
]);
const
PNS_SEGMENT
s
(
*
line
,
l
.
CSegment
(
i
)
);
n
+=
QueryColliding
(
&
s
,
obs
,
aKindMask
,
1
);
if
(
n
)
return
OptObstacle
(
obs
[
0
]
);
}
if
(
line
->
EndsWithVia
()
)
if
(
line
->
EndsWithVia
()
)
{
n
+=
QueryColliding
(
&
line
->
GetVia
(),
obs
,
aKindMask
,
1
);
if
(
n
)
return
OptObstacle
(
obs
[
0
]);
n
+=
QueryColliding
(
&
line
->
GetVia
(),
obs
,
aKindMask
,
1
);
if
(
n
)
return
OptObstacle
(
obs
[
0
]
);
}
}
else
if
(
QueryColliding
(
aItemA
,
obs
,
aKindMask
,
1
)
>
0
)
return
OptObstacle
(
obs
[
0
]
);
}
else
if
(
QueryColliding
(
aItemA
,
obs
,
aKindMask
,
1
)
>
0
)
return
OptObstacle
(
obs
[
0
]);
return
OptObstacle
();
}
bool
PNS_NODE
::
CheckColliding
(
const
PNS_ITEM
*
aItemA
,
const
PNS_ITEM
*
aItemB
,
int
aKindMask
)
bool
PNS_NODE
::
CheckColliding
(
const
PNS_ITEM
*
aItemA
,
const
PNS_ITEM
*
aItemB
,
int
aKindMask
)
{
Obstacles
dummy
;
assert
(
aItemB
);
assert
(
aItemB
);
// return QueryColliding(aItemA, dummy, aKindMask, 1) > 0;
return
aItemA
->
Collide
(
aItemB
,
GetClearance
(
aItemA
,
aItemB
)
);
return
aItemA
->
Collide
(
aItemB
,
GetClearance
(
aItemA
,
aItemB
)
);
}
struct
hitVisitor
{
struct
hitVisitor
{
PNS_ITEMSET
&
m_items
;
const
VECTOR2I
&
m_point
;
PNS_NODE
*
m_world
;
PNS_NODE
*
m_world
;
hitVisitor
(
PNS_ITEMSET
&
aTab
,
const
VECTOR2I
&
aPoint
,
PNS_NODE
*
aWorld
)
:
m_items
(
aTab
),
m_point
(
aPoint
),
m_world
(
aWorld
)
{
};
hitVisitor
(
PNS_ITEMSET
&
aTab
,
const
VECTOR2I
&
aPoint
,
PNS_NODE
*
aWorld
)
:
m_items
(
aTab
),
m_point
(
aPoint
),
m_world
(
aWorld
)
{};
bool
operator
()(
PNS_ITEM
*
aItem
)
{
SHAPE_CIRCLE
cp
(
m_point
,
0
);
bool
operator
()(
PNS_ITEM
*
aItem
)
{
SHAPE_CIRCLE
cp
(
m_point
,
0
);
int
cl
=
0
;
if
(
aItem
->
GetKind
()
==
PNS_ITEM
::
SEGMENT
)
if
(
aItem
->
GetKind
()
==
PNS_ITEM
::
SEGMENT
)
cl
+=
static_cast
<
PNS_SEGMENT
*>
(
aItem
)
->
GetWidth
()
/
2
;
if
(
aItem
->
GetShape
()
->
Collide
(
&
cp
,
cl
))
m_items
.
Add
(
aItem
);
if
(
aItem
->
GetShape
()
->
Collide
(
&
cp
,
cl
)
)
m_items
.
Add
(
aItem
);
return
true
;
}
};
const
PNS_ITEMSET
PNS_NODE
::
HitTest
(
const
VECTOR2I
&
aPoint
)
{
PNS_ITEMSET
items
;
SHAPE_CIRCLE
s
(
aPoint
,
0
);
// fixme: we treat a point as an infinitely small circle - this is inefficient.
hitVisitor
visitor
(
items
,
aPoint
,
this
);
// fixme: we treat a point as an infinitely small circle - this is inefficient.
SHAPE_CIRCLE
s
(
aPoint
,
0
);
hitVisitor
visitor
(
items
,
aPoint
,
this
);
m_index
->
Query
(
&
s
,
m_maxClearance
,
visitor
);
m_index
->
Query
(
&
s
,
m_maxClearance
,
visitor
);
if
(
!
isRoot
()
)
// fixme: could be made cleaner
if
(
!
isRoot
()
)
// fixme: could be made cleaner
{
PNS_ITEMSET
items_root
;
hitVisitor
visitor_root
(
items_root
,
aPoint
,
m_root
);
hitVisitor
visitor_root
(
items_root
,
aPoint
,
m_root
);
m_root
->
m_index
->
Query
(
&
s
,
m_maxClearance
,
visitor_root
);
BOOST_FOREACH
(
PNS_ITEM
*
item
,
items_root
.
Items
()
)
BOOST_FOREACH
(
PNS_ITEM
*
item
,
items_root
.
Items
()
)
{
if
(
!
overrides
(
item
)
)
items
.
Add
(
item
);
if
(
!
overrides
(
item
)
)
items
.
Add
(
item
);
}
}
return
items
;
}
void
PNS_NODE
::
addSolid
(
PNS_SOLID
*
aSolid
)
void
PNS_NODE
::
addSolid
(
PNS_SOLID
*
aSolid
)
{
linkJoint
(
aSolid
->
GetCenter
(),
aSolid
->
GetLayers
(),
aSolid
->
GetNet
(),
aSolid
);
m_index
->
Add
(
aSolid
);
m_index
->
Add
(
aSolid
);
}
void
PNS_NODE
::
addVia
(
PNS_VIA
*
aVia
)
void
PNS_NODE
::
addVia
(
PNS_VIA
*
aVia
)
{
linkJoint
(
aVia
->
GetPos
(),
aVia
->
GetLayers
(),
aVia
->
GetNet
(),
aVia
);
m_index
->
Add
(
aVia
);
m_index
->
Add
(
aVia
);
}
void
PNS_NODE
::
addLine
(
PNS_LINE
*
aLine
)
void
PNS_NODE
::
addLine
(
PNS_LINE
*
aLine
)
{
const
SHAPE_LINE_CHAIN
&
l
=
aLine
->
GetLine
();
for
(
int
i
=
0
;
i
<
l
.
SegmentCount
();
i
++
)
for
(
int
i
=
0
;
i
<
l
.
SegmentCount
();
i
++
)
{
SEG
s
=
l
.
CSegment
(
i
);
SEG
s
=
l
.
CSegment
(
i
);
if
(
s
.
a
!=
s
.
b
)
if
(
s
.
a
!=
s
.
b
)
{
PNS_SEGMENT
*
pseg
=
new
PNS_SEGMENT
(
*
aLine
,
s
);
PNS_SEGMENT
*
pseg
=
new
PNS_SEGMENT
(
*
aLine
,
s
);
pseg
->
SetOwner
(
this
);
pseg
->
SetOwner
(
this
);
linkJoint
(
s
.
a
,
pseg
->
GetLayers
(),
aLine
->
GetNet
(),
pseg
);
linkJoint
(
s
.
b
,
pseg
->
GetLayers
(),
aLine
->
GetNet
(),
pseg
);
aLine
->
LinkSegment
(
pseg
);
aLine
->
LinkSegment
(
pseg
);
m_index
->
Add
(
pseg
);
m_index
->
Add
(
pseg
);
}
}
}
void
PNS_NODE
::
addSegment
(
PNS_SEGMENT
*
aSeg
)
void
PNS_NODE
::
addSegment
(
PNS_SEGMENT
*
aSeg
)
{
if
(
aSeg
->
GetSeg
().
a
==
aSeg
->
GetSeg
().
b
)
if
(
aSeg
->
GetSeg
().
a
==
aSeg
->
GetSeg
().
b
)
{
TRACEn
(
0
,
"attempting to add a segment with same end coordinates, ignoring."
)
TRACEn
(
0
,
"attempting to add a segment with same end coordinates, ignoring."
)
return
;
}
aSeg
->
SetOwner
(
this
);
aSeg
->
SetOwner
(
this
);
linkJoint
(
aSeg
->
GetSeg
().
a
,
aSeg
->
GetLayers
(),
aSeg
->
GetNet
(),
aSeg
);
linkJoint
(
aSeg
->
GetSeg
().
b
,
aSeg
->
GetLayers
(),
aSeg
->
GetNet
(),
aSeg
);
m_index
->
Add
(
aSeg
);
m_index
->
Add
(
aSeg
);
}
void
PNS_NODE
::
Add
(
PNS_ITEM
*
aItem
)
{
aItem
->
SetOwner
(
this
);
void
PNS_NODE
::
Add
(
PNS_ITEM
*
aItem
)
{
aItem
->
SetOwner
(
this
);
switch
(
aItem
->
GetKind
()
)
switch
(
aItem
->
GetKind
()
)
{
case
PNS_ITEM
:
:
SOLID
:
addSolid
(
static_cast
<
PNS_SOLID
*>
(
aItem
)
);
addSolid
(
static_cast
<
PNS_SOLID
*>
(
aItem
)
);
break
;
case
PNS_ITEM
:
:
SEGMENT
:
addSegment
(
static_cast
<
PNS_SEGMENT
*>
(
aItem
)
);
addSegment
(
static_cast
<
PNS_SEGMENT
*>
(
aItem
)
);
break
;
case
PNS_ITEM
:
:
LINE
:
addLine
(
static_cast
<
PNS_LINE
*>
(
aItem
)
);
addLine
(
static_cast
<
PNS_LINE
*>
(
aItem
)
);
break
;
case
PNS_ITEM
:
:
VIA
:
addVia
(
static_cast
<
PNS_VIA
*>
(
aItem
)
);
addVia
(
static_cast
<
PNS_VIA
*>
(
aItem
)
);
break
;
default
:
assert
(
false
);
assert
(
false
);
}
}
void
PNS_NODE
::
doRemove
(
PNS_ITEM
*
aItem
)
void
PNS_NODE
::
doRemove
(
PNS_ITEM
*
aItem
)
{
// case 1: removing an item that is stored in the root node from any branch: mark it as overridden, but do not remove
if
(
aItem
->
BelongsTo
(
m_root
)
&&
!
isRoot
()
)
m_override
.
insert
(
aItem
);
// case 1: removing an item that is stored in the root node from any branch:
// mark it as overridden, but do not remove
if
(
aItem
->
BelongsTo
(
m_root
)
&&
!
isRoot
()
)
m_override
.
insert
(
aItem
);
// case 2: the item belongs to this branch or a parent, non-root branch, or the root itself and we are the root: remove from the index
else
if
(
!
aItem
->
BelongsTo
(
m_root
)
||
isRoot
()
)
// case 2: the item belongs to this branch or a parent, non-root branch,
// or the root itself and we are the root: remove from the index
else
if
(
!
aItem
->
BelongsTo
(
m_root
)
||
isRoot
()
)
m_index
->
Remove
(
aItem
);
// the item belongs to this particular branch: un-reference it
if
(
aItem
->
BelongsTo
(
this
)
)
aItem
->
SetOwner
(
NULL
);
if
(
aItem
->
BelongsTo
(
this
)
)
aItem
->
SetOwner
(
NULL
);
}
void
PNS_NODE
::
removeSegment
(
PNS_SEGMENT
*
aSeg
)
void
PNS_NODE
::
removeSegment
(
PNS_SEGMENT
*
aSeg
)
{
unlinkJoint
(
aSeg
->
GetSeg
().
a
,
aSeg
->
GetLayers
(),
aSeg
->
GetNet
(),
aSeg
);
unlinkJoint
(
aSeg
->
GetSeg
().
b
,
aSeg
->
GetLayers
(),
aSeg
->
GetNet
(),
aSeg
);
unlinkJoint
(
aSeg
->
GetSeg
().
a
,
aSeg
->
GetLayers
(),
aSeg
->
GetNet
(),
aSeg
);
unlinkJoint
(
aSeg
->
GetSeg
().
b
,
aSeg
->
GetLayers
(),
aSeg
->
GetNet
(),
aSeg
);
doRemove
(
aSeg
);
doRemove
(
aSeg
);
}
void
PNS_NODE
::
removeLine
(
PNS_LINE
*
aLine
)
void
PNS_NODE
::
removeLine
(
PNS_LINE
*
aLine
)
{
vector
<
PNS_SEGMENT
*>
*
segRefs
=
aLine
->
GetLinkedSegments
();
vector
<
PNS_SEGMENT
*>*
segRefs
=
aLine
->
GetLinkedSegments
();
if
(
!
segRefs
)
if
(
!
segRefs
)
return
;
assert
(
aLine
->
GetOwner
()
);
assert
(
aLine
->
GetOwner
()
);
BOOST_FOREACH
(
PNS_SEGMENT
*
seg
,
*
segRefs
)
BOOST_FOREACH
(
PNS_SEGMENT
*
seg
,
*
segRefs
)
{
removeSegment
(
seg
);
removeSegment
(
seg
);
}
aLine
->
SetOwner
(
NULL
);
aLine
->
SetOwner
(
NULL
);
}
void
PNS_NODE
::
removeVia
(
PNS_VIA
*
aVia
)
void
PNS_NODE
::
removeVia
(
PNS_VIA
*
aVia
)
{
unlinkJoint
(
aVia
->
GetPos
(),
aVia
->
GetLayers
(),
aVia
->
GetNet
(),
aVia
);
unlinkJoint
(
aVia
->
GetPos
(),
aVia
->
GetLayers
(),
aVia
->
GetNet
(),
aVia
);
doRemove
(
aVia
);
doRemove
(
aVia
);
}
void
PNS_NODE
::
Replace
(
PNS_ITEM
*
aOldItem
,
PNS_ITEM
*
aNewItem
)
void
PNS_NODE
::
Replace
(
PNS_ITEM
*
aOldItem
,
PNS_ITEM
*
aNewItem
)
{
Remove
(
aOldItem
);
Add
(
aNewItem
);
Remove
(
aOldItem
);
Add
(
aNewItem
);
}
void
PNS_NODE
::
Remove
(
PNS_ITEM
*
aItem
)
{
switch
(
aItem
->
GetKind
())
void
PNS_NODE
::
Remove
(
PNS_ITEM
*
aItem
)
{
switch
(
aItem
->
GetKind
()
)
{
case
PNS_ITEM
:
:
SOLID
:
assert
(
false
);
assert
(
false
);
break
;
case
PNS_ITEM
:
:
SEGMENT
:
removeSegment
(
static_cast
<
PNS_SEGMENT
*>
(
aItem
)
);
removeSegment
(
static_cast
<
PNS_SEGMENT
*>
(
aItem
)
);
break
;
case
PNS_ITEM
:
:
LINE
:
removeLine
(
static_cast
<
PNS_LINE
*>
(
aItem
)
);
removeLine
(
static_cast
<
PNS_LINE
*>
(
aItem
)
);
break
;
case
PNS_ITEM
:
:
VIA
:
removeVia
(
static_cast
<
PNS_VIA
*>
(
aItem
)
);
removeVia
(
static_cast
<
PNS_VIA
*>
(
aItem
)
);
break
;
default
:
...
...
@@ -574,125 +620,139 @@ void PNS_NODE::Remove(PNS_ITEM *aItem)
}
}
void
PNS_NODE
::
followLine
(
PNS_SEGMENT
*
current
,
bool
scanDirection
,
int
&
pos
,
int
limit
,
VECTOR2I
*
corners
,
PNS_SEGMENT
**
segments
)
void
PNS_NODE
::
followLine
(
PNS_SEGMENT
*
current
,
bool
scanDirection
,
int
&
pos
,
int
limit
,
VECTOR2I
*
corners
,
PNS_SEGMENT
**
segments
)
{
bool
prevReversed
=
false
;
for
(;;
)
for
(
;
;
)
{
const
VECTOR2I
p
=
(
scanDirection
^
prevReversed
)
?
current
->
GetSeg
().
b
:
current
->
GetSeg
().
a
;
const
OptJoint
jt
=
FindJoint
(
p
,
current
->
GetLayer
(),
current
->
GetNet
());
const
VECTOR2I
p
=
(
scanDirection
^
prevReversed
)
?
current
->
GetSeg
().
b
:
current
->
GetSeg
().
a
;
const
OptJoint
jt
=
FindJoint
(
p
,
current
->
GetLayer
(),
current
->
GetNet
()
);
assert
(
jt
);
assert
(
pos
>
0
&&
pos
<
limit
);
assert
(
jt
);
assert
(
pos
>
0
&&
pos
<
limit
);
corners
[
pos
]
=
jt
->
GetPos
();
segments
[
pos
]
=
current
;
corners
[
pos
]
=
jt
->
GetPos
();
segments
[
pos
]
=
current
;
pos
+=
(
scanDirection
?
1
:
-
1
);
if
(
!
jt
->
IsLineCorner
()
)
if
(
!
jt
->
IsLineCorner
()
)
break
;
current
=
jt
->
NextSegment
(
current
);
prevReversed
=
(
jt
->
GetPos
()
==
(
scanDirection
?
current
->
GetSeg
().
b
:
current
->
GetSeg
().
a
));
prevReversed
=
(
jt
->
GetPos
()
==
(
scanDirection
?
current
->
GetSeg
().
b
:
current
->
GetSeg
().
a
)
);
}
}
PNS_LINE
*
PNS_NODE
::
AssembleLine
(
PNS_SEGMENT
*
aSeg
,
const
OptJoint
&
a
,
const
OptJoint
&
b
)
PNS_LINE
*
PNS_NODE
::
AssembleLine
(
PNS_SEGMENT
*
aSeg
,
const
OptJoint
&
a
,
const
OptJoint
&
b
)
{
const
int
MaxVerts
=
1024
;
VECTOR2I
corners
[
MaxVerts
+
1
];
PNS_SEGMENT
*
segs
[
MaxVerts
+
1
];
VECTOR2I
corners
[
MaxVerts
+
1
];
PNS_SEGMENT
*
segs
[
MaxVerts
+
1
];
PNS_LINE
*
pl
=
new
PNS_LINE
;
int
i_start
=
MaxVerts
/
2
,
i_end
=
i_start
+
1
;
PNS_LINE
*
pl
=
new
PNS_LINE
;
int
i_start
=
MaxVerts
/
2
,
i_end
=
i_start
+
1
;
pl
->
SetWidth
(
aSeg
->
GetWidth
()
);
pl
->
SetLayers
(
aSeg
->
GetLayers
()
);
pl
->
SetNet
(
aSeg
->
GetNet
()
);
pl
->
SetOwner
(
this
);
pl
->
SetNet
(
aSeg
->
GetNet
()
);
pl
->
SetOwner
(
this
);
//
pl->LinkSegment(aSeg);
//
pl->LinkSegment(aSeg);
followLine
(
aSeg
,
false
,
i_start
,
MaxVerts
,
corners
,
segs
);
followLine
(
aSeg
,
true
,
i_end
,
MaxVerts
,
corners
,
segs
);
followLine
(
aSeg
,
false
,
i_start
,
MaxVerts
,
corners
,
segs
);
followLine
(
aSeg
,
true
,
i_end
,
MaxVerts
,
corners
,
segs
);
int
clip_start
=
-
1
,
clip_end
=
-
1
;
for
(
int
i
=
i_start
+
1
;
i
<
i_end
;
i
++
)
for
(
int
i
=
i_start
+
1
;
i
<
i_end
;
i
++
)
{
const
VECTOR2I
&
p
=
corners
[
i
];
const
VECTOR2I
&
p
=
corners
[
i
];
if
(
a
&&
(
p
==
a
->
GetPos
()
||
p
==
b
->
GetPos
()
)
)
if
(
a
&&
(
p
==
a
->
GetPos
()
||
p
==
b
->
GetPos
()
)
)
{
clip_start
=
std
::
min
(
clip_start
,
i
);
clip_end
=
std
::
max
(
clip_end
,
i
);
clip_start
=
std
::
min
(
clip_start
,
i
);
clip_end
=
std
::
max
(
clip_end
,
i
);
}
pl
->
GetLine
().
Append
(
p
);
if
(
segs
[
i
-
1
]
!=
segs
[
i
])
pl
->
LinkSegment
(
segs
[
i
]);
pl
->
GetLine
().
Append
(
p
);
if
(
segs
[
i
-
1
]
!=
segs
[
i
]
)
pl
->
LinkSegment
(
segs
[
i
]
);
}
return
pl
;
}
void
PNS_NODE
::
FindLineEnds
(
PNS_LINE
*
aLine
,
PNS_JOINT
&
a
,
PNS_JOINT
&
b
)
void
PNS_NODE
::
FindLineEnds
(
PNS_LINE
*
aLine
,
PNS_JOINT
&
a
,
PNS_JOINT
&
b
)
{
a
=
*
FindJoint
(
aLine
->
GetCLine
().
CPoint
(
0
),
aLine
->
GetLayers
().
Start
(),
aLine
->
GetNet
()
);
b
=
*
FindJoint
(
aLine
->
GetCLine
().
CPoint
(
-
1
),
aLine
->
GetLayers
().
Start
(),
aLine
->
GetNet
());
a
=
*
FindJoint
(
aLine
->
GetCLine
().
CPoint
(
0
),
aLine
->
GetLayers
().
Start
(),
aLine
->
GetNet
()
);
b
=
*
FindJoint
(
aLine
->
GetCLine
().
CPoint
(
-
1
),
aLine
->
GetLayers
().
Start
(),
aLine
->
GetNet
()
);
}
int
PNS_NODE
::
FindLinesBetweenJoints
(
PNS_JOINT
&
a
,
PNS_JOINT
&
b
,
vector
<
PNS_LINE
*>
&
aLines
)
int
PNS_NODE
::
FindLinesBetweenJoints
(
PNS_JOINT
&
a
,
PNS_JOINT
&
b
,
vector
<
PNS_LINE
*>&
aLines
)
{
BOOST_FOREACH
(
PNS_ITEM
*
item
,
a
.
GetLinkList
()
)
BOOST_FOREACH
(
PNS_ITEM
*
item
,
a
.
GetLinkList
()
)
{
if
(
item
->
GetKind
()
==
PNS_ITEM
::
SEGMENT
)
if
(
item
->
GetKind
()
==
PNS_ITEM
::
SEGMENT
)
{
PNS_SEGMENT
*
seg
=
static_cast
<
PNS_SEGMENT
*>
(
item
);
PNS_LINE
*
line
=
AssembleLine
(
seg
);
PNS_SEGMENT
*
seg
=
static_cast
<
PNS_SEGMENT
*>
(
item
);
PNS_LINE
*
line
=
AssembleLine
(
seg
);
PNS_JOINT
j_start
,
j_end
;
FindLineEnds
(
line
,
j_start
,
j_end
);
if
(
(
j_start
==
a
&&
j_end
==
b
)
||
(
j_end
==
a
&&
j_start
==
b
))
aLines
.
push_back
(
line
);
if
(
(
j_start
==
a
&&
j_end
==
b
)
||
(
j_end
==
a
&&
j_start
==
b
)
)
aLines
.
push_back
(
line
);
else
delete
line
;
}
}
return
0
;
}
const
PNS_NODE
::
OptJoint
PNS_NODE
::
FindJoint
(
const
VECTOR2I
&
aPos
,
int
aLayer
,
int
aNet
)
const
PNS_NODE
::
OptJoint
PNS_NODE
::
FindJoint
(
const
VECTOR2I
&
aPos
,
int
aLayer
,
int
aNet
)
{
PNS_JOINT
::
HashTag
tag
;
tag
.
net
=
aNet
;
tag
.
pos
=
aPos
;
JointMap
::
iterator
f
=
m_joints
.
find
(
tag
),
end
=
m_joints
.
end
();
JointMap
::
iterator
f
=
m_joints
.
find
(
tag
),
end
=
m_joints
.
end
();
if
(
f
==
end
&&
!
isRoot
()
)
if
(
f
==
end
&&
!
isRoot
()
)
{
end
=
m_root
->
m_joints
.
end
();
f
=
m_root
->
m_joints
.
find
(
tag
);
//
m_root->FindJoint(aPos, aLayer, aNet);
f
=
m_root
->
m_joints
.
find
(
tag
);
//
m_root->FindJoint(aPos, aLayer, aNet);
}
if
(
f
==
end
)
if
(
f
==
end
)
return
OptJoint
();
while
(
f
!=
end
)
while
(
f
!=
end
)
{
if
(
f
->
second
.
GetLayers
().
Overlaps
(
aLayer
)
)
if
(
f
->
second
.
GetLayers
().
Overlaps
(
aLayer
)
)
return
f
->
second
;
++
f
;
}
return
OptJoint
();
}
PNS_JOINT
&
PNS_NODE
::
touchJoint
(
const
VECTOR2I
&
aPos
,
const
PNS_LAYERSET
&
aLayers
,
int
aNet
)
{
PNS_JOINT
::
HashTag
tag
;
...
...
@@ -701,201 +761,227 @@ PNS_JOINT& PNS_NODE::touchJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLaye
tag
.
net
=
aNet
;
// try to find the joint in this node.
JointMap
::
iterator
f
=
m_joints
.
find
(
tag
);
JointMap
::
iterator
f
=
m_joints
.
find
(
tag
);
pair
<
JointMap
::
iterator
,
JointMap
::
iterator
>
range
;
// not found and we are not root? find in the root and copy results here.
if
(
f
==
m_joints
.
end
()
&&
!
isRoot
()
)
if
(
f
==
m_joints
.
end
()
&&
!
isRoot
()
)
{
range
=
m_root
->
m_joints
.
equal_range
(
tag
);
for
(
f
=
range
.
first
;
f
!=
range
.
second
;
++
f
)
range
=
m_root
->
m_joints
.
equal_range
(
tag
);
for
(
f
=
range
.
first
;
f
!=
range
.
second
;
++
f
)
m_joints
.
insert
(
*
f
);
}
// now insert and combine overlapping joints
PNS_JOINT
jt
(
aPos
,
aLayers
,
aNet
);
PNS_JOINT
jt
(
aPos
,
aLayers
,
aNet
);
bool
merged
;
do
{
merged
=
false
;
range
=
m_joints
.
equal_range
(
tag
);
range
=
m_joints
.
equal_range
(
tag
);
if
(
range
.
first
==
m_joints
.
end
()
)
if
(
range
.
first
==
m_joints
.
end
()
)
break
;
for
(
f
=
range
.
first
;
f
!=
range
.
second
;
++
f
)
for
(
f
=
range
.
first
;
f
!=
range
.
second
;
++
f
)
{
if
(
aLayers
.
Overlaps
(
f
->
second
.
GetLayers
())
)
if
(
aLayers
.
Overlaps
(
f
->
second
.
GetLayers
()
)
)
{
jt
.
Merge
(
f
->
second
);
m_joints
.
erase
(
f
);
jt
.
Merge
(
f
->
second
);
m_joints
.
erase
(
f
);
merged
=
true
;
break
;
}
}
}
while
(
merged
);
}
while
(
merged
);
return
m_joints
.
insert
(
TagJointPair
(
tag
,
jt
)
)
->
second
;
return
m_joints
.
insert
(
TagJointPair
(
tag
,
jt
)
)
->
second
;
}
void
PNS_JOINT
::
Dump
()
const
{
printf
(
"joint layers %d-%d, net %d, pos %s, links: %d
\n
"
,
m_layers
.
Start
(),
m_layers
.
End
(),
m_tag
.
net
,
m_tag
.
pos
.
Format
().
c_str
(),
LinkCount
()
);
printf
(
"joint layers %d-%d, net %d, pos %s, links: %d
\n
"
,
m_layers
.
Start
(),
m_layers
.
End
(),
m_tag
.
net
,
m_tag
.
pos
.
Format
().
c_str
(),
LinkCount
()
);
}
void
PNS_NODE
::
linkJoint
(
const
VECTOR2I
&
aPos
,
const
PNS_LAYERSET
&
aLayers
,
int
aNet
,
PNS_ITEM
*
aWhere
)
void
PNS_NODE
::
linkJoint
(
const
VECTOR2I
&
aPos
,
const
PNS_LAYERSET
&
aLayers
,
int
aNet
,
PNS_ITEM
*
aWhere
)
{
PNS_JOINT
&
jt
=
touchJoint
(
aPos
,
aLayers
,
aNet
);
jt
.
Link
(
aWhere
);
jt
.
Link
(
aWhere
);
}
void
PNS_NODE
::
unlinkJoint
(
const
VECTOR2I
&
aPos
,
const
PNS_LAYERSET
&
aLayers
,
int
aNet
,
PNS_ITEM
*
aWhere
)
void
PNS_NODE
::
unlinkJoint
(
const
VECTOR2I
&
aPos
,
const
PNS_LAYERSET
&
aLayers
,
int
aNet
,
PNS_ITEM
*
aWhere
)
{
// fixme: remove dangling joints
PNS_JOINT
&
jt
=
touchJoint
(
aPos
,
aLayers
,
aNet
);
jt
.
Unlink
(
aWhere
);
jt
.
Unlink
(
aWhere
);
}
void
PNS_NODE
::
Dump
(
bool
aLong
)
void
PNS_NODE
::
Dump
(
bool
aLong
)
{
#if 0
boost::unordered_set<PNS_SEGMENT
*> all_segs;
SHAPE_INDEX_LIST<PNS_ITEM
*>::iterator i;
boost::unordered_set<PNS_SEGMENT
*> all_segs;
SHAPE_INDEX_LIST<PNS_ITEM
*>::iterator i;
for(i = m_items.begin(); i != m_items.end() ; i++
)
for( i = m_items.begin(); i != m_items.end(); i++
)
{
if((*i)->GetKind() == PNS_ITEM::SEGMENT
)
all_segs.insert(static_cast<PNS_SEGMENT*>(*i)
);
if( (*i)->GetKind() == PNS_ITEM::SEGMENT
)
all_segs.insert( static_cast<PNS_SEGMENT*>(*i)
);
}
if(!isRoot()
)
for(i = m_root->m_items.begin(); i != m_root->m_items.end() ; i++
)
if( !isRoot()
)
for( i = m_root->m_items.begin(); i != m_root->m_items.end(); i++
)
{
if((*i)->GetKind() == PNS_ITEM::SEGMENT && !overrides(*i)
)
all_segs.insert(static_cast<PNS_SEGMENT*>(*i)
);
if( (*i)->GetKind() == PNS_ITEM::SEGMENT && !overrides( *i )
)
all_segs.insert( static_cast<PNS_SEGMENT*>(*i)
);
}
JointMap::iterator j;
if(aLong)
for(j=m_joints.begin(); j!=m_joints.end(); ++j)
if( aLong )
for( j = m_joints.begin(); j!=m_joints.end(); ++j )
{
printf("joint : %s, links : %d\n", j->second.GetPos().Format().c_str(), j->second.LinkCount());
printf( "joint : %s, links : %d\n",
j->second.GetPos().Format().c_str(), j->second.LinkCount() );
PNS_JOINT::LinkedItems::const_iterator k;
for(k = j->second.GetLinkList().begin(); k != j->second.GetLinkList().end(); ++k)
for( k = j->second.GetLinkList().begin(); k != j->second.GetLinkList().end(); ++k )
{
const PNS_ITEM *
item = *k;
const PNS_ITEM*
item = *k;
switch(item->GetKind()
)
switch( item->GetKind()
)
{
case PNS_ITEM::SEGMENT:
{
const PNS_SEGMENT *seg = static_cast<const PNS_SEGMENT *>(item);
printf(" -> seg %s %s\n", seg->GetSeg().a.Format().c_str(), seg->GetSeg().b.Format().c_str());
const PNS_SEGMENT* seg = static_cast<const PNS_SEGMENT*>(item);
printf( " -> seg %s %s\n", seg->GetSeg().a.Format().c_str(),
seg->GetSeg().b.Format().c_str() );
break;
}
default:
break;
}
}
}
int lines_count = 0;
while(!all_segs.empty())
while( !all_segs.empty() )
{
PNS_SEGMENT *
s = *all_segs.begin();
PNS_LINE *l = AssembleLine(s
);
PNS_SEGMENT*
s = *all_segs.begin();
PNS_LINE* l = AssembleLine( s
);
PNS_LINE::LinkedSegments* seg_refs = l->GetLinkedSegments();
if(aLong
)
printf(
"Line: %s, net %d ", l->GetLine().Format().c_str(), l->GetNet() );
if( aLong
)
printf(
"Line: %s, net %d ", l->GetLine().Format().c_str(), l->GetNet() );
for(vector<PNS_SEGMENT *>::iterator j = seg_refs->begin(); j != seg_refs->end(); ++j
)
for( vector<PNS_SEGMENT*>::iterator j = seg_refs->begin(); j != seg_refs->end(); ++j
)
{
printf("%s ", (*j)->GetSeg().a.Format().c_str() );
if(j+1 == seg_refs->end())
printf("%s\n", (*j)->GetSeg().b.Format().c_str() );
all_segs.erase(*j);
printf( "%s ", (*j)->GetSeg().a.Format().c_str() );
if( j + 1 == seg_refs->end() )
printf( "%s\n", (*j)->GetSeg().b.Format().c_str() );
all_segs.erase( *j );
}
lines_count++;
}
printf("Local joints: %d, lines : %d \n", m_joints.size(), lines_count
);
printf( "Local joints: %d, lines : %d \n", m_joints.size(), lines_count
);
#endif
}
void
PNS_NODE
::
GetUpdatedItems
(
ItemVector
&
aRemoved
,
ItemVector
&
aAdded
)
void
PNS_NODE
::
GetUpdatedItems
(
ItemVector
&
aRemoved
,
ItemVector
&
aAdded
)
{
aRemoved
.
reserve
(
m_override
.
size
()
);
aAdded
.
reserve
(
m_index
->
Size
()
);
aRemoved
.
reserve
(
m_override
.
size
()
);
aAdded
.
reserve
(
m_index
->
Size
()
);
if
(
isRoot
()
)
if
(
isRoot
()
)
return
;
BOOST_FOREACH
(
PNS_ITEM
*
item
,
m_override
)
aRemoved
.
push_back
(
item
);
BOOST_FOREACH
(
PNS_ITEM
*
item
,
m_override
)
aRemoved
.
push_back
(
item
);
for
(
PNS_INDEX
::
ItemSet
::
iterator
i
=
m_index
->
begin
();
i
!=
m_index
->
end
();
++
i
)
aAdded
.
push_back
(
*
i
);
for
(
PNS_INDEX
::
ItemSet
::
iterator
i
=
m_index
->
begin
();
i
!=
m_index
->
end
();
++
i
)
aAdded
.
push_back
(
*
i
);
}
void
PNS_NODE
::
releaseChildren
()
void
PNS_NODE
::
releaseChildren
()
{
// copy the kids as the PNS_NODE destructor erases the item from the parent node.
vector
<
PNS_NODE
*>
kids
=
m_children
;
vector
<
PNS_NODE
*>
kids
=
m_children
;
BOOST_FOREACH
(
PNS_NODE
*
node
,
kids
)
{
BOOST_FOREACH
(
PNS_NODE
*
node
,
kids
)
{
node
->
releaseChildren
();
delete
node
;
}
}
void
PNS_NODE
::
Commit
(
PNS_NODE
*
aNode
)
{
if
(
aNode
->
isRoot
())
void
PNS_NODE
::
Commit
(
PNS_NODE
*
aNode
)
{
if
(
aNode
->
isRoot
()
)
return
;
BOOST_FOREACH
(
PNS_ITEM
*
item
,
aNode
->
m_override
)
Remove
(
item
);
BOOST_FOREACH
(
PNS_ITEM
*
item
,
aNode
->
m_override
)
Remove
(
item
);
for
(
PNS_INDEX
::
ItemSet
::
iterator
i
=
aNode
->
m_index
->
begin
();
i
!=
aNode
->
m_index
->
end
();
++
i
)
Add
(
*
i
);
for
(
PNS_INDEX
::
ItemSet
::
iterator
i
=
aNode
->
m_index
->
begin
();
i
!=
aNode
->
m_index
->
end
();
++
i
)
Add
(
*
i
);
releaseChildren
();
}
void
PNS_NODE
::
KillChildren
()
{
assert
(
isRoot
()
);
assert
(
isRoot
()
);
releaseChildren
();
}
void
PNS_NODE
::
AllItemsInNet
(
int
aNet
,
std
::
list
<
PNS_ITEM
*>&
aItems
)
void
PNS_NODE
::
AllItemsInNet
(
int
aNet
,
std
::
list
<
PNS_ITEM
*>&
aItems
)
{
PNS_INDEX
::
NetItemsList
*
l_cur
=
m_index
->
GetItemsForNet
(
aNet
);
PNS_INDEX
::
NetItemsList
*
l_cur
=
m_index
->
GetItemsForNet
(
aNet
);
if
(
!
l_cur
)
if
(
!
l_cur
)
return
;
std
::
copy
(
aItems
.
begin
(),
l_cur
->
begin
(),
l_cur
->
end
()
);
if
(
!
isRoot
()
)
std
::
copy
(
aItems
.
begin
(),
l_cur
->
begin
(),
l_cur
->
end
()
);
if
(
!
isRoot
()
)
{
PNS_INDEX
::
NetItemsList
*
l_root
=
m_root
->
m_index
->
GetItemsForNet
(
aNet
);
PNS_INDEX
::
NetItemsList
*
l_root
=
m_root
->
m_index
->
GetItemsForNet
(
aNet
);
for
(
PNS_INDEX
::
NetItemsList
::
iterator
i
=
l_root
->
begin
();
i
!=
l_root
->
end
();
++
i
)
if
(
!
overrides
(
*
i
)
)
aItems
.
push_back
(
*
i
);
for
(
PNS_INDEX
::
NetItemsList
::
iterator
i
=
l_root
->
begin
();
i
!=
l_root
->
end
();
++
i
)
if
(
!
overrides
(
*
i
))
aItems
.
push_back
(
*
i
);
}
}
pcbnew/router/pns_node.h
View file @
5598acb6
...
...
@@ -45,9 +45,10 @@ class PNS_INDEX;
using
boost
::
shared_ptr
;
class
PNS_CLEARANCE_FUNC
{
public
:
virtual
int
operator
()
(
const
PNS_ITEM
*
a
,
const
PNS_ITEM
*
b
)
=
0
;
class
PNS_CLEARANCE_FUNC
{
public
:
virtual
int
operator
()(
const
PNS_ITEM
*
a
,
const
PNS_ITEM
*
b
)
=
0
;
};
/**
...
...
@@ -59,16 +60,16 @@ class PNS_CLEARANCE_FUNC {
struct
PNS_OBSTACLE
{
///> Item we search collisions with
PNS_ITEM
*
head
;
PNS_ITEM
*
head
;
///> Item found to be colliding with head
PNS_ITEM
*
item
;
PNS_ITEM
*
item
;
///> Hull of the colliding item
SHAPE_LINE_CHAIN
hull
;
///> First and last intersection point between the head item and the hull of the
////
colliding item
///> First and last intersection point between the head item and the hull
///> of the
colliding item
VECTOR2I
ip_first
,
ip_last
;
///> ... and the distance thereof
...
...
@@ -78,28 +79,29 @@ struct PNS_OBSTACLE
/**
* Class PNS_NODE
*
* Keeps the router "world" - i.e. all the tracks, vias, solids in a hierarchical and indexed way.
* Keeps the router "world" - i.e. all the tracks, vias, solids in a
* hierarchical and indexed way.
* Features:
* - spatial-indexed container for PCB item shapes
* - collision search (with clearance checking)
* - assembly of lines connecting joints, finding loops and unique paths
* - lightweight cloning/branching (for recursive optimization and shove springback)
* - lightweight cloning/branching (for recursive optimization and shove
* springback)
**/
class
PNS_NODE
{
class
PNS_NODE
{
public
:
typedef
boost
::
optional
<
PNS_OBSTACLE
>
OptObstacle
;
typedef
std
::
vector
<
PNS_ITEM
*>
ItemVector
;
typedef
std
::
vector
<
PNS_ITEM
*>
ItemVector
;
typedef
std
::
vector
<
PNS_OBSTACLE
>
Obstacles
;
typedef
boost
::
optional
<
PNS_JOINT
>
OptJoint
;
PNS_NODE
();
~
PNS_NODE
();
PNS_NODE
();
~
PNS_NODE
();
///> Returns the expected clearance between items a and b.
int
GetClearance
(
const
PNS_ITEM
*
a
,
const
PNS_ITEM
*
b
)
const
;
int
GetClearance
(
const
PNS_ITEM
*
a
,
const
PNS_ITEM
*
b
)
const
;
///> Returns the pre-set worst case clearance between any pair of items
int
GetMaxClearance
()
const
...
...
@@ -112,39 +114,48 @@ public:
m_maxClearance
=
aClearance
;
}
void
SetClearanceFunctor
(
PNS_CLEARANCE_FUNC
*
aFunc
)
void
SetClearanceFunctor
(
PNS_CLEARANCE_FUNC
*
aFunc
)
{
m_clearanceFunctor
=
aFunc
;
}
///> Finds items that collide with aItem and stores collision information in aObstacles.
int
QueryColliding
(
const
PNS_ITEM
*
aItem
,
Obstacles
&
aObstacles
,
int
aKindMask
=
PNS_ITEM
::
ANY
,
int
aLimitCount
=
-
1
);
///> Finds items that collide with aItem and stores collision information
///> in aObstacles.
int
QueryColliding
(
const
PNS_ITEM
*
aItem
,
Obstacles
&
aObstacles
,
int
aKindMask
=
PNS_ITEM
::
ANY
,
int
aLimitCount
=
-
1
);
///> Finds the nearest item that collides with aItem.
OptObstacle
NearestObstacle
(
const
PNS_LINE
*
aItem
,
int
aKindMask
=
PNS_ITEM
::
ANY
);
OptObstacle
NearestObstacle
(
const
PNS_LINE
*
aItem
,
int
aKindMask
=
PNS_ITEM
::
ANY
);
///> Checks if the item collides with anything else in the world, and returns it if so.
OptObstacle
CheckColliding
(
const
PNS_ITEM
*
aItem
,
int
aKindMask
=
PNS_ITEM
::
ANY
);
///> Checks if the item collides with anything else in the world,
///> and returns it if so.
OptObstacle
CheckColliding
(
const
PNS_ITEM
*
aItem
,
int
aKindMask
=
PNS_ITEM
::
ANY
);
///> Checks if two items collide [deprecated].
bool
CheckColliding
(
const
PNS_ITEM
*
aItemA
,
const
PNS_ITEM
*
aItemB
,
int
aKindMask
=
PNS_ITEM
::
ANY
);
bool
CheckColliding
(
const
PNS_ITEM
*
aItemA
,
const
PNS_ITEM
*
aItemB
,
int
aKindMask
=
PNS_ITEM
::
ANY
);
///> Hit detection
const
PNS_ITEMSET
HitTest
(
const
VECTOR2I
&
aPoint
);
void
Add
(
PNS_ITEM
*
aItem
);
void
Remove
(
PNS_ITEM
*
aItem
);
void
Replace
(
PNS_ITEM
*
aOldItem
,
PNS_ITEM
*
aNewItem
);
void
Add
(
PNS_ITEM
*
aItem
);
void
Remove
(
PNS_ITEM
*
aItem
);
void
Replace
(
PNS_ITEM
*
aOldItem
,
PNS_ITEM
*
aNewItem
);
///> Creates a lightweight copy ("branch") of self. Note that if there are any branches
///
in use, their parents must NOT be deleted.
PNS_NODE
*
Branch
();
///> Creates a lightweight copy ("branch") of self. Note that if there are
///> any branches
in use, their parents must NOT be deleted.
PNS_NODE
*
Branch
();
///> Assembles a line connecting two non-trivial joints the segment aSeg belongs to.
PNS_LINE
*
AssembleLine
(
PNS_SEGMENT
*
aSeg
,
const
OptJoint
&
a
=
OptJoint
(),
const
OptJoint
&
b
=
OptJoint
());
///> Assembles a line connecting two non-trivial joints the
///> segment aSeg belongs to.
PNS_LINE
*
AssembleLine
(
PNS_SEGMENT
*
aSeg
,
const
OptJoint
&
a
=
OptJoint
(),
const
OptJoint
&
b
=
OptJoint
()
);
///> Dumps the contents and joints structure
void
Dump
(
bool
aLong
=
false
);
void
Dump
(
bool
aLong
=
false
);
///> Returns the number of joints
int
JointCount
()
const
...
...
@@ -152,106 +163,116 @@ public:
return
m_joints
.
size
();
}
///> Returns the lists of items removed and added in this branch, with respect
///> to the root.
void
GetUpdatedItems
(
ItemVector
&
aRemoved
,
ItemVector
&
aAdded
);
///> Returns the lists of items removed and added in this branch, with
///> respect to the root.
void
GetUpdatedItems
(
ItemVector
&
aRemoved
,
ItemVector
&
aAdded
);
///> Copies the changes from a given branch (aNode) to the root. Called on
///> a non-root branch will fail.
void
Commit
(
PNS_NODE
*
aNode
);
void
Commit
(
PNS_NODE
*
aNode
);
///> finds a joint at a given position, layer and nets
const
OptJoint
FindJoint
(
const
VECTOR2I
&
aPos
,
int
aLayer
,
int
aNet
);
const
OptJoint
FindJoint
(
const
VECTOR2I
&
aPos
,
int
aLayer
,
int
aNet
);
///> finds all linest between a pair of joints. Used by the loop removal engine.
int
FindLinesBetweenJoints
(
PNS_JOINT
&
a
,
PNS_JOINT
&
b
,
std
::
vector
<
PNS_LINE
*>
&
aLines
);
int
FindLinesBetweenJoints
(
PNS_JOINT
&
a
,
PNS_JOINT
&
b
,
std
::
vector
<
PNS_LINE
*>&
aLines
);
///> finds the joints corresponding to the ends of line aLine
void
FindLineEnds
(
PNS_LINE
*
aLine
,
PNS_JOINT
&
a
,
PNS_JOINT
&
b
);
void
FindLineEnds
(
PNS_LINE
*
aLine
,
PNS_JOINT
&
a
,
PNS_JOINT
&
b
);
///> finds all joints that have an (in)direct connection(s) (i.e. segments/vias) with the joint aJoint.
void
FindConnectedJoints
(
const
PNS_JOINT
&
aJoint
,
std
::
vector
<
PNS_JOINT
*>
&
aConnectedJoints
);
///> finds all joints that have an (in)direct connection(s)
///> (i.e. segments/vias) with the joint aJoint.
void
FindConnectedJoints
(
const
PNS_JOINT
&
aJoint
,
std
::
vector
<
PNS_JOINT
*>&
aConnectedJoints
);
///> Destroys all child nodes. Applicable only to the root node.
void
KillChildren
();
void
AllItemsInNet
(
int
aNet
,
std
::
list
<
PNS_ITEM
*>&
aItems
);
void
AllItemsInNet
(
int
aNet
,
std
::
list
<
PNS_ITEM
*>&
aItems
);
private
:
struct
obstacleVisitor
;
typedef
boost
::
unordered_multimap
<
PNS_JOINT
::
HashTag
,
PNS_JOINT
>
JointMap
;
typedef
JointMap
::
value_type
TagJointPair
;
/// nodes are not copyable
PNS_NODE
(
const
PNS_NODE
&
b
);
PNS_NODE
&
operator
=
(
const
PNS_NODE
&
b
);
PNS_NODE
(
const
PNS_NODE
&
b
);
PNS_NODE
&
operator
=
(
const
PNS_NODE
&
b
);
///> tries to find matching joint and creates a new one if not found
PNS_JOINT
&
touchJoint
(
const
VECTOR2I
&
aPos
,
const
PNS_LAYERSET
&
aLayers
,
int
aNet
);
PNS_JOINT
&
touchJoint
(
const
VECTOR2I
&
aPos
,
const
PNS_LAYERSET
&
aLayers
,
int
aNet
);
///> touches a joint and links it to an item
void
linkJoint
(
const
VECTOR2I
&
aPos
,
const
PNS_LAYERSET
&
aLayers
,
int
aNet
,
PNS_ITEM
*
aWhere
);
void
linkJoint
(
const
VECTOR2I
&
aPos
,
const
PNS_LAYERSET
&
aLayers
,
int
aNet
,
PNS_ITEM
*
aWhere
);
///> unlinks an item from a joint
void
unlinkJoint
(
const
VECTOR2I
&
aPos
,
const
PNS_LAYERSET
&
aLayers
,
int
aNet
,
PNS_ITEM
*
aWhere
);
void
unlinkJoint
(
const
VECTOR2I
&
aPos
,
const
PNS_LAYERSET
&
aLayers
,
int
aNet
,
PNS_ITEM
*
aWhere
);
///> helpers for adding/removing items
void
addSolid
(
PNS_SOLID
*
aSeg
);
void
addSegment
(
PNS_SEGMENT
*
aSeg
);
void
addLine
(
PNS_LINE
*
aLine
);
void
addVia
(
PNS_VIA
*
aVia
);
void
removeSolid
(
PNS_SOLID
*
aSeg
);
void
removeLine
(
PNS_LINE
*
aLine
);
void
removeSegment
(
PNS_SEGMENT
*
aSeg
);
void
removeVia
(
PNS_VIA
*
aVia
);
void
doRemove
(
PNS_ITEM
*
aItem
);
void
unlinkParent
(
);
void
releaseChildren
();
void
addSolid
(
PNS_SOLID
*
aSeg
);
void
addSegment
(
PNS_SEGMENT
*
aSeg
);
void
addLine
(
PNS_LINE
*
aLine
);
void
addVia
(
PNS_VIA
*
aVia
);
void
removeSolid
(
PNS_SOLID
*
aSeg
);
void
removeLine
(
PNS_LINE
*
aLine
);
void
removeSegment
(
PNS_SEGMENT
*
aSeg
);
void
removeVia
(
PNS_VIA
*
aVia
);
void
doRemove
(
PNS_ITEM
*
aItem
);
void
unlinkParent
();
void
releaseChildren
();
bool
isRoot
()
const
{
return
m_parent
==
NULL
;
}
///> checks if this branch contains an updated version of the item from the root branch.
bool
overrides
(
PNS_ITEM
*
aItem
)
const
///> checks if this branch contains an updated version of the item
///> from the root branch.
bool
overrides
(
PNS_ITEM
*
aItem
)
const
{
return
m_override
.
find
(
aItem
)
!=
m_override
.
end
();
return
m_override
.
find
(
aItem
)
!=
m_override
.
end
();
}
///> scans the joint map, forming a line starting from segment (current).
void
followLine
(
PNS_SEGMENT
*
current
,
bool
scanDirection
,
int
&
pos
,
int
limit
,
VECTOR2I
*
corners
,
PNS_SEGMENT
**
segments
);
void
followLine
(
PNS_SEGMENT
*
current
,
bool
scanDirection
,
int
&
pos
,
int
limit
,
VECTOR2I
*
corners
,
PNS_SEGMENT
**
segments
);
///> spatial index of all items
//
SHAPE_INDEX_LIST<PNS_ITEM *> m_items;
//
SHAPE_INDEX_LIST<PNS_ITEM *> m_items;
///> hash table with the joints, linking the items. Joints are hashed by their
///> position, layer set and net.
///> hash table with the joints, linking the items. Joints are hashed by
///> their position, layer set and net.
JointMap
m_joints
;
///> node this node was branched from
PNS_NODE
*
m_parent
;
PNS_NODE
*
m_parent
;
///> root node of the whole hierarchy
PNS_NODE
*
m_root
;
PNS_NODE
*
m_root
;
///> list of nodes branched from this one
std
::
vector
<
PNS_NODE
*>
m_children
;
std
::
vector
<
PNS_NODE
*>
m_children
;
///> hash of root's items that are more recent in this node
boost
::
unordered_set
<
PNS_ITEM
*>
m_override
;
boost
::
unordered_set
<
PNS_ITEM
*>
m_override
;
///> worst case item-item clearance
int
m_maxClearance
;
///> Clearance resolution functor
PNS_CLEARANCE_FUNC
*
m_clearanceFunctor
;
PNS_CLEARANCE_FUNC
*
m_clearanceFunctor
;
///> Geometric/Net index of the items
PNS_INDEX
*
m_index
;
PNS_INDEX
*
m_index
;
///> list of currently processed obstacles.
Obstacles
m_obstacleList
;
...
...
pcbnew/router/pns_optimizer.cpp
View file @
5598acb6
...
...
@@ -17,6 +17,7 @@
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>.
*/
#include <boost/foreach.hpp>
#include <geometry/shape_line_chain.h>
...
...
@@ -27,76 +28,90 @@
#include "pns_optimizer.h"
#include "pns_utils.h"
using
namespace
std
;
/**
*
* Cost Estimator Methods
*
**/
Cost Estimator Methods
**/
int
PNS_COST_ESTIMATOR
::
CornerCost
(
const
SEG
&
a
,
const
SEG
&
b
)
int
PNS_COST_ESTIMATOR
::
CornerCost
(
const
SEG
&
a
,
const
SEG
&
b
)
{
DIRECTION_45
dir_a
(
a
),
dir_b
(
b
);
DIRECTION_45
dir_a
(
a
),
dir_b
(
b
);
switch
(
dir_a
.
Angle
(
dir_b
)
)
switch
(
dir_a
.
Angle
(
dir_b
)
)
{
case
DIRECTION_45
:
:
ANG_OBTUSE
:
return
1
;
case
DIRECTION_45
:
:
ANG_STRAIGHT
:
return
0
;
case
DIRECTION_45
:
:
ANG_ACUTE
:
return
50
;
case
DIRECTION_45
:
:
ANG_RIGHT
:
return
30
;
case
DIRECTION_45
:
:
ANG_HALF_FULL
:
return
60
;
default
:
return
100
;
}
}
int
PNS_COST_ESTIMATOR
::
CornerCost
(
const
SHAPE_LINE_CHAIN
&
aLine
)
int
PNS_COST_ESTIMATOR
::
CornerCost
(
const
SHAPE_LINE_CHAIN
&
aLine
)
{
int
total
=
0
;
for
(
int
i
=
0
;
i
<
aLine
.
SegmentCount
()
-
1
;
++
i
)
total
+=
CornerCost
(
aLine
.
CSegment
(
i
),
aLine
.
CSegment
(
i
+
1
));
for
(
int
i
=
0
;
i
<
aLine
.
SegmentCount
()
-
1
;
++
i
)
total
+=
CornerCost
(
aLine
.
CSegment
(
i
),
aLine
.
CSegment
(
i
+
1
)
);
return
total
;
}
int
PNS_COST_ESTIMATOR
::
CornerCost
(
const
PNS_LINE
&
aLine
)
int
PNS_COST_ESTIMATOR
::
CornerCost
(
const
PNS_LINE
&
aLine
)
{
return
CornerCost
(
aLine
.
GetCLine
()
);
return
CornerCost
(
aLine
.
GetCLine
()
);
}
void
PNS_COST_ESTIMATOR
::
Add
(
PNS_LINE
&
aLine
)
void
PNS_COST_ESTIMATOR
::
Add
(
PNS_LINE
&
aLine
)
{
m_lengthCost
+=
aLine
.
GetCLine
().
Length
();
m_cornerCost
+=
CornerCost
(
aLine
);
m_cornerCost
+=
CornerCost
(
aLine
);
}
void
PNS_COST_ESTIMATOR
::
Remove
(
PNS_LINE
&
aLine
)
void
PNS_COST_ESTIMATOR
::
Remove
(
PNS_LINE
&
aLine
)
{
m_lengthCost
-=
aLine
.
GetCLine
().
Length
();
m_cornerCost
-=
CornerCost
(
aLine
);
m_cornerCost
-=
CornerCost
(
aLine
);
}
void
PNS_COST_ESTIMATOR
::
Replace
(
PNS_LINE
&
aOldLine
,
PNS_LINE
&
aNewLine
)
void
PNS_COST_ESTIMATOR
::
Replace
(
PNS_LINE
&
aOldLine
,
PNS_LINE
&
aNewLine
)
{
m_lengthCost
-=
aOldLine
.
GetCLine
().
Length
();
m_cornerCost
-=
CornerCost
(
aOldLine
);
m_cornerCost
-=
CornerCost
(
aOldLine
);
m_lengthCost
+=
aNewLine
.
GetCLine
().
Length
();
m_cornerCost
+=
CornerCost
(
aNewLine
);
m_cornerCost
+=
CornerCost
(
aNewLine
);
}
bool
PNS_COST_ESTIMATOR
::
IsBetter
(
PNS_COST_ESTIMATOR
&
aOther
,
double
aLengthTollerance
,
double
aCornerTollerance
)
const
bool
PNS_COST_ESTIMATOR
::
IsBetter
(
PNS_COST_ESTIMATOR
&
aOther
,
double
aLengthTollerance
,
double
aCornerTollerance
)
const
{
if
(
aOther
.
m_cornerCost
<
m_cornerCost
&&
aOther
.
m_lengthCost
<
m_lengthCost
)
if
(
aOther
.
m_cornerCost
<
m_cornerCost
&&
aOther
.
m_lengthCost
<
m_lengthCost
)
return
true
;
else
if
(
aOther
.
m_cornerCost
<
m_cornerCost
*
aCornerTollerance
&&
aOther
.
m_lengthCost
<
m_lengthCost
*
aLengthTollerance
)
else
if
(
aOther
.
m_cornerCost
<
m_cornerCost
*
aCornerTollerance
&&
aOther
.
m_lengthCost
<
m_lengthCost
*
aLengthTollerance
)
return
true
;
return
false
;
...
...
@@ -104,133 +119,139 @@ bool PNS_COST_ESTIMATOR::IsBetter( PNS_COST_ESTIMATOR& aOther, double aLengthTol
/**
Optimizer
**/
PNS_OPTIMIZER
::
PNS_OPTIMIZER
(
PNS_NODE
*
aWorld
)
:
m_world
(
aWorld
),
m_collisionKindMask
(
PNS_ITEM
::
ANY
),
m_effortLevel
(
MERGE_SEGMENTS
)
{
*
* Optimizer
*
**/
PNS_OPTIMIZER
::
PNS_OPTIMIZER
(
PNS_NODE
*
aWorld
)
:
m_world
(
aWorld
),
m_collisionKindMask
(
PNS_ITEM
::
ANY
),
m_effortLevel
(
MERGE_SEGMENTS
)
{
// m_cache = new SHAPE_INDEX_LIST<PNS_ITEM*>();
}
}
PNS_OPTIMIZER
::~
PNS_OPTIMIZER
(
)
PNS_OPTIMIZER
::~
PNS_OPTIMIZER
(
)
{
//
delete m_cache;
//
delete m_cache;
}
struct
PNS_OPTIMIZER
::
CacheVisitor
{
CacheVisitor
(
const
PNS_ITEM
*
aOurItem
,
PNS_NODE
*
aNode
,
int
aMask
)
:
m_ourItem
(
aOurItem
),
m_collidingItem
(
NULL
),
m_node
(
aNode
),
m_mask
(
aMask
)
CacheVisitor
(
const
PNS_ITEM
*
aOurItem
,
PNS_NODE
*
aNode
,
int
aMask
)
:
m_ourItem
(
aOurItem
),
m_collidingItem
(
NULL
),
m_node
(
aNode
),
m_mask
(
aMask
)
{};
bool
operator
()
(
PNS_ITEM
*
aOtherItem
)
bool
operator
()(
PNS_ITEM
*
aOtherItem
)
{
if
(
!
m_mask
&
aOtherItem
->
GetKind
()
)
if
(
!
m_mask
&
aOtherItem
->
GetKind
()
)
return
true
;
int
clearance
=
m_node
->
GetClearance
(
aOtherItem
,
m_ourItem
);
int
clearance
=
m_node
->
GetClearance
(
aOtherItem
,
m_ourItem
);
if
(
!
aOtherItem
->
Collide
(
m_ourItem
,
clearance
)
)
if
(
!
aOtherItem
->
Collide
(
m_ourItem
,
clearance
)
)
return
true
;
m_collidingItem
=
aOtherItem
;
return
false
;
}
const
PNS_ITEM
*
m_ourItem
;
PNS_ITEM
*
m_collidingItem
;
PNS_NODE
*
m_node
;
const
PNS_ITEM
*
m_ourItem
;
PNS_ITEM
*
m_collidingItem
;
PNS_NODE
*
m_node
;
int
m_mask
;
};
void
PNS_OPTIMIZER
::
cacheAdd
(
PNS_ITEM
*
aItem
,
bool
aIsStatic
=
false
)
void
PNS_OPTIMIZER
::
cacheAdd
(
PNS_ITEM
*
aItem
,
bool
aIsStatic
=
false
)
{
if
(
m_cacheTags
.
find
(
aItem
)
!=
m_cacheTags
.
end
()
)
if
(
m_cacheTags
.
find
(
aItem
)
!=
m_cacheTags
.
end
()
)
return
;
m_cache
.
Add
(
aItem
);
m_cache
.
Add
(
aItem
);
m_cacheTags
[
aItem
].
hits
=
1
;
m_cacheTags
[
aItem
].
isStatic
=
aIsStatic
;
}
void
PNS_OPTIMIZER
::
removeCachedSegments
(
PNS_LINE
*
aLine
,
int
aStartVertex
,
int
aEndVertex
)
void
PNS_OPTIMIZER
::
removeCachedSegments
(
PNS_LINE
*
aLine
,
int
aStartVertex
,
int
aEndVertex
)
{
std
::
vector
<
PNS_SEGMENT
*>
*
segs
=
aLine
->
GetLinkedSegments
();
std
::
vector
<
PNS_SEGMENT
*>*
segs
=
aLine
->
GetLinkedSegments
();
if
(
!
segs
)
if
(
!
segs
)
return
;
if
(
aEndVertex
<
0
)
if
(
aEndVertex
<
0
)
aEndVertex
+=
aLine
->
GetCLine
().
PointCount
();
for
(
int
i
=
aStartVertex
;
i
<
aEndVertex
-
1
;
i
++
)
for
(
int
i
=
aStartVertex
;
i
<
aEndVertex
-
1
;
i
++
)
{
PNS_SEGMENT
*
s
=
(
*
segs
)[
i
];
m_cacheTags
.
erase
(
s
);
m_cache
.
Remove
(
s
);
}
//
*cacheRemove( (*segs)[i] );
PNS_SEGMENT
*
s
=
(
*
segs
)[
i
];
m_cacheTags
.
erase
(
s
);
m_cache
.
Remove
(
s
);
}
//
*cacheRemove( (*segs)[i] );
}
void
PNS_OPTIMIZER
::
CacheRemove
(
PNS_ITEM
*
aItem
)
void
PNS_OPTIMIZER
::
CacheRemove
(
PNS_ITEM
*
aItem
)
{
if
(
aItem
->
GetKind
()
==
PNS_ITEM
::
LINE
)
removeCachedSegments
(
static_cast
<
PNS_LINE
*>
(
aItem
)
);
if
(
aItem
->
GetKind
()
==
PNS_ITEM
::
LINE
)
removeCachedSegments
(
static_cast
<
PNS_LINE
*>
(
aItem
)
);
}
void
PNS_OPTIMIZER
::
CacheStaticItem
(
PNS_ITEM
*
aItem
)
void
PNS_OPTIMIZER
::
CacheStaticItem
(
PNS_ITEM
*
aItem
)
{
cacheAdd
(
aItem
,
true
);
cacheAdd
(
aItem
,
true
);
}
void
PNS_OPTIMIZER
::
ClearCache
(
bool
aStaticOnly
)
{
if
(
!
aStaticOnly
)
if
(
!
aStaticOnly
)
{
m_cacheTags
.
clear
();
m_cache
.
Clear
();
return
;
}
for
(
CachedItemTags
::
iterator
i
=
m_cacheTags
.
begin
();
i
!=
m_cacheTags
.
end
();
++
i
)
for
(
CachedItemTags
::
iterator
i
=
m_cacheTags
.
begin
();
i
!=
m_cacheTags
.
end
();
++
i
)
{
if
(
i
->
second
.
isStatic
)
if
(
i
->
second
.
isStatic
)
{
m_cache
.
Remove
(
i
->
first
);
m_cacheTags
.
erase
(
i
->
first
);
m_cache
.
Remove
(
i
->
first
);
m_cacheTags
.
erase
(
i
->
first
);
}
}
}
bool
PNS_OPTIMIZER
::
checkColliding
(
PNS_ITEM
*
aItem
,
bool
aUpdateCache
)
bool
PNS_OPTIMIZER
::
checkColliding
(
PNS_ITEM
*
aItem
,
bool
aUpdateCache
)
{
CacheVisitor
v
(
aItem
,
m_world
,
m_collisionKindMask
);
CacheVisitor
v
(
aItem
,
m_world
,
m_collisionKindMask
);
return
m_world
->
CheckColliding
(
aItem
);
return
m_world
->
CheckColliding
(
aItem
);
// something is wrong with the cache, need to investigate.
m_cache
.
Query
(
aItem
->
GetShape
(),
m_world
->
GetMaxClearance
(),
v
,
false
);
m_cache
.
Query
(
aItem
->
GetShape
(),
m_world
->
GetMaxClearance
(),
v
,
false
);
if
(
!
v
.
m_collidingItem
)
if
(
!
v
.
m_collidingItem
)
{
PNS_NODE
::
OptObstacle
obs
=
m_world
->
CheckColliding
(
aItem
);
PNS_NODE
::
OptObstacle
obs
=
m_world
->
CheckColliding
(
aItem
);
if
(
obs
)
{
if
(
obs
)
{
if
(
aUpdateCache
)
cacheAdd
(
obs
->
item
);
if
(
aUpdateCache
)
cacheAdd
(
obs
->
item
);
return
true
;
}
}
else
{
}
else
{
m_cacheTags
[
v
.
m_collidingItem
].
hits
++
;
return
true
;
}
...
...
@@ -238,34 +259,38 @@ bool PNS_OPTIMIZER::checkColliding ( PNS_ITEM *aItem, bool aUpdateCache )
return
false
;
}
bool
PNS_OPTIMIZER
::
checkColliding
(
PNS_LINE
*
aLine
,
const
SHAPE_LINE_CHAIN
&
aOptPath
)
bool
PNS_OPTIMIZER
::
checkColliding
(
PNS_LINE
*
aLine
,
const
SHAPE_LINE_CHAIN
&
aOptPath
)
{
PNS_LINE
tmp
(
*
aLine
,
aOptPath
);
return
checkColliding
(
&
tmp
);
PNS_LINE
tmp
(
*
aLine
,
aOptPath
);
return
checkColliding
(
&
tmp
);
}
bool
PNS_OPTIMIZER
::
mergeObtuse
(
PNS_LINE
*
aLine
)
bool
PNS_OPTIMIZER
::
mergeObtuse
(
PNS_LINE
*
aLine
)
{
SHAPE_LINE_CHAIN
&
line
=
aLine
->
GetLine
();
SHAPE_LINE_CHAIN
&
line
=
aLine
->
GetLine
();
int
step
=
line
.
PointCount
()
-
3
;
int
iter
=
0
;
int
segs_pre
=
line
.
SegmentCount
();
if
(
step
<
0
)
if
(
step
<
0
)
return
false
;
SHAPE_LINE_CHAIN
current_path
(
line
);
SHAPE_LINE_CHAIN
current_path
(
line
);
while
(
1
)
while
(
1
)
{
iter
++
;
int
n_segs
=
current_path
.
SegmentCount
();
int
max_step
=
n_segs
-
2
;
if
(
step
>
max_step
)
if
(
step
>
max_step
)
step
=
max_step
;
if
(
step
<
2
)
if
(
step
<
2
)
{
line
=
current_path
;
return
current_path
.
SegmentCount
()
<
segs_pre
;
...
...
@@ -274,103 +299,107 @@ bool PNS_OPTIMIZER::mergeObtuse (PNS_LINE *aLine)
bool
found_anything
=
false
;
int
n
=
0
;
while
(
n
<
n_segs
-
step
)
while
(
n
<
n_segs
-
step
)
{
const
SEG
s1
=
current_path
.
CSegment
(
n
);
const
SEG
s2
=
current_path
.
CSegment
(
n
+
step
);
const
SEG
s1
=
current_path
.
CSegment
(
n
);
const
SEG
s2
=
current_path
.
CSegment
(
n
+
step
);
SEG
s1opt
,
s2opt
;
if
(
DIRECTION_45
(
s1
).
IsObtuse
(
DIRECTION_45
(
s2
))
)
if
(
DIRECTION_45
(
s1
).
IsObtuse
(
DIRECTION_45
(
s2
)
)
)
{
VECTOR2I
ip
=
*
s1
.
IntersectLines
(
s2
);
VECTOR2I
ip
=
*
s1
.
IntersectLines
(
s2
);
if
(
s1
.
Distance
(
ip
)
<=
1
||
s2
.
Distance
(
ip
)
<=
1
)
if
(
s1
.
Distance
(
ip
)
<=
1
||
s2
.
Distance
(
ip
)
<=
1
)
{
s1opt
=
SEG
(
s1
.
a
,
ip
);
s2opt
=
SEG
(
ip
,
s2
.
b
);
}
else
{
s1opt
=
SEG
(
s1
.
a
,
ip
);
s2opt
=
SEG
(
ip
,
s2
.
b
);
s1opt
=
SEG
(
s1
.
a
,
ip
);
s2opt
=
SEG
(
ip
,
s2
.
b
);
}
else
{
s1opt
=
SEG
(
s1
.
a
,
ip
);
s2opt
=
SEG
(
ip
,
s2
.
b
);
}
if
(
DIRECTION_45
(
s1opt
).
IsObtuse
(
DIRECTION_45
(
s2opt
))
)
if
(
DIRECTION_45
(
s1opt
).
IsObtuse
(
DIRECTION_45
(
s2opt
)
)
)
{
SHAPE_LINE_CHAIN
opt_path
;
opt_path
.
Append
(
s1opt
.
a
);
opt_path
.
Append
(
s1opt
.
b
);
opt_path
.
Append
(
s2opt
.
b
);
opt_path
.
Append
(
s1opt
.
a
);
opt_path
.
Append
(
s1opt
.
b
);
opt_path
.
Append
(
s2opt
.
b
);
PNS_LINE
opt_track
(
*
aLine
,
opt_path
);
PNS_LINE
opt_track
(
*
aLine
,
opt_path
);
if
(
!
checkColliding
(
&
opt_track
)
)
if
(
!
checkColliding
(
&
opt_track
)
)
{
current_path
.
Replace
(
s1
.
Index
()
+
1
,
s2
.
Index
(),
ip
);
//
removeCachedSegments(aLine, s1.Index(), s2.Index());
current_path
.
Replace
(
s1
.
Index
()
+
1
,
s2
.
Index
(),
ip
);
//
removeCachedSegments(aLine, s1.Index(), s2.Index());
n_segs
=
current_path
.
SegmentCount
();
found_anything
=
true
;
break
;
}
}
}
n
++
;
}
if
(
!
found_anything
)
if
(
!
found_anything
)
{
if
(
step
<=
2
)
{
line
=
current_path
;
return
line
.
SegmentCount
()
<
segs_pre
;
}
step
--
;
step
--
;
}
}
return
line
.
SegmentCount
()
<
segs_pre
;
}
bool
PNS_OPTIMIZER
::
mergeFull
(
PNS_LINE
*
aLine
)
bool
PNS_OPTIMIZER
::
mergeFull
(
PNS_LINE
*
aLine
)
{
SHAPE_LINE_CHAIN
&
line
=
aLine
->
GetLine
();
SHAPE_LINE_CHAIN
&
line
=
aLine
->
GetLine
();
int
step
=
line
.
SegmentCount
()
-
1
;
int
segs_pre
=
line
.
SegmentCount
();
line
.
Simplify
();
if
(
step
<
0
)
if
(
step
<
0
)
return
false
;
SHAPE_LINE_CHAIN
current_path
(
line
);
SHAPE_LINE_CHAIN
current_path
(
line
);
while
(
1
)
while
(
1
)
{
int
n_segs
=
current_path
.
SegmentCount
();
int
max_step
=
n_segs
-
2
;
if
(
step
>
max_step
)
if
(
step
>
max_step
)
step
=
max_step
;
if
(
step
<
1
)
if
(
step
<
1
)
break
;
bool
found_anything
=
mergeStep
(
aLine
,
current_path
,
step
);
if
(
!
found_anything
)
step
--
;
bool
found_anything
=
mergeStep
(
aLine
,
current_path
,
step
);
if
(
!
found_anything
)
step
--
;
}
aLine
->
SetShape
(
current_path
);
aLine
->
SetShape
(
current_path
);
return
current_path
.
SegmentCount
()
<
segs_pre
;
}
bool
PNS_OPTIMIZER
::
Optimize
(
PNS_LINE
*
aLine
,
PNS_LINE
*
aResult
,
int
aStartVertex
,
int
aEndVertex
)
bool
PNS_OPTIMIZER
::
Optimize
(
PNS_LINE
*
aLine
,
PNS_LINE
*
aResult
,
int
aStartVertex
,
int
aEndVertex
)
{
if
(
!
aResult
)
if
(
!
aResult
)
aResult
=
aLine
;
else
*
aResult
=
*
aLine
;
...
...
@@ -378,99 +407,107 @@ bool PNS_OPTIMIZER::Optimize ( PNS_LINE *aLine, PNS_LINE *aResult , int aStartVe
m_keepPostures
=
false
;
bool
rv
=
false
;
if
(
m_effortLevel
&
MERGE_SEGMENTS
)
rv
|=
mergeFull
(
aResult
);
if
(
m_effortLevel
&
MERGE_OBTUSE
)
rv
|=
mergeObtuse
(
aResult
);
if
(
m_effortLevel
&
SMART_PADS
)
rv
|=
runSmartPads
(
aResult
);
if
(
m_effortLevel
&
MERGE_SEGMENTS
)
rv
|=
mergeFull
(
aResult
);
if
(
m_effortLevel
&
MERGE_OBTUSE
)
rv
|=
mergeObtuse
(
aResult
);
if
(
m_effortLevel
&
SMART_PADS
)
rv
|=
runSmartPads
(
aResult
);
return
rv
;
}
bool
PNS_OPTIMIZER
::
mergeStep
(
PNS_LINE
*
aLine
,
SHAPE_LINE_CHAIN
&
aCurrentPath
,
int
step
)
bool
PNS_OPTIMIZER
::
mergeStep
(
PNS_LINE
*
aLine
,
SHAPE_LINE_CHAIN
&
aCurrentPath
,
int
step
)
{
int
n
=
0
;
int
n_segs
=
aCurrentPath
.
SegmentCount
();
int
cost_orig
=
PNS_COST_ESTIMATOR
::
CornerCost
(
aCurrentPath
);
int
cost_orig
=
PNS_COST_ESTIMATOR
::
CornerCost
(
aCurrentPath
);
if
(
aLine
->
GetCLine
().
SegmentCount
()
<
4
)
if
(
aLine
->
GetCLine
().
SegmentCount
()
<
4
)
return
false
;
DIRECTION_45
orig_start
(
aLine
->
GetCLine
().
CSegment
(
0
)
);
DIRECTION_45
orig_end
(
aLine
->
GetCLine
().
CSegment
(
-
1
)
);
DIRECTION_45
orig_start
(
aLine
->
GetCLine
().
CSegment
(
0
)
);
DIRECTION_45
orig_end
(
aLine
->
GetCLine
().
CSegment
(
-
1
)
);
while
(
n
<
n_segs
-
step
)
while
(
n
<
n_segs
-
step
)
{
const
SEG
s1
=
aCurrentPath
.
CSegment
(
n
);
const
SEG
s2
=
aCurrentPath
.
CSegment
(
n
+
step
);
const
SEG
s1
=
aCurrentPath
.
CSegment
(
n
);
const
SEG
s2
=
aCurrentPath
.
CSegment
(
n
+
step
);
SHAPE_LINE_CHAIN
path
[
2
],
*
picked
=
NULL
;
SHAPE_LINE_CHAIN
path
[
2
],
*
picked
=
NULL
;
int
cost
[
2
];
for
(
int
i
=
0
;
i
<
2
;
i
++
)
for
(
int
i
=
0
;
i
<
2
;
i
++
)
{
bool
postureMatch
=
true
;
SHAPE_LINE_CHAIN
bypass
=
DIRECTION_45
().
BuildInitialTrace
(
s1
.
a
,
s2
.
b
,
i
);
SHAPE_LINE_CHAIN
bypass
=
DIRECTION_45
().
BuildInitialTrace
(
s1
.
a
,
s2
.
b
,
i
);
cost
[
i
]
=
INT_MAX
;
if
(
n
==
0
&&
orig_start
!=
DIRECTION_45
(
bypass
.
CSegment
(
0
)
)
)
if
(
n
==
0
&&
orig_start
!=
DIRECTION_45
(
bypass
.
CSegment
(
0
)
)
)
postureMatch
=
false
;
else
if
(
n
==
n_segs
-
step
&&
orig_end
!=
DIRECTION_45
(
bypass
.
CSegment
(
-
1
))
)
else
if
(
n
==
n_segs
-
step
&&
orig_end
!=
DIRECTION_45
(
bypass
.
CSegment
(
-
1
)
)
)
postureMatch
=
false
;
if
((
postureMatch
||
!
m_keepPostures
)
&&
!
checkColliding
(
aLine
,
bypass
)
)
if
(
(
postureMatch
||
!
m_keepPostures
)
&&
!
checkColliding
(
aLine
,
bypass
)
)
{
path
[
i
]
=
aCurrentPath
;
path
[
i
].
Replace
(
s1
.
Index
(),
s2
.
Index
(),
bypass
);
path
[
i
].
Replace
(
s1
.
Index
(),
s2
.
Index
(),
bypass
);
path
[
i
].
Simplify
();
cost
[
i
]
=
PNS_COST_ESTIMATOR
::
CornerCost
(
path
[
i
]
);
cost
[
i
]
=
PNS_COST_ESTIMATOR
::
CornerCost
(
path
[
i
]
);
}
}
if
(
cost
[
0
]
<
cost_orig
&&
cost
[
0
]
<
cost
[
1
]
)
if
(
cost
[
0
]
<
cost_orig
&&
cost
[
0
]
<
cost
[
1
]
)
picked
=
&
path
[
0
];
else
if
(
cost
[
1
]
<
cost_orig
)
else
if
(
cost
[
1
]
<
cost_orig
)
picked
=
&
path
[
1
];
if
(
picked
)
if
(
picked
)
{
n_segs
=
aCurrentPath
.
SegmentCount
();
aCurrentPath
=
*
picked
;
return
true
;
}
n
++
;
}
return
false
;
}
PNS_OPTIMIZER
::
BreakoutList
PNS_OPTIMIZER
::
circleBreakouts
(
int
aWidth
,
const
SHAPE
*
aShape
,
bool
aPermitDiagonal
)
const
PNS_OPTIMIZER
::
BreakoutList
PNS_OPTIMIZER
::
circleBreakouts
(
int
aWidth
,
const
SHAPE
*
aShape
,
bool
aPermitDiagonal
)
const
{
BreakoutList
breakouts
;
for
(
int
angle
=
0
;
angle
<
360
;
angle
+=
45
)
for
(
int
angle
=
0
;
angle
<
360
;
angle
+=
45
)
{
const
SHAPE_CIRCLE
*
cir
=
static_cast
<
const
SHAPE_CIRCLE
*>
(
aShape
);
const
SHAPE_CIRCLE
*
cir
=
static_cast
<
const
SHAPE_CIRCLE
*>
(
aShape
);
SHAPE_LINE_CHAIN
l
;
VECTOR2I
p0
=
cir
->
GetCenter
();
VECTOR2I
v0
(
cir
->
GetRadius
()
*
M_SQRT2
,
0
);
l
.
Append
(
p0
);
l
.
Append
(
p0
+
v0
.
Rotate
(
angle
*
M_PI
/
180.0
)
);
breakouts
.
push_back
(
l
);
VECTOR2I
p0
=
cir
->
GetCenter
();
VECTOR2I
v0
(
cir
->
GetRadius
()
*
M_SQRT2
,
0
);
l
.
Append
(
p0
);
l
.
Append
(
p0
+
v0
.
Rotate
(
angle
*
M_PI
/
180.0
)
);
breakouts
.
push_back
(
l
);
}
return
breakouts
;
}
PNS_OPTIMIZER
::
BreakoutList
PNS_OPTIMIZER
::
rectBreakouts
(
int
aWidth
,
const
SHAPE
*
aShape
,
bool
aPermitDiagonal
)
const
PNS_OPTIMIZER
::
BreakoutList
PNS_OPTIMIZER
::
rectBreakouts
(
int
aWidth
,
const
SHAPE
*
aShape
,
bool
aPermitDiagonal
)
const
{
const
SHAPE_RECT
*
rect
=
static_cast
<
const
SHAPE_RECT
*>
(
aShape
);
VECTOR2I
s
=
rect
->
GetSize
(),
c
=
rect
->
GetPosition
()
+
VECTOR2I
(
s
.
x
/
2
,
s
.
y
/
2
);
const
SHAPE_RECT
*
rect
=
static_cast
<
const
SHAPE_RECT
*>
(
aShape
);
VECTOR2I
s
=
rect
->
GetSize
(),
c
=
rect
->
GetPosition
()
+
VECTOR2I
(
s
.
x
/
2
,
s
.
y
/
2
);
BreakoutList
breakouts
;
VECTOR2I
d_offset
;
...
...
@@ -478,33 +515,42 @@ PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::rectBreakouts( int aWidth, const SHAP
d_offset
.
x
=
(
s
.
x
>
s
.
y
)
?
(
s
.
x
-
s
.
y
)
/
2
:
0
;
d_offset
.
y
=
(
s
.
x
<
s
.
y
)
?
(
s
.
y
-
s
.
x
)
/
2
:
0
;
VECTOR2I
d_vert
=
VECTOR2I
(
0
,
s
.
y
/
2
+
aWidth
);
VECTOR2I
d_horiz
=
VECTOR2I
(
s
.
x
/
2
+
aWidth
,
0
);
VECTOR2I
d_vert
=
VECTOR2I
(
0
,
s
.
y
/
2
+
aWidth
);
VECTOR2I
d_horiz
=
VECTOR2I
(
s
.
x
/
2
+
aWidth
,
0
);
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
+
d_horiz
)
);
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
-
d_horiz
)
);
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
+
d_vert
)
);
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
-
d_vert
)
);
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
+
d_horiz
)
);
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
-
d_horiz
)
);
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
+
d_vert
)
);
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
-
d_vert
)
);
if
(
aPermitDiagonal
)
if
(
aPermitDiagonal
)
{
int
l
=
aWidth
+
std
::
min
(
s
.
x
,
s
.
y
)
/
2
;
VECTOR2I
d_diag
;
int
l
=
aWidth
+
std
::
min
(
s
.
x
,
s
.
y
)
/
2
;
VECTOR2I
d_diag
;
if
(
s
.
x
>=
s
.
y
)
if
(
s
.
x
>=
s
.
y
)
{
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
+
d_offset
,
c
+
d_offset
+
VECTOR2I
(
l
,
l
)
)
);
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
+
d_offset
,
c
+
d_offset
-
VECTOR2I
(
-
l
,
l
)
)
);
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
-
d_offset
,
c
-
d_offset
+
VECTOR2I
(
-
l
,
l
)
)
);
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
-
d_offset
,
c
-
d_offset
-
VECTOR2I
(
l
,
l
)
)
);
}
else
{
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
+
d_offset
,
c
+
d_offset
+
VECTOR2I
(
l
,
l
)));
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
+
d_offset
,
c
+
d_offset
-
VECTOR2I
(
-
l
,
l
)));
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
-
d_offset
,
c
-
d_offset
+
VECTOR2I
(
-
l
,
l
)));
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
-
d_offset
,
c
-
d_offset
-
VECTOR2I
(
l
,
l
)));
}
else
{
// fixme: this could be done more efficiently
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
+
d_offset
,
c
+
d_offset
+
VECTOR2I
(
l
,
l
)));
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
-
d_offset
,
c
-
d_offset
-
VECTOR2I
(
-
l
,
l
)));
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
+
d_offset
,
c
+
d_offset
+
VECTOR2I
(
-
l
,
l
)));
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
-
d_offset
,
c
-
d_offset
-
VECTOR2I
(
l
,
l
)));
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
+
d_offset
,
c
+
d_offset
+
VECTOR2I
(
l
,
l
)
)
);
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
-
d_offset
,
c
-
d_offset
-
VECTOR2I
(
-
l
,
l
)
)
);
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
+
d_offset
,
c
+
d_offset
+
VECTOR2I
(
-
l
,
l
)
)
);
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
-
d_offset
,
c
-
d_offset
-
VECTOR2I
(
l
,
l
)
)
);
}
}
...
...
@@ -512,114 +558,123 @@ PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::rectBreakouts( int aWidth, const SHAP
}
PNS_OPTIMIZER
::
BreakoutList
PNS_OPTIMIZER
::
computeBreakouts
(
int
aWidth
,
const
PNS_ITEM
*
aItem
,
bool
aPermitDiagonal
)
const
PNS_OPTIMIZER
::
BreakoutList
PNS_OPTIMIZER
::
computeBreakouts
(
int
aWidth
,
const
PNS_ITEM
*
aItem
,
bool
aPermitDiagonal
)
const
{
switch
(
aItem
->
GetKind
()
)
switch
(
aItem
->
GetKind
()
)
{
case
PNS_ITEM
:
:
VIA
:
{
const
PNS_VIA
*
via
=
static_cast
<
const
PNS_VIA
*>
(
aItem
);
return
circleBreakouts
(
aWidth
,
via
->
GetShape
(),
aPermitDiagonal
);
const
PNS_VIA
*
via
=
static_cast
<
const
PNS_VIA
*>
(
aItem
);
return
circleBreakouts
(
aWidth
,
via
->
GetShape
(),
aPermitDiagonal
);
}
case
PNS_ITEM
:
:
SOLID
:
{
const
SHAPE
*
shape
=
aItem
->
GetShape
();
switch
(
shape
->
Type
())
const
SHAPE
*
shape
=
aItem
->
GetShape
();
switch
(
shape
->
Type
()
)
{
case
SH_RECT
:
return
rectBreakouts
(
aWidth
,
shape
,
aPermitDiagonal
);
return
rectBreakouts
(
aWidth
,
shape
,
aPermitDiagonal
);
case
SH_CIRCLE
:
return
circleBreakouts
(
aWidth
,
shape
,
aPermitDiagonal
);
return
circleBreakouts
(
aWidth
,
shape
,
aPermitDiagonal
);
default
:
break
;
}
}
default
:
break
;
}
return
BreakoutList
();
}
PNS_ITEM
*
PNS_OPTIMIZER
::
findPadOrVia
(
int
aLayer
,
int
aNet
,
const
VECTOR2I
&
aP
)
const
PNS_ITEM
*
PNS_OPTIMIZER
::
findPadOrVia
(
int
aLayer
,
int
aNet
,
const
VECTOR2I
&
aP
)
const
{
PNS_NODE
::
OptJoint
jt
=
m_world
->
FindJoint
(
aP
,
aLayer
,
aNet
);
if
(
!
jt
)
PNS_NODE
::
OptJoint
jt
=
m_world
->
FindJoint
(
aP
,
aLayer
,
aNet
);
if
(
!
jt
)
return
NULL
;
BOOST_FOREACH
(
PNS_ITEM
*
item
,
jt
->
GetLinkList
()
)
BOOST_FOREACH
(
PNS_ITEM
*
item
,
jt
->
GetLinkList
()
)
{
if
(
item
->
GetKind
()
==
PNS_ITEM
::
VIA
||
item
->
GetKind
()
==
PNS_ITEM
::
SOLID
)
if
(
item
->
GetKind
()
==
PNS_ITEM
::
VIA
||
item
->
GetKind
()
==
PNS_ITEM
::
SOLID
)
return
item
;
}
return
NULL
;
}
int
PNS_OPTIMIZER
::
smartPadsSingle
(
PNS_LINE
*
aLine
,
PNS_ITEM
*
aPad
,
bool
aEnd
,
int
aEndVertex
)
int
PNS_OPTIMIZER
::
smartPadsSingle
(
PNS_LINE
*
aLine
,
PNS_ITEM
*
aPad
,
bool
aEnd
,
int
aEndVertex
)
{
int
min_cost
=
INT_MAX
;
//
PNS_COST_ESTIMATOR::CornerCost( line );
int
min_cost
=
INT_MAX
;
//
PNS_COST_ESTIMATOR::CornerCost( line );
int
min_len
=
INT_MAX
;
DIRECTION_45
dir
;
const
int
ForbiddenAngles
=
DIRECTION_45
::
ANG_ACUTE
|
DIRECTION_45
::
ANG_RIGHT
|
DIRECTION_45
::
ANG_HALF_FULL
|
DIRECTION_45
::
ANG_UNDEFINED
;
const
int
ForbiddenAngles
=
DIRECTION_45
::
ANG_ACUTE
|
DIRECTION_45
::
ANG_RIGHT
|
DIRECTION_45
::
ANG_HALF_FULL
|
DIRECTION_45
::
ANG_UNDEFINED
;
typedef
pair
<
int
,
SHAPE_LINE_CHAIN
>
RtVariant
;
vector
<
RtVariant
>
variants
;
BreakoutList
breakouts
=
computeBreakouts
(
aLine
->
GetWidth
(),
aPad
,
true
);
SHAPE_LINE_CHAIN
line
=
(
aEnd
?
aLine
->
GetCLine
().
Reverse
()
:
aLine
->
GetCLine
()
);
SHAPE_LINE_CHAIN
line
=
(
aEnd
?
aLine
->
GetCLine
().
Reverse
()
:
aLine
->
GetCLine
()
);
//
bool startDiagonal = DIRECTION_45( line.CSegment(0) ).IsDiagonal();
//
bool startDiagonal = DIRECTION_45( line.CSegment(0) ).IsDiagonal();
int
p_end
=
min
(
aEndVertex
,
min
(
3
,
line
.
PointCount
()
-
1
)
);
int
p_end
=
min
(
aEndVertex
,
min
(
3
,
line
.
PointCount
()
-
1
)
);
for
(
int
p
=
1
;
p
<=
p_end
;
p
++
)
{
BOOST_FOREACH
(
SHAPE_LINE_CHAIN
&
l
,
breakouts
)
for
(
int
p
=
1
;
p
<=
p_end
;
p
++
)
{
//PNSDisplayDebugLine (l, 0);
BOOST_FOREACH
(
SHAPE_LINE_CHAIN
&
l
,
breakouts
)
{
// PNSDisplayDebugLine (l, 0);
for
(
int
diag
=
0
;
diag
<
2
;
diag
++
)
for
(
int
diag
=
0
;
diag
<
2
;
diag
++
)
{
SHAPE_LINE_CHAIN
v
;
SHAPE_LINE_CHAIN
connect
=
dir
.
BuildInitialTrace
(
l
.
CPoint
(
-
1
),
line
.
CPoint
(
p
),
diag
==
0
);
SHAPE_LINE_CHAIN
connect
=
dir
.
BuildInitialTrace
(
l
.
CPoint
(
-
1
),
line
.
CPoint
(
p
),
diag
==
0
);
DIRECTION_45
dir_bkout
(
l
.
CSegment
(
-
1
)
);
//
DIRECTION_45 dir_head ( line.CSegment(p + 1));
DIRECTION_45
dir_bkout
(
l
.
CSegment
(
-
1
)
);
//
DIRECTION_45 dir_head ( line.CSegment(p + 1));
int
ang1
=
dir_bkout
.
Angle
(
DIRECTION_45
(
connect
.
CSegment
(
0
)
)
);
int
ang1
=
dir_bkout
.
Angle
(
DIRECTION_45
(
connect
.
CSegment
(
0
)
)
);
int
ang2
=
0
;
//
int ang2 = dir_head.Angle ( DIRECTION_45(connect.CSegment(-1) ));
//
int ang2 = dir_head.Angle ( DIRECTION_45(connect.CSegment(-1) ));
if
(
(
ang1
|
ang2
)
&
ForbiddenAngles
)
continue
;
if
(
l
.
Length
()
>
line
.
Length
()
)
if
(
l
.
Length
()
>
line
.
Length
()
)
continue
;
v
=
l
;
v
.
Append
(
connect
);
v
.
Append
(
connect
);
for
(
int
i
=
p
+
1
;
i
<
line
.
PointCount
();
i
++
)
v
.
Append
(
line
.
CPoint
(
i
)
);
for
(
int
i
=
p
+
1
;
i
<
line
.
PointCount
();
i
++
)
v
.
Append
(
line
.
CPoint
(
i
)
);
PNS_LINE
tmp
(
*
aLine
,
v
);
//
tmp.GetLine().Simplify();
int
cc
=
tmp
.
CountCorners
(
ForbiddenAngles
);
PNS_LINE
tmp
(
*
aLine
,
v
);
//
tmp.GetLine().Simplify();
int
cc
=
tmp
.
CountCorners
(
ForbiddenAngles
);
if
(
cc
==
0
)
if
(
cc
==
0
)
{
RtVariant
vp
;
vp
.
first
=
p
;
vp
.
second
=
aEnd
?
v
.
Reverse
()
:
v
;
vp
.
second
.
Simplify
();
variants
.
push_back
(
vp
);
variants
.
push_back
(
vp
);
}
}
}
}
...
...
@@ -628,37 +683,35 @@ int PNS_OPTIMIZER::smartPadsSingle( PNS_LINE *aLine, PNS_ITEM *aPad, bool aEnd,
bool
found
=
false
;
int
p_best
=
-
1
;
BOOST_FOREACH
(
RtVariant
&
vp
,
variants
)
BOOST_FOREACH
(
RtVariant
&
vp
,
variants
)
{
PNS_LINE
tmp
(
*
aLine
,
vp
.
second
);
int
cost
=
PNS_COST_ESTIMATOR
::
CornerCost
(
vp
.
second
);
PNS_LINE
tmp
(
*
aLine
,
vp
.
second
);
int
cost
=
PNS_COST_ESTIMATOR
::
CornerCost
(
vp
.
second
);
int
len
=
vp
.
second
.
Length
();
if
(
!
checkColliding
(
&
tmp
)
)
if
(
!
checkColliding
(
&
tmp
)
)
{
/* if(aEnd)
PNSDisplayDebugLine (l_best, 6);
else
PNSDisplayDebugLine (l_best, 5);*/
*
PNSDisplayDebugLine (l_best, 6);
*
else
*
PNSDisplayDebugLine (l_best, 5);*/
if
(
cost
<
min_cost
||
(
cost
==
min_cost
&&
len
<
min_len
)
)
if
(
cost
<
min_cost
||
(
cost
==
min_cost
&&
len
<
min_len
)
)
{
l_best
=
vp
.
second
;
p_best
=
vp
.
first
;
found
=
true
;
//if(cost == min_cost)
if
(
cost
==
min_cost
)
min_len
=
std
::
min
(
len
,
min_len
);
min_cost
=
std
::
min
(
cost
,
min_cost
);
}
// if(cost == min_cost)
if
(
cost
==
min_cost
)
min_len
=
std
::
min
(
len
,
min_len
);
min_cost
=
std
::
min
(
cost
,
min_cost
);
}
}
}
if
(
found
)
if
(
found
)
{
// printf("end: %d, p-best: %d, p-end: %d, p-total: %d\n", aEnd, p_best, p_end, l_best.PointCount());
...
...
@@ -666,39 +719,46 @@ int PNS_OPTIMIZER::smartPadsSingle( PNS_LINE *aLine, PNS_ITEM *aPad, bool aEnd,
// PNSDisplayDebugLine (l_best, 5);
// else
aLine
->
SetShape
(
l_best
);
aLine
->
SetShape
(
l_best
);
return
p_best
;
}
return
-
1
;
}
bool
PNS_OPTIMIZER
::
runSmartPads
(
PNS_LINE
*
aLine
)
bool
PNS_OPTIMIZER
::
runSmartPads
(
PNS_LINE
*
aLine
)
{
SHAPE_LINE_CHAIN
&
line
=
aLine
->
GetLine
();
if
(
line
.
PointCount
()
<
3
)
if
(
line
.
PointCount
()
<
3
)
return
false
;
VECTOR2I
p_start
=
line
.
CPoint
(
0
),
p_end
=
line
.
CPoint
(
-
1
);
VECTOR2I
p_start
=
line
.
CPoint
(
0
),
p_end
=
line
.
CPoint
(
-
1
);
PNS_ITEM
*
startPad
=
findPadOrVia
(
aLine
->
GetLayer
(),
aLine
->
GetNet
(),
p_start
);
PNS_ITEM
*
endPad
=
findPadOrVia
(
aLine
->
GetLayer
(),
aLine
->
GetNet
(),
p_end
);
PNS_ITEM
*
startPad
=
findPadOrVia
(
aLine
->
GetLayer
(),
aLine
->
GetNet
(),
p_start
);
PNS_ITEM
*
endPad
=
findPadOrVia
(
aLine
->
GetLayer
(),
aLine
->
GetNet
(),
p_end
);
int
vtx
=
-
1
;
if
(
startPad
)
vtx
=
smartPadsSingle
(
aLine
,
startPad
,
false
,
3
);
if
(
endPad
)
smartPadsSingle
(
aLine
,
endPad
,
true
,
vtx
<
0
?
line
.
PointCount
()
-
1
:
line
.
PointCount
()
-
1
-
vtx
);
if
(
startPad
)
vtx
=
smartPadsSingle
(
aLine
,
startPad
,
false
,
3
);
if
(
endPad
)
smartPadsSingle
(
aLine
,
endPad
,
true
,
vtx
<
0
?
line
.
PointCount
()
-
1
:
line
.
PointCount
()
-
1
-
vtx
);
aLine
->
GetLine
().
Simplify
();
return
true
;
}
bool
PNS_OPTIMIZER
::
Optimize
(
PNS_LINE
*
aLine
,
int
aEffortLevel
,
PNS_NODE
*
aWorld
)
bool
PNS_OPTIMIZER
::
Optimize
(
PNS_LINE
*
aLine
,
int
aEffortLevel
,
PNS_NODE
*
aWorld
)
{
PNS_OPTIMIZER
opt
(
aWorld
?
aWorld
:
aLine
->
GetWorld
()
);
opt
.
SetEffortLevel
(
aEffortLevel
);
opt
.
SetCollisionMask
(
-
1
);
return
opt
.
Optimize
(
aLine
);
opt
.
SetEffortLevel
(
aEffortLevel
);
opt
.
SetCollisionMask
(
-
1
);
return
opt
.
Optimize
(
aLine
);
}
pcbnew/router/pns_optimizer.h
View file @
5598acb6
...
...
@@ -17,6 +17,7 @@
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>.
*/
#ifndef __PNS_OPTIMIZER_H
#define __PNS_OPTIMIZER_H
...
...
@@ -30,7 +31,6 @@ class PNS_NODE;
class
PNS_LINE
;
class
PNS_ROUTER
;
/**
* Class PNS_COST_ESTIMATOR
*
...
...
@@ -39,33 +39,34 @@ class PNS_ROUTER;
class
PNS_COST_ESTIMATOR
{
public
:
PNS_COST_ESTIMATOR
()
:
m_lengthCost
(
0
),
m_cornerCost
(
0
)
public
:
PNS_COST_ESTIMATOR
()
:
m_lengthCost
(
0
),
m_cornerCost
(
0
)
{};
PNS_COST_ESTIMATOR
(
const
PNS_COST_ESTIMATOR
&
b
)
:
m_lengthCost
(
b
.
m_lengthCost
),
m_cornerCost
(
b
.
m_cornerCost
)
PNS_COST_ESTIMATOR
(
const
PNS_COST_ESTIMATOR
&
b
)
:
m_lengthCost
(
b
.
m_lengthCost
),
m_cornerCost
(
b
.
m_cornerCost
)
{};
~
PNS_COST_ESTIMATOR
()
{};
static
int
CornerCost
(
const
SEG
&
a
,
const
SEG
&
b
);
static
int
CornerCost
(
const
SHAPE_LINE_CHAIN
&
aLine
);
static
int
CornerCost
(
const
PNS_LINE
&
aLine
);
static
int
CornerCost
(
const
SEG
&
a
,
const
SEG
&
b
);
static
int
CornerCost
(
const
SHAPE_LINE_CHAIN
&
aLine
);
static
int
CornerCost
(
const
PNS_LINE
&
aLine
);
void
Add
(
PNS_LINE
&
aLine
);
void
Remove
(
PNS_LINE
&
aLine
);
void
Replace
(
PNS_LINE
&
aOldLine
,
PNS_LINE
&
aNewLine
);
void
Add
(
PNS_LINE
&
aLine
);
void
Remove
(
PNS_LINE
&
aLine
);
void
Replace
(
PNS_LINE
&
aOldLine
,
PNS_LINE
&
aNewLine
);
bool
IsBetter
(
PNS_COST_ESTIMATOR
&
aOther
,
double
aLengthTollerance
,
double
aCornerTollerace
)
const
;
bool
IsBetter
(
PNS_COST_ESTIMATOR
&
aOther
,
double
aLengthTollerance
,
double
aCornerTollerace
)
const
;
double
GetLengthCost
()
const
{
return
m_lengthCost
;
}
double
GetCornerCost
()
const
{
return
m_cornerCost
;
}
private
:
private
:
double
m_lengthCost
;
int
m_cornerCost
;
};
...
...
@@ -84,39 +85,39 @@ class PNS_COST_ESTIMATOR
class
PNS_OPTIMIZER
{
public
:
enum
OptimizationEffort
{
MERGE_SEGMENTS
=
0x
1
,
SMART_PADS
=
0x
2
,
MERGE_OBTUSE
=
0x
4
public
:
enum
OptimizationEffort
{
MERGE_SEGMENTS
=
0x0
1
,
SMART_PADS
=
0x0
2
,
MERGE_OBTUSE
=
0x0
4
};
PNS_OPTIMIZER
(
PNS_NODE
*
aWorld
);
PNS_OPTIMIZER
(
PNS_NODE
*
aWorld
);
~
PNS_OPTIMIZER
();
///> a quick shortcut to optmize a line without creating and setting up an optimizer
static
bool
Optimize
(
PNS_LINE
*
aLine
,
int
aEffortLevel
,
PNS_NODE
*
aWorld
=
NULL
);
static
bool
Optimize
(
PNS_LINE
*
aLine
,
int
aEffortLevel
,
PNS_NODE
*
aWorld
=
NULL
);
bool
Optimize
(
PNS_LINE
*
aLine
,
PNS_LINE
*
aResult
=
NULL
,
int
aStartVertex
=
0
,
int
aEndVertex
=
-
1
);
bool
Optimize
(
PNS_LINE
*
aLine
,
PNS_LINE
*
aResult
=
NULL
,
int
aStartVertex
=
0
,
int
aEndVertex
=
-
1
);
void
SetWorld
(
PNS_NODE
*
aNode
)
{
m_world
=
aNode
;
}
void
CacheStaticItem
(
PNS_ITEM
*
aItem
);
void
CacheRemove
(
PNS_ITEM
*
aItem
);
void
SetWorld
(
PNS_NODE
*
aNode
)
{
m_world
=
aNode
;
}
void
CacheStaticItem
(
PNS_ITEM
*
aItem
);
void
CacheRemove
(
PNS_ITEM
*
aItem
);
void
ClearCache
(
bool
aStaticOnly
=
false
);
void
SetCollisionMask
(
int
aMask
)
void
SetCollisionMask
(
int
aMask
)
{
m_collisionKindMask
=
aMask
;
}
void
SetEffortLevel
(
int
aEffort
)
void
SetEffortLevel
(
int
aEffort
)
{
m_effortLevel
=
aEffort
;
}
private
:
private
:
static
const
int
MaxCachedItems
=
256
;
typedef
std
::
vector
<
SHAPE_LINE_CHAIN
>
BreakoutList
;
...
...
@@ -129,36 +130,38 @@ class PNS_OPTIMIZER
bool
isStatic
;
};
bool
mergeObtuse
(
PNS_LINE
*
aLine
);
bool
mergeFull
(
PNS_LINE
*
aLine
);
bool
removeUglyCorners
(
PNS_LINE
*
aLine
);
bool
runSmartPads
(
PNS_LINE
*
aLine
);
bool
mergeStep
(
PNS_LINE
*
aLine
,
SHAPE_LINE_CHAIN
&
aCurrentLine
,
int
step
);
bool
mergeObtuse
(
PNS_LINE
*
aLine
);
bool
mergeFull
(
PNS_LINE
*
aLine
);
bool
removeUglyCorners
(
PNS_LINE
*
aLine
);
bool
runSmartPads
(
PNS_LINE
*
aLine
);
bool
mergeStep
(
PNS_LINE
*
aLine
,
SHAPE_LINE_CHAIN
&
aCurrentLine
,
int
step
);
bool
checkColliding
(
PNS_ITEM
*
aItem
,
bool
aUpdateCache
=
true
);
bool
checkColliding
(
PNS_LINE
*
aLine
,
const
SHAPE_LINE_CHAIN
&
aOptPath
);
bool
checkColliding
(
PNS_ITEM
*
aItem
,
bool
aUpdateCache
=
true
);
bool
checkColliding
(
PNS_LINE
*
aLine
,
const
SHAPE_LINE_CHAIN
&
aOptPath
);
void
cacheAdd
(
PNS_ITEM
*
aItem
,
bool
aIsStatic
);
void
removeCachedSegments
(
PNS_LINE
*
aLine
,
int
aStartVertex
=
0
,
int
aEndVertex
=
-
1
);
void
cacheAdd
(
PNS_ITEM
*
aItem
,
bool
aIsStatic
);
void
removeCachedSegments
(
PNS_LINE
*
aLine
,
int
aStartVertex
=
0
,
int
aEndVertex
=
-
1
);
BreakoutList
circleBreakouts
(
int
aWidth
,
const
SHAPE
*
aShape
,
bool
aPermitDiagonal
)
const
;
BreakoutList
rectBreakouts
(
int
aWidth
,
const
SHAPE
*
aShape
,
bool
aPermitDiagonal
)
const
;
BreakoutList
ovalBreakouts
(
int
aWidth
,
const
SHAPE
*
aShape
,
bool
aPermitDiagonal
)
const
;
BreakoutList
computeBreakouts
(
int
aWidth
,
const
PNS_ITEM
*
aItem
,
bool
aPermitDiagonal
)
const
;
BreakoutList
circleBreakouts
(
int
aWidth
,
const
SHAPE
*
aShape
,
bool
aPermitDiagonal
)
const
;
BreakoutList
rectBreakouts
(
int
aWidth
,
const
SHAPE
*
aShape
,
bool
aPermitDiagonal
)
const
;
BreakoutList
ovalBreakouts
(
int
aWidth
,
const
SHAPE
*
aShape
,
bool
aPermitDiagonal
)
const
;
BreakoutList
computeBreakouts
(
int
aWidth
,
const
PNS_ITEM
*
aItem
,
bool
aPermitDiagonal
)
const
;
int
smartPadsSingle
(
PNS_LINE
*
aLine
,
PNS_ITEM
*
aPad
,
bool
aEnd
,
int
aEndVertex
);
int
smartPadsSingle
(
PNS_LINE
*
aLine
,
PNS_ITEM
*
aPad
,
bool
aEnd
,
int
aEndVertex
);
PNS_ITEM
*
findPadOrVia
(
int
aLayer
,
int
aNet
,
const
VECTOR2I
&
aP
)
const
;
PNS_ITEM
*
findPadOrVia
(
int
aLayer
,
int
aNet
,
const
VECTOR2I
&
aP
)
const
;
SHAPE_INDEX_LIST
<
PNS_ITEM
*>
m_cache
;
SHAPE_INDEX_LIST
<
PNS_ITEM
*>
m_cache
;
typedef
boost
::
unordered_map
<
PNS_ITEM
*
,
CachedItem
>
CachedItemTags
;
CachedItemTags
m_cacheTags
;
PNS_NODE
*
m_world
;
PNS_NODE
*
m_world
;
int
m_collisionKindMask
;
int
m_effortLevel
;
bool
m_keepPostures
;
};
#endif
pcbnew/router/pns_router.cpp
View file @
5598acb6
...
...
@@ -17,6 +17,7 @@
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>.
*/
#include <cstdio>
#include <vector>
...
...
@@ -52,216 +53,227 @@
using
namespace
std
;
// an ugly singleton for drawing debug items within the router context. To be fixed sometime in the future.
static
PNS_ROUTER
*
theRouter
;
// an ugly singleton for drawing debug items within the router context.
// To be fixed sometime in the future.
static
PNS_ROUTER
*
theRouter
;
class
PCBNEW_CLEARANCE_FUNC
:
public
PNS_CLEARANCE_FUNC
{
public
:
PCBNEW_CLEARANCE_FUNC
(
BOARD
*
aBoard
)
public
:
PCBNEW_CLEARANCE_FUNC
(
BOARD
*
aBoard
)
{
m_clearanceCache
.
resize
(
aBoard
->
GetNetCount
()
);
m_clearanceCache
.
resize
(
aBoard
->
GetNetCount
()
);
for
(
unsigned
int
i
=
0
;
i
<
aBoard
->
GetNetCount
();
i
++
)
for
(
unsigned
int
i
=
0
;
i
<
aBoard
->
GetNetCount
();
i
++
)
{
NETINFO_ITEM
*
ni
=
aBoard
->
FindNet
(
i
);
NETINFO_ITEM
*
ni
=
aBoard
->
FindNet
(
i
);
wxString
netClassName
=
ni
->
GetClassName
();
NETCLASS
*
nc
=
aBoard
->
m_NetClasses
.
Find
(
netClassName
);
NETCLASS
*
nc
=
aBoard
->
m_NetClasses
.
Find
(
netClassName
);
int
clearance
=
nc
->
GetClearance
();
m_clearanceCache
[
i
]
=
clearance
;
TRACE
(
1
,
"Add net %d netclass %s clearance %d"
,
i
%
netClassName
.
mb_str
()
%
clearance
);
TRACE
(
1
,
"Add net %d netclass %s clearance %d"
,
i
%
netClassName
.
mb_str
()
%
clearance
);
}
m_defaultClearance
=
254000
;
//
aBoard->m_NetClasses.Find ("Default clearance")->GetClearance();
m_defaultClearance
=
254000
;
//
aBoard->m_NetClasses.Find ("Default clearance")->GetClearance();
}
int
operator
()
(
const
PNS_ITEM
*
a
,
const
PNS_ITEM
*
b
)
int
operator
()(
const
PNS_ITEM
*
a
,
const
PNS_ITEM
*
b
)
{
int
net_a
=
a
->
GetNet
();
int
cl_a
=
(
net_a
>=
0
?
m_clearanceCache
[
net_a
]
:
m_defaultClearance
);
int
net_b
=
b
->
GetNet
();
int
cl_b
=
(
net_b
>=
0
?
m_clearanceCache
[
net_b
]
:
m_defaultClearance
);
return
std
::
max
(
cl_a
,
cl_b
);
}
private
:
return
std
::
max
(
cl_a
,
cl_b
);
}
private
:
vector
<
int
>
m_clearanceCache
;
int
m_defaultClearance
;
};
PNS_ITEM
*
PNS_ROUTER
::
syncPad
(
D_PAD
*
aPad
)
PNS_ITEM
*
PNS_ROUTER
::
syncPad
(
D_PAD
*
aPad
)
{
PNS_LAYERSET
layers
;
switch
(
aPad
->
GetAttribute
()
)
switch
(
aPad
->
GetAttribute
()
)
{
case
PAD_STANDARD
:
layers
=
PNS_LAYERSET
(
0
,
15
);
layers
=
PNS_LAYERSET
(
0
,
15
);
break
;
case
PAD_SMD
:
case
PAD_CONN
:
{
LAYER_MSK
lmsk
=
aPad
->
GetLayerMask
();
int
i
;
for
(
i
=
FIRST_COPPER_LAYER
;
i
<=
LAST_COPPER_LAYER
;
i
++
)
if
(
lmsk
&
(
1
<<
i
)
)
for
(
i
=
FIRST_COPPER_LAYER
;
i
<=
LAST_COPPER_LAYER
;
i
++
)
if
(
lmsk
&
(
1
<<
i
)
)
{
layers
=
PNS_LAYERSET
(
i
);
break
;
}
break
;
}
default
:
TRACE
(
0
,
"unsupported pad type 0x%x"
,
aPad
->
GetAttribute
()
);
TRACE
(
0
,
"unsupported pad type 0x%x"
,
aPad
->
GetAttribute
()
);
return
NULL
;
}
PNS_SOLID
*
solid
=
new
PNS_SOLID
;
PNS_SOLID
*
solid
=
new
PNS_SOLID
;
solid
->
SetLayers
(
layers
);
solid
->
SetLayers
(
layers
);
solid
->
SetNet
(
aPad
->
GetNet
()
);
wxPoint
wx_c
=
aPad
->
GetPosition
();
wxSize
wx_sz
=
aPad
->
GetSize
();
VECTOR2I
c
(
wx_c
.
x
,
wx_c
.
y
);
VECTOR2I
sz
(
wx_sz
.
x
,
wx_sz
.
y
);
VECTOR2I
c
(
wx_c
.
x
,
wx_c
.
y
);
VECTOR2I
sz
(
wx_sz
.
x
,
wx_sz
.
y
);
solid
->
SetCenter
(
c
);
double
orient
=
aPad
->
GetOrientation
()
/
10.0
;
if
(
orient
==
90.0
||
orient
==
270.0
)
sz
=
VECTOR2I
(
sz
.
y
,
sz
.
x
);
else
if
(
orient
!=
0.0
&&
orient
!=
180.0
)
if
(
orient
==
90.0
||
orient
==
270.0
)
sz
=
VECTOR2I
(
sz
.
y
,
sz
.
x
);
else
if
(
orient
!=
0.0
&&
orient
!=
180.0
)
{
TRACEn
(
0
,
"non-orthogonal pad rotations not supported yet"
);
TRACEn
(
0
,
"non-orthogonal pad rotations not supported yet"
);
delete
solid
;
return
NULL
;
}
switch
(
aPad
->
GetShape
()
)
switch
(
aPad
->
GetShape
()
)
{
case
PAD_CIRCLE
:
solid
->
SetShape
(
new
SHAPE_CIRCLE
(
c
,
sz
.
x
/
2
)
);
solid
->
SetShape
(
new
SHAPE_CIRCLE
(
c
,
sz
.
x
/
2
)
);
break
;
case
PAD_OVAL
:
if
(
sz
.
x
==
sz
.
y
)
solid
->
SetShape
(
new
SHAPE_CIRCLE
(
c
,
sz
.
x
/
2
)
);
if
(
sz
.
x
==
sz
.
y
)
solid
->
SetShape
(
new
SHAPE_CIRCLE
(
c
,
sz
.
x
/
2
)
);
else
solid
->
SetShape
(
new
SHAPE_RECT
(
c
-
sz
/
2
,
sz
.
x
,
sz
.
y
)
);
solid
->
SetShape
(
new
SHAPE_RECT
(
c
-
sz
/
2
,
sz
.
x
,
sz
.
y
)
);
break
;
case
PAD_RECT
:
solid
->
SetShape
(
new
SHAPE_RECT
(
c
-
sz
/
2
,
sz
.
x
,
sz
.
y
)
);
solid
->
SetShape
(
new
SHAPE_RECT
(
c
-
sz
/
2
,
sz
.
x
,
sz
.
y
)
);
break
;
default
:
TRACEn
(
0
,
"unsupported pad shape"
);
TRACEn
(
0
,
"unsupported pad shape"
);
delete
solid
;
return
NULL
;
}
solid
->
SetParent
(
aPad
);
solid
->
SetParent
(
aPad
);
return
solid
;
}
PNS_ITEM
*
PNS_ROUTER
::
syncTrack
(
TRACK
*
aTrack
)
{
PNS_SEGMENT
*
s
=
new
PNS_SEGMENT
(
SEG
(
aTrack
->
GetStart
(),
aTrack
->
GetEnd
()
),
aTrack
->
GetNet
()
);
PNS_ITEM
*
PNS_ROUTER
::
syncTrack
(
TRACK
*
aTrack
)
{
PNS_SEGMENT
*
s
=
new
PNS_SEGMENT
(
SEG
(
aTrack
->
GetStart
(),
aTrack
->
GetEnd
()
),
aTrack
->
GetNet
()
);
s
->
SetWidth
(
aTrack
->
GetWidth
()
);
s
->
SetLayers
(
PNS_LAYERSET
(
aTrack
->
GetLayer
())
);
s
->
SetParent
(
aTrack
);
s
->
SetLayers
(
PNS_LAYERSET
(
aTrack
->
GetLayer
()
)
);
s
->
SetParent
(
aTrack
);
return
s
;
}
PNS_ITEM
*
PNS_ROUTER
::
syncVia
(
SEGVIA
*
aVia
)
PNS_ITEM
*
PNS_ROUTER
::
syncVia
(
SEGVIA
*
aVia
)
{
PNS_VIA
*
v
=
new
PNS_VIA
(
PNS_VIA
*
v
=
new
PNS_VIA
(
aVia
->
GetPosition
(),
PNS_LAYERSET
(
0
,
15
),
PNS_LAYERSET
(
0
,
15
),
aVia
->
GetWidth
(),
aVia
->
GetNet
()
);
aVia
->
GetNet
()
);
v
->
SetParent
(
aVia
);
v
->
SetParent
(
aVia
);
return
v
;
}
void
PNS_ROUTER
::
SetBoard
(
BOARD
*
aBoard
)
void
PNS_ROUTER
::
SetBoard
(
BOARD
*
aBoard
)
{
m_board
=
aBoard
;
TRACE
(
1
,
"m_board = %p
\n
"
,
m_board
);
TRACE
(
1
,
"m_board = %p
\n
"
,
m_board
);
}
int
PNS_ROUTER
::
NextCopperLayer
(
bool
aUp
)
{
LAYER_MSK
mask
=
m_board
->
GetEnabledLayers
()
&
m_board
->
GetVisibleLayers
();
LAYER_NUM
l
=
m_currentLayer
;
do
{
l
+=
(
aUp
?
1
:
-
1
);
if
(
l
>
LAST_COPPER_LAYER
)
l
+=
(
aUp
?
1
:
-
1
);
if
(
l
>
LAST_COPPER_LAYER
)
l
=
FIRST_COPPER_LAYER
;
if
(
l
<
FIRST_COPPER_LAYER
)
if
(
l
<
FIRST_COPPER_LAYER
)
l
=
LAST_COPPER_LAYER
;
if
(
mask
&
GetLayerMask
(
l
)
)
if
(
mask
&
GetLayerMask
(
l
)
)
return
l
;
}
while
(
l
!=
m_currentLayer
);
}
while
(
l
!=
m_currentLayer
);
return
l
;
}
void
PNS_ROUTER
::
SyncWorld
()
{
vector
<
D_PAD
*>
pads
;
vector
<
D_PAD
*>
pads
;
if
(
!
m_board
)
if
(
!
m_board
)
{
TRACEn
(
0
,
"No board attached, aborting sync."
);
TRACEn
(
0
,
"No board attached, aborting sync."
);
return
;
}
ClearWorld
();
m_clearanceFunc
=
new
PCBNEW_CLEARANCE_FUNC
(
m_board
);
m_clearanceFunc
=
new
PCBNEW_CLEARANCE_FUNC
(
m_board
);
m_world
=
new
PNS_NODE
();
m_world
->
SetClearanceFunctor
(
m_clearanceFunc
);
m_world
->
SetMaxClearance
(
1000000
);
//
m_board->GetBiggestClearanceValue());
m_world
->
SetClearanceFunctor
(
m_clearanceFunc
);
m_world
->
SetMaxClearance
(
1000000
);
//
m_board->GetBiggestClearanceValue());
pads
=
m_board
->
GetPads
();
BOOST_FOREACH
(
D_PAD
*
pad
,
pads
)
{
PNS_ITEM
*
solid
=
syncPad
(
pad
);
if
(
solid
)
m_world
->
Add
(
solid
);
BOOST_FOREACH
(
D_PAD
*
pad
,
pads
)
{
PNS_ITEM
*
solid
=
syncPad
(
pad
);
if
(
solid
)
m_world
->
Add
(
solid
);
}
for
(
TRACK
*
t
=
m_board
->
m_Track
;
t
;
t
=
t
->
Next
()
)
for
(
TRACK
*
t
=
m_board
->
m_Track
;
t
;
t
=
t
->
Next
()
)
{
KICAD_T
type
=
t
->
Type
();
PNS_ITEM
*
item
=
NULL
;
if
(
type
==
PCB_TRACE_T
)
item
=
syncTrack
(
t
);
PNS_ITEM
*
item
=
NULL
;
if
(
type
==
PCB_TRACE_T
)
item
=
syncTrack
(
t
);
else
if
(
type
==
PCB_VIA_T
)
item
=
syncVia
(
static_cast
<
SEGVIA
*>
(
t
)
);
item
=
syncVia
(
static_cast
<
SEGVIA
*>
(
t
)
);
if
(
item
)
m_world
->
Add
(
item
);
if
(
item
)
m_world
->
Add
(
item
);
}
m_placer
=
new
PNS_LINE_PLACER
(
m_world
);
m_placer
=
new
PNS_LINE_PLACER
(
m_world
);
}
PNS_ROUTER
::
PNS_ROUTER
()
{
theRouter
=
this
;
...
...
@@ -278,44 +290,48 @@ PNS_ROUTER::PNS_ROUTER()
m_start_diagonal
=
false
;
m_board
=
NULL
;
TRACE
(
1
,
"m_board = %p
\n
"
,
m_board
);
TRACE
(
1
,
"m_board = %p
\n
"
,
m_board
);
}
void
PNS_ROUTER
::
SetView
(
KiGfx
::
VIEW
*
aView
)
void
PNS_ROUTER
::
SetView
(
KiGfx
::
VIEW
*
aView
)
{
if
(
m_previewItems
)
if
(
m_previewItems
)
{
m_previewItems
->
FreeItems
();
delete
m_previewItems
;
}
m_view
=
aView
;
m_previewItems
=
new
KiGfx
::
VIEW_GROUP
(
m_view
);
m_previewItems
->
SetLayer
(
ITEM_GAL_LAYER
(
GP_OVERLAY
));
m_view
->
Add
(
m_previewItems
);
m_previewItems
->
ViewSetVisible
(
true
);
m_previewItems
=
new
KiGfx
::
VIEW_GROUP
(
m_view
);
m_previewItems
->
SetLayer
(
ITEM_GAL_LAYER
(
GP_OVERLAY
)
);
m_view
->
Add
(
m_previewItems
);
m_previewItems
->
ViewSetVisible
(
true
);
}
PNS_ROUTER
*
PNS_ROUTER
::
GetInstance
()
PNS_ROUTER
*
PNS_ROUTER
::
GetInstance
()
{
return
theRouter
;
}
PNS_ROUTER
::~
PNS_ROUTER
()
{
ClearWorld
();
theRouter
=
NULL
;
}
void
PNS_ROUTER
::
ClearWorld
()
{
if
(
m_world
)
if
(
m_world
)
delete
m_world
;
if
(
m_clearanceFunc
)
if
(
m_clearanceFunc
)
delete
m_clearanceFunc
;
if
(
m_placer
)
if
(
m_placer
)
delete
m_placer
;
m_clearanceFunc
=
NULL
;
...
...
@@ -323,77 +339,85 @@ void PNS_ROUTER::ClearWorld()
m_placer
=
NULL
;
}
void
PNS_ROUTER
::
SetCurrentWidth
(
int
w
)
void
PNS_ROUTER
::
SetCurrentWidth
(
int
w
)
{
// fixme: change width while routing
m_currentWidth
=
w
;
}
bool
PNS_ROUTER
::
RoutingInProgress
()
const
{
return
m_state
!=
IDLE
;
}
const
PNS_ITEMSET
PNS_ROUTER
::
QueryHoverItems
(
const
VECTOR2I
&
aP
)
const
PNS_ITEMSET
PNS_ROUTER
::
QueryHoverItems
(
const
VECTOR2I
&
aP
)
{
if
(
m_state
==
IDLE
)
if
(
m_state
==
IDLE
)
return
m_world
->
HitTest
(
aP
);
else
return
m_placer
->
GetCurrentNode
()
->
HitTest
(
aP
);
return
m_placer
->
GetCurrentNode
()
->
HitTest
(
aP
);
}
const
VECTOR2I
PNS_ROUTER
::
SnapToItem
(
PNS_ITEM
*
item
,
VECTOR2I
aP
,
bool
&
aSplitsSegment
)
const
VECTOR2I
PNS_ROUTER
::
SnapToItem
(
PNS_ITEM
*
item
,
VECTOR2I
aP
,
bool
&
aSplitsSegment
)
{
VECTOR2I
anchor
;
if
(
!
item
)
if
(
!
item
)
{
aSplitsSegment
=
false
;
return
aP
;
}
switch
(
item
->
GetKind
()
)
switch
(
item
->
GetKind
()
)
{
case
PNS_ITEM
:
:
SOLID
:
anchor
=
static_cast
<
PNS_SOLID
*>
(
item
)
->
GetCenter
();
anchor
=
static_cast
<
PNS_SOLID
*>
(
item
)
->
GetCenter
();
aSplitsSegment
=
false
;
break
;
case
PNS_ITEM
:
:
VIA
:
anchor
=
static_cast
<
PNS_VIA
*>
(
item
)
->
GetPos
();
anchor
=
static_cast
<
PNS_VIA
*>
(
item
)
->
GetPos
();
aSplitsSegment
=
false
;
break
;
case
PNS_ITEM
:
:
SEGMENT
:
{
PNS_SEGMENT
*
seg
=
static_cast
<
PNS_SEGMENT
*>
(
item
);
PNS_SEGMENT
*
seg
=
static_cast
<
PNS_SEGMENT
*>
(
item
);
const
SEG
&
s
=
seg
->
GetSeg
();
int
w
=
seg
->
GetWidth
();
aSplitsSegment
=
false
;
if
((
aP
-
s
.
a
).
EuclideanNorm
()
<
w
/
2
)
if
(
(
aP
-
s
.
a
).
EuclideanNorm
()
<
w
/
2
)
anchor
=
s
.
a
;
else
if
((
aP
-
s
.
b
).
EuclideanNorm
()
<
w
/
2
)
else
if
(
(
aP
-
s
.
b
).
EuclideanNorm
()
<
w
/
2
)
anchor
=
s
.
b
;
else
{
anchor
=
s
.
NearestPoint
(
aP
);
else
{
anchor
=
s
.
NearestPoint
(
aP
);
aSplitsSegment
=
true
;
}
break
;
}
default
:
break
;
}
return
anchor
;
}
void
PNS_ROUTER
::
StartRouting
(
const
VECTOR2I
&
aP
,
PNS_ITEM
*
aStartItem
)
void
PNS_ROUTER
::
StartRouting
(
const
VECTOR2I
&
aP
,
PNS_ITEM
*
aStartItem
)
{
VECTOR2I
p
;
static
int
unknowNetIdx
=
0
;
//
-10000;
static
int
unknowNetIdx
=
0
;
//
-10000;
m_placingVia
=
false
;
m_startsOnVia
=
false
;
...
...
@@ -403,7 +427,7 @@ void PNS_ROUTER::StartRouting(const VECTOR2I& aP, PNS_ITEM *aStartItem)
p
=
SnapToItem
(
aStartItem
,
aP
,
splitSeg
);
if
(
!
aStartItem
||
aStartItem
->
GetNet
()
<
0
)
if
(
!
aStartItem
||
aStartItem
->
GetNet
()
<
0
)
m_currentNet
=
unknowNetIdx
--
;
else
m_currentNet
=
aStartItem
->
GetNet
();
...
...
@@ -412,178 +436,183 @@ void PNS_ROUTER::StartRouting(const VECTOR2I& aP, PNS_ITEM *aStartItem)
m_originalStart
=
p
;
m_currentEnd
=
p
;
m_placer
->
SetInitialDirection
(
m_start_diagonal
?
DIRECTION_45
(
DIRECTION_45
::
NE
)
:
DIRECTION_45
(
DIRECTION_45
::
N
));
m_placer
->
StartPlacement
(
m_originalStart
,
m_currentNet
,
m_currentWidth
,
m_currentLayer
);
m_placer
->
SetInitialDirection
(
m_start_diagonal
?
DIRECTION_45
(
DIRECTION_45
::
NE
)
:
DIRECTION_45
(
DIRECTION_45
::
N
)
);
m_placer
->
StartPlacement
(
m_originalStart
,
m_currentNet
,
m_currentWidth
,
m_currentLayer
);
m_state
=
ROUTE_TRACK
;
if
(
splitSeg
)
splitAdjacentSegments
(
m_placer
->
GetCurrentNode
(),
aStartItem
,
p
);
if
(
splitSeg
)
splitAdjacentSegments
(
m_placer
->
GetCurrentNode
(),
aStartItem
,
p
);
}
const
VECTOR2I
PNS_ROUTER
::
GetCurrentEnd
(
)
const
const
VECTOR2I
PNS_ROUTER
::
GetCurrentEnd
()
const
{
return
m_currentEnd
;
}
void
PNS_ROUTER
::
EraseView
()
{
BOOST_FOREACH
(
BOARD_ITEM
*
item
,
m_hiddenItems
)
BOOST_FOREACH
(
BOARD_ITEM
*
item
,
m_hiddenItems
)
{
item
->
ViewSetVisible
(
true
);
item
->
ViewSetVisible
(
true
);
}
if
(
m_previewItems
)
if
(
m_previewItems
)
m_previewItems
->
FreeItems
();
m_previewItems
->
ViewUpdate
(
KiGfx
::
VIEW_ITEM
::
GEOMETRY
);
}
void
PNS_ROUTER
::
DisplayItem
(
const
PNS_ITEM
*
aItem
,
bool
aIsHead
)
void
PNS_ROUTER
::
DisplayItem
(
const
PNS_ITEM
*
aItem
,
bool
aIsHead
)
{
ROUTER_PREVIEW_ITEM
*
pitem
=
new
ROUTER_PREVIEW_ITEM
(
aItem
,
m_previewItems
);
ROUTER_PREVIEW_ITEM
*
pitem
=
new
ROUTER_PREVIEW_ITEM
(
aItem
,
m_previewItems
);
m_previewItems
->
Add
(
pitem
);
m_previewItems
->
Add
(
pitem
);
if
(
aIsHead
)
if
(
aIsHead
)
pitem
->
MarkAsHead
();
pitem
->
ViewSetVisible
(
true
);
pitem
->
ViewSetVisible
(
true
);
m_previewItems
->
ViewUpdate
(
KiGfx
::
VIEW_ITEM
::
GEOMETRY
|
KiGfx
::
VIEW_ITEM
::
APPEARANCE
);
}
void
PNS_ROUTER
::
DisplayDebugLine
(
const
SHAPE_LINE_CHAIN
&
aLine
,
int
aType
,
int
aWidth
)
void
PNS_ROUTER
::
DisplayDebugLine
(
const
SHAPE_LINE_CHAIN
&
aLine
,
int
aType
,
int
aWidth
)
{
ROUTER_PREVIEW_ITEM
*
pitem
=
new
ROUTER_PREVIEW_ITEM
(
NULL
,
m_previewItems
);
ROUTER_PREVIEW_ITEM
*
pitem
=
new
ROUTER_PREVIEW_ITEM
(
NULL
,
m_previewItems
);
pitem
->
DebugLine
(
aLine
,
aWidth
,
aType
);
m_previewItems
->
Add
(
pitem
);
pitem
->
ViewSetVisible
(
true
);
pitem
->
DebugLine
(
aLine
,
aWidth
,
aType
);
m_previewItems
->
Add
(
pitem
);
pitem
->
ViewSetVisible
(
true
);
m_previewItems
->
ViewUpdate
(
KiGfx
::
VIEW_ITEM
::
GEOMETRY
|
KiGfx
::
VIEW_ITEM
::
APPEARANCE
);
}
void
PNS_ROUTER
::
DisplayDebugBox
(
const
BOX2I
&
aBox
,
int
aType
,
int
aWidth
)
{
void
PNS_ROUTER
::
DisplayDebugBox
(
const
BOX2I
&
aBox
,
int
aType
,
int
aWidth
)
{
}
void
PNS_ROUTER
::
Move
(
const
VECTOR2I
&
aP
,
PNS_ITEM
*
endItem
)
void
PNS_ROUTER
::
Move
(
const
VECTOR2I
&
aP
,
PNS_ITEM
*
endItem
)
{
PNS_NODE
::
ItemVector
removed
,
added
;
VECTOR2I
p
=
aP
;
if
(
m_state
==
IDLE
)
if
(
m_state
==
IDLE
)
return
;
if
(
m_state
==
START_ROUTING
)
// TODO is something missing here?
if
(
m_state
==
START_ROUTING
)
{
}
EraseView
();
m_currentEnd
=
p
;
m_placer
->
Route
(
p
);
m_placer
->
Route
(
p
);
PNS_LINE
current
=
m_placer
->
GetTrace
();
DisplayItem
(
&
current
,
true
);
DisplayItem
(
&
current
,
true
);
if
(
current
.
EndsWithVia
()
)
if
(
current
.
EndsWithVia
()
)
DisplayItem
(
&
current
.
GetVia
(),
true
);
m_placer
->
GetCurrentNode
()
->
GetUpdatedItems
(
removed
,
added
);
m_placer
->
GetCurrentNode
()
->
GetUpdatedItems
(
removed
,
added
);
BOOST_FOREACH
(
PNS_ITEM
*
item
,
added
)
{
DisplayItem
(
item
);
BOOST_FOREACH
(
PNS_ITEM
*
item
,
added
)
{
DisplayItem
(
item
);
}
BOOST_FOREACH
(
PNS_ITEM
*
item
,
removed
)
BOOST_FOREACH
(
PNS_ITEM
*
item
,
removed
)
{
BOARD_ITEM
*
parent
=
item
->
GetParent
();
BOARD_ITEM
*
parent
=
item
->
GetParent
();
if
(
parent
)
if
(
parent
)
{
if
(
parent
->
ViewIsVisible
()
)
m_hiddenItems
.
insert
(
parent
);
if
(
parent
->
ViewIsVisible
()
)
m_hiddenItems
.
insert
(
parent
);
parent
->
ViewSetVisible
(
false
);
parent
->
ViewUpdate
(
KiGfx
::
VIEW_ITEM
::
APPEARANCE
);
parent
->
ViewSetVisible
(
false
);
parent
->
ViewUpdate
(
KiGfx
::
VIEW_ITEM
::
APPEARANCE
);
}
}
}
void
PNS_ROUTER
::
splitAdjacentSegments
(
PNS_NODE
*
aNode
,
PNS_ITEM
*
aSeg
,
const
VECTOR2I
&
aP
)
void
PNS_ROUTER
::
splitAdjacentSegments
(
PNS_NODE
*
aNode
,
PNS_ITEM
*
aSeg
,
const
VECTOR2I
&
aP
)
{
if
(
aSeg
&&
aSeg
->
OfKind
(
PNS_ITEM
::
SEGMENT
)
)
if
(
aSeg
&&
aSeg
->
OfKind
(
PNS_ITEM
::
SEGMENT
)
)
{
PNS_NODE
::
OptJoint
jt
=
aNode
->
FindJoint
(
aP
,
aSeg
->
GetLayers
().
Start
(),
aSeg
->
GetNet
()
);
PNS_NODE
::
OptJoint
jt
=
aNode
->
FindJoint
(
aP
,
aSeg
->
GetLayers
().
Start
(),
aSeg
->
GetNet
()
);
if
(
jt
&&
jt
->
LinkCount
()
>=
1
)
if
(
jt
&&
jt
->
LinkCount
()
>=
1
)
return
;
PNS_SEGMENT
*
s_old
=
static_cast
<
PNS_SEGMENT
*>
(
aSeg
);
PNS_SEGMENT
*
s_new
[
2
];
PNS_SEGMENT
*
s_old
=
static_cast
<
PNS_SEGMENT
*>
(
aSeg
);
PNS_SEGMENT
*
s_new
[
2
];
s_new
[
0
]
=
s_old
->
Clone
();
s_new
[
1
]
=
s_old
->
Clone
();
s_new
[
0
]
->
SetEnds
(
s_old
->
GetSeg
().
a
,
aP
);
s_new
[
1
]
->
SetEnds
(
aP
,
s_old
->
GetSeg
().
b
);
s_new
[
0
]
->
SetEnds
(
s_old
->
GetSeg
().
a
,
aP
);
s_new
[
1
]
->
SetEnds
(
aP
,
s_old
->
GetSeg
().
b
);
aNode
->
Remove
(
s_old
);
aNode
->
Add
(
s_new
[
0
]
);
aNode
->
Add
(
s_new
[
1
]
);
aNode
->
Add
(
s_new
[
0
]
);
aNode
->
Add
(
s_new
[
1
]
);
}
}
void
PNS_ROUTER
::
commitRouting
(
PNS_NODE
*
aNode
)
void
PNS_ROUTER
::
commitRouting
(
PNS_NODE
*
aNode
)
{
PNS_NODE
::
ItemVector
removed
,
added
;
aNode
->
GetUpdatedItems
(
removed
,
added
);
aNode
->
GetUpdatedItems
(
removed
,
added
);
for
(
unsigned
int
i
=
0
;
i
<
removed
.
size
();
i
++
)
for
(
unsigned
int
i
=
0
;
i
<
removed
.
size
();
i
++
)
{
BOARD_ITEM
*
parent
=
removed
[
i
]
->
GetParent
();
BOARD_ITEM
*
parent
=
removed
[
i
]
->
GetParent
();
if
(
parent
)
if
(
parent
)
{
m_view
->
Remove
(
parent
);
m_board
->
Remove
(
parent
);
m_view
->
Remove
(
parent
);
m_board
->
Remove
(
parent
);
}
}
BOOST_FOREACH
(
PNS_ITEM
*
item
,
added
)
BOOST_FOREACH
(
PNS_ITEM
*
item
,
added
)
{
BOARD_ITEM
*
newBI
=
NULL
;
switch
(
item
->
GetKind
())
BOARD_ITEM
*
newBI
=
NULL
;
switch
(
item
->
GetKind
()
)
{
case
PNS_ITEM
:
:
SEGMENT
:
{
PNS_SEGMENT
*
seg
=
static_cast
<
PNS_SEGMENT
*>
(
item
);
TRACK
*
track
=
new
TRACK
(
m_board
);
PNS_SEGMENT
*
seg
=
static_cast
<
PNS_SEGMENT
*>
(
item
);
TRACK
*
track
=
new
TRACK
(
m_board
);
const
SEG
&
s
=
seg
->
GetSeg
();
track
->
SetStart
(
wxPoint
(
s
.
a
.
x
,
s
.
a
.
y
)
);
track
->
SetEnd
(
wxPoint
(
s
.
b
.
x
,
s
.
b
.
y
)
);
track
->
SetWidth
(
seg
->
GetWidth
()
);
track
->
SetLayer
(
seg
->
GetLayers
().
Start
()
);
track
->
SetNet
(
seg
->
GetNet
()
);
track
->
SetStart
(
wxPoint
(
s
.
a
.
x
,
s
.
a
.
y
)
);
track
->
SetEnd
(
wxPoint
(
s
.
b
.
x
,
s
.
b
.
y
)
);
track
->
SetWidth
(
seg
->
GetWidth
()
);
track
->
SetLayer
(
seg
->
GetLayers
().
Start
()
);
track
->
SetNet
(
seg
->
GetNet
()
);
newBI
=
track
;
break
;
}
case
PNS_ITEM
:
:
VIA
:
{
SEGVIA
*
via_board
=
new
SEGVIA
(
m_board
);
PNS_VIA
*
via
=
static_cast
<
PNS_VIA
*>
(
item
);
via_board
->
SetPosition
(
wxPoint
(
via
->
GetPos
().
x
,
via
->
GetPos
().
y
)
);
via_board
->
SetWidth
(
via
->
GetDiameter
()
);
via_board
->
SetNet
(
via
->
GetNet
()
);
SEGVIA
*
via_board
=
new
SEGVIA
(
m_board
);
PNS_VIA
*
via
=
static_cast
<
PNS_VIA
*>
(
item
);
via_board
->
SetPosition
(
wxPoint
(
via
->
GetPos
().
x
,
via
->
GetPos
().
y
)
);
via_board
->
SetWidth
(
via
->
GetDiameter
()
);
via_board
->
SetNet
(
via
->
GetNet
()
);
newBI
=
via_board
;
break
;
}
...
...
@@ -592,12 +621,12 @@ void PNS_ROUTER::commitRouting( PNS_NODE *aNode )
break
;
}
if
(
newBI
)
if
(
newBI
)
{
item
->
SetParent
(
newBI
);
item
->
SetParent
(
newBI
);
newBI
->
ClearFlags
();
m_view
->
Add
(
newBI
);
m_board
->
Add
(
newBI
);
m_view
->
Add
(
newBI
);
m_board
->
Add
(
newBI
);
newBI
->
ViewUpdate
(
KiGfx
::
VIEW_ITEM
::
GEOMETRY
);
}
}
...
...
@@ -605,41 +634,43 @@ void PNS_ROUTER::commitRouting( PNS_NODE *aNode )
m_world
->
Commit
(
aNode
);
}
PNS_VIA
*
PNS_ROUTER
::
checkLoneVia
(
PNS_JOINT
*
aJoint
)
const
PNS_VIA
*
PNS_ROUTER
::
checkLoneVia
(
PNS_JOINT
*
aJoint
)
const
{
PNS_VIA
*
theVia
=
NULL
;
PNS_VIA
*
theVia
=
NULL
;
PNS_LAYERSET
l
;
BOOST_FOREACH
(
PNS_ITEM
*
item
,
aJoint
->
GetLinkList
()
)
BOOST_FOREACH
(
PNS_ITEM
*
item
,
aJoint
->
GetLinkList
()
)
{
if
(
item
->
GetKind
()
==
PNS_ITEM
::
VIA
)
theVia
=
static_cast
<
PNS_VIA
*>
(
item
);
if
(
item
->
GetKind
()
==
PNS_ITEM
::
VIA
)
theVia
=
static_cast
<
PNS_VIA
*>
(
item
);
l
.
Merge
(
item
->
GetLayers
()
);
l
.
Merge
(
item
->
GetLayers
()
);
}
if
(
l
.
Start
()
==
l
.
End
()
)
if
(
l
.
Start
()
==
l
.
End
()
)
return
theVia
;
return
NULL
;
}
PNS_NODE
*
PNS_ROUTER
::
removeLoops
(
PNS_NODE
*
aNode
,
PNS_SEGMENT
*
aLatestSeg
)
PNS_NODE
*
PNS_ROUTER
::
removeLoops
(
PNS_NODE
*
aNode
,
PNS_SEGMENT
*
aLatestSeg
)
{
PNS_LINE
*
ourLine
=
aNode
->
AssembleLine
(
aLatestSeg
);
PNS_NODE
*
cleaned
=
aNode
->
Branch
();
PNS_LINE
*
ourLine
=
aNode
->
AssembleLine
(
aLatestSeg
);
PNS_NODE
*
cleaned
=
aNode
->
Branch
();
PNS_JOINT
a
,
b
;
vector
<
PNS_LINE
*>
lines
;
vector
<
PNS_LINE
*>
lines
;
cleaned
->
FindLineEnds
(
ourLine
,
a
,
b
);
cleaned
->
FindLinesBetweenJoints
(
a
,
b
,
lines
);
cleaned
->
FindLineEnds
(
ourLine
,
a
,
b
);
cleaned
->
FindLinesBetweenJoints
(
a
,
b
,
lines
);
BOOST_FOREACH
(
PNS_LINE
*
line
,
lines
)
BOOST_FOREACH
(
PNS_LINE
*
line
,
lines
)
{
if
(
!
(
line
->
ContainsSegment
(
aLatestSeg
)
)
)
if
(
!
(
line
->
ContainsSegment
(
aLatestSeg
)
)
)
{
cleaned
->
Remove
(
line
);
cleaned
->
Remove
(
line
);
}
}
...
...
@@ -647,85 +678,85 @@ PNS_NODE *PNS_ROUTER::removeLoops ( PNS_NODE *aNode, PNS_SEGMENT *aLatestSeg )
}
bool
PNS_ROUTER
::
FixRoute
(
const
VECTOR2I
&
aP
,
PNS_ITEM
*
aEndItem
)
{
bool
PNS_ROUTER
::
FixRoute
(
const
VECTOR2I
&
aP
,
PNS_ITEM
*
aEndItem
)
{
bool
real_end
=
false
;
PNS_LINE
pl
=
m_placer
->
GetTrace
();
const
SHAPE_LINE_CHAIN
&
l
=
pl
.
GetCLine
();
if
(
!
l
.
SegmentCount
()
)
if
(
!
l
.
SegmentCount
()
)
return
true
;
VECTOR2I
p_pre_last
=
l
.
CPoint
(
-
1
);
const
VECTOR2I
p_last
=
l
.
CPoint
(
-
1
);
DIRECTION_45
d_last
(
l
.
CSegment
(
-
1
)
);
VECTOR2I
p_pre_last
=
l
.
CPoint
(
-
1
);
const
VECTOR2I
p_last
=
l
.
CPoint
(
-
1
);
DIRECTION_45
d_last
(
l
.
CSegment
(
-
1
)
);
if
(
l
.
PointCount
()
>
2
)
p_pre_last
=
l
.
CPoint
(
-
2
);
if
(
l
.
PointCount
()
>
2
)
p_pre_last
=
l
.
CPoint
(
-
2
);
if
(
aEndItem
&&
m_currentNet
>=
0
&&
m_currentNet
==
aEndItem
->
GetNet
()
)
if
(
aEndItem
&&
m_currentNet
>=
0
&&
m_currentNet
==
aEndItem
->
GetNet
()
)
real_end
=
true
;
int
last
=
(
real_end
||
m_placingVia
)
?
l
.
SegmentCount
()
:
max
(
1
,
l
.
SegmentCount
()
-
1
);
int
last
=
(
real_end
||
m_placingVia
)
?
l
.
SegmentCount
()
:
max
(
1
,
l
.
SegmentCount
()
-
1
);
PNS_NODE
*
latest
=
m_placer
->
GetCurrentNode
();
PNS_NODE
*
latest
=
m_placer
->
GetCurrentNode
();
if
(
real_end
)
splitAdjacentSegments
(
latest
,
aEndItem
,
aP
);
if
(
real_end
)
splitAdjacentSegments
(
latest
,
aEndItem
,
aP
);
PNS_SEGMENT
*
lastSeg
=
NULL
;
for
(
int
i
=
0
;
i
<
last
;
i
++
)
PNS_SEGMENT
*
lastSeg
=
NULL
;
for
(
int
i
=
0
;
i
<
last
;
i
++
)
{
const
SEG
&
s
=
pl
.
GetCLine
().
CSegment
(
i
);
PNS_SEGMENT
*
seg
=
new
PNS_SEGMENT
(
s
,
m_currentNet
);
seg
->
SetWidth
(
pl
.
GetWidth
()
);
seg
->
SetLayer
(
m_currentLayer
);
latest
->
Add
(
seg
);
const
SEG
&
s
=
pl
.
GetCLine
().
CSegment
(
i
);
PNS_SEGMENT
*
seg
=
new
PNS_SEGMENT
(
s
,
m_currentNet
);
seg
->
SetWidth
(
pl
.
GetWidth
()
);
seg
->
SetLayer
(
m_currentLayer
);
latest
->
Add
(
seg
);
lastSeg
=
seg
;
}
if
(
pl
.
EndsWithVia
()
)
latest
->
Add
(
pl
.
GetVia
().
Clone
()
);
latest
->
Add
(
pl
.
GetVia
().
Clone
()
);
if
(
real_end
)
if
(
real_end
)
latest
=
removeLoops
(
latest
,
lastSeg
);
commitRouting
(
latest
);
commitRouting
(
latest
);
EraseView
();
if
(
real_end
)
if
(
real_end
)
{
m_state
=
IDLE
;
//m_world->KillChildren();
}
else
{
// m_world->KillChildren();
}
else
{
m_state
=
ROUTE_TRACK
;
m_placer
->
SetInitialDirection
(
d_last
);
m_placer
->
SetInitialDirection
(
d_last
);
m_currentStart
=
m_placingVia
?
p_last
:
p_pre_last
;
if
(
m_placingVia
)
m_currentLayer
=
NextCopperLayer
(
true
);
if
(
m_placingVia
)
m_currentLayer
=
NextCopperLayer
(
true
);
m_placer
->
StartPlacement
(
m_currentStart
,
m_currentNet
,
m_currentWidth
,
m_currentLayer
);
m_placer
->
StartPlacement
(
m_currentStart
,
m_currentNet
,
m_currentWidth
,
m_currentLayer
);
m_startsOnVia
=
m_placingVia
;
m_placingVia
=
false
;
}
return
real_end
;
}
void
PNS_ROUTER
::
StopRouting
()
{
if
(
!
RoutingInProgress
()
)
if
(
!
RoutingInProgress
()
)
return
;
//
highlightCurrent(false);
//
highlightCurrent(false);
EraseView
();
...
...
@@ -733,42 +764,50 @@ void PNS_ROUTER::StopRouting()
m_world
->
KillChildren
();
}
void
PNS_ROUTER
::
FlipPosture
()
{
if
(
m_placer
->
GetTail
().
GetCLine
().
SegmentCount
()
==
0
)
if
(
m_placer
->
GetTail
().
GetCLine
().
SegmentCount
()
==
0
)
{
m_start_diagonal
=
!
m_start_diagonal
;
m_placer
->
SetInitialDirection
(
m_start_diagonal
?
DIRECTION_45
(
DIRECTION_45
::
NE
)
:
DIRECTION_45
(
DIRECTION_45
::
N
));
}
else
m_placer
->
SetInitialDirection
(
m_start_diagonal
?
DIRECTION_45
(
DIRECTION_45
::
NE
)
:
DIRECTION_45
(
DIRECTION_45
::
N
)
);
}
else
m_placer
->
FlipPosture
();
Move
(
m_currentEnd
,
NULL
);
Move
(
m_currentEnd
,
NULL
);
}
void
PNS_ROUTER
::
SwitchLayer
(
int
layer
)
void
PNS_ROUTER
::
SwitchLayer
(
int
layer
)
{
switch
(
m_state
)
switch
(
m_state
)
{
case
IDLE
:
m_currentLayer
=
layer
;
break
;
case
ROUTE_TRACK
:
if
(
m_startsOnVia
)
if
(
m_startsOnVia
)
{
m_currentLayer
=
layer
;
m_placer
->
StartPlacement
(
m_currentStart
,
m_currentNet
,
m_currentWidth
,
m_currentLayer
);
m_placer
->
StartPlacement
(
m_currentStart
,
m_currentNet
,
m_currentWidth
,
m_currentLayer
);
}
default
:
break
;
}
}
void
PNS_ROUTER
::
ToggleViaPlacement
()
void
PNS_ROUTER
::
ToggleViaPlacement
()
{
if
(
m_state
==
ROUTE_TRACK
)
if
(
m_state
==
ROUTE_TRACK
)
{
m_placingVia
=
!
m_placingVia
;
m_placer
->
AddVia
(
m_placingVia
,
m_currentViaDiameter
,
m_currentViaDrill
);
m_placer
->
AddVia
(
m_placingVia
,
m_currentViaDiameter
,
m_currentViaDrill
);
}
}
pcbnew/router/pns_router.h
View file @
5598acb6
...
...
@@ -17,6 +17,7 @@
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>.
*/
#ifndef __PNS_ROUTER_H
#define __PNS_ROUTER_H
...
...
@@ -48,8 +49,8 @@ class PNS_CLEARANCE_FUNC;
class
VIEW_GROUP
;
namespace
KiGfx
{
class
VIEW
;
class
VIEW_GROUP
;
class
VIEW
;
class
VIEW_GROUP
;
};
...
...
@@ -59,10 +60,11 @@ namespace KiGfx {
* Main router class.
*/
class
PNS_ROUTER
{
class
PNS_ROUTER
{
private
:
enum
RouterState
{
enum
RouterState
{
IDLE
,
START_ROUTING
,
ROUTE_TRACK
,
...
...
@@ -70,28 +72,27 @@ private:
};
public
:
PNS_ROUTER
();
~
PNS_ROUTER
();
PNS_ROUTER
();
~
PNS_ROUTER
();
static
PNS_ROUTER
*
GetInstance
();
static
PNS_ROUTER
*
GetInstance
();
void
ClearWorld
();
void
SetBoard
(
BOARD
*
aBoard
);
void
SetBoard
(
BOARD
*
aBoard
);
void
SyncWorld
();
void
SetView
(
KiGfx
::
VIEW
*
aView
);
void
SetView
(
KiGfx
::
VIEW
*
aView
);
bool
RoutingInProgress
()
const
;
void
StartRouting
(
const
VECTOR2I
&
aP
,
PNS_ITEM
*
aItem
);
void
Move
(
const
VECTOR2I
&
aP
,
PNS_ITEM
*
aItem
);
bool
FixRoute
(
const
VECTOR2I
&
aP
,
PNS_ITEM
*
aItem
);
void
StartRouting
(
const
VECTOR2I
&
aP
,
PNS_ITEM
*
aItem
);
void
Move
(
const
VECTOR2I
&
aP
,
PNS_ITEM
*
aItem
);
bool
FixRoute
(
const
VECTOR2I
&
aP
,
PNS_ITEM
*
aItem
);
void
StopRouting
();
const
VECTOR2I
GetCurrentEnd
()
const
;
int
GetClearance
(
const
PNS_ITEM
*
a
,
const
PNS_ITEM
*
b
)
const
;
int
GetClearance
(
const
PNS_ITEM
*
a
,
const
PNS_ITEM
*
b
)
const
;
PNS_NODE
*
GetWorld
()
const
{
...
...
@@ -100,24 +101,26 @@ public:
void
FlipPosture
();
void
DisplayItem
(
const
PNS_ITEM
*
aItem
,
bool
aIsHead
=
false
);
void
DisplayDebugLine
(
const
SHAPE_LINE_CHAIN
&
aLine
,
int
aType
=
0
,
int
aWidth
=
0
);
void
DisplayDebugBox
(
const
BOX2I
&
aBox
,
int
aType
=
0
,
int
aWidth
=
0
);
void
DisplayItem
(
const
PNS_ITEM
*
aItem
,
bool
aIsHead
=
false
);
void
DisplayDebugLine
(
const
SHAPE_LINE_CHAIN
&
aLine
,
int
aType
=
0
,
int
aWidth
=
0
);
void
DisplayDebugBox
(
const
BOX2I
&
aBox
,
int
aType
=
0
,
int
aWidth
=
0
);
void
EraseView
();
void
SwitchLayer
(
int
layer
);
void
EraseView
(
);
void
SwitchLayer
(
int
layer
);
int
GetCurrentLayer
()
const
{
return
m_currentLayer
;
}
void
ToggleViaPlacement
();
void
ToggleViaPlacement
();
void
SetCurrentWidth
(
int
w
);
void
SetCurrentViaDiameter
(
int
d
)
{
m_currentViaDiameter
=
d
;}
void
SetCurrentViaDrill
(
int
d
)
{
m_currentViaDrill
=
d
;}
void
SetCurrentWidth
(
int
w
);
void
SetCurrentViaDiameter
(
int
d
)
{
m_currentViaDiameter
=
d
;
}
void
SetCurrentViaDrill
(
int
d
)
{
m_currentViaDrill
=
d
;
}
int
GetCurrentWidth
()
const
{
return
m_currentWidth
;
}
int
GetCurrentViaDiameter
()
const
{
return
m_currentViaDiameter
;
}
int
GetCurrentViaDrill
()
const
{
return
m_currentViaDrill
;
}
int
GetCurrentNet
()
const
{
return
m_currentNet
;
}
PNS_CLEARANCE_FUNC
*
GetClearanceFunc
()
const
PNS_CLEARANCE_FUNC
*
GetClearanceFunc
()
const
{
return
m_clearanceFunc
;
}
...
...
@@ -127,41 +130,35 @@ public:
return
m_placingVia
;
}
int
NextCopperLayer
(
bool
aUp
);
//typedef boost::optional<hoverItem> optHoverItem;
const
PNS_ITEMSET
QueryHoverItems
(
const
VECTOR2I
&
aP
);
const
VECTOR2I
SnapToItem
(
PNS_ITEM
*
item
,
VECTOR2I
aP
,
bool
&
aSplitsSegment
);
// typedef boost::optional<hoverItem> optHoverItem;
const
PNS_ITEMSET
QueryHoverItems
(
const
VECTOR2I
&
aP
);
const
VECTOR2I
SnapToItem
(
PNS_ITEM
*
item
,
VECTOR2I
aP
,
bool
&
aSplitsSegment
);
private
:
void
clearViewFlags
();
//
optHoverItem queryHoverItemEx(const VECTOR2I& aP);
//
optHoverItem queryHoverItemEx(const VECTOR2I& aP);
PNS_ITEM
*
pickSingleItem
(
PNS_ITEMSET
&
aItems
)
const
;
//
std::vector<PNS_ITEM*> aItems) const;
void
splitAdjacentSegments
(
PNS_NODE
*
aNode
,
PNS_ITEM
*
aSeg
,
const
VECTOR2I
&
aP
);
//
optHoverItem& aItem);
void
commitRouting
(
PNS_NODE
*
aNode
);
PNS_NODE
*
removeLoops
(
PNS_NODE
*
aNode
,
PNS_SEGMENT
*
aLatestSeg
);
PNS_NODE
*
removeLoops
(
PNS_NODE
*
aNode
,
PNS_LINE
*
aNewLine
);
PNS_VIA
*
checkLoneVia
(
PNS_JOINT
*
aJoint
)
const
;
PNS_ITEM
*
pickSingleItem
(
PNS_ITEMSET
&
aItems
)
const
;
//
std::vector<PNS_ITEM*> aItems) const;
void
splitAdjacentSegments
(
PNS_NODE
*
aNode
,
PNS_ITEM
*
aSeg
,
const
VECTOR2I
&
aP
);
//
optHoverItem& aItem);
void
commitRouting
(
PNS_NODE
*
aNode
);
PNS_NODE
*
removeLoops
(
PNS_NODE
*
aNode
,
PNS_SEGMENT
*
aLatestSeg
);
PNS_NODE
*
removeLoops
(
PNS_NODE
*
aNode
,
PNS_LINE
*
aNewLine
);
PNS_VIA
*
checkLoneVia
(
PNS_JOINT
*
aJoint
)
const
;
PNS_ITEM
*
syncPad
(
D_PAD
*
aPad
);
PNS_ITEM
*
syncTrack
(
TRACK
*
aTrack
);
PNS_ITEM
*
syncVia
(
SEGVIA
*
aVia
);
PNS_ITEM
*
syncPad
(
D_PAD
*
aPad
);
PNS_ITEM
*
syncTrack
(
TRACK
*
aTrack
);
PNS_ITEM
*
syncVia
(
SEGVIA
*
aVia
);
void
commitPad
(
PNS_SOLID
*
aPad
);
void
commitSegment
(
PNS_SEGMENT
*
aTrack
);
void
commitVia
(
PNS_VIA
*
aVia
);
void
commitPad
(
PNS_SOLID
*
aPad
);
void
commitSegment
(
PNS_SEGMENT
*
aTrack
);
void
commitVia
(
PNS_VIA
*
aVia
);
void
highlightCurrent
(
bool
enabled
);
int
m_currentLayer
;
int
m_currentNet
;
int
m_currentWidth
;
...
...
@@ -172,12 +169,12 @@ private:
RouterState
m_state
;
BOARD
*
m_board
;
PNS_NODE
*
m_world
;
PNS_LINE_PLACER
*
m_placer
;
BOARD
*
m_board
;
PNS_NODE
*
m_world
;
PNS_LINE_PLACER
*
m_placer
;
KiGfx
::
VIEW
*
m_view
;
KiGfx
::
VIEW_GROUP
*
m_previewItems
;
KiGfx
::
VIEW
*
m_view
;
KiGfx
::
VIEW_GROUP
*
m_previewItems
;
VECTOR2I
m_currentEnd
;
VECTOR2I
m_currentStart
;
...
...
@@ -188,10 +185,10 @@ private:
// optHoverItem m_startItem, m_endItem;
PNS_ROUTING_SETTINGS
m_settings
;
PNS_CLEARANCE_FUNC
*
m_clearanceFunc
;
boost
::
unordered_set
<
BOARD_ITEM
*>
m_hiddenItems
;
PNS_CLEARANCE_FUNC
*
m_clearanceFunc
;
boost
::
unordered_set
<
BOARD_ITEM
*>
m_hiddenItems
;
};
#endif
pcbnew/router/pns_routing_settings.h
View file @
5598acb6
...
...
@@ -22,7 +22,8 @@
#define __PNS_ROUTER_SETTINGS
///> Routing modes
enum
PNS_MODE
{
enum
PNS_MODE
{
RM_Ignore
=
0
,
///> Ignore collisions
RM_Shove
,
///> Only shove
RM_Walkaround
,
///> Only walkaround
...
...
@@ -31,7 +32,7 @@ enum PNS_MODE {
class
PNS_ROUTING_SETTINGS
{
public
:
public
:
PNS_MODE
m_routingMode
;
bool
m_removeLoops
;
...
...
pcbnew/router/pns_segment.h
View file @
5598acb6
...
...
@@ -32,42 +32,44 @@
class
PNS_NODE
;
class
PNS_SEGMENT
:
public
PNS_ITEM
{
class
PNS_SEGMENT
:
public
PNS_ITEM
{
public
:
PNS_SEGMENT
()
:
PNS_ITEM
(
SEGMENT
)
PNS_SEGMENT
()
:
PNS_ITEM
(
SEGMENT
)
{};
PNS_SEGMENT
(
const
SEG
&
aSeg
,
int
aNet
)
:
PNS_ITEM
(
SEGMENT
)
PNS_SEGMENT
(
const
SEG
&
aSeg
,
int
aNet
)
:
PNS_ITEM
(
SEGMENT
)
{
m_net
=
aNet
;
m_shape
.
Clear
();
m_shape
.
Append
(
aSeg
.
a
);
m_shape
.
Append
(
aSeg
.
b
);
m_shape
.
Append
(
aSeg
.
a
);
m_shape
.
Append
(
aSeg
.
b
);
};
PNS_SEGMENT
(
const
PNS_LINE
&
aParentLine
,
const
SEG
&
aSeg
)
:
PNS_ITEM
(
SEGMENT
)
PNS_SEGMENT
(
const
PNS_LINE
&
aParentLine
,
const
SEG
&
aSeg
)
:
PNS_ITEM
(
SEGMENT
)
{
m_net
=
aParentLine
.
GetNet
();
m_layers
=
aParentLine
.
GetLayers
();
m_width
=
aParentLine
.
GetWidth
();
m_shape
.
Clear
();
m_shape
.
Append
(
aSeg
.
a
);
m_shape
.
Append
(
aSeg
.
b
);
m_shape
.
Append
(
aSeg
.
a
);
m_shape
.
Append
(
aSeg
.
b
);
};
PNS_SEGMENT
*
Clone
()
const
;
PNS_SEGMENT
*
Clone
()
const
;
const
SHAPE
*
GetShape
()
const
{
return
static_cast
<
const
SHAPE
*>
(
&
m_shape
);
const
SHAPE
*
GetShape
()
const
{
return
static_cast
<
const
SHAPE
*>
(
&
m_shape
);
}
void
SetLayer
(
int
aLayer
)
void
SetLayer
(
int
aLayer
)
{
SetLayers
(
PNS_LAYERSET
(
aLayer
)
);
SetLayers
(
PNS_LAYERSET
(
aLayer
)
);
}
int
GetLayer
()
const
...
...
@@ -85,22 +87,26 @@ public:
m_width
=
aWidth
;
}
int
GetWidth
()
const
{
int
GetWidth
()
const
{
return
m_width
;
}
const
SEG
GetSeg
()
const
{
assert
(
m_shape
.
PointCount
()
>=
1
);
if
(
m_shape
.
PointCount
()
==
1
)
return
SEG
(
m_shape
.
CPoint
(
0
),
m_shape
.
CPoint
(
0
));
return
SEG
(
m_shape
.
CPoint
(
0
),
m_shape
.
CPoint
(
1
));
const
SEG
GetSeg
()
const
{
assert
(
m_shape
.
PointCount
()
>=
1
);
if
(
m_shape
.
PointCount
()
==
1
)
return
SEG
(
m_shape
.
CPoint
(
0
),
m_shape
.
CPoint
(
0
)
);
return
SEG
(
m_shape
.
CPoint
(
0
),
m_shape
.
CPoint
(
1
)
);
}
void
SetEnds
(
const
VECTOR2I
&
a
,
const
VECTOR2I
&
b
)
void
SetEnds
(
const
VECTOR2I
&
a
,
const
VECTOR2I
&
b
)
{
m_shape
.
Clear
();
m_shape
.
Append
(
a
);
m_shape
.
Append
(
b
);
m_shape
.
Append
(
a
);
m_shape
.
Append
(
b
);
}
void
SwapEnds
()
...
...
@@ -108,12 +114,12 @@ public:
m_shape
=
m_shape
.
Reverse
();
}
const
SHAPE_LINE_CHAIN
Hull
(
int
aClearance
,
int
aWalkaroundThickness
)
const
;
const
SHAPE_LINE_CHAIN
Hull
(
int
aClearance
,
int
aWalkaroundThickness
)
const
;
private
:
SHAPE_LINE_CHAIN
m_shape
;
int
m_width
;
};
#endif
pcbnew/router/pns_shove.cpp
View file @
5598acb6
...
...
@@ -37,30 +37,34 @@
using
namespace
std
;
PNS_SHOVE
::
PNS_SHOVE
(
PNS_NODE
*
aWorld
)
PNS_SHOVE
::
PNS_SHOVE
(
PNS_NODE
*
aWorld
)
{
m_root
=
aWorld
;
m_iterLimit
=
100
;
};
PNS_SHOVE
::~
PNS_SHOVE
()
{
}
struct
range
{
struct
range
{
range
()
{
min_v
=
max_v
=
-
1
;
}
void
add
(
int
x
)
void
add
(
int
x
)
{
if
(
min_v
<
0
)
min_v
=
x
;
if
(
max_v
<
0
)
max_v
=
x
;
if
(
min_v
<
0
)
min_v
=
x
;
if
(
x
<
min_v
)
if
(
max_v
<
0
)
max_v
=
x
;
if
(
x
<
min_v
)
min_v
=
x
;
else
if
(
x
>
max_v
)
else
if
(
x
>
max_v
)
max_v
=
x
;
}
...
...
@@ -78,56 +82,58 @@ struct range {
};
// fixme: this is damn f***ing inefficient. And fails much too often due to broken direction finding algorithm.
bool
PNS_SHOVE
::
tryShove
(
PNS_NODE
*
aNode
,
PNS_LINE
*
aHead
,
PNS_LINE
*
aObstacle
,
PNS_SEGMENT
&
aObstacleSeg
,
PNS_LINE
*
aResult
,
bool
aInvertWinding
)
bool
PNS_SHOVE
::
tryShove
(
PNS_NODE
*
aNode
,
PNS_LINE
*
aHead
,
PNS_LINE
*
aObstacle
,
PNS_SEGMENT
&
aObstacleSeg
,
PNS_LINE
*
aResult
,
bool
aInvertWinding
)
{
const
SHAPE_LINE_CHAIN
&
head
=
aHead
->
GetCLine
();
const
SHAPE_LINE_CHAIN
&
head
=
aHead
->
GetCLine
();
bool
cw
=
false
;
int
i
;
if
(
aHead
->
EndsWithVia
()
&&
!
aHead
->
GetLayers
().
Overlaps
(
aObstacle
->
GetLayers
())
)
if
(
aHead
->
EndsWithVia
()
&&
!
aHead
->
GetLayers
().
Overlaps
(
aObstacle
->
GetLayers
()
)
)
{
int
clearance
=
aNode
->
GetClearance
(
aHead
,
aObstacle
);
int
clearance
=
aNode
->
GetClearance
(
aHead
,
aObstacle
);
SHAPE_LINE_CHAIN
hull
=
aHead
->
GetVia
().
Hull
(
clearance
-
aObstacle
->
GetWidth
()
/
2
);
//
SHAPE_LINE_CHAIN path_pre, path_walk_cw, path_walk_ccw, path_post;
//
SHAPE_LINE_CHAIN path_pre, path_walk_cw, path_walk_ccw, path_post;
SHAPE_LINE_CHAIN
path_cw
,
path_ccw
,
*
path
;
SHAPE_LINE_CHAIN
path_cw
,
path_ccw
,
*
path
;
aObstacle
->
NewWalkaround
(
hull
,
path_cw
,
true
);
aObstacle
->
NewWalkaround
(
hull
,
path_ccw
,
false
);
aObstacle
->
NewWalkaround
(
hull
,
path_cw
,
true
);
aObstacle
->
NewWalkaround
(
hull
,
path_ccw
,
false
);
path
=
path_ccw
.
Length
()
<
path_cw
.
Length
()
?
&
path_ccw
:
&
path_cw
;
aResult
->
SetShape
(
*
path
);
aResult
->
SetShape
(
*
path
);
//
PNSDisplayDebugLine (*path, 5);
//
PNSDisplayDebugLine (*path, 5);
if
(
!
aResult
->
Is45Degree
()
)
if
(
!
aResult
->
Is45Degree
()
)
{
//
printf("polyset non-45\npoly %s\nendpolyset\n", aResult->GetCLine().Format().c_str());
//
printf("polyset non-45\npoly %s\nendpolyset\n", aResult->GetCLine().Format().c_str());
}
/*... special case for vias? */
return
!
aNode
->
CheckColliding
(
aResult
,
aHead
);
return
!
aNode
->
CheckColliding
(
aResult
,
aHead
);
}
int
ns
=
head
.
SegmentCount
();
if
(
aHead
->
EndsWithVia
())
ns
++
;
for
(
i
=
0
;
i
<
head
.
SegmentCount
();
i
++
)
{
const
PNS_SEGMENT
hs
(
*
aHead
,
head
.
CSegment
(
i
));
if
(
aHead
->
EndsWithVia
()
)
ns
++
;
for
(
i
=
0
;
i
<
head
.
SegmentCount
();
i
++
)
{
const
PNS_SEGMENT
hs
(
*
aHead
,
head
.
CSegment
(
i
)
);
if
(
aNode
->
CheckColliding
(
&
hs
,
aObstacle
)
)
if
(
aNode
->
CheckColliding
(
&
hs
,
aObstacle
)
)
{
VECTOR2I
v1
=
hs
.
GetSeg
().
b
-
hs
.
GetSeg
().
a
;
VECTOR2I
v2
=
aObstacleSeg
.
GetSeg
().
b
-
aObstacleSeg
.
GetSeg
().
a
;
VECTOR2I
::
extended_type
det
=
v1
.
Cross
(
v2
);
VECTOR2I
::
extended_type
det
=
v1
.
Cross
(
v2
);
if
(
det
>
0
)
if
(
det
>
0
)
cw
=
true
;
else
cw
=
false
;
...
...
@@ -136,76 +142,79 @@ bool PNS_SHOVE::tryShove(PNS_NODE *aNode, PNS_LINE *aHead, PNS_LINE *aObstacle,
}
}
if
(
aInvertWinding
)
if
(
aInvertWinding
)
{
if
(
cw
)
if
(
cw
)
cw
=
false
;
else
cw
=
true
;
}
PNS_LINE
shoved
(
*
aObstacle
);
PNS_LINE
shoved
(
*
aObstacle
);
int
clearance
=
aNode
->
GetClearance
(
aHead
,
aObstacle
);
int
clearance
=
aNode
->
GetClearance
(
aHead
,
aObstacle
);
range
r
;
for
(
i
=
0
;
i
<
ns
;
i
++
)
for
(
i
=
0
;
i
<
ns
;
i
++
)
{
SHAPE_LINE_CHAIN
hull
;
if
(
i
<
head
.
SegmentCount
()
)
if
(
i
<
head
.
SegmentCount
()
)
{
const
PNS_SEGMENT
hs
(
*
aHead
,
head
.
CSegment
(
i
)
);
const
PNS_SEGMENT
hs
(
*
aHead
,
head
.
CSegment
(
i
)
);
hull
=
hs
.
Hull
(
clearance
,
0
);
}
else
hull
=
aHead
->
GetVia
().
Hull
(
clearance
-
aObstacle
->
GetWidth
()
/
2
);
}
else
hull
=
aHead
->
GetVia
().
Hull
(
clearance
-
aObstacle
->
GetWidth
()
/
2
);
SHAPE_LINE_CHAIN
path_pre
,
path_walk
,
path_post
,
tmp
;
SHAPE_LINE_CHAIN
path_pre2
,
path_walk2
,
path_post2
;
//
shoved.NewWalkaround(hull, path_pre, path_walk, path_post, cw);
shoved
.
NewWalkaround
(
hull
,
path_pre
,
path_walk
,
path_post
,
cw
);
//
shoved.NewWalkaround(hull, path_pre, path_walk, path_post, cw);
shoved
.
NewWalkaround
(
hull
,
path_pre
,
path_walk
,
path_post
,
cw
);
/*if(path_pre != path_pre2 || path_post != path_post2 || path_walk != path_walk2 )
{
TRACE(5, "polyset orig\npoly %s\npoly %s\npoly %s\nendpolyset\n", path_pre.Format().c_str() % path_walk.Format().c_str() % path_post.Format().c_str());
TRACE(5, "polyset err\npoly %s\npoly %s\npoly %s\nendpolyset\n", path_pre2.Format().c_str() % path_walk2.Format().c_str() % path_post2.Format().c_str());
}*/
*
{
*
TRACE(5, "polyset orig\npoly %s\npoly %s\npoly %s\nendpolyset\n", path_pre.Format().c_str() % path_walk.Format().c_str() % path_post.Format().c_str());
*
TRACE(5, "polyset err\npoly %s\npoly %s\npoly %s\nendpolyset\n", path_pre2.Format().c_str() % path_walk2.Format().c_str() % path_post2.Format().c_str());
*
}*/
tmp
=
shoved
.
GetCLine
();
if
(
path_walk
.
SegmentCount
())
r
.
add
(
i
);
path_pre
.
Append
(
path_walk
);
path_pre
.
Append
(
path_post
);
if
(
path_walk
.
SegmentCount
()
)
r
.
add
(
i
);
path_pre
.
Append
(
path_walk
);
path_pre
.
Append
(
path_post
);
path_pre
.
Simplify
();
shoved
.
SetShape
(
path_pre
);
shoved
.
SetShape
(
path_pre
);
// shoved.SetAffectedRange ( start, end );
*
aResult
=
shoved
;
if
(
!
aResult
->
Is45Degree
()
)
if
(
!
aResult
->
Is45Degree
()
)
{
//
TRACE(5, "polyset non-45\npoly %s\npoly %s\npoly %s\nendpolyset\n", tmp.Format().c_str() % hull.Format().c_str() % aResult->GetCLine().Format().c_str());
//
TRACE(5, "polyset non-45\npoly %s\npoly %s\npoly %s\nendpolyset\n", tmp.Format().c_str() % hull.Format().c_str() % aResult->GetCLine().Format().c_str());
}
}
TRACE
(
2
,
"CW %d affectedRange %d-%d [total %d]"
,
(
cw
?
1
:
0
)
%
r
.
start
()
%
r
.
end
()
%
ns
);
TRACE
(
2
,
"CW %d affectedRange %d-%d [total %d]"
,
(
cw
?
1
:
0
)
%
r
.
start
()
%
r
.
end
()
%
ns
);
return
!
aNode
->
CheckColliding
(
aResult
,
aHead
);
return
!
aNode
->
CheckColliding
(
aResult
,
aHead
);
}
PNS_SHOVE
::
ShoveStatus
PNS_SHOVE
::
shoveSingleLine
(
PNS_NODE
*
aNode
,
PNS_LINE
*
aCurrent
,
PNS_LINE
*
aObstacle
,
PNS_SEGMENT
&
aObstacleSeg
,
PNS_LINE
*
aResult
)
PNS_SHOVE
::
ShoveStatus
PNS_SHOVE
::
shoveSingleLine
(
PNS_NODE
*
aNode
,
PNS_LINE
*
aCurrent
,
PNS_LINE
*
aObstacle
,
PNS_SEGMENT
&
aObstacleSeg
,
PNS_LINE
*
aResult
)
{
bool
rv
=
tryShove
(
aNode
,
aCurrent
,
aObstacle
,
aObstacleSeg
,
aResult
,
false
);
bool
rv
=
tryShove
(
aNode
,
aCurrent
,
aObstacle
,
aObstacleSeg
,
aResult
,
false
);
if
(
!
rv
)
rv
=
tryShove
(
aNode
,
aCurrent
,
aObstacle
,
aObstacleSeg
,
aResult
,
true
);
rv
=
tryShove
(
aNode
,
aCurrent
,
aObstacle
,
aObstacleSeg
,
aResult
,
true
);
if
(
!
rv
)
{
TRACEn
(
2
,
"Shove failed"
);
TRACEn
(
2
,
"Shove failed"
);
return
SH_INCOMPLETE
;
}
...
...
@@ -214,105 +223,111 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::shoveSingleLine(PNS_NODE *aNode, PNS_LINE *aCu
const
SHAPE_LINE_CHAIN
&
sh_shoved
=
aResult
->
GetCLine
();
const
SHAPE_LINE_CHAIN
&
sh_orig
=
aObstacle
->
GetCLine
();
if
(
sh_shoved
.
SegmentCount
()
>
1
&&
sh_shoved
.
CPoint
(
0
)
==
sh_orig
.
CPoint
(
0
)
&&
sh_shoved
.
CPoint
(
-
1
)
==
sh_orig
.
CPoint
(
-
1
)
)
if
(
sh_shoved
.
SegmentCount
()
>
1
&&
sh_shoved
.
CPoint
(
0
)
==
sh_orig
.
CPoint
(
0
)
&&
sh_shoved
.
CPoint
(
-
1
)
==
sh_orig
.
CPoint
(
-
1
)
)
return
SH_OK
;
else
if
(
!
sh_shoved
.
SegmentCount
()
)
else
if
(
!
sh_shoved
.
SegmentCount
()
)
return
SH_NULL
;
else
return
SH_INCOMPLETE
;
}
bool
PNS_SHOVE
::
reduceSpringback
(
PNS_LINE
*
aHead
)
bool
PNS_SHOVE
::
reduceSpringback
(
PNS_LINE
*
aHead
)
{
bool
rv
=
false
;
while
(
!
m_nodeStack
.
empty
()
)
while
(
!
m_nodeStack
.
empty
()
)
{
SpringbackTag
st_stack
=
m_nodeStack
.
back
();
bool
tail_ok
=
true
;
if
(
!
st_stack
.
node
->
CheckColliding
(
aHead
)
&&
tail_ok
)
if
(
!
st_stack
.
node
->
CheckColliding
(
aHead
)
&&
tail_ok
)
{
rv
=
true
;
delete
st_stack
.
node
;
m_nodeStack
.
pop_back
();
}
else
}
else
break
;
}
return
rv
;
}
bool
PNS_SHOVE
::
pushSpringback
(
PNS_NODE
*
aNode
,
PNS_LINE
*
aHead
,
const
PNS_COST_ESTIMATOR
&
aCost
)
bool
PNS_SHOVE
::
pushSpringback
(
PNS_NODE
*
aNode
,
PNS_LINE
*
aHead
,
const
PNS_COST_ESTIMATOR
&
aCost
)
{
BOX2I
headBB
=
aHead
->
GetCLine
().
BBox
();
SpringbackTag
st
;
st
.
node
=
aNode
;
st
.
cost
=
aCost
;
st
.
length
=
std
::
max
(
headBB
.
GetWidth
(),
headBB
.
GetHeight
()
);;
m_nodeStack
.
push_back
(
st
);
st
.
length
=
std
::
max
(
headBB
.
GetWidth
(),
headBB
.
GetHeight
()
);;
m_nodeStack
.
push_back
(
st
);
return
true
;
}
const
PNS_COST_ESTIMATOR
PNS_SHOVE
::
TotalCost
()
const
{
if
(
m_nodeStack
.
empty
()
)
if
(
m_nodeStack
.
empty
()
)
return
PNS_COST_ESTIMATOR
();
else
return
m_nodeStack
.
back
().
cost
;
}
PNS_SHOVE
::
ShoveStatus
PNS_SHOVE
::
ShoveLines
(
PNS_LINE
*
aCurrentHead
)
PNS_SHOVE
::
ShoveStatus
PNS_SHOVE
::
ShoveLines
(
PNS_LINE
*
aCurrentHead
)
{
stack
<
PNS_LINE
*>
lineStack
;
PNS_NODE
*
node
,
*
parent
;
PNS_VIA
*
headVia
=
NULL
;
stack
<
PNS_LINE
*>
lineStack
;
PNS_NODE
*
node
,
*
parent
;
PNS_VIA
*
headVia
=
NULL
;
bool
fail
=
false
;
int
iter
=
0
;
PNS_LINE
*
head
=
aCurrentHead
->
Clone
();
PNS_LINE
*
head
=
aCurrentHead
->
Clone
();
reduceSpringback
(
aCurrentHead
);
reduceSpringback
(
aCurrentHead
);
parent
=
m_nodeStack
.
empty
()
?
m_root
:
m_nodeStack
.
back
().
node
;
node
=
parent
->
Branch
();
lineStack
.
push
(
head
);
lineStack
.
push
(
head
);
//
node->Add(tail);
node
->
Add
(
head
);
//
node->Add(tail);
node
->
Add
(
head
);
if
(
head
->
EndsWithVia
()
)
if
(
head
->
EndsWithVia
()
)
{
headVia
=
head
->
GetVia
().
Clone
();
node
->
Add
(
headVia
);
}
PNS_OPTIMIZER
optimizer
(
node
);
PNS_OPTIMIZER
optimizer
(
node
);
optimizer
.
SetEffortLevel
(
PNS_OPTIMIZER
::
MERGE_SEGMENTS
|
PNS_OPTIMIZER
::
SMART_PADS
);
optimizer
.
SetEffortLevel
(
PNS_OPTIMIZER
::
MERGE_SEGMENTS
|
PNS_OPTIMIZER
::
SMART_PADS
);
optimizer
.
SetCollisionMask
(
-
1
);
PNS_NODE
::
OptObstacle
nearest
;
optimizer
.
CacheStaticItem
(
head
);
if
(
headVia
)
optimizer
.
CacheStaticItem
(
headVia
);
optimizer
.
CacheStaticItem
(
head
);
TRACE
(
1
,
"ShoveStart [root: %d jts, node: %d jts]"
,
m_root
->
JointCount
()
%
node
->
JointCount
());
if
(
headVia
)
optimizer
.
CacheStaticItem
(
headVia
);
//PNS_ITEM *lastWalkSolid = NULL;
prof_counter
totalRealTime
;
TRACE
(
1
,
"ShoveStart [root: %d jts, node: %d jts]"
,
m_root
->
JointCount
()
%
node
->
JointCount
()
)
;
// PNS_ITEM *lastWalkSolid = NULL;
prof_counter
totalRealTime
;
wxLongLong
t_start
=
wxGetLocalTimeMillis
();
while
(
!
lineStack
.
empty
()
)
while
(
!
lineStack
.
empty
()
)
{
wxLongLong
t_cur
=
wxGetLocalTimeMillis
();
if
((
t_cur
-
t_start
).
ToLong
()
>
ShoveTimeLimit
)
if
(
(
t_cur
-
t_start
).
ToLong
()
>
ShoveTimeLimit
)
{
fail
=
true
;
break
;
...
...
@@ -320,80 +335,85 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines(PNS_LINE* aCurrentHead)
iter
++
;
if
(
iter
>
m_iterLimit
)
if
(
iter
>
m_iterLimit
)
{
fail
=
true
;
break
;
}
PNS_LINE
*
currentLine
=
lineStack
.
top
();
PNS_LINE
*
currentLine
=
lineStack
.
top
();
prof_start
(
&
totalRealTime
,
false
);
nearest
=
node
->
NearestObstacle
(
currentLine
,
PNS_ITEM
::
ANY
);
nearest
=
node
->
NearestObstacle
(
currentLine
,
PNS_ITEM
::
ANY
);
prof_end
(
&
totalRealTime
);
TRACE
(
2
,
"t-nearestObstacle %lld us"
,
(
totalRealTime
.
value
)
);
TRACE
(
2
,
"t-nearestObstacle %lld us"
,
(
totalRealTime
.
value
)
);
if
(
!
nearest
)
if
(
!
nearest
)
{
if
(
lineStack
.
size
()
>
1
)
if
(
lineStack
.
size
()
>
1
)
{
PNS_LINE
*
original
=
lineStack
.
top
();
PNS_LINE
*
original
=
lineStack
.
top
();
PNS_LINE
optimized
;
int
r_start
,
r_end
;
original
->
GetAffectedRange
(
r_start
,
r_end
);
original
->
GetAffectedRange
(
r_start
,
r_end
);
TRACE
(
1
,
"Iter %d optimize-line [range %d-%d, total %d]"
,
iter
%
r_start
%
r_end
%
original
->
GetCLine
().
PointCount
()
);
//lastWalkSolid = NULL;
TRACE
(
1
,
"Iter %d optimize-line [range %d-%d, total %d]"
,
iter
%
r_start
%
r_end
%
original
->
GetCLine
().
PointCount
()
);
// lastWalkSolid = NULL;
prof_start
(
&
totalRealTime
,
false
);
if
(
optimizer
.
Optimize
(
original
,
&
optimized
)
)
if
(
optimizer
.
Optimize
(
original
,
&
optimized
)
)
{
node
->
Remove
(
original
);
optimizer
.
CacheRemove
(
original
);
node
->
Add
(
&
optimized
);
node
->
Remove
(
original
);
optimizer
.
CacheRemove
(
original
);
node
->
Add
(
&
optimized
);
if
(
original
->
BelongsTo
(
node
)
)
if
(
original
->
BelongsTo
(
node
)
)
delete
original
;
}
prof_end
(
&
totalRealTime
);
TRACE
(
2
,
"t-optimizeObstacle %lld us"
,
(
totalRealTime
.
value
)
);
prof_end
(
&
totalRealTime
);
TRACE
(
2
,
"t-optimizeObstacle %lld us"
,
(
totalRealTime
.
value
)
);
}
lineStack
.
pop
();
}
else
{
switch
(
nearest
->
item
->
GetKind
())
lineStack
.
pop
();
}
else
{
switch
(
nearest
->
item
->
GetKind
()
)
{
case
PNS_ITEM
:
:
SEGMENT
:
{
TRACE
(
1
,
"Iter %d shove-line"
,
iter
);
TRACE
(
1
,
"Iter %d shove-line"
,
iter
);
PNS_SEGMENT
*
pseg
=
static_cast
<
PNS_SEGMENT
*>
(
nearest
->
item
);
PNS_LINE
*
collidingLine
=
node
->
AssembleLine
(
pseg
);
PNS_LINE
*
shovedLine
=
collidingLine
->
CloneProperties
();
PNS_SEGMENT
*
pseg
=
static_cast
<
PNS_SEGMENT
*>
(
nearest
->
item
);
PNS_LINE
*
collidingLine
=
node
->
AssembleLine
(
pseg
);
PNS_LINE
*
shovedLine
=
collidingLine
->
CloneProperties
();
prof_start
(
&
totalRealTime
,
false
);
ShoveStatus
st
=
shoveSingleLine
(
node
,
currentLine
,
collidingLine
,
*
pseg
,
shovedLine
);
ShoveStatus
st
=
shoveSingleLine
(
node
,
currentLine
,
collidingLine
,
*
pseg
,
shovedLine
);
prof_end
(
&
totalRealTime
);
TRACE
(
2
,
"t-shoveSingle %lld us"
,
(
totalRealTime
.
value
)
);
TRACE
(
2
,
"t-shoveSingle %lld us"
,
(
totalRealTime
.
value
)
);
if
(
st
==
SH_OK
)
if
(
st
==
SH_OK
)
{
node
->
Replace
(
collidingLine
,
shovedLine
);
node
->
Replace
(
collidingLine
,
shovedLine
);
if
(
collidingLine
->
BelongsTo
(
node
)
)
if
(
collidingLine
->
BelongsTo
(
node
)
)
delete
collidingLine
;
optimizer
.
CacheRemove
(
collidingLine
);
optimizer
.
CacheRemove
(
collidingLine
);
lineStack
.
push
(
shovedLine
);
}
else
}
else
fail
=
true
;
//
lastWalkSolid = NULL;
//
lastWalkSolid = NULL;
break
;
}
// case SEGMENT
...
...
@@ -401,67 +421,72 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines(PNS_LINE* aCurrentHead)
case
PNS_ITEM
:
:
SOLID
:
case
PNS_ITEM
:
:
VIA
:
{
TRACE
(
1
,
"Iter %d walkaround-solid [%p]"
,
iter
%
nearest
->
item
);
TRACE
(
1
,
"Iter %d walkaround-solid [%p]"
,
iter
%
nearest
->
item
);
if
(
lineStack
.
size
()
==
1
)
if
(
lineStack
.
size
()
==
1
)
{
fail
=
true
;
break
;
}
/* if(lastWalkSolid == nearest->item)
{
fail = true;
break;
}*/
*
{
*
fail = true;
*
break;
*
}*/
PNS_WALKAROUND
walkaround
(
node
);
PNS_LINE
*
walkaroundLine
=
currentLine
->
CloneProperties
();
PNS_WALKAROUND
walkaround
(
node
);
PNS_LINE
*
walkaroundLine
=
currentLine
->
CloneProperties
();
walkaround
.
SetSolidsOnly
(
true
);
walkaround
.
SetSingleDirection
(
true
);
walkaround
.
SetSolidsOnly
(
true
);
walkaround
.
SetSingleDirection
(
true
);
prof_start
(
&
totalRealTime
,
false
);
walkaround
.
Route
(
*
currentLine
,
*
walkaroundLine
,
false
);
walkaround
.
Route
(
*
currentLine
,
*
walkaroundLine
,
false
);
prof_end
(
&
totalRealTime
);
TRACE
(
2
,
"t-walkSolid %lld us"
,
(
totalRealTime
.
value
)
);
TRACE
(
2
,
"t-walkSolid %lld us"
,
(
totalRealTime
.
value
)
);
node
->
Replace
(
currentLine
,
walkaroundLine
);
node
->
Replace
(
currentLine
,
walkaroundLine
);
if
(
currentLine
->
BelongsTo
(
node
)
)
if
(
currentLine
->
BelongsTo
(
node
)
)
delete
currentLine
;
optimizer
.
CacheRemove
(
currentLine
);
optimizer
.
CacheRemove
(
currentLine
);
lineStack
.
top
()
=
walkaroundLine
;
//
lastWalkSolid = nearest->item;
//
lastWalkSolid = nearest->item;
break
;
}
default
:
break
;
}
// switch
if
(
fail
)
if
(
fail
)
break
;
}
}
node
->
Remove
(
head
);
node
->
Remove
(
head
);
delete
head
;
if
(
headVia
)
if
(
headVia
)
{
node
->
Remove
(
headVia
);
node
->
Remove
(
headVia
);
delete
headVia
;
}
TRACE
(
1
,
"Shove status : %s after %d iterations"
,
(
fail
?
"FAILED"
:
"OK"
)
%
iter
);
if
(
!
fail
)
TRACE
(
1
,
"Shove status : %s after %d iterations"
,
(
fail
?
"FAILED"
:
"OK"
)
%
iter
);
if
(
!
fail
)
{
pushSpringback
(
node
,
aCurrentHead
,
PNS_COST_ESTIMATOR
()
);
pushSpringback
(
node
,
aCurrentHead
,
PNS_COST_ESTIMATOR
()
);
return
SH_OK
;
}
else
{
}
else
{
delete
node
;
return
SH_INCOMPLETE
;
}
...
...
pcbnew/router/pns_shove.h
View file @
5598acb6
...
...
@@ -30,21 +30,22 @@ class PNS_LINE;
class
PNS_NODE
;
class
PNS_ROUTER
;
class
PNS_SHOVE
{
public
:
PNS_SHOVE
(
PNS_NODE
*
aWorld
);
class
PNS_SHOVE
{
public
:
PNS_SHOVE
(
PNS_NODE
*
aWorld
);
~
PNS_SHOVE
();
enum
ShoveStatus
{
enum
ShoveStatus
{
SH_OK
=
0
,
SH_NULL
,
SH_INCOMPLETE
};
ShoveStatus
ShoveLines
(
PNS_LINE
*
aCurrentHead
);
ShoveStatus
ShoveLines
(
PNS_LINE
*
aCurrentHead
);
PNS_NODE
*
GetCurrentNode
()
PNS_NODE
*
GetCurrentNode
()
{
return
m_nodeStack
.
empty
()
?
m_root
:
m_nodeStack
.
back
().
node
;
}
...
...
@@ -54,29 +55,32 @@ class PNS_SHOVE {
void
Reset
();
void
KillChildNodes
();
private
:
private
:
static
const
int
ShoveTimeLimit
=
3000
;
bool
tryShove
(
PNS_NODE
*
aWorld
,
PNS_LINE
*
aTrack
,
PNS_LINE
*
aObstacle
,
PNS_SEGMENT
&
aObstacleSeg
,
PNS_LINE
*
aResult
,
bool
aInvertWinding
);
bool
tryShove
(
PNS_NODE
*
aWorld
,
PNS_LINE
*
aTrack
,
PNS_LINE
*
aObstacle
,
PNS_SEGMENT
&
aObstacleSeg
,
PNS_LINE
*
aResult
,
bool
aInvertWinding
);
ShoveStatus
shoveSingleLine
(
PNS_NODE
*
aNode
,
PNS_LINE
*
aCurrent
,
PNS_LINE
*
aObstacle
,
PNS_SEGMENT
&
aObstacleSeg
,
PNS_LINE
*
aResult
);
ShoveStatus
shoveSingleLine
(
PNS_NODE
*
aNode
,
PNS_LINE
*
aCurrent
,
PNS_LINE
*
aObstacle
,
PNS_SEGMENT
&
aObstacleSeg
,
PNS_LINE
*
aResult
);
bool
reduceSpringback
(
PNS_LINE
*
aHead
);
bool
pushSpringback
(
PNS_NODE
*
aNode
,
PNS_LINE
*
aHead
,
const
PNS_COST_ESTIMATOR
&
aCost
);
bool
reduceSpringback
(
PNS_LINE
*
aHead
);
bool
pushSpringback
(
PNS_NODE
*
aNode
,
PNS_LINE
*
aHead
,
const
PNS_COST_ESTIMATOR
&
aCost
);
struct
SpringbackTag
{
struct
SpringbackTag
{
int64_t
length
;
int
segments
;
VECTOR2I
p
;
PNS_NODE
*
node
;
PNS_NODE
*
node
;
PNS_COST_ESTIMATOR
cost
;
};
std
::
vector
<
SpringbackTag
>
m_nodeStack
;
PNS_NODE
*
m_root
;
PNS_NODE
*
m_currentNode
;
PNS_NODE
*
m_root
;
PNS_NODE
*
m_currentNode
;
int
m_iterLimit
;
};
#endif
pcbnew/router/pns_solid.cpp
View file @
5598acb6
...
...
@@ -28,28 +28,25 @@
#include "pns_solid.h"
#include "pns_utils.h"
const
SHAPE_LINE_CHAIN
PNS_SOLID
::
Hull
(
int
aClearance
,
int
aWalkaroundThickness
)
const
const
SHAPE_LINE_CHAIN
PNS_SOLID
::
Hull
(
int
aClearance
,
int
aWalkaroundThickness
)
const
{
switch
(
m_shape
->
Type
()
)
switch
(
m_shape
->
Type
()
)
{
case
SH_RECT
:
{
SHAPE_RECT
*
rect
=
static_cast
<
SHAPE_RECT
*>
(
m_shape
);
return
OctagonalHull
(
rect
->
GetPosition
(),
rect
->
GetSize
(),
aClearance
+
1
,
0.2
*
aClearance
);
SHAPE_RECT
*
rect
=
static_cast
<
SHAPE_RECT
*>
(
m_shape
);
return
OctagonalHull
(
rect
->
GetPosition
(),
rect
->
GetSize
(),
aClearance
+
1
,
0.2
*
aClearance
);
}
case
SH_CIRCLE
:
{
SHAPE_CIRCLE
*
circle
=
static_cast
<
SHAPE_CIRCLE
*>
(
m_shape
);
SHAPE_CIRCLE
*
circle
=
static_cast
<
SHAPE_CIRCLE
*>
(
m_shape
);
int
r
=
circle
->
GetRadius
();
return
OctagonalHull
(
circle
->
GetCenter
()
-
VECTOR2I
(
r
,
r
),
VECTOR2I
(
2
*
r
,
2
*
r
),
aClearance
+
1
,
0.52
*
(
r
+
aClearance
)
);
return
OctagonalHull
(
circle
->
GetCenter
()
-
VECTOR2I
(
r
,
r
),
VECTOR2I
(
2
*
r
,
2
*
r
),
aClearance
+
1
,
0.52
*
(
r
+
aClearance
)
);
}
default
:
break
;
}
...
...
@@ -57,8 +54,10 @@ const SHAPE_LINE_CHAIN PNS_SOLID::Hull(int aClearance, int aWalkaroundThickness)
return
SHAPE_LINE_CHAIN
();
}
PNS_ITEM
*
PNS_SOLID
::
Clone
()
const
PNS_ITEM
*
PNS_SOLID
::
Clone
()
const
{
// solids are never cloned as the shove algorithm never moves them
assert
(
false
);
assert
(
false
);
}
pcbnew/router/pns_solid.h
View file @
5598acb6
...
...
@@ -29,24 +29,26 @@
#include "pns_item.h"
class
PNS_SOLID
:
public
PNS_ITEM
{
class
PNS_SOLID
:
public
PNS_ITEM
{
public
:
PNS_SOLID
()
:
PNS_ITEM
(
SOLID
)
PNS_SOLID
()
:
PNS_ITEM
(
SOLID
)
{
m_movable
=
false
;
m_shape
=
NULL
;
}
PNS_ITEM
*
Clone
()
const
;
PNS_ITEM
*
Clone
()
const
;
const
SHAPE
*
GetShape
()
const
{
return
m_shape
;
}
const
SHAPE_LINE_CHAIN
Hull
(
int
aClearance
=
0
,
int
aWalkaroundThickness
=
0
)
const
;
const
SHAPE_LINE_CHAIN
Hull
(
int
aClearance
=
0
,
int
aWalkaroundThickness
=
0
)
const
;
void
SetShape
(
SHAPE
*
shape
)
void
SetShape
(
SHAPE
*
shape
)
{
if
(
m_shape
)
if
(
m_shape
)
delete
m_shape
;
m_shape
=
shape
;
}
...
...
@@ -61,7 +63,6 @@ public:
}
private
:
VECTOR2I
m_center
;
SHAPE
*
m_shape
;
};
...
...
pcbnew/router/pns_utils.cpp
View file @
5598acb6
...
...
@@ -22,20 +22,23 @@
#include "pns_line.h"
#include "pns_router.h"
const
SHAPE_LINE_CHAIN
OctagonalHull
(
const
VECTOR2I
&
aP0
,
const
VECTOR2I
&
aSize
,
int
aClearance
,
int
aChamfer
)
const
SHAPE_LINE_CHAIN
OctagonalHull
(
const
VECTOR2I
&
aP0
,
const
VECTOR2I
&
aSize
,
int
aClearance
,
int
aChamfer
)
{
SHAPE_LINE_CHAIN
s
;
s
.
SetClosed
(
true
);
s
.
Append
(
aP0
.
x
-
aClearance
,
aP0
.
y
-
aClearance
+
aChamfer
);
s
.
Append
(
aP0
.
x
-
aClearance
+
aChamfer
,
aP0
.
y
-
aClearance
);
s
.
Append
(
aP0
.
x
+
aSize
.
x
+
aClearance
-
aChamfer
,
aP0
.
y
-
aClearance
);
s
.
Append
(
aP0
.
x
+
aSize
.
x
+
aClearance
,
aP0
.
y
-
aClearance
+
aChamfer
);
s
.
Append
(
aP0
.
x
+
aSize
.
x
+
aClearance
,
aP0
.
y
+
aSize
.
y
+
aClearance
-
aChamfer
);
s
.
Append
(
aP0
.
x
+
aSize
.
x
+
aClearance
-
aChamfer
,
aP0
.
y
+
aSize
.
y
+
aClearance
);
s
.
Append
(
aP0
.
x
-
aClearance
+
aChamfer
,
aP0
.
y
+
aSize
.
y
+
aClearance
);
s
.
Append
(
aP0
.
x
-
aClearance
,
aP0
.
y
+
aSize
.
y
+
aClearance
-
aChamfer
);
s
.
Append
(
aP0
.
x
-
aClearance
,
aP0
.
y
-
aClearance
+
aChamfer
);
s
.
Append
(
aP0
.
x
-
aClearance
+
aChamfer
,
aP0
.
y
-
aClearance
);
s
.
Append
(
aP0
.
x
+
aSize
.
x
+
aClearance
-
aChamfer
,
aP0
.
y
-
aClearance
);
s
.
Append
(
aP0
.
x
+
aSize
.
x
+
aClearance
,
aP0
.
y
-
aClearance
+
aChamfer
);
s
.
Append
(
aP0
.
x
+
aSize
.
x
+
aClearance
,
aP0
.
y
+
aSize
.
y
+
aClearance
-
aChamfer
);
s
.
Append
(
aP0
.
x
+
aSize
.
x
+
aClearance
-
aChamfer
,
aP0
.
y
+
aSize
.
y
+
aClearance
);
s
.
Append
(
aP0
.
x
-
aClearance
+
aChamfer
,
aP0
.
y
+
aSize
.
y
+
aClearance
);
s
.
Append
(
aP0
.
x
-
aClearance
,
aP0
.
y
+
aSize
.
y
+
aClearance
-
aChamfer
);
return
s
;
}
...
...
pcbnew/router/pns_utils.h
View file @
5598acb6
...
...
@@ -24,10 +24,10 @@
#include <math/vector2d.h>
#include <geometry/shape_line_chain.h>
/** Various utility functions */
const
SHAPE_LINE_CHAIN
OctagonalHull
(
const
VECTOR2I
&
aP0
,
const
VECTOR2I
&
aSize
,
int
aClearance
,
int
aChamfer
);
const
SHAPE_LINE_CHAIN
OctagonalHull
(
const
VECTOR2I
&
aP0
,
const
VECTOR2I
&
aSize
,
int
aClearance
,
int
aChamfer
);
#endif // __PNS_UTILS_H
pcbnew/router/pns_via.cpp
View file @
5598acb6
...
...
@@ -26,36 +26,39 @@
static
bool
Circle2Circle
(
VECTOR2I
p1
,
VECTOR2I
p2
,
int
r1
,
int
r2
,
VECTOR2I
&
force
)
{
int
mindist
=
r1
+
r2
;
VECTOR2I
delta
=
p2
-
p1
;
int
dist
=
delta
.
EuclideanNorm
();
if
(
dist
>=
mindist
)
if
(
dist
>=
mindist
)
return
false
;
force
=
delta
.
Resize
(
abs
(
mindist
-
dist
)
+
1
);
force
=
delta
.
Resize
(
abs
(
mindist
-
dist
)
+
1
);
return
true
;
};
static
bool
Rect2Circle
(
VECTOR2I
rp0
,
VECTOR2I
rsize
,
VECTOR2I
cc
,
int
cr
,
VECTOR2I
&
force
)
{
VECTOR2I
vts
[]
=
{
VECTOR2I
(
rp0
.
x
,
rp0
.
y
),
VECTOR2I
(
rp0
.
x
,
rp0
.
y
+
rsize
.
y
),
VECTOR2I
(
rp0
.
x
+
rsize
.
x
,
rp0
.
y
+
rsize
.
y
),
VECTOR2I
(
rp0
.
x
+
rsize
.
x
,
rp0
.
y
),
VECTOR2I
(
rp0
.
x
,
rp0
.
y
)
};
VECTOR2I
vts
[]
=
{
VECTOR2I
(
rp0
.
x
,
rp0
.
y
),
VECTOR2I
(
rp0
.
x
,
rp0
.
y
+
rsize
.
y
),
VECTOR2I
(
rp0
.
x
+
rsize
.
x
,
rp0
.
y
+
rsize
.
y
),
VECTOR2I
(
rp0
.
x
+
rsize
.
x
,
rp0
.
y
),
VECTOR2I
(
rp0
.
x
,
rp0
.
y
)
};
int
dist
=
INT_MAX
;
VECTOR2I
nearest
;
for
(
int
i
=
0
;
i
<
4
;
i
++
)
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
SEG
s
(
vts
[
i
],
vts
[
i
+
1
]
);
SEG
s
(
vts
[
i
],
vts
[
i
+
1
]
);
VECTOR2I
pn
=
s
.
NearestPoint
(
cc
);
int
d
=
(
pn
-
cc
).
EuclideanNorm
();
if
(
d
<
dist
)
{
nearest
=
pn
;
...
...
@@ -68,81 +71,91 @@ static bool Rect2Circle( VECTOR2I rp0, VECTOR2I rsize, VECTOR2I cc, int cr, VECT
VECTOR2I
delta
=
cc
-
nearest
;
if
(
dist
>=
cr
&&
!
inside
)
if
(
dist
>=
cr
&&
!
inside
)
return
false
;
if
(
inside
)
force
=
-
delta
.
Resize
(
abs
(
cr
+
dist
)
+
1
);
if
(
inside
)
force
=
-
delta
.
Resize
(
abs
(
cr
+
dist
)
+
1
);
else
force
=
delta
.
Resize
(
abs
(
cr
-
dist
)
+
1
);
force
=
delta
.
Resize
(
abs
(
cr
-
dist
)
+
1
);
return
true
;
};
static
bool
ShPushoutForce
(
const
SHAPE
*
shape
,
VECTOR2I
p
,
int
r
,
VECTOR2I
&
force
,
int
clearance
)
static
bool
ShPushoutForce
(
const
SHAPE
*
shape
,
VECTOR2I
p
,
int
r
,
VECTOR2I
&
force
,
int
clearance
)
{
switch
(
shape
->
Type
()
)
switch
(
shape
->
Type
()
)
{
case
SH_CIRCLE
:
{
const
SHAPE_CIRCLE
*
cir
=
static_cast
<
const
SHAPE_CIRCLE
*>
(
shape
);
const
SHAPE_CIRCLE
*
cir
=
static_cast
<
const
SHAPE_CIRCLE
*>
(
shape
);
return
Circle2Circle
(
cir
->
GetCenter
(),
p
,
cir
->
GetRadius
(),
r
+
clearance
+
1
,
force
);
}
case
SH_RECT
:
{
const
SHAPE_RECT
*
rect
=
static_cast
<
const
SHAPE_RECT
*>
(
shape
);
const
SHAPE_RECT
*
rect
=
static_cast
<
const
SHAPE_RECT
*>
(
shape
);
return
Rect2Circle
(
rect
->
GetPosition
(),
rect
->
GetSize
(),
p
,
r
+
clearance
+
1
,
force
);
}
default:
return
false
;
}
return
false
;
}
bool
PNS_VIA
::
PushoutForce
(
PNS_NODE
*
aNode
,
const
VECTOR2I
&
aDirection
,
VECTOR2I
&
aForce
,
bool
aSolidsOnly
,
int
aMaxIterations
)
bool
PNS_VIA
::
PushoutForce
(
PNS_NODE
*
aNode
,
const
VECTOR2I
&
aDirection
,
VECTOR2I
&
aForce
,
bool
aSolidsOnly
,
int
aMaxIterations
)
{
int
iter
=
0
;
PNS_VIA
mv
(
*
this
);
PNS_VIA
mv
(
*
this
);
VECTOR2I
force
,
totalForce
;
while
(
iter
<
aMaxIterations
)
while
(
iter
<
aMaxIterations
)
{
PNS_NODE
::
OptObstacle
obs
=
aNode
->
CheckColliding
(
&
mv
,
aSolidsOnly
?
PNS_ITEM
::
SOLID
:
PNS_ITEM
::
ANY
);
PNS_NODE
::
OptObstacle
obs
=
aNode
->
CheckColliding
(
&
mv
,
aSolidsOnly
?
PNS_ITEM
::
SOLID
:
PNS_ITEM
::
ANY
);
if
(
!
obs
)
if
(
!
obs
)
break
;
int
clearance
=
aNode
->
GetClearance
(
obs
->
item
,
&
mv
);
int
clearance
=
aNode
->
GetClearance
(
obs
->
item
,
&
mv
);
if
(
iter
>
10
)
if
(
iter
>
10
)
{
VECTOR2I
l
=
-
aDirection
.
Resize
(
m_diameter
/
4
);
VECTOR2I
l
=
-
aDirection
.
Resize
(
m_diameter
/
4
);
totalForce
+=
l
;
mv
.
SetPos
(
mv
.
GetPos
()
+
l
);
mv
.
SetPos
(
mv
.
GetPos
()
+
l
);
}
if
(
ShPushoutForce
(
obs
->
item
->
GetShape
(),
mv
.
GetPos
(),
mv
.
GetDiameter
()
/
2
,
force
,
clearance
)
)
if
(
ShPushoutForce
(
obs
->
item
->
GetShape
(),
mv
.
GetPos
(),
mv
.
GetDiameter
()
/
2
,
force
,
clearance
)
)
{
totalForce
+=
force
;
mv
.
SetPos
(
mv
.
GetPos
()
+
force
);
mv
.
SetPos
(
mv
.
GetPos
()
+
force
);
}
iter
++
;
}
if
(
iter
==
aMaxIterations
)
if
(
iter
==
aMaxIterations
)
return
false
;
aForce
=
totalForce
;
return
true
;
}
const
SHAPE_LINE_CHAIN
PNS_VIA
::
Hull
(
int
aClearance
,
int
aWalkaroundThickness
)
const
const
SHAPE_LINE_CHAIN
PNS_VIA
::
Hull
(
int
aClearance
,
int
aWalkaroundThickness
)
const
{
return
OctagonalHull
(
m_pos
-
VECTOR2I
(
m_diameter
/
2
,
m_diameter
/
2
),
VECTOR2I
(
m_diameter
,
m_diameter
),
aClearance
+
1
,
(
2
*
aClearance
+
m_diameter
)
*
0.26
);
return
OctagonalHull
(
m_pos
-
VECTOR2I
(
m_diameter
/
2
,
m_diameter
/
2
),
VECTOR2I
(
m_diameter
,
m_diameter
),
aClearance
+
1
,
(
2
*
aClearance
+
m_diameter
)
*
0.26
);
}
\ No newline at end of file
pcbnew/router/pns_via.h
View file @
5598acb6
...
...
@@ -30,27 +30,28 @@ class PNS_NODE;
class
PNS_VIA
:
public
PNS_ITEM
{
public
:
PNS_VIA
(
)
:
PNS_ITEM
(
VIA
)
{};
PNS_VIA
(
const
VECTOR2I
&
aPos
,
const
PNS_LAYERSET
&
aLayers
,
int
aDiameter
,
int
aNet
=
-
1
)
:
PNS_ITEM
(
VIA
)
{
SetNet
(
aNet
);
SetLayers
(
aLayers
);
public
:
PNS_VIA
()
:
PNS_ITEM
(
VIA
)
{};
PNS_VIA
(
const
VECTOR2I
&
aPos
,
const
PNS_LAYERSET
&
aLayers
,
int
aDiameter
,
int
aNet
=
-
1
)
:
PNS_ITEM
(
VIA
)
{
SetNet
(
aNet
);
SetLayers
(
aLayers
);
m_pos
=
aPos
;
m_diameter
=
aDiameter
;
m_shape
=
SHAPE_CIRCLE
(
aPos
,
aDiameter
/
2
);
m_shape
=
SHAPE_CIRCLE
(
aPos
,
aDiameter
/
2
);
};
PNS_VIA
(
const
PNS_VIA
&
b
)
:
PNS_ITEM
(
VIA
)
PNS_VIA
(
const
PNS_VIA
&
b
)
:
PNS_ITEM
(
VIA
)
{
SetNet
(
b
.
GetNet
()
);
SetLayers
(
b
.
GetLayers
()
);
SetNet
(
b
.
GetNet
()
);
SetLayers
(
b
.
GetLayers
()
);
m_pos
=
b
.
m_pos
;
m_diameter
=
b
.
m_diameter
;
m_shape
=
SHAPE_CIRCLE
(
m_pos
,
m_diameter
/
2
);
m_shape
=
SHAPE_CIRCLE
(
m_pos
,
m_diameter
/
2
);
}
const
VECTOR2I
&
GetPos
()
const
...
...
@@ -61,7 +62,7 @@ class PNS_VIA : public PNS_ITEM
void
SetPos
(
const
VECTOR2I
&
aPos
)
{
m_pos
=
aPos
;
m_shape
.
SetCenter
(
aPos
);
m_shape
.
SetCenter
(
aPos
);
}
int
GetDiameter
()
const
...
...
@@ -69,10 +70,10 @@ class PNS_VIA : public PNS_ITEM
return
m_diameter
;
}
void
SetDiameter
(
int
aDiameter
)
void
SetDiameter
(
int
aDiameter
)
{
m_diameter
=
aDiameter
;
m_shape
.
SetRadius
(
m_diameter
/
2
);
m_shape
.
SetRadius
(
m_diameter
/
2
);
}
int
GetDrill
()
const
...
...
@@ -80,34 +81,38 @@ class PNS_VIA : public PNS_ITEM
return
m_drill
;
}
void
SetDrill
(
int
aDrill
)
void
SetDrill
(
int
aDrill
)
{
m_drill
=
aDrill
;
}
bool
PushoutForce
(
PNS_NODE
*
aNode
,
const
VECTOR2I
&
aDirection
,
VECTOR2I
&
aForce
,
bool
aSolidsOnly
=
true
,
int
aMaxIterations
=
10
);
bool
PushoutForce
(
PNS_NODE
*
aNode
,
const
VECTOR2I
&
aDirection
,
VECTOR2I
&
aForce
,
bool
aSolidsOnly
=
true
,
int
aMaxIterations
=
10
);
const
SHAPE
*
GetShape
()
const
const
SHAPE
*
GetShape
()
const
{
return
&
m_shape
;
}
PNS_VIA
*
Clone
()
const
PNS_VIA
*
Clone
()
const
{
PNS_VIA
*
v
=
new
PNS_VIA
();
PNS_VIA
*
v
=
new
PNS_VIA
();
v
->
SetNet
(
GetNet
()
);
v
->
SetLayers
(
GetLayers
()
);
v
->
SetNet
(
GetNet
()
);
v
->
SetLayers
(
GetLayers
()
);
v
->
m_pos
=
m_pos
;
v
->
m_diameter
=
m_diameter
;
v
->
m_shape
=
SHAPE_CIRCLE
(
m_pos
,
m_diameter
/
2
);
v
->
m_shape
=
SHAPE_CIRCLE
(
m_pos
,
m_diameter
/
2
);
return
v
;
}
const
SHAPE_LINE_CHAIN
Hull
(
int
aClearance
=
0
,
int
aWalkaroundThickness
=
0
)
const
;
const
SHAPE_LINE_CHAIN
Hull
(
int
aClearance
=
0
,
int
aWalkaroundThickness
=
0
)
const
;
private
:
private
:
int
m_diameter
;
int
m_drill
;
...
...
pcbnew/router/pns_walkaround.cpp
View file @
5598acb6
...
...
@@ -40,182 +40,192 @@ void PNS_WALKAROUND::start( const PNS_LINE& aInitialPath )
}
PNS_NODE
::
OptObstacle
PNS_WALKAROUND
::
nearestObstacle
(
const
PNS_LINE
&
aPath
)
PNS_NODE
::
OptObstacle
PNS_WALKAROUND
::
nearestObstacle
(
const
PNS_LINE
&
aPath
)
{
return
m_world
->
NearestObstacle
(
&
aPath
,
m_solids_only
?
(
PNS_ITEM
::
SOLID
|
PNS_ITEM
::
VIA
)
:
PNS_ITEM
::
ANY
);
return
m_world
->
NearestObstacle
(
&
aPath
,
m_solids_only
?
(
PNS_ITEM
::
SOLID
|
PNS_ITEM
::
VIA
)
:
PNS_ITEM
::
ANY
);
}
PNS_WALKAROUND
::
WalkaroundStatus
PNS_WALKAROUND
::
singleStep
(
PNS_LINE
&
aPath
,
bool
aWindingDirection
)
PNS_WALKAROUND
::
WalkaroundStatus
PNS_WALKAROUND
::
singleStep
(
PNS_LINE
&
aPath
,
bool
aWindingDirection
)
{
optional
<
PNS_OBSTACLE
>&
current_obs
=
aWindingDirection
?
m_currentObstacle
[
0
]
:
m_currentObstacle
[
1
];
optional
<
PNS_OBSTACLE
>&
current_obs
=
aWindingDirection
?
m_currentObstacle
[
0
]
:
m_currentObstacle
[
1
];
bool
&
prev_recursive
=
aWindingDirection
?
m_recursiveCollision
[
0
]
:
m_recursiveCollision
[
1
];
if
(
!
current_obs
)
if
(
!
current_obs
)
return
DONE
;
SHAPE_LINE_CHAIN
path_pre
[
2
],
path_walk
[
2
],
path_post
[
2
];
VECTOR2I
last
=
aPath
.
GetCLine
().
CPoint
(
-
1
);
VECTOR2I
last
=
aPath
.
GetCLine
().
CPoint
(
-
1
);
if
((
current_obs
->
hull
).
PointInside
(
last
)
)
if
(
(
current_obs
->
hull
).
PointInside
(
last
)
)
{
m_recursiveBlockageCount
++
;
m_recursiveBlockageCount
++
;
if
(
m_recursiveBlockageCount
<
3
)
aPath
.
GetLine
().
Append
(
current_obs
->
hull
.
NearestPoint
(
last
)
);
else
{
aPath
=
aPath
.
ClipToNearestObstacle
(
m_world
);
if
(
m_recursiveBlockageCount
<
3
)
aPath
.
GetLine
().
Append
(
current_obs
->
hull
.
NearestPoint
(
last
)
);
else
{
aPath
=
aPath
.
ClipToNearestObstacle
(
m_world
);
return
STUCK
;
}
}
aPath
.
NewWalkaround
(
current_obs
->
hull
,
path_pre
[
0
],
path_walk
[
0
],
path_post
[
0
],
aWindingDirection
);
aPath
.
NewWalkaround
(
current_obs
->
hull
,
path_pre
[
1
],
path_walk
[
1
],
path_post
[
1
],
!
aWindingDirection
);
aPath
.
NewWalkaround
(
current_obs
->
hull
,
path_pre
[
0
],
path_walk
[
0
],
path_post
[
0
],
aWindingDirection
);
aPath
.
NewWalkaround
(
current_obs
->
hull
,
path_pre
[
1
],
path_walk
[
1
],
path_post
[
1
],
!
aWindingDirection
);
int
len_pre
=
path_walk
[
0
].
Length
();
int
len_alt
=
path_walk
[
1
].
Length
();
PNS_LINE
walk_path
(
aPath
,
path_walk
[
1
]
);
PNS_LINE
walk_path
(
aPath
,
path_walk
[
1
]
);
bool
alt_collides
=
m_world
->
CheckColliding
(
&
walk_path
,
m_solids_only
?
PNS_ITEM
::
SOLID
:
PNS_ITEM
::
ANY
);
bool
alt_collides
=
m_world
->
CheckColliding
(
&
walk_path
,
m_solids_only
?
PNS_ITEM
::
SOLID
:
PNS_ITEM
::
ANY
);
SHAPE_LINE_CHAIN
pnew
;
if
(
!
m_forceSingleDirection
&&
len_alt
<
len_pre
&&
!
alt_collides
&&
!
prev_recursive
)
if
(
!
m_forceSingleDirection
&&
len_alt
<
len_pre
&&
!
alt_collides
&&
!
prev_recursive
)
{
pnew
=
path_pre
[
1
];
pnew
.
Append
(
path_walk
[
1
]
);
pnew
.
Append
(
path_post
[
1
]
);
pnew
.
Append
(
path_walk
[
1
]
);
pnew
.
Append
(
path_post
[
1
]
);
current_obs
=
nearestObstacle
(
PNS_LINE
(
aPath
,
path_post
[
1
])
);
current_obs
=
nearestObstacle
(
PNS_LINE
(
aPath
,
path_post
[
1
]
)
);
prev_recursive
=
false
;
}
else
{
}
else
{
pnew
=
path_pre
[
0
];
pnew
.
Append
(
path_walk
[
0
]
);
pnew
.
Append
(
path_post
[
0
]
);
pnew
.
Append
(
path_walk
[
0
]
);
pnew
.
Append
(
path_post
[
0
]
);
current_obs
=
nearestObstacle
(
PNS_LINE
(
aPath
,
path_walk
[
0
])
);
current_obs
=
nearestObstacle
(
PNS_LINE
(
aPath
,
path_walk
[
0
]
)
);
if
(
!
current_obs
)
if
(
!
current_obs
)
{
prev_recursive
=
false
;
current_obs
=
nearestObstacle
(
PNS_LINE
(
aPath
,
path_post
[
0
]));
}
else
current_obs
=
nearestObstacle
(
PNS_LINE
(
aPath
,
path_post
[
0
]
)
);
}
else
prev_recursive
=
true
;
}
pnew
.
Simplify
();
aPath
.
SetShape
(
pnew
);
aPath
.
SetShape
(
pnew
);
return
IN_PROGRESS
;
}
PNS_WALKAROUND
::
WalkaroundStatus
PNS_WALKAROUND
::
Route
(
const
PNS_LINE
&
aInitialPath
,
PNS_LINE
&
aWalkPath
,
bool
aOptimize
)
PNS_WALKAROUND
::
WalkaroundStatus
PNS_WALKAROUND
::
Route
(
const
PNS_LINE
&
aInitialPath
,
PNS_LINE
&
aWalkPath
,
bool
aOptimize
)
{
PNS_LINE
path_cw
(
aInitialPath
),
path_ccw
(
aInitialPath
);
PNS_LINE
path_cw
(
aInitialPath
),
path_ccw
(
aInitialPath
);
WalkaroundStatus
s_cw
=
IN_PROGRESS
,
s_ccw
=
IN_PROGRESS
;
SHAPE_LINE_CHAIN
best_path
;
start
(
aInitialPath
);
start
(
aInitialPath
);
m_currentObstacle
[
0
]
=
m_currentObstacle
[
1
]
=
nearestObstacle
(
aInitialPath
);
m_currentObstacle
[
0
]
=
m_currentObstacle
[
1
]
=
nearestObstacle
(
aInitialPath
);
m_recursiveBlockageCount
=
0
;
aWalkPath
=
aInitialPath
;
while
(
m_iteration
<
m_iteration_limit
)
while
(
m_iteration
<
m_iteration_limit
)
{
if
(
s_cw
!=
STUCK
)
s_cw
=
singleStep
(
path_cw
,
true
);
if
(
s_cw
!=
STUCK
)
s_cw
=
singleStep
(
path_cw
,
true
);
if
(
s_ccw
!=
STUCK
)
s_ccw
=
singleStep
(
path_ccw
,
false
);
if
(
s_ccw
!=
STUCK
)
s_ccw
=
singleStep
(
path_ccw
,
false
);
if
((
s_cw
==
DONE
&&
s_ccw
==
DONE
)
||
(
s_cw
==
STUCK
&&
s_ccw
==
STUCK
)
)
if
(
(
s_cw
==
DONE
&&
s_ccw
==
DONE
)
||
(
s_cw
==
STUCK
&&
s_ccw
==
STUCK
)
)
{
int
len_cw
=
path_cw
.
GetCLine
().
Length
();
int
len_ccw
=
path_ccw
.
GetCLine
().
Length
();
if
(
m_forceLongerPath
)
if
(
m_forceLongerPath
)
aWalkPath
=
(
len_cw
>
len_ccw
?
path_cw
:
path_ccw
);
else
aWalkPath
=
(
len_cw
<
len_ccw
?
path_cw
:
path_ccw
);
break
;
}
else
if
(
s_cw
==
DONE
&&
!
m_forceLongerPath
)
{
}
else
if
(
s_cw
==
DONE
&&
!
m_forceLongerPath
)
{
aWalkPath
=
path_cw
;
break
;
}
else
if
(
s_ccw
==
DONE
&&
!
m_forceLongerPath
)
{
}
else
if
(
s_ccw
==
DONE
&&
!
m_forceLongerPath
)
{
aWalkPath
=
path_ccw
;
break
;
}
m_iteration
++
;
}
if
(
m_iteration
==
m_iteration_limit
)
if
(
m_iteration
==
m_iteration_limit
)
{
int
len_cw
=
path_cw
.
GetCLine
().
Length
();
int
len_ccw
=
path_ccw
.
GetCLine
().
Length
();
if
(
m_forceLongerPath
)
if
(
m_forceLongerPath
)
aWalkPath
=
(
len_cw
>
len_ccw
?
path_cw
:
path_ccw
);
else
aWalkPath
=
(
len_cw
<
len_ccw
?
path_cw
:
path_ccw
);
}
if
(
m_cursorApproachMode
)
if
(
m_cursorApproachMode
)
{
//
int len_cw = path_cw.GetCLine().Length();
//
int len_ccw = path_ccw.GetCLine().Length();
//
int len_cw = path_cw.GetCLine().Length();
//
int len_ccw = path_ccw.GetCLine().Length();
bool
found
=
false
;
SHAPE_LINE_CHAIN
l
=
aWalkPath
.
GetCLine
();
for
(
int
i
=
0
;
i
<
l
.
SegmentCount
();
i
++
)
for
(
int
i
=
0
;
i
<
l
.
SegmentCount
();
i
++
)
{
const
SEG
s
=
l
.
Segment
(
i
);
const
SEG
s
=
l
.
Segment
(
i
);
VECTOR2I
nearest
=
s
.
NearestPoint
(
m_cursorPos
);
VECTOR2I
nearest
=
s
.
NearestPoint
(
m_cursorPos
);
VECTOR2I
::
extended_type
dist_a
=
(
s
.
a
-
m_cursorPos
).
SquaredEuclideanNorm
();
VECTOR2I
::
extended_type
dist_b
=
(
s
.
b
-
m_cursorPos
).
SquaredEuclideanNorm
();
VECTOR2I
::
extended_type
dist_n
=
(
nearest
-
m_cursorPos
).
SquaredEuclideanNorm
();
if
(
dist_n
<=
dist_a
&&
dist_n
<
dist_b
)
if
(
dist_n
<=
dist_a
&&
dist_n
<
dist_b
)
{
//
PNSDisplayDebugLine(l, 3);
l
.
Remove
(
i
+
1
,
-
1
);
//
PNSDisplayDebugLine(l, 3);
l
.
Remove
(
i
+
1
,
-
1
);
l
.
Append
(
nearest
);
l
.
Simplify
();
found
=
true
;
break
;
}
}
if
(
found
)
if
(
found
)
{
aWalkPath
=
aInitialPath
;
aWalkPath
.
SetShape
(
l
);
aWalkPath
.
SetShape
(
l
);
}
}
aWalkPath
.
SetWorld
(
m_world
);
aWalkPath
.
SetWorld
(
m_world
);
aWalkPath
.
GetLine
().
Simplify
();
WalkaroundStatus
st
=
s_ccw
==
DONE
||
s_cw
==
DONE
?
DONE
:
STUCK
;
if
(
aOptimize
&&
st
==
DONE
)
PNS_OPTIMIZER
::
Optimize
(
&
aWalkPath
,
PNS_OPTIMIZER
::
MERGE_OBTUSE
,
m_world
);
if
(
aOptimize
&&
st
==
DONE
)
PNS_OPTIMIZER
::
Optimize
(
&
aWalkPath
,
PNS_OPTIMIZER
::
MERGE_OBTUSE
,
m_world
);
return
st
;
}
pcbnew/router/pns_walkaround.h
View file @
5598acb6
...
...
@@ -24,28 +24,28 @@
#include "pns_line.h"
#include "pns_node.h"
class
PNS_WALKAROUND
{
class
PNS_WALKAROUND
{
static
const
int
DefaultIterationLimit
=
50
;
public
:
PNS_WALKAROUND
(
PNS_NODE
*
aWorld
)
:
m_world
(
aWorld
),
m_iteration_limit
(
DefaultIterationLimit
)
{
public
:
PNS_WALKAROUND
(
PNS_NODE
*
aWorld
)
:
m_world
(
aWorld
),
m_iteration_limit
(
DefaultIterationLimit
)
{
m_forceSingleDirection
=
false
;
m_forceLongerPath
=
false
;
m_cursorApproachMode
=
false
;
};
~
PNS_WALKAROUND
()
{};
enum
WalkaroundStatus
{
enum
WalkaroundStatus
{
IN_PROGRESS
=
0
,
DONE
,
STUCK
};
void
SetWorld
(
PNS_NODE
*
aNode
)
void
SetWorld
(
PNS_NODE
*
aNode
)
{
m_world
=
aNode
;
}
...
...
@@ -55,34 +55,33 @@ class PNS_WALKAROUND {
m_iteration_limit
=
aIterLimit
;
}
void
SetSolidsOnly
(
bool
aSolidsOnly
)
void
SetSolidsOnly
(
bool
aSolidsOnly
)
{
m_solids_only
=
aSolidsOnly
;
}
void
SetSingleDirection
(
bool
aForceSingleDirection
)
void
SetSingleDirection
(
bool
aForceSingleDirection
)
{
m_forceSingleDirection
=
aForceSingleDirection
;
m_forceLongerPath
=
true
;
}
void
SetApproachCursor
(
bool
aEnabled
,
const
VECTOR2I
&
aPos
)
void
SetApproachCursor
(
bool
aEnabled
,
const
VECTOR2I
&
aPos
)
{
m_cursorPos
=
aPos
;
m_cursorApproachMode
=
aEnabled
;
}
WalkaroundStatus
Route
(
const
PNS_LINE
&
aInitialPath
,
PNS_LINE
&
aWalkPath
,
bool
aOptimize
=
true
);
WalkaroundStatus
Route
(
const
PNS_LINE
&
aInitialPath
,
PNS_LINE
&
aWalkPath
,
bool
aOptimize
=
true
);
private
:
private
:
void
start
(
const
PNS_LINE
&
aInitialPath
);
WalkaroundStatus
singleStep
(
PNS_LINE
&
aPath
,
bool
aWindingDirection
);
PNS_NODE
::
OptObstacle
nearestObstacle
(
const
PNS_LINE
&
aPath
);
WalkaroundStatus
singleStep
(
PNS_LINE
&
aPath
,
bool
aWindingDirection
);
PNS_NODE
::
OptObstacle
nearestObstacle
(
const
PNS_LINE
&
aPath
);
PNS_NODE
*
m_world
;
PNS_NODE
*
m_world
;
int
m_recursiveBlockageCount
;
int
m_iteration
;
...
...
pcbnew/router/readme.txt
deleted
100644 → 0
View file @
87b3f2e4
You'll see the P&S router sources here, but just not right now.
We are still dealing with some non-technical issues that should be solved by the next week.
Tom
\ No newline at end of file
pcbnew/router/router_preview_item.cpp
View file @
5598acb6
...
...
@@ -31,167 +31,200 @@
using
namespace
KiGfx
;
ROUTER_PREVIEW_ITEM
::
ROUTER_PREVIEW_ITEM
(
const
PNS_ITEM
*
aItem
,
VIEW_GROUP
*
aParent
)
:
EDA_ITEM
(
NOT_USED
)
{
ROUTER_PREVIEW_ITEM
::
ROUTER_PREVIEW_ITEM
(
const
PNS_ITEM
*
aItem
,
VIEW_GROUP
*
aParent
)
:
EDA_ITEM
(
NOT_USED
)
{
m_Flags
=
0
;
m_parent
=
aParent
;
if
(
aItem
)
Update
(
aItem
);
}
if
(
aItem
)
Update
(
aItem
);
}
ROUTER_PREVIEW_ITEM
::~
ROUTER_PREVIEW_ITEM
()
{
}
void
ROUTER_PREVIEW_ITEM
::
Update
(
const
PNS_ITEM
*
aItem
)
void
ROUTER_PREVIEW_ITEM
::
Update
(
const
PNS_ITEM
*
aItem
)
{
m_layer
=
aItem
->
GetLayers
().
Start
();
m_color
=
getLayerColor
(
m_layer
);
m_color
.
a
=
0.8
;
switch
(
aItem
->
GetKind
()
)
switch
(
aItem
->
GetKind
()
)
{
case
PNS_ITEM
:
:
LINE
:
m_type
=
PR_LINE
;
m_width
=
static_cast
<
const
PNS_LINE
*>
(
aItem
)
->
GetWidth
();
m_line
=
*
static_cast
<
const
SHAPE_LINE_CHAIN
*>
(
aItem
->
GetShape
()
);
m_width
=
static_cast
<
const
PNS_LINE
*>
(
aItem
)
->
GetWidth
();
m_line
=
*
static_cast
<
const
SHAPE_LINE_CHAIN
*>
(
aItem
->
GetShape
()
);
break
;
case
PNS_ITEM
:
:
SEGMENT
:
m_type
=
PR_LINE
;
m_width
=
static_cast
<
const
PNS_SEGMENT
*>
(
aItem
)
->
GetWidth
();
m_line
=
*
static_cast
<
const
SHAPE_LINE_CHAIN
*>
(
aItem
->
GetShape
()
);
m_width
=
static_cast
<
const
PNS_SEGMENT
*>
(
aItem
)
->
GetWidth
();
m_line
=
*
static_cast
<
const
SHAPE_LINE_CHAIN
*>
(
aItem
->
GetShape
()
);
break
;
case
PNS_ITEM
:
:
VIA
:
m_type
=
PR_VIA
;
m_color
=
COLOR4D
(
0.7
,
0.7
,
0.7
,
0.8
);
m_width
=
static_cast
<
const
PNS_VIA
*>
(
aItem
)
->
GetDiameter
();
m_viaCenter
=
static_cast
<
const
PNS_VIA
*>
(
aItem
)
->
GetPos
();
m_color
=
COLOR4D
(
0.7
,
0.7
,
0.7
,
0.8
);
m_width
=
static_cast
<
const
PNS_VIA
*>
(
aItem
)
->
GetDiameter
();
m_viaCenter
=
static_cast
<
const
PNS_VIA
*>
(
aItem
)
->
GetPos
();
break
;
default
:
break
;
}
ViewSetVisible
(
true
);
ViewUpdate
(
GEOMETRY
|
APPEARANCE
);
ViewSetVisible
(
true
);
ViewUpdate
(
GEOMETRY
|
APPEARANCE
);
}
void
ROUTER_PREVIEW_ITEM
::
MarkAsHead
(
)
void
ROUTER_PREVIEW_ITEM
::
MarkAsHead
()
{
if
(
m_type
!=
PR_VIA
)
m_color
.
Saturate
(
1.0
);
if
(
m_type
!=
PR_VIA
)
m_color
.
Saturate
(
1.0
);
}
const
BOX2I
ROUTER_PREVIEW_ITEM
::
ViewBBox
()
const
{
BOX2I
bbox
;
switch
(
m_type
)
switch
(
m_type
)
{
case
PR_LINE
:
bbox
=
m_line
.
BBox
();
bbox
.
Inflate
(
m_width
/
2
);
bbox
.
Inflate
(
m_width
/
2
);
return
bbox
;
case
PR_VIA
:
bbox
=
BOX2I
(
m_viaCenter
,
VECTOR2I
(
0
,
0
)
);
bbox
.
Inflate
(
m_width
/
2
);
bbox
=
BOX2I
(
m_viaCenter
,
VECTOR2I
(
0
,
0
)
);
bbox
.
Inflate
(
m_width
/
2
);
return
bbox
;
default
:
break
;
}
return
bbox
;
}
void
ROUTER_PREVIEW_ITEM
::
ViewDraw
(
int
aLayer
,
KiGfx
::
GAL
*
aGal
)
const
{
switch
(
m_type
)
{
case
PR_LINE
:
aGal
->
SetLayerDepth
(
-
100.0
);
aGal
->
SetLineWidth
(
m_width
);
aGal
->
SetStrokeColor
(
m_color
);
aGal
->
SetIsStroke
(
true
);
aGal
->
SetIsFill
(
false
);
aGal
->
SetLayerDepth
(
-
100.0
);
aGal
->
SetLineWidth
(
m_width
);
aGal
->
SetStrokeColor
(
m_color
);
aGal
->
SetIsStroke
(
true
);
aGal
->
SetIsFill
(
false
);
for
(
int
s
=
0
;
s
<
m_line
.
SegmentCount
();
s
++
)
aGal
->
DrawLine
(
m_line
.
CSegment
(
s
).
a
,
m_line
.
CSegment
(
s
).
b
);
if
(
m_line
.
IsClosed
())
aGal
->
DrawLine
(
m_line
.
CSegment
(
-
1
).
b
,
m_line
.
CSegment
(
0
).
a
);
for
(
int
s
=
0
;
s
<
m_line
.
SegmentCount
();
s
++
)
aGal
->
DrawLine
(
m_line
.
CSegment
(
s
).
a
,
m_line
.
CSegment
(
s
).
b
);
if
(
m_line
.
IsClosed
()
)
aGal
->
DrawLine
(
m_line
.
CSegment
(
-
1
).
b
,
m_line
.
CSegment
(
0
).
a
);
break
;
case
PR_VIA
:
aGal
->
SetLayerDepth
(
-
101.0
);
aGal
->
SetIsStroke
(
false
);
aGal
->
SetIsFill
(
true
);
aGal
->
SetFillColor
(
m_color
);
aGal
->
DrawCircle
(
m_viaCenter
,
m_width
/
2
);
case
PR_VIA
:
aGal
->
SetLayerDepth
(
-
101.0
);
aGal
->
SetIsStroke
(
false
);
aGal
->
SetIsFill
(
true
);
aGal
->
SetFillColor
(
m_color
);
aGal
->
DrawCircle
(
m_viaCenter
,
m_width
/
2
);
break
;
default
:
break
;
}
}
void
ROUTER_PREVIEW_ITEM
::
DebugLine
(
const
SHAPE_LINE_CHAIN
&
aLine
,
int
aWidth
,
int
aStyle
)
void
ROUTER_PREVIEW_ITEM
::
DebugLine
(
const
SHAPE_LINE_CHAIN
&
aLine
,
int
aWidth
,
int
aStyle
)
{
#if 0
m_line = aLine;
m_width = aWidth;
m_color = assignColor(aStyle
);
m_color = assignColor( aStyle
);
m_type = PR_LINE;
ViewUpdate(GEOMETRY | APPEARANCE
);
ViewUpdate( GEOMETRY | APPEARANCE
);
#endif
}
void
ROUTER_PREVIEW_ITEM
::
DebugBox
(
const
BOX2I
&
aBox
,
int
aStyle
)
void
ROUTER_PREVIEW_ITEM
::
DebugBox
(
const
BOX2I
&
aBox
,
int
aStyle
)
{
#if 0
assert(false
);
assert( false
);
m_line.Clear();
m_line.Append( aBox.GetX(), aBox.GetY() );
m_line.Append( aBox.GetX() + aBox.GetWidth(), aBox.GetY() + aBox.GetHeight()
);
m_line.Append( aBox.GetX() + aBox.GetWidth(), aBox.GetY() + aBox.GetHeight()
);
m_line.Append( aBox.GetX(), aBox.GetY() + aBox.GetHeight()
);
m_line.SetClosed(true
);
m_line.Append( aBox.GetX() + aBox.GetWidth(), aBox.GetY() + aBox.GetHeight()
);
m_line.Append( aBox.GetX() + aBox.GetWidth(), aBox.GetY() + aBox.GetHeight()
);
m_line.Append( aBox.GetX(), aBox.GetY() + aBox.GetHeight()
);
m_line.SetClosed( true
);
m_width = 20000;
m_color = assignColor(aStyle
);
m_color = assignColor( aStyle
);
m_type = PR_LINE;
ViewUpdate(GEOMETRY | APPEARANCE
);
ViewUpdate( GEOMETRY | APPEARANCE
);
#endif
}
const
COLOR4D
ROUTER_PREVIEW_ITEM
::
getLayerColor
(
int
layer
)
const
const
COLOR4D
ROUTER_PREVIEW_ITEM
::
getLayerColor
(
int
aLayer
)
const
{
//assert (m_view != NULL);
// assert (m_view != NULL);
PCB_RENDER_SETTINGS
*
settings
=
static_cast
<
PCB_RENDER_SETTINGS
*>
(
m_parent
->
GetView
()
->
GetPainter
()
->
GetSettings
()
);
PCB_RENDER_SETTINGS
*
settings
=
static_cast
<
PCB_RENDER_SETTINGS
*>
(
m_parent
->
GetView
()
->
GetPainter
()
->
GetSettings
());
return
settings
->
GetLayerColor
(
layer
);
return
settings
->
GetLayerColor
(
aLayer
);
}
const
COLOR4D
ROUTER_PREVIEW_ITEM
::
assignColor
(
int
s
tyle
)
const
const
COLOR4D
ROUTER_PREVIEW_ITEM
::
assignColor
(
int
aS
tyle
)
const
{
COLOR4D
color
;
switch
(
style
)
switch
(
aStyle
)
{
case
0
:
color
=
COLOR4D
(
0
,
1
,
0
,
1
);
break
;
case
1
:
color
=
COLOR4D
(
1
,
0
,
0
,
0.3
);
break
;
case
2
:
color
=
COLOR4D
(
1
,
0.5
,
0.5
,
1
);
break
;
case
3
:
color
=
COLOR4D
(
0
,
0
,
1
,
1
);
break
;
case
4
:
color
=
COLOR4D
(
1
,
1
,
1
,
1
);
break
;
case
5
:
color
=
COLOR4D
(
1
,
1
,
0
,
1
);
break
;
case
6
:
color
=
COLOR4D
(
0
,
1
,
1
,
1
);
break
;
case
32
:
color
=
COLOR4D
(
0
,
0
,
1
,
0.5
);
break
;
default
:
break
;
case
0
:
color
=
COLOR4D
(
0
,
1
,
0
,
1
);
break
;
case
1
:
color
=
COLOR4D
(
1
,
0
,
0
,
0.3
);
break
;
case
2
:
color
=
COLOR4D
(
1
,
0.5
,
0.5
,
1
);
break
;
case
3
:
color
=
COLOR4D
(
0
,
0
,
1
,
1
);
break
;
case
4
:
color
=
COLOR4D
(
1
,
1
,
1
,
1
);
break
;
case
5
:
color
=
COLOR4D
(
1
,
1
,
0
,
1
);
break
;
case
6
:
color
=
COLOR4D
(
0
,
1
,
1
,
1
);
break
;
case
32
:
color
=
COLOR4D
(
0
,
0
,
1
,
0.5
);
break
;
default
:
break
;
}
return
color
;
}
pcbnew/router/router_preview_item.h
View file @
5598acb6
...
...
@@ -43,29 +43,31 @@ class PNS_ROUTER;
class
ROUTER_PREVIEW_ITEM
:
public
EDA_ITEM
{
public
:
enum
ItemType
{
public
:
enum
ItemType
{
PR_VIA
,
PR_LINE
,
PR_STUCK_MARKER
};
enum
ItemFlags
{
enum
ItemFlags
{
PR_SUGGESTION
=
1
};
ROUTER_PREVIEW_ITEM
(
const
PNS_ITEM
*
aItem
=
NULL
,
KiGfx
::
VIEW_GROUP
*
aParent
=
NULL
);
ROUTER_PREVIEW_ITEM
(
const
PNS_ITEM
*
aItem
=
NULL
,
KiGfx
::
VIEW_GROUP
*
aParent
=
NULL
);
~
ROUTER_PREVIEW_ITEM
();
void
Update
(
const
PNS_ITEM
*
aItem
);
void
Update
(
const
PNS_ITEM
*
aItem
);
void
StuckMarker
(
VECTOR2I
&
aPosition
);
void
DebugLine
(
const
SHAPE_LINE_CHAIN
&
aLine
,
int
aWidth
=
0
,
int
aStyle
=
0
);
void
DebugBox
(
const
BOX2I
&
aBox
,
int
aStyle
=
0
);
void
Show
(
int
a
,
std
::
ostream
&
b
)
const
{};
void
DebugLine
(
const
SHAPE_LINE_CHAIN
&
aLine
,
int
aWidth
=
0
,
int
aStyle
=
0
);
void
DebugBox
(
const
BOX2I
&
aBox
,
int
aStyle
=
0
);
const
BOX2I
ViewBBox
()
const
;
void
Show
(
int
a
,
std
::
ostream
&
b
)
const
{}
;
const
BOX2I
ViewBBox
()
const
;
virtual
void
ViewDraw
(
int
aLayer
,
KiGfx
::
GAL
*
aGal
)
const
;
...
...
@@ -75,16 +77,15 @@ class ROUTER_PREVIEW_ITEM : public EDA_ITEM
aCount
=
1
;
}
void
MarkAsHead
(
);
void
MarkAsHead
(
);
private
:
private
:
const
KiGfx
::
COLOR4D
assignColor
(
int
aStyle
)
const
;
const
KiGfx
::
COLOR4D
getLayerColor
(
int
aLayer
)
const
;
const
KiGfx
::
COLOR4D
assignColor
(
int
style
)
const
;
const
KiGfx
::
COLOR4D
getLayerColor
(
int
layer
)
const
;
KiGfx
::
VIEW_GROUP
*
m_parent
;
KiGfx
::
VIEW_GROUP
*
m_parent
;
PNS_ROUTER
*
m_router
;
PNS_ROUTER
*
m_router
;
SHAPE_LINE_CHAIN
m_line
;
ItemType
m_type
;
...
...
@@ -96,8 +97,7 @@ class ROUTER_PREVIEW_ITEM : public EDA_ITEM
VECTOR2I
m_stuckPosition
;
VECTOR2I
m_viaCenter
;
};
#endif
pcbnew/router/router_tool.cpp
View file @
5598acb6
...
...
@@ -42,27 +42,27 @@ using namespace KiGfx;
using
namespace
std
;
using
boost
::
optional
;
static
TOOL_ACTION
ACT_AutoEndRoute
(
"AutoEndRoute"
,
AS_CONTEXT
,
'F'
);
static
TOOL_ACTION
ACT_PlaceVia
(
"PlaceVia"
,
AS_CONTEXT
,
'V'
);
static
TOOL_ACTION
ACT_OpenRouteOptions
(
"OpenRouterOptions"
,
AS_CONTEXT
,
'E'
);
static
TOOL_ACTION
ACT_SwitchPosture
(
"SwitchPosture"
,
AS_CONTEXT
,
'/'
);
static
TOOL_ACTION
ACT_EndTrack
(
"SwitchPosture"
,
AS_CONTEXT
,
WXK_END
);
static
TOOL_ACTION
ACT_AutoEndRoute
(
"AutoEndRoute"
,
AS_CONTEXT
,
'F'
);
static
TOOL_ACTION
ACT_PlaceVia
(
"PlaceVia"
,
AS_CONTEXT
,
'V'
);
static
TOOL_ACTION
ACT_OpenRouteOptions
(
"OpenRouterOptions"
,
AS_CONTEXT
,
'E'
);
static
TOOL_ACTION
ACT_SwitchPosture
(
"SwitchPosture"
,
AS_CONTEXT
,
'/'
);
static
TOOL_ACTION
ACT_EndTrack
(
"SwitchPosture"
,
AS_CONTEXT
,
WXK_END
);
ROUTER_TOOL
::
ROUTER_TOOL
()
:
TOOL_INTERACTIVE
(
"pcbnew.InteractiveRouter"
)
{
m_router
=
NULL
;
m_menu
=
new
CONTEXT_MENU
;
m_menu
=
new
CONTEXT_MENU
;
m_menu
->
SetTitle
(
wxT
(
"Interactive router"
)
);
// fixme: not implemented yet. Sorry.
m_menu
->
Add
(
wxT
(
"Cancel"
),
0
);
m_menu
->
Add
(
wxT
(
"New track"
),
1
);
m_menu
->
Add
(
wxT
(
"End track"
),
2
);
m_menu
->
Add
(
wxT
(
"Auto-end track"
),
2
);
m_menu
->
Add
(
wxT
(
"Place via"
),
3
);
m_menu
->
Add
(
wxT
(
"Switch posture"
),
4
);
m_menu
->
SetTitle
(
wxT
(
"Interactive router"
)
);
// fixme: not implemented yet. Sorry.
m_menu
->
Add
(
wxT
(
"Cancel"
),
0
);
m_menu
->
Add
(
wxT
(
"New track"
),
1
);
m_menu
->
Add
(
wxT
(
"End track"
),
2
);
m_menu
->
Add
(
wxT
(
"Auto-end track"
),
2
);
m_menu
->
Add
(
wxT
(
"Place via"
),
3
);
m_menu
->
Add
(
wxT
(
"Switch posture"
),
4
);
m_menu
->
Add
(
wxT
(
"Routing options..."
),
5
);
m_menu
->
Add
(
wxT
(
"Routing options..."
),
5
);
}
...
...
@@ -74,38 +74,41 @@ ROUTER_TOOL::~ROUTER_TOOL()
void
ROUTER_TOOL
::
Reset
()
{
if
(
m_router
)
if
(
m_router
)
delete
m_router
;
m_router
=
new
PNS_ROUTER
;
TRACEn
(
0
,
"Reset"
);
TRACEn
(
0
,
"Reset"
);
m_router
->
ClearWorld
();
m_router
->
SetBoard
(
getModel
<
BOARD
>
(
PCB_T
)
);
m_router
->
SetBoard
(
getModel
<
BOARD
>
(
PCB_T
)
);
m_router
->
SyncWorld
();
if
(
getView
()
)
if
(
getView
()
)
m_router
->
SetView
(
getView
()
);
Go
(
&
ROUTER_TOOL
::
Main
,
TOOL_EVENT
(
TC_Command
,
TA_Action
,
GetName
()
)
);
}
int
ROUTER_TOOL
::
getDefaultWidth
(
int
aNetCode
)
{
int
w
,
d1
,
d2
;
getNetclassDimensions
(
aNetCode
,
w
,
d1
,
d2
);
getNetclassDimensions
(
aNetCode
,
w
,
d1
,
d2
);
return
w
;
}
void
ROUTER_TOOL
::
getNetclassDimensions
(
int
aNetCode
,
int
&
aWidth
,
int
&
aViaDiameter
,
int
&
aViaDrill
)
void
ROUTER_TOOL
::
getNetclassDimensions
(
int
aNetCode
,
int
&
aWidth
,
int
&
aViaDiameter
,
int
&
aViaDrill
)
{
BOARD
*
board
=
getModel
<
BOARD
>
(
PCB_T
);
BOARD
*
board
=
getModel
<
BOARD
>
(
PCB_T
);
NETCLASS
*
netClass
=
NULL
;
NETINFO_ITEM
*
ni
=
board
->
FindNet
(
aNetCode
);
NETINFO_ITEM
*
ni
=
board
->
FindNet
(
aNetCode
);
if
(
ni
)
if
(
ni
)
{
wxString
netClassName
=
ni
->
GetClassName
();
netClass
=
board
->
m_NetClasses
.
Find
(
netClassName
);
...
...
@@ -120,19 +123,20 @@ void ROUTER_TOOL::getNetclassDimensions ( int aNetCode, int& aWidth, int& aViaDi
}
PNS_ITEM
*
ROUTER_TOOL
::
pickSingleItem
(
const
VECTOR2I
&
aWhere
,
int
aNet
,
int
aLayer
)
PNS_ITEM
*
ROUTER_TOOL
::
pickSingleItem
(
const
VECTOR2I
&
aWhere
,
int
aNet
,
int
aLayer
)
{
int
tl
=
getView
()
->
GetTopLayer
();
if
(
aLayer
>
0
)
if
(
aLayer
>
0
)
tl
=
aLayer
;
PNS_ITEM
*
picked_seg
=
NULL
,
*
picked_via
=
NULL
;
PNS_ITEMSET
candidates
=
m_router
->
QueryHoverItems
(
aWhere
);
PNS_ITEM
*
picked_seg
=
NULL
;
PNS_ITEM
*
picked_via
=
NULL
;
PNS_ITEMSET
candidates
=
m_router
->
QueryHoverItems
(
aWhere
);
BOOST_FOREACH
(
PNS_ITEM
*
item
,
candidates
.
Items
()
)
BOOST_FOREACH
(
PNS_ITEM
*
item
,
candidates
.
Items
()
)
{
if
(
!
IsCopperLayer
(
item
->
GetLayers
().
Start
())
)
if
(
!
IsCopperLayer
(
item
->
GetLayers
().
Start
()
)
)
continue
;
if
(
item
->
GetParent
()
&&
!
item
->
GetParent
()
->
ViewIsVisible
()
)
...
...
@@ -140,12 +144,14 @@ PNS_ITEM *ROUTER_TOOL::pickSingleItem( const VECTOR2I& aWhere, int aNet, int aLa
if
(
aNet
<
0
||
item
->
GetNet
()
==
aNet
)
{
if
(
item
->
OfKind
(
PNS_ITEM
::
VIA
|
PNS_ITEM
::
SOLID
)
)
if
(
item
->
OfKind
(
PNS_ITEM
::
VIA
|
PNS_ITEM
::
SOLID
)
)
{
if
(
item
->
GetLayers
().
Overlaps
(
tl
)
||
!
picked_via
)
if
(
item
->
GetLayers
().
Overlaps
(
tl
)
||
!
picked_via
)
picked_via
=
item
;
}
else
{
if
(
item
->
GetLayers
().
Overlaps
(
tl
)
||
!
picked_seg
)
}
else
{
if
(
item
->
GetLayers
().
Overlaps
(
tl
)
||
!
picked_seg
)
picked_seg
=
item
;
}
}
...
...
@@ -153,95 +159,101 @@ PNS_ITEM *ROUTER_TOOL::pickSingleItem( const VECTOR2I& aWhere, int aNet, int aLa
if
(
DisplayOpt
.
ContrastModeDisplay
)
{
if
(
picked_seg
&&
!
picked_seg
->
GetLayers
().
Overlaps
(
tl
)
)
if
(
picked_seg
&&
!
picked_seg
->
GetLayers
().
Overlaps
(
tl
)
)
picked_seg
=
NULL
;
}
PNS_ITEM
*
rv
=
picked_via
?
picked_via
:
picked_seg
;
PNS_ITEM
*
rv
=
picked_via
?
picked_via
:
picked_seg
;
if
(
rv
&&
aLayer
>=
0
&&
!
rv
->
GetLayers
().
Overlaps
(
aLayer
)
)
if
(
rv
&&
aLayer
>=
0
&&
!
rv
->
GetLayers
().
Overlaps
(
aLayer
)
)
rv
=
NULL
;
if
(
rv
)
TRACE
(
0
,
"%s, layer : %d, tl: %d"
,
rv
->
GetKindStr
().
c_str
()
%
rv
->
GetLayers
().
Start
()
%
tl
);
if
(
rv
)
TRACE
(
0
,
"%s, layer : %d, tl: %d"
,
rv
->
GetKindStr
().
c_str
()
%
rv
->
GetLayers
().
Start
()
%
tl
);
return
rv
;
}
void
ROUTER_TOOL
::
setMsgPanel
(
bool
enabled
,
int
entry
,
const
wxString
&
aUpperMessage
,
const
wxString
&
aLowerMessage
)
void
ROUTER_TOOL
::
setMsgPanel
(
bool
aEnabled
,
int
aEntry
,
const
wxString
&
aUpperMessage
,
const
wxString
&
aLowerMessage
)
{
PCB_EDIT_FRAME
*
frame
=
getEditFrame
<
PCB_EDIT_FRAME
>
();
PCB_EDIT_FRAME
*
frame
=
getEditFrame
<
PCB_EDIT_FRAME
>
();
if
(
m_panelItems
.
size
()
<=
(
unsigned
int
)
entry
)
m_panelItems
.
resize
(
entry
+
1
);
if
(
m_panelItems
.
size
()
<=
(
unsigned
int
)
aEntry
)
m_panelItems
.
resize
(
aEntry
+
1
);
m_panelItems
[
e
ntry
]
=
MSG_PANEL_ITEM
(
aUpperMessage
,
aLowerMessage
,
BLACK
);
frame
->
SetMsgPanel
(
m_panelItems
);
m_panelItems
[
aE
ntry
]
=
MSG_PANEL_ITEM
(
aUpperMessage
,
aLowerMessage
,
BLACK
);
frame
->
SetMsgPanel
(
m_panelItems
);
}
void
ROUTER_TOOL
::
clearMsgPanel
()
{
PCB_EDIT_FRAME
*
frame
=
getEditFrame
<
PCB_EDIT_FRAME
>
();
PCB_EDIT_FRAME
*
frame
=
getEditFrame
<
PCB_EDIT_FRAME
>
();
frame
->
ClearMsgPanel
();
}
void
ROUTER_TOOL
::
highlightNet
(
bool
enabled
,
int
netcode
)
void
ROUTER_TOOL
::
highlightNet
(
bool
aEnabled
,
int
aNetcode
)
{
RENDER_SETTINGS
*
rs
=
getView
()
->
GetPainter
()
->
GetSettings
();
RENDER_SETTINGS
*
rs
=
getView
()
->
GetPainter
()
->
GetSettings
();
if
(
netcode
>=
0
&&
enabled
)
rs
->
SetHighlight
(
true
,
netcode
);
if
(
aNetcode
>=
0
&&
aEnabled
)
rs
->
SetHighlight
(
true
,
aNetcode
);
else
rs
->
SetHighlight
(
false
);
rs
->
SetHighlight
(
false
);
getView
()
->
UpdateAllLayersColor
();
}
void
ROUTER_TOOL
::
updateStartItem
(
TOOL_EVENT
&
aEvent
)
{
VIEW_CONTROLS
*
ctls
=
getViewControls
();
VIEW_CONTROLS
*
ctls
=
getViewControls
();
int
tl
=
getView
()
->
GetTopLayer
();
PNS_ITEM
*
startItem
=
NULL
;
PNS_ITEM
*
startItem
=
NULL
;
if
(
aEvent
.
IsMotion
()
||
aEvent
.
IsClick
()
)
{
VECTOR2I
p
=
aEvent
.
Position
();
startItem
=
pickSingleItem
(
p
);
startItem
=
pickSingleItem
(
p
);
if
(
startItem
&&
startItem
->
GetNet
()
>=
0
)
if
(
startItem
&&
startItem
->
GetNet
()
>=
0
)
{
bool
dummy
;
VECTOR2I
cursorPos
=
m_router
->
SnapToItem
(
startItem
,
p
,
dummy
);
ctls
->
ForceCursorPosition
(
true
,
cursorPos
);
VECTOR2I
cursorPos
=
m_router
->
SnapToItem
(
startItem
,
p
,
dummy
);
ctls
->
ForceCursorPosition
(
true
,
cursorPos
);
m_startSnapPoint
=
cursorPos
;
if
(
startItem
->
GetLayers
().
IsMultilayer
())
if
(
startItem
->
GetLayers
().
IsMultilayer
()
)
m_startLayer
=
tl
;
else
m_startLayer
=
startItem
->
GetLayers
().
Start
();
m_startItem
=
startItem
;
}
else
{
}
else
{
m_startItem
=
NULL
;
m_startSnapPoint
=
p
;
m_startLayer
=
tl
;
ctls
->
ForceCursorPosition
(
false
);
ctls
->
ForceCursorPosition
(
false
);
}
}
}
void
ROUTER_TOOL
::
updateEndItem
(
TOOL_EVENT
&
aEvent
)
{
VIEW_CONTROLS
*
ctls
=
getViewControls
();
VIEW_CONTROLS
*
ctls
=
getViewControls
();
VECTOR2I
p
=
aEvent
.
Position
();
int
layer
;
if
(
m_router
->
GetCurrentNet
()
<
0
||
!
m_startItem
)
if
(
m_router
->
GetCurrentNet
()
<
0
||
!
m_startItem
)
{
m_endItem
=
NULL
;
m_endSnapPoint
=
p
;
...
...
@@ -250,47 +262,52 @@ void ROUTER_TOOL::updateEndItem( TOOL_EVENT& aEvent )
bool
dummy
;
if
(
m_router
->
IsPlacingVia
()
)
if
(
m_router
->
IsPlacingVia
()
)
layer
=
-
1
;
else
layer
=
m_router
->
GetCurrentLayer
();
PNS_ITEM
*
endItem
=
pickSingleItem
(
p
,
m_startItem
->
GetNet
(),
layer
);
PNS_ITEM
*
endItem
=
pickSingleItem
(
p
,
m_startItem
->
GetNet
(),
layer
);
if
(
endItem
)
if
(
endItem
)
{
VECTOR2I
cursorPos
=
m_router
->
SnapToItem
(
endItem
,
p
,
dummy
);
ctls
->
ForceCursorPosition
(
true
,
cursorPos
);
VECTOR2I
cursorPos
=
m_router
->
SnapToItem
(
endItem
,
p
,
dummy
);
ctls
->
ForceCursorPosition
(
true
,
cursorPos
);
m_endItem
=
endItem
;
m_endSnapPoint
=
cursorPos
;
}
else
{
}
else
{
m_endItem
=
NULL
;
m_endSnapPoint
=
p
;
ctls
->
ForceCursorPosition
(
false
);
ctls
->
ForceCursorPosition
(
false
);
}
if
(
m_endItem
)
TRACE
(
0
,
"%s, layer : %d"
,
m_endItem
->
GetKindStr
().
c_str
()
%
m_endItem
->
GetLayers
().
Start
()
);
if
(
m_endItem
)
TRACE
(
0
,
"%s, layer : %d"
,
m_endItem
->
GetKindStr
().
c_str
()
%
m_endItem
->
GetLayers
().
Start
()
);
}
void
ROUTER_TOOL
::
startRouting
(
)
void
ROUTER_TOOL
::
startRouting
()
{
VIEW_CONTROLS
*
ctls
=
getViewControls
();
VIEW_CONTROLS
*
ctls
=
getViewControls
();
int
width
=
getDefaultWidth
(
m_startItem
?
m_startItem
->
GetNet
()
:
-
1
);
int
width
=
getDefaultWidth
(
m_startItem
?
m_startItem
->
GetNet
()
:
-
1
);
if
(
m_startItem
&&
m_startItem
->
OfKind
(
PNS_ITEM
::
SEGMENT
))
width
=
static_cast
<
PNS_SEGMENT
*>
(
m_startItem
)
->
GetWidth
();
if
(
m_startItem
&&
m_startItem
->
OfKind
(
PNS_ITEM
::
SEGMENT
)
)
width
=
static_cast
<
PNS_SEGMENT
*>
(
m_startItem
)
->
GetWidth
();
m_router
->
SetCurrentWidth
(
width
);
m_router
->
SwitchLayer
(
m_startLayer
);
m_router
->
SetCurrentWidth
(
width
);
m_router
->
SwitchLayer
(
m_startLayer
);
getEditFrame
<
PCB_EDIT_FRAME
>
()
->
SetTopLayer
(
m_startLayer
);
getEditFrame
<
PCB_EDIT_FRAME
>
()
->
SetTopLayer
(
m_startLayer
);
if
(
m_startItem
&&
m_startItem
->
GetNet
()
>=
0
)
highlightNet
(
true
,
m_startItem
->
GetNet
()
);
if
(
m_startItem
&&
m_startItem
->
GetNet
()
>=
0
)
highlightNet
(
true
,
m_startItem
->
GetNet
()
);
ctls
->
ForceCursorPosition
(
false
);
ctls
->
SetAutoPan
(
true
);
ctls
->
ForceCursorPosition
(
false
);
ctls
->
SetAutoPan
(
true
);
m_router
->
StartRouting
(
m_startSnapPoint
,
m_startItem
);
...
...
@@ -301,18 +318,21 @@ void ROUTER_TOOL::startRouting ( )
{
if
(
evt
->
IsCancel
()
)
break
;
else
if
(
evt
->
IsMotion
()
)
else
if
(
evt
->
IsMotion
()
)
{
updateEndItem
(
*
evt
);
m_router
->
Move
(
m_endSnapPoint
,
m_endItem
);
m_router
->
Move
(
m_endSnapPoint
,
m_endItem
);
}
else
if
(
evt
->
IsClick
(
MB_Left
)
)
else
if
(
evt
->
IsClick
(
MB_Left
)
)
{
updateEndItem
(
*
evt
);
if
(
m_router
->
FixRoute
(
m_endSnapPoint
,
m_endItem
))
if
(
m_router
->
FixRoute
(
m_endSnapPoint
,
m_endItem
)
)
break
;
m_router
->
Move
(
m_endSnapPoint
,
m_endItem
);
}
else
if
(
evt
->
IsKeyUp
())
m_router
->
Move
(
m_endSnapPoint
,
m_endItem
);
}
else
if
(
evt
->
IsKeyUp
()
)
{
switch
(
evt
->
KeyCode
()
)
{
...
...
@@ -320,11 +340,11 @@ void ROUTER_TOOL::startRouting ( )
{
int
w
,
diameter
,
drill
;
getNetclassDimensions
(
m_router
->
GetCurrentNet
(),
w
,
diameter
,
drill
);
m_router
->
SetCurrentViaDiameter
(
diameter
);
m_router
->
SetCurrentViaDrill
(
drill
);
m_router
->
SetCurrentViaDiameter
(
diameter
);
m_router
->
SetCurrentViaDrill
(
drill
);
m_router
->
ToggleViaPlacement
();
getEditFrame
<
PCB_EDIT_FRAME
>
()
->
SetTopLayer
(
m_router
->
GetCurrentLayer
()
);
m_router
->
Move
(
m_endSnapPoint
,
m_endItem
);
getEditFrame
<
PCB_EDIT_FRAME
>
()
->
SetTopLayer
(
m_router
->
GetCurrentLayer
()
);
m_router
->
Move
(
m_endSnapPoint
,
m_endItem
);
break
;
}
...
...
@@ -334,58 +354,56 @@ void ROUTER_TOOL::startRouting ( )
case
'+'
:
case
'='
:
m_router
->
SwitchLayer
(
m_router
->
NextCopperLayer
(
true
)
);
m_router
->
SwitchLayer
(
m_router
->
NextCopperLayer
(
true
)
);
updateEndItem
(
*
evt
);
getEditFrame
<
PCB_EDIT_FRAME
>
()
->
SetTopLayer
(
m_router
->
GetCurrentLayer
()
);
m_router
->
Move
(
m_endSnapPoint
,
m_endItem
);
getEditFrame
<
PCB_EDIT_FRAME
>
()
->
SetTopLayer
(
m_router
->
GetCurrentLayer
()
);
m_router
->
Move
(
m_endSnapPoint
,
m_endItem
);
break
;
case
'-'
:
m_router
->
SwitchLayer
(
m_router
->
NextCopperLayer
(
false
)
);
getEditFrame
<
PCB_EDIT_FRAME
>
()
->
SetTopLayer
(
m_router
->
GetCurrentLayer
()
);
m_router
->
Move
(
m_endSnapPoint
,
m_endItem
);
m_router
->
SwitchLayer
(
m_router
->
NextCopperLayer
(
false
)
);
getEditFrame
<
PCB_EDIT_FRAME
>
()
->
SetTopLayer
(
m_router
->
GetCurrentLayer
()
);
m_router
->
Move
(
m_endSnapPoint
,
m_endItem
);
break
;
}
}
}
if
(
m_router
->
RoutingInProgress
()
)
if
(
m_router
->
RoutingInProgress
()
)
m_router
->
StopRouting
();
ctls
->
SetAutoPan
(
false
);
ctls
->
ForceCursorPosition
(
false
);
highlightNet
(
false
);
ctls
->
SetAutoPan
(
false
);
ctls
->
ForceCursorPosition
(
false
);
highlightNet
(
false
);
}
int
ROUTER_TOOL
::
Main
(
TOOL_EVENT
&
aEvent
)
{
VIEW_CONTROLS
*
ctls
=
getViewControls
();
VIEW_CONTROLS
*
ctls
=
getViewControls
();
//SetContextMenu ( m_menu );
//setMsgPanel(true, 0, wxT("KiRouter"), wxT("Pick an item to start routing"));
//
SetContextMenu ( m_menu );
//
setMsgPanel(true, 0, wxT("KiRouter"), wxT("Pick an item to start routing"));
ctls
->
SetSnapping
(
true
);
ctls
->
SetSnapping
(
true
);
ctls
->
ShowCursor
(
true
);
// Main loop: keep receiving events
while
(
OPT_TOOL_EVENT
evt
=
Wait
()
)
{
if
(
evt
->
IsCancel
()
)
break
;
// Finish
else
if
(
evt
->
IsMotion
(
)
)
else
if
(
evt
->
IsMotion
()
)
updateStartItem
(
*
evt
);
else
if
(
evt
->
IsClick
(
MB_Left
)
)
else
if
(
evt
->
IsClick
(
MB_Left
)
)
{
updateStartItem
(
*
evt
);
startRouting
(
);
startRouting
();
}
}
//clearMsgPanel();
// clearMsgPanel();
// Restore the default settings
ctls
->
SetAutoPan
(
false
);
...
...
@@ -394,4 +412,3 @@ int ROUTER_TOOL::Main( TOOL_EVENT& aEvent )
return
0
;
}
pcbnew/router/router_tool.h
View file @
5598acb6
...
...
@@ -46,34 +46,35 @@ public:
private
:
PNS_ITEM
*
pickSingleItem
(
const
VECTOR2I
&
aWhere
,
int
aNet
=
-
1
,
int
aLayer
=
-
1
);
PNS_ITEM
*
pickSingleItem
(
const
VECTOR2I
&
aWhere
,
int
aNet
=
-
1
,
int
aLayer
=
-
1
);
void
setMsgPanel
(
bool
enabled
,
int
entry
,
const
wxString
&
aUpperMessage
=
wxT
(
""
),
const
wxString
&
aLowerMessage
=
wxT
(
""
)
);
void
setMsgPanel
(
bool
enabled
,
int
entry
,
const
wxString
&
aUpperMessage
=
wxT
(
""
),
const
wxString
&
aLowerMessage
=
wxT
(
""
)
);
void
clearMsgPanel
();
int
getDefaultWidth
(
int
aNetCode
);
void
startRouting
(
);
void
highlightNet
(
bool
enabled
,
int
netcode
=
-
1
);
void
startRouting
(
);
void
highlightNet
(
bool
enabled
,
int
netcode
=
-
1
);
void
updateStartItem
(
TOOL_EVENT
&
aEvent
);
void
updateEndItem
(
TOOL_EVENT
&
aEvent
);
void
getNetclassDimensions
(
int
aNetCode
,
int
&
aWidth
,
int
&
aViaDiameter
,
int
&
aViaDrill
);
void
getNetclassDimensions
(
int
aNetCode
,
int
&
aWidth
,
int
&
aViaDiameter
,
int
&
aViaDrill
);
MSG_PANEL_ITEMS
m_panelItems
;
PNS_ROUTER
*
m_router
;
PNS_ROUTER
*
m_router
;
PNS_ITEM
*
m_startItem
;
PNS_ITEM
*
m_startItem
;
int
m_startLayer
;
VECTOR2I
m_startSnapPoint
;
PNS_ITEM
*
m_endItem
;
PNS_ITEM
*
m_endItem
;
VECTOR2I
m_endSnapPoint
;
/*boost::shared_ptr<CONTEXT_MENU> m_menu;*/
CONTEXT_MENU
*
m_menu
;
CONTEXT_MENU
*
m_menu
;
};
#endif
pcbnew/router/trace.h
View file @
5598acb6
...
...
@@ -21,30 +21,27 @@
#ifndef __TRACE_H
#define __TRACE_H
#ifdef DEBUG
#include <string>
#include <iostream>
#include <boost/format.hpp>
static
void
_trace_print
(
const
char
*
funcName
,
int
level
,
const
std
::
string
&
msg
)
static
void
_trace_print
(
const
char
*
funcName
,
int
level
,
const
std
::
string
&
msg
)
{
std
::
cerr
<<
"trace["
<<
level
<<
"]: "
<<
funcName
<<
": "
<<
msg
<<
std
::
endl
;
}
#define TRACE( level, fmt, ... ) \
_trace_print( __FUNCTION__, level, (boost::format( fmt ) % __VA_ARGS__).str() );
#define TRACE(level, fmt, ...) \
_trace_print(__FUNCTION__, level, (boost::format(fmt) % __VA_ARGS__).str() );
#define TRACEn(level, msg) \
_trace_print(__FUNCTION__, level, std::string(msg));
#define TRACEn( level, msg ) \
_trace_print( __FUNCTION__, level, std::string( msg ) );
#else
#define TRACE(
level, fmt, ...
)
#define TRACEn(
level, msg
)
#define TRACE(
level, fmt, ...
)
#define TRACEn(
level, msg
)
#endif
...
...
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