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
c97afea4
Commit
c97afea4
authored
May 18, 2014
by
Maciej Sumiński
Browse files
Options
Browse Files
Download
Plain Diff
Upstream merge.
parents
46020e20
d54ade94
Changes
12
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
384 additions
and
289 deletions
+384
-289
3d_draw.cpp
3d-viewer/3d_draw.cpp
+1
-1
gr_basic.cpp
common/gr_basic.cpp
+1
-1
board_items_to_polygon_shape_transform.cpp
pcbnew/board_items_to_polygon_shape_transform.cpp
+82
-24
class_pad.cpp
pcbnew/class_pad.cpp
+33
-0
class_pad.h
pcbnew/class_pad.h
+11
-0
class_pad_draw_functions.cpp
pcbnew/class_pad_draw_functions.cpp
+6
-22
class_track.cpp
pcbnew/class_track.cpp
+44
-112
class_track.h
pcbnew/class_track.h
+6
-1
clean.cpp
pcbnew/clean.cpp
+51
-119
move_or_drag_track.cpp
pcbnew/move_or_drag_track.cpp
+4
-4
pcbplot.h
pcbnew/pcbplot.h
+11
-0
plot_board_layers.cpp
pcbnew/plot_board_layers.cpp
+134
-5
No files found.
3d-viewer/3d_draw.cpp
View file @
c97afea4
...
...
@@ -239,7 +239,7 @@ void EDA_3D_CANVAS::BuildBoard3DView()
BOARD
*
pcb
=
GetBoard
();
bool
realistic_mode
=
g_Parm_3D_Visu
.
IsRealisticMode
();
// Number of segments to
draw a circle using segments
// Number of segments to
convert a circle to polygon
const
int
segcountforcircle
=
16
;
double
correctionFactor
=
1.0
/
cos
(
M_PI
/
(
segcountforcircle
*
2
)
);
const
int
segcountLowQuality
=
12
;
// segments to draw a circle with low quality
...
...
common/gr_basic.cpp
View file @
c97afea4
...
...
@@ -848,7 +848,7 @@ static void GRSClosedPoly( EDA_RECT* aClipBox, wxDC* aDC,
// Close the polygon
if
(
aPoints
[
lastpt
]
!=
aPoints
[
0
]
)
{
GRLineTo
(
aClipBox
,
aDC
,
aPoints
[
lastpt
].
x
,
aPoints
[
lastpt
].
y
,
aWidth
,
aColor
);
GRLineTo
(
aClipBox
,
aDC
,
aPoints
[
0
].
x
,
aPoints
[
0
].
y
,
aWidth
,
aColor
);
}
}
}
...
...
pcbnew/board_items_to_polygon_shape_transform.cpp
View file @
c97afea4
...
...
@@ -14,6 +14,7 @@
#include <pcbnew.h>
#include <wxPcbStruct.h>
#include <trigo.h>
#include <class_board.h>
#include <class_pad.h>
#include <class_track.h>
#include <class_drawsegment.h>
...
...
@@ -38,6 +39,80 @@ static void addTextSegmToPoly( int x0, int y0, int xf, int yf )
s_textCircle2SegmentCount
,
s_textWidth
);
}
/**
* Function ConvertBrdLayerToPolygonalContours
* Build a set of polygons which are the outlines of copper items
* (pads, tracks, texts, zones)
* the holes in vias or pads are ignored
* Usefull to export the shape of copper layers to dxf polygons
* or 3D viewer
* the polygons are not merged.
* @param aLayer = A layer, like LAYER_N_BACK, etc.
* @param aOutlines The CPOLYGONS_LIST to fill in with main outlines.
* @return true if success, false if a contour is not valid
*/
void
BOARD
::
ConvertBrdLayerToPolygonalContours
(
LAYER_NUM
aLayer
,
CPOLYGONS_LIST
&
aOutlines
)
{
// Number of segments to convert a circle to a polygon
const
int
segcountforcircle
=
16
;
double
correctionFactor
=
1.0
/
cos
(
M_PI
/
(
segcountforcircle
*
2
)
);
// convert tracks and vias:
for
(
TRACK
*
track
=
m_Track
;
track
!=
NULL
;
track
=
track
->
Next
()
)
{
if
(
!
track
->
IsOnLayer
(
aLayer
)
)
continue
;
track
->
TransformShapeWithClearanceToPolygon
(
aOutlines
,
0
,
segcountforcircle
,
correctionFactor
);
}
// convert pads
for
(
MODULE
*
module
=
m_Modules
;
module
!=
NULL
;
module
=
module
->
Next
()
)
{
module
->
TransformPadsShapesWithClearanceToPolygon
(
aLayer
,
aOutlines
,
0
,
segcountforcircle
,
correctionFactor
);
// Micro-wave modules may have items on copper layers
module
->
TransformGraphicShapesWithClearanceToPolygonSet
(
aLayer
,
aOutlines
,
0
,
segcountforcircle
,
correctionFactor
);
}
// convert copper zones
for
(
int
ii
=
0
;
ii
<
GetAreaCount
();
ii
++
)
{
ZONE_CONTAINER
*
zone
=
GetArea
(
ii
);
LAYER_NUM
zonelayer
=
zone
->
GetLayer
();
if
(
zonelayer
==
aLayer
)
zone
->
TransformSolidAreasShapesToPolygonSet
(
aOutlines
,
segcountforcircle
,
correctionFactor
);
}
// convert graphic items on copper layers (texts)
for
(
BOARD_ITEM
*
item
=
m_Drawings
;
item
;
item
=
item
->
Next
()
)
{
if
(
!
item
->
IsOnLayer
(
aLayer
)
)
continue
;
switch
(
item
->
Type
()
)
{
case
PCB_LINE_T
:
// should not exist on copper layers
(
(
DRAWSEGMENT
*
)
item
)
->
TransformShapeWithClearanceToPolygon
(
aOutlines
,
0
,
segcountforcircle
,
correctionFactor
);
break
;
case
PCB_TEXT_T
:
(
(
TEXTE_PCB
*
)
item
)
->
TransformShapeWithClearanceToPolygonSet
(
aOutlines
,
0
,
segcountforcircle
,
correctionFactor
);
break
;
default
:
break
;
}
}
}
/* generate pads shapes on layer aLayer as polygons,
* and adds these polygons to aCornerBuffer
* aCornerBuffer = the buffer to store polygons
...
...
@@ -614,43 +689,26 @@ bool D_PAD::BuildPadDrillShapePolygon( CPOLYGONS_LIST& aCornerBuffer,
int
aInflateValue
,
int
aSegmentsPerCircle
)
const
{
wxSize
drillsize
=
GetDrillSize
();
bool
hasHole
=
drillsize
.
x
&&
drillsize
.
y
;
if
(
!
hasHole
)
if
(
!
drillsize
.
x
||
!
drillsize
.
y
)
return
false
;
drillsize
.
x
+=
aInflateValue
;
drillsize
.
y
+=
aInflateValue
;
if
(
drillsize
.
x
==
drillsize
.
y
)
// usual round hole
{
TransformCircleToPolygon
(
aCornerBuffer
,
GetPosition
(),
drillsize
.
x
/
2
,
aSegmentsPerCircle
);
(
drillsize
.
x
/
2
)
+
aInflateValue
,
aSegmentsPerCircle
);
}
else
// Oblong hole
{
wxPoint
ends_offset
;
wxPoint
start
,
end
;
int
width
;
if
(
drillsize
.
x
>
drillsize
.
y
)
// Horizontal oval
{
ends_offset
.
x
=
(
drillsize
.
x
-
drillsize
.
y
)
/
2
;
width
=
drillsize
.
y
;
}
else
// Vertical oval
{
ends_offset
.
y
=
(
drillsize
.
y
-
drillsize
.
x
)
/
2
;
width
=
drillsize
.
x
;
}
RotatePoint
(
&
ends_offset
,
GetOrientation
()
);
GetOblongDrillGeometry
(
start
,
end
,
width
);
wxPoint
start
=
GetPosition
()
+
ends_offset
;
wxPoint
end
=
GetPosition
()
-
ends_offset
;
width
+=
aInflateValue
*
2
;
// Prepare the shape creation
TransformRoundedEndsSegmentToPolygon
(
aCornerBuffer
,
start
,
end
,
aSegmentsPerCircle
,
width
);
TransformRoundedEndsSegmentToPolygon
(
aCornerBuffer
,
GetPosition
()
+
start
,
GetPosition
()
+
end
,
aSegmentsPerCircle
,
width
);
}
return
true
;
...
...
pcbnew/class_pad.cpp
View file @
c97afea4
...
...
@@ -637,6 +637,39 @@ bool D_PAD::IsOnLayer( LAYER_NUM aLayer ) const
}
void
D_PAD
::
GetOblongDrillGeometry
(
wxPoint
&
aStartPoint
,
wxPoint
&
aEndPoint
,
int
&
aWidth
)
const
{
// calculates the start point, end point and width
// of an equivalent segment which have the same position and width as the hole
int
delta_cx
,
delta_cy
;
wxSize
halfsize
=
GetDrillSize
();;
halfsize
.
x
/=
2
;
halfsize
.
y
/=
2
;
if
(
m_Drill
.
x
>
m_Drill
.
y
)
// horizontal
{
delta_cx
=
halfsize
.
x
-
halfsize
.
y
;
delta_cy
=
0
;
aWidth
=
m_Drill
.
y
;
}
else
// vertical
{
delta_cx
=
0
;
delta_cy
=
halfsize
.
y
-
halfsize
.
x
;
aWidth
=
m_Drill
.
x
;
}
RotatePoint
(
&
delta_cx
,
&
delta_cy
,
m_Orient
);
aStartPoint
.
x
=
delta_cx
;
aStartPoint
.
y
=
delta_cy
;
aEndPoint
.
x
=
-
delta_cx
;
aEndPoint
.
y
=
-
delta_cy
;
}
bool
D_PAD
::
HitTest
(
const
wxPoint
&
aPosition
)
const
{
int
dx
,
dy
;
...
...
pcbnew/class_pad.h
View file @
c97afea4
...
...
@@ -169,6 +169,17 @@ public:
{
m_drillShape
=
aDrillShape
;
}
PAD_DRILL_SHAPE_T
GetDrillShape
()
const
{
return
m_drillShape
;
}
/**
* Function GetOblongDrillGeometry calculates the start point, end point and width
* of an equivalent segment which have the same position and width as the hole
* Usefull to plot/draw oblong holes like segments with rounded ends
* used in draw and plot functions
* @param aStartPoint = first point of the equivalent segment, relative to the pad position.
* @param aEndPoint = second point of the equivalent segment, relative to the pad position.
* @param aWidth = width equivalent segment.
*/
void
GetOblongDrillGeometry
(
wxPoint
&
aStartPoint
,
wxPoint
&
aEndPoint
,
int
&
aWidth
)
const
;
void
SetLayerMask
(
LAYER_MSK
aLayerMask
)
{
m_layerMask
=
aLayerMask
;
}
LAYER_MSK
GetLayerMask
()
const
{
return
m_layerMask
;
}
...
...
pcbnew/class_pad_draw_functions.cpp
View file @
c97afea4
...
...
@@ -310,7 +310,6 @@ void D_PAD::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, GR_DRAWMODE aDraw_mode,
void
D_PAD
::
DrawShape
(
EDA_RECT
*
aClipBox
,
wxDC
*
aDC
,
PAD_DRAWINFO
&
aDrawInfo
)
{
wxPoint
coord
[
4
];
int
delta_cx
,
delta_cy
;
double
angle
=
m_Orient
;
int
seg_width
;
...
...
@@ -439,27 +438,12 @@ void D_PAD::DrawShape( EDA_RECT* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo )
break
;
case
PAD_DRILL_OBLONG
:
halfsize
.
x
=
m_Drill
.
x
>>
1
;
halfsize
.
y
=
m_Drill
.
y
>>
1
;
if
(
m_Drill
.
x
>
m_Drill
.
y
)
// horizontal
{
delta_cx
=
halfsize
.
x
-
halfsize
.
y
;
delta_cy
=
0
;
seg_width
=
m_Drill
.
y
;
}
else
// vertical
{
delta_cx
=
0
;
delta_cy
=
halfsize
.
y
-
halfsize
.
x
;
seg_width
=
m_Drill
.
x
;
wxPoint
drl_start
,
drl_end
;
GetOblongDrillGeometry
(
drl_start
,
drl_end
,
seg_width
);
GRFilledSegment
(
aClipBox
,
aDC
,
holepos
+
drl_start
,
holepos
+
drl_end
,
seg_width
,
hole_color
);
}
RotatePoint
(
&
delta_cx
,
&
delta_cy
,
angle
);
GRFillCSegm
(
aClipBox
,
aDC
,
holepos
.
x
+
delta_cx
,
holepos
.
y
+
delta_cy
,
holepos
.
x
-
delta_cx
,
holepos
.
y
-
delta_cy
,
seg_width
,
hole_color
);
break
;
default
:
...
...
pcbnew/class_track.cpp
View file @
c97afea4
...
...
@@ -66,28 +66,6 @@ static bool ShowClearance( const TRACK* aTrack )
}
/*
* return true if the dist between p1 and p2 < max_dist
* Currently in test (currently ratsnest algos work only if p1 == p2)
*/
inline
bool
IsNear
(
const
wxPoint
&
p1
,
const
wxPoint
&
p2
,
int
max_dist
)
{
#if 0 // Do not change it: does not work
int dist;
dist = abs( p1.x - p2.x ) + abs( p1.y - p2.y );
dist *= 7;
dist /= 10;
if ( dist < max_dist )
return true;
#else
if
(
p1
==
p2
)
return
true
;
#endif
return
false
;
}
TRACK
*
GetTrack
(
TRACK
*
aStartTrace
,
const
TRACK
*
aEndTrace
,
const
wxPoint
&
aPosition
,
LAYER_MSK
aLayerMask
)
{
...
...
@@ -1303,123 +1281,77 @@ VIA* TRACK::GetVia( TRACK* aEndTrace, const wxPoint& aPosition, LAYER_MSK aLayer
}
TRACK
*
TRACK
::
GetTrack
(
TRACK
*
aStartTrace
,
TRACK
*
aEndTrace
,
ENDPOINT_T
aEndPoint
)
TRACK
*
TRACK
::
GetTrack
(
TRACK
*
aStartTrace
,
TRACK
*
aEndTrace
,
ENDPOINT_T
aEndPoint
,
bool
aSameNetOnly
,
bool
aSequential
)
{
const
int
NEIGHTBOUR_COUNT_MAX
=
50
;
TRACK
*
previousSegment
;
TRACK
*
nextSegment
;
int
Reflayer
;
int
ii
;
int
max_dist
;
const
wxPoint
&
position
=
GetEndPoint
(
aEndPoint
);
LAYER_MSK
refLayers
=
GetLayerMask
();
TRACK
*
previousSegment
;
TRACK
*
nextSegment
;
Reflayer
=
GetLayerMask
();
previousSegment
=
nextSegment
=
this
;
// Local search:
for
(
ii
=
0
;
ii
<
NEIGHTBOUR_COUNT_MAX
;
ii
++
)
if
(
aSequential
)
{
if
(
(
nextSegment
==
NULL
)
&&
(
previousSegment
==
NULL
)
)
break
;
if
(
nextSegment
)
// Simple sequential search: from aStartTrace forward to aEndTrace
previousSegment
=
NULL
;
nextSegment
=
aStartTrace
;
}
else
{
if
(
nextSegment
->
GetState
(
BUSY
|
IS_DELETED
)
)
goto
suite
;
if
(
nextSegment
==
this
)
goto
suite
;
/* max_dist is the max distance between 2 track ends which
* ensure a copper continuity */
max_dist
=
(
nextSegment
->
m_Width
+
this
->
m_Width
)
/
2
;
/* Local bidirectional search: from this backward to aStartTrace
* AND forward to aEndTrace. The idea is that nearest segments
* are found (on average) faster in this way. In fact same-net
* segments are almost guaranteed to be found faster, in a global
* search, since they are grouped together in the track list */
previousSegment
=
this
;
nextSegment
=
this
;
}
if
(
IsNear
(
position
,
nextSegment
->
m_Start
,
max_dist
)
)
while
(
nextSegment
||
previousSegment
)
{
if
(
Reflayer
&
nextSegment
->
GetLayerMask
()
)
return
nextSegment
;
// Terminate the search in the direction if the netcode mismatches
if
(
aSameNetOnly
)
{
if
(
nextSegment
&&
(
nextSegment
->
GetNetCode
()
!=
GetNetCode
())
)
nextSegment
=
NULL
;
if
(
previousSegment
&&
(
previousSegment
->
GetNetCode
()
!=
GetNetCode
())
)
previousSegment
=
NULL
;
}
if
(
IsNear
(
position
,
nextSegment
->
m_End
,
max_dist
)
)
if
(
nextSegment
)
{
if
(
Reflayer
&
nextSegment
->
GetLayerMask
()
)
if
(
(
nextSegment
!=
this
)
&&
!
nextSegment
->
GetState
(
BUSY
|
IS_DELETED
)
&&
(
refLayers
&
nextSegment
->
GetLayerMask
())
)
{
if
(
(
position
==
nextSegment
->
m_Start
)
||
(
position
==
nextSegment
->
m_End
)
)
return
nextSegment
;
}
suite
:
// Keep looking forward
if
(
nextSegment
==
aEndTrace
)
nextSegment
=
NULL
;
else
nextSegment
=
nextSegment
->
Next
();
}
// Same as above, looking back. During sequential search this branch is inactive
if
(
previousSegment
)
{
if
(
previousSegment
->
GetState
(
BUSY
|
IS_DELETED
)
)
goto
suite1
;
if
(
previousSegment
==
this
)
goto
suite1
;
max_dist
=
(
previousSegment
->
m_Width
+
m_Width
)
/
2
;
if
(
IsNear
(
position
,
previousSegment
->
m_Start
,
max_dist
)
)
if
(
(
previousSegment
!=
this
)
&&
!
previousSegment
->
GetState
(
BUSY
|
IS_DELETED
)
&&
(
refLayers
&
previousSegment
->
GetLayerMask
())
)
{
if
(
Reflayer
&
previousSegment
->
GetLayerMask
()
)
if
(
(
position
==
previousSegment
->
m_Start
)
||
(
position
==
previousSegment
->
m_End
)
)
return
previousSegment
;
}
if
(
IsNear
(
position
,
previousSegment
->
m_End
,
max_dist
)
)
{
if
(
Reflayer
&
previousSegment
->
GetLayerMask
()
)
return
previousSegment
;
}
suite1
:
if
(
previousSegment
==
aStartTrace
)
previousSegment
=
NULL
;
else
if
(
previousSegment
->
Type
()
!=
PCB_T
)
previousSegment
=
previousSegment
->
Back
();
else
previousSegment
=
NULL
;
}
}
// General search
for
(
nextSegment
=
aStartTrace
;
nextSegment
!=
NULL
;
nextSegment
=
nextSegment
->
Next
()
)
{
if
(
nextSegment
->
GetState
(
IS_DELETED
|
BUSY
)
)
{
if
(
nextSegment
==
aEndTrace
)
break
;
continue
;
}
if
(
nextSegment
==
this
)
{
if
(
nextSegment
==
aEndTrace
)
break
;
continue
;
}
max_dist
=
(
nextSegment
->
m_Width
+
m_Width
)
/
2
;
if
(
IsNear
(
position
,
nextSegment
->
m_Start
,
max_dist
)
)
{
if
(
Reflayer
&
nextSegment
->
GetLayerMask
()
)
return
nextSegment
;
}
if
(
IsNear
(
position
,
nextSegment
->
m_End
,
max_dist
)
)
{
if
(
Reflayer
&
nextSegment
->
GetLayerMask
()
)
return
nextSegment
;
previousSegment
=
previousSegment
->
Back
();
}
if
(
nextSegment
==
aEndTrace
)
break
;
}
return
NULL
;
...
...
pcbnew/class_track.h
View file @
c97afea4
...
...
@@ -261,9 +261,14 @@ public:
* @param aEndTrace A pointer to the TRACK object to stop the search. A NULL value
* searches to the end of the list.
* @param aEndPoint The start or end point of the segment to test against.
* @param aSameNetOnly if true stop searching when the netcode changes
* @param aSequential If true, forces a forward sequential search,
* which is restartable; the default search can be faster but the
* position of the returned track in the list is unpredictable
* @return A TRACK object pointer if found otherwise NULL.
*/
TRACK
*
GetTrack
(
TRACK
*
aStartTrace
,
TRACK
*
aEndTrace
,
ENDPOINT_T
aEndPoint
);
TRACK
*
GetTrack
(
TRACK
*
aStartTrace
,
TRACK
*
aEndTrace
,
ENDPOINT_T
aEndPoint
,
bool
aSameNetOnly
,
bool
aSequential
);
/**
* Function GetEndSegments
...
...
pcbnew/clean.cpp
View file @
c97afea4
...
...
@@ -303,7 +303,7 @@ bool TRACKS_CLEANER::testTrackEndpointDangling( TRACK *aTrack, ENDPOINT_T aEndPo
{
bool
flag_erase
=
false
;
TRACK
*
other
=
aTrack
->
GetTrack
(
m_Brd
->
m_Track
,
NULL
,
aEndPoint
);
TRACK
*
other
=
aTrack
->
GetTrack
(
m_Brd
->
m_Track
,
NULL
,
aEndPoint
,
true
,
false
);
if
(
(
other
==
NULL
)
&&
(
zoneForTrackEndpoint
(
aTrack
,
aEndPoint
)
==
NULL
)
)
flag_erase
=
true
;
// Start endpoint is neither on pad, zone or other track
...
...
@@ -324,7 +324,7 @@ bool TRACKS_CLEANER::testTrackEndpointDangling( TRACK *aTrack, ENDPOINT_T aEndPo
// search for another segment following the via
aTrack
->
SetState
(
BUSY
,
true
);
other
=
via
->
GetTrack
(
m_Brd
->
m_Track
,
NULL
,
aEndPoint
);
other
=
via
->
GetTrack
(
m_Brd
->
m_Track
,
NULL
,
aEndPoint
,
true
,
false
);
// There is a via on the start but it goes nowhere
if
(
(
other
==
NULL
)
&&
...
...
@@ -450,41 +450,37 @@ bool TRACKS_CLEANER::remove_duplicates_of_track( const TRACK *aTrack )
bool
TRACKS_CLEANER
::
merge_collinear_of_track
(
TRACK
*
aSegment
)
{
bool
merged_this
=
false
;
bool
flag
=
false
;
// If there are connections to this on the endpoint
//
search for a possible point connected to the START point of the current segment
TRACK
*
segStart
=
aSegment
->
Next
()
;
while
(
true
)
//
*WHY* doesn't C++ have prec and succ (or ++ --) like PASCAL?
for
(
ENDPOINT_T
endpoint
=
ENDPOINT_START
;
endpoint
<=
ENDPOINT_END
;
endpoint
=
ENDPOINT_T
(
endpoint
+
1
)
)
{
segStart
=
aSegment
->
GetTrack
(
segStart
,
NULL
,
ENDPOINT_START
);
if
(
segStart
)
// search for a possible segment connected to the current endpoint of the current one
TRACK
*
other
=
aSegment
->
Next
();
if
(
other
)
{
// the two segments must have the same width
if
(
aSegment
->
GetWidth
()
!=
segStart
->
GetWidth
()
)
break
;
// it cannot be a via
if
(
segStart
->
Type
()
!=
PCB_TRACE_T
)
break
;
// We must have only one segment connected
segStart
->
SetState
(
BUSY
,
true
);
TRACK
*
other
=
aSegment
->
GetTrack
(
m_Brd
->
m_Track
,
NULL
,
ENDPOINT_START
);
segStart
->
SetState
(
BUSY
,
false
);
other
=
aSegment
->
GetTrack
(
other
,
NULL
,
endpoint
,
true
,
false
);
if
(
other
==
NULL
)
flag
=
true
;
// OK
break
;
}
break
;
}
if
(
other
)
{
// the two segments must have the same width and the other
// cannot be a via
if
(
(
aSegment
->
GetWidth
()
==
other
->
GetWidth
())
&&
(
other
->
Type
()
==
PCB_TRACE_T
)
)
{
// There can be only one segment connected
other
->
SetState
(
BUSY
,
true
);
TRACK
*
yet_another
=
aSegment
->
GetTrack
(
m_Brd
->
m_Track
,
NULL
,
endpoint
,
true
,
false
);
other
->
SetState
(
BUSY
,
false
);
if
(
flag
)
// We have the starting point of the segment is connected to an other segment
if
(
!
yet_another
)
{
TRACK
*
segDelete
=
mergeCollinearSegmentIfPossible
(
aSegment
,
segStart
,
ENDPOINT_START
);
// Try to merge them
TRACK
*
segDelete
=
mergeCollinearSegmentIfPossible
(
aSegment
,
other
,
endpoint
);
// Merge succesful, the other one has to go away
if
(
segDelete
)
{
m_Brd
->
GetRatsnest
()
->
Remove
(
segDelete
);
...
...
@@ -493,52 +489,11 @@ bool TRACKS_CLEANER::merge_collinear_of_track( TRACK *aSegment )
merged_this
=
true
;
}
}
// Do the same with the other endpoint
flag
=
false
;
// search for a possible point connected to the END point of the current segment:
TRACK
*
segEnd
=
aSegment
->
Next
();
while
(
true
)
{
segEnd
=
aSegment
->
GetTrack
(
segEnd
,
NULL
,
ENDPOINT_END
);
if
(
segEnd
)
{
if
(
aSegment
->
GetWidth
()
!=
segEnd
->
GetWidth
()
)
break
;
if
(
segEnd
->
Type
()
!=
PCB_TRACE_T
)
break
;
// We must have only one segment connected
segEnd
->
SetState
(
BUSY
,
true
);
TRACK
*
other
=
aSegment
->
GetTrack
(
m_Brd
->
m_Track
,
NULL
,
ENDPOINT_END
);
segEnd
->
SetState
(
BUSY
,
false
);
if
(
other
==
NULL
)
flag
=
true
;
// Ok
break
;
}
else
{
break
;
}
}
if
(
flag
)
// We have the ending point of the segment is connected to an other segment
{
TRACK
*
segDelete
=
mergeCollinearSegmentIfPossible
(
aSegment
,
segEnd
,
ENDPOINT_END
);
if
(
segDelete
)
{
m_Brd
->
GetRatsnest
()
->
Remove
(
segDelete
);
segDelete
->
ViewRelease
();
segDelete
->
DeleteStructure
();
merged_this
=
true
;
}
}
return
merged_this
;
}
...
...
@@ -550,12 +505,9 @@ bool TRACKS_CLEANER::clean_segments()
// Easy things first
modified
|=
delete_null_segments
();
// Delete redundant segments, i.e. segments having the same end points
// and layers
// Delete redundant segments, i.e. segments having the same end points and layers
for
(
TRACK
*
segment
=
m_Brd
->
m_Track
;
segment
;
segment
=
segment
->
Next
()
)
{
modified
|=
remove_duplicates_of_track
(
segment
);
}
// merge collinear segments:
TRACK
*
nextsegment
;
...
...
@@ -568,7 +520,7 @@ bool TRACKS_CLEANER::clean_segments()
bool
merged_this
=
merge_collinear_of_track
(
segment
);
modified
|=
merged_this
;
if
(
merged_this
)
// The current segment was modified, retry to merge it
if
(
merged_this
)
// The current segment was modified, retry to merge it
again
nextsegment
=
segment
->
Next
();
}
}
...
...
@@ -579,44 +531,24 @@ bool TRACKS_CLEANER::clean_segments()
/* Utility: check for parallelism between two segments */
static
bool
parallelism_test
(
int
dx1
,
int
dy1
,
int
dx2
,
int
dy2
)
{
/
/ The following condition tree
is ugly and repetitive, but I have
//
not a better way to express clearly the trivial cases. Hope the
//
compiler optimize it better than always doing the product
// below...
/
* The following condition list
is ugly and repetitive, but I have
*
not a better way to express clearly the trivial cases. Hope the
*
compiler optimize it better than always doing the product
* below... */
// test for vertical alignment (easy to handle)
if
(
dx1
==
0
)
{
if
(
dx2
!=
0
)
return
false
;
else
return
true
;
}
return
dx2
==
0
;
if
(
dx2
==
0
)
{
if
(
dx1
!=
0
)
return
false
;
else
return
true
;
}
return
dx1
==
0
;
// test for horizontal alignment (easy to handle)
if
(
dy1
==
0
)
{
if
(
dy2
!=
0
)
return
false
;
else
return
true
;
}
return
dy2
==
0
;
if
(
dy2
==
0
)
{
if
(
dy1
!=
0
)
return
false
;
else
return
true
;
}
return
dy1
==
0
;
/* test for alignment in other cases: Do the usual cross product test
* (the same as testing the slope, but without a division) */
...
...
@@ -746,7 +678,7 @@ bool PCB_EDIT_FRAME::RemoveMisConnectedTracks()
}
else
{
other
=
segment
->
GetTrack
(
GetBoard
()
->
m_Track
,
NULL
,
ENDPOINT_START
);
other
=
segment
->
GetTrack
(
GetBoard
()
->
m_Track
,
NULL
,
ENDPOINT_START
,
false
,
false
);
if
(
other
)
net_code_s
=
other
->
GetNetCode
();
...
...
@@ -764,7 +696,7 @@ bool PCB_EDIT_FRAME::RemoveMisConnectedTracks()
}
else
{
other
=
segment
->
GetTrack
(
GetBoard
()
->
m_Track
,
NULL
,
ENDPOINT_END
);
other
=
segment
->
GetTrack
(
GetBoard
()
->
m_Track
,
NULL
,
ENDPOINT_END
,
false
,
false
);
if
(
other
)
net_code_e
=
other
->
GetNetCode
();
...
...
pcbnew/move_or_drag_track.cpp
View file @
c97afea4
...
...
@@ -709,7 +709,7 @@ void PCB_EDIT_FRAME::Start_DragTrackSegmentAndKeepSlope( TRACK* track, wxDC* DC
s_StartSegmentPresent
=
s_EndSegmentPresent
=
true
;
if
(
(
track
->
start
==
NULL
)
||
(
track
->
start
->
Type
()
==
PCB_TRACE_T
)
)
TrackToStartPoint
=
track
->
GetTrack
(
GetBoard
()
->
m_Track
,
NULL
,
ENDPOINT_START
);
TrackToStartPoint
=
track
->
GetTrack
(
GetBoard
()
->
m_Track
,
NULL
,
ENDPOINT_START
,
true
,
false
);
// Test if more than one segment is connected to this point
if
(
TrackToStartPoint
)
...
...
@@ -717,14 +717,14 @@ void PCB_EDIT_FRAME::Start_DragTrackSegmentAndKeepSlope( TRACK* track, wxDC* DC
TrackToStartPoint
->
SetState
(
BUSY
,
true
);
if
(
(
TrackToStartPoint
->
Type
()
==
PCB_VIA_T
)
||
track
->
GetTrack
(
GetBoard
()
->
m_Track
,
NULL
,
ENDPOINT_START
)
)
||
track
->
GetTrack
(
GetBoard
()
->
m_Track
,
NULL
,
ENDPOINT_START
,
true
,
false
)
)
error
=
true
;
TrackToStartPoint
->
SetState
(
BUSY
,
false
);
}
if
(
(
track
->
end
==
NULL
)
||
(
track
->
end
->
Type
()
==
PCB_TRACE_T
)
)
TrackToEndPoint
=
track
->
GetTrack
(
GetBoard
()
->
m_Track
,
NULL
,
ENDPOINT_END
);
TrackToEndPoint
=
track
->
GetTrack
(
GetBoard
()
->
m_Track
,
NULL
,
ENDPOINT_END
,
true
,
false
);
// Test if more than one segment is connected to this point
if
(
TrackToEndPoint
)
...
...
@@ -732,7 +732,7 @@ void PCB_EDIT_FRAME::Start_DragTrackSegmentAndKeepSlope( TRACK* track, wxDC* DC
TrackToEndPoint
->
SetState
(
BUSY
,
true
);
if
(
(
TrackToEndPoint
->
Type
()
==
PCB_VIA_T
)
||
track
->
GetTrack
(
GetBoard
()
->
m_Track
,
NULL
,
ENDPOINT_END
)
)
||
track
->
GetTrack
(
GetBoard
()
->
m_Track
,
NULL
,
ENDPOINT_END
,
true
,
false
)
)
error
=
true
;
TrackToEndPoint
->
SetState
(
BUSY
,
false
);
...
...
pcbnew/pcbplot.h
View file @
c97afea4
...
...
@@ -204,6 +204,17 @@ void PlotOneBoardLayer( BOARD *aBoard, PLOTTER* aPlotter, LAYER_NUM aLayer,
void
PlotStandardLayer
(
BOARD
*
aBoard
,
PLOTTER
*
aPlotter
,
LAYER_MSK
aLayerMask
,
const
PCB_PLOT_PARAMS
&
aPlotOpt
);
/**
* Function PlotLayerOutlines
* plot copper outline of a copper layer.
* @param aBoard = the board to plot
* @param aPlotter = the plotter to use
* @param aLayerMask = the mask to define the layers to plot
* @param aPlotOpt = the plot options. Has meaning for some formats only
*/
void
PlotLayerOutlines
(
BOARD
*
aBoard
,
PLOTTER
*
aPlotter
,
LAYER_MSK
aLayerMask
,
const
PCB_PLOT_PARAMS
&
aPlotOpt
);
/**
* Function PlotSilkScreen
* plot silkscreen layers which have specific requirements, mainly for pads.
...
...
pcbnew/plot_board_layers.cpp
View file @
c97afea4
...
...
@@ -176,10 +176,18 @@ void PlotOneBoardLayer( BOARD *aBoard, PLOTTER* aPlotter, LAYER_NUM aLayer,
case
LAYER_N_15
:
case
LAST_COPPER_LAYER
:
// Skip NPTH pads on copper layers ( only if hole size == pad size ):
plotOpt
.
SetSkipPlotNPTH_Pads
(
true
);
// Drill mark will be plotted,
// if drill mark is SMALL_DRILL_SHAPE or FULL_DRILL_SHAPE
if
(
plotOpt
.
GetFormat
()
==
PLOT_FORMAT_DXF
)
{
plotOpt
.
SetSkipPlotNPTH_Pads
(
false
);
PlotLayerOutlines
(
aBoard
,
aPlotter
,
layer_mask
,
plotOpt
);
}
else
{
plotOpt
.
SetSkipPlotNPTH_Pads
(
true
);
PlotStandardLayer
(
aBoard
,
aPlotter
,
layer_mask
,
plotOpt
);
}
break
;
case
SOLDERMASK_N_BACK
:
...
...
@@ -190,7 +198,12 @@ void PlotOneBoardLayer( BOARD *aBoard, PLOTTER* aPlotter, LAYER_NUM aLayer,
// Plot solder mask:
if
(
soldermask_min_thickness
==
0
)
{
if
(
plotOpt
.
GetFormat
()
==
PLOT_FORMAT_DXF
)
PlotLayerOutlines
(
aBoard
,
aPlotter
,
layer_mask
,
plotOpt
);
else
PlotStandardLayer
(
aBoard
,
aPlotter
,
layer_mask
,
plotOpt
);
}
else
PlotSolderMaskLayer
(
aBoard
,
aPlotter
,
layer_mask
,
plotOpt
,
soldermask_min_thickness
);
...
...
@@ -202,11 +215,18 @@ void PlotOneBoardLayer( BOARD *aBoard, PLOTTER* aPlotter, LAYER_NUM aLayer,
plotOpt
.
SetSkipPlotNPTH_Pads
(
false
);
// Disable plot pad holes
plotOpt
.
SetDrillMarksType
(
PCB_PLOT_PARAMS
::
NO_DRILL_SHAPE
);
if
(
plotOpt
.
GetFormat
()
==
PLOT_FORMAT_DXF
)
PlotLayerOutlines
(
aBoard
,
aPlotter
,
layer_mask
,
plotOpt
);
else
PlotStandardLayer
(
aBoard
,
aPlotter
,
layer_mask
,
plotOpt
);
break
;
case
SILKSCREEN_N_FRONT
:
case
SILKSCREEN_N_BACK
:
if
(
plotOpt
.
GetFormat
()
==
PLOT_FORMAT_DXF
)
PlotLayerOutlines
(
aBoard
,
aPlotter
,
layer_mask
,
plotOpt
);
else
PlotSilkScreen
(
aBoard
,
aPlotter
,
layer_mask
,
plotOpt
);
// Gerber: Subtract soldermask from silkscreen if enabled
...
...
@@ -444,6 +464,115 @@ void PlotStandardLayer( BOARD *aBoard, PLOTTER* aPlotter,
itemplotter
.
PlotDrillMarks
();
}
/* Plot outlines of copper, for copper layer
*/
#include "clipper.hpp"
void
PlotLayerOutlines
(
BOARD
*
aBoard
,
PLOTTER
*
aPlotter
,
LAYER_MSK
aLayerMask
,
const
PCB_PLOT_PARAMS
&
aPlotOpt
)
{
BRDITEMS_PLOTTER
itemplotter
(
aPlotter
,
aBoard
,
aPlotOpt
);
itemplotter
.
SetLayerMask
(
aLayerMask
);
CPOLYGONS_LIST
outlines
;
for
(
LAYER_NUM
layer
=
FIRST_LAYER
;
layer
<
NB_PCB_LAYERS
;
layer
++
)
{
LAYER_MSK
layer_mask
=
GetLayerMask
(
layer
);
if
(
(
aLayerMask
&
layer_mask
)
==
0
)
continue
;
outlines
.
RemoveAllContours
();
aBoard
->
ConvertBrdLayerToPolygonalContours
(
layer
,
outlines
);
// Merge all overlapping polygons.
KI_POLYGON_SET
kpolygons
;
KI_POLYGON_SET
ktmp
;
outlines
.
ExportTo
(
ktmp
);
kpolygons
+=
ktmp
;
// Plot outlines
std
::
vector
<
wxPoint
>
cornerList
;
for
(
unsigned
ii
=
0
;
ii
<
kpolygons
.
size
();
ii
++
)
{
KI_POLYGON
polygon
=
kpolygons
[
ii
];
// polygon contains only one polygon, but it can have holes linked by
// overlapping segments.
// To plot clean outlines, we have to break this polygon into more polygons with
// no overlapping segments, using Clipper, because boost::polygon
// does not allow that
ClipperLib
::
Path
raw_polygon
;
ClipperLib
::
Paths
normalized_polygons
;
for
(
unsigned
ic
=
0
;
ic
<
polygon
.
size
();
ic
++
)
{
KI_POLY_POINT
corner
=
*
(
polygon
.
begin
()
+
ic
);
raw_polygon
.
push_back
(
ClipperLib
::
IntPoint
(
corner
.
x
(),
corner
.
y
()
)
);
}
ClipperLib
::
SimplifyPolygon
(
raw_polygon
,
normalized_polygons
);
// Now we have one or more basic polygons: plot each polygon
for
(
unsigned
ii
=
0
;
ii
<
normalized_polygons
.
size
();
ii
++
)
{
ClipperLib
::
Path
&
polygon
=
normalized_polygons
[
ii
];
cornerList
.
clear
();
for
(
unsigned
jj
=
0
;
jj
<
polygon
.
size
();
jj
++
)
cornerList
.
push_back
(
wxPoint
(
polygon
[
jj
].
X
,
polygon
[
jj
].
Y
)
);
// Ensure the polygon is closed
if
(
cornerList
[
0
]
!=
cornerList
[
cornerList
.
size
()
-
1
]
)
cornerList
.
push_back
(
cornerList
[
0
]
);
aPlotter
->
PlotPoly
(
cornerList
,
NO_FILL
);
}
}
// Plot pad holes
if
(
aPlotOpt
.
GetDrillMarksType
()
!=
PCB_PLOT_PARAMS
::
NO_DRILL_SHAPE
)
{
for
(
MODULE
*
module
=
aBoard
->
m_Modules
;
module
;
module
=
module
->
Next
()
)
{
for
(
D_PAD
*
pad
=
module
->
Pads
();
pad
;
pad
=
pad
->
Next
()
)
{
wxSize
hole
=
pad
->
GetDrillSize
();
if
(
hole
.
x
==
0
||
hole
.
y
==
0
)
continue
;
if
(
hole
.
x
==
hole
.
y
)
aPlotter
->
Circle
(
pad
->
GetPosition
(),
hole
.
x
,
NO_FILL
);
else
{
wxPoint
drl_start
,
drl_end
;
int
width
;
pad
->
GetOblongDrillGeometry
(
drl_start
,
drl_end
,
width
);
aPlotter
->
ThickSegment
(
pad
->
GetPosition
()
+
drl_start
,
pad
->
GetPosition
()
+
drl_end
,
width
,
SKETCH
);
}
}
}
}
// Plot vias holes
for
(
TRACK
*
track
=
aBoard
->
m_Track
;
track
;
track
=
track
->
Next
()
)
{
const
VIA
*
via
=
dynamic_cast
<
const
VIA
*>
(
track
);
if
(
via
&&
via
->
IsOnLayer
(
layer
)
)
// via holes can be not through holes
{
aPlotter
->
Circle
(
via
->
GetPosition
(),
via
->
GetDrillValue
(),
NO_FILL
);
}
}
}
}
/* Plot a solder mask layer.
* Solder mask layers have a minimum thickness value and cannot be drawn like standard layers,
* unless the minimum thickness is 0.
...
...
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