@ -42,6 +42,7 @@
# include <dialogs/dialog_outset_items.h>
# include <footprint.h>
# include <footprint_edit_frame.h>
# include <geometry/roundrect.h>
# include <geometry/shape_compound.h>
# include <pcb_edit_frame.h>
# include <pcb_shape.h>
@ -963,60 +964,6 @@ int CONVERT_TOOL::CreateLines( const TOOL_EVENT& aEvent )
if ( selection . Empty ( ) )
return 0 ;
auto getPolySet =
[ ] ( EDA_ITEM * aItem )
{
SHAPE_POLY_SET set ;
switch ( aItem - > Type ( ) )
{
case PCB_ZONE_T :
set = * static_cast < ZONE * > ( aItem ) - > Outline ( ) ;
break ;
case PCB_SHAPE_T :
{
PCB_SHAPE * graphic = static_cast < PCB_SHAPE * > ( aItem ) ;
if ( graphic - > GetShape ( ) = = SHAPE_T : : RECTANGLE )
{
graphic - > TransformShapeToPolygon ( set , graphic - > GetLayer ( ) , 0 , graphic - > GetMaxError ( ) , ERROR_INSIDE ) ;
}
else if ( graphic - > GetShape ( ) = = SHAPE_T : : POLY )
{
set = graphic - > GetPolyShape ( ) ;
}
else
{
wxFAIL_MSG ( wxT ( " Unhandled graphic shape type in PolyToLines - getPolySet " ) ) ;
}
break ;
}
default :
wxFAIL_MSG ( wxT ( " Unhandled type in PolyToLines - getPolySet " ) ) ;
break ;
}
return set ;
} ;
auto getSegList =
[ ] ( SHAPE_POLY_SET & aPoly )
{
std : : vector < SEG > segs ;
// Our input should be valid polys, so OK to assert here
wxASSERT ( aPoly . VertexCount ( ) > = 2 ) ;
for ( int i = 1 ; i < aPoly . VertexCount ( ) ; i + + )
segs . emplace_back ( SEG ( aPoly . CVertex ( i - 1 ) , aPoly . CVertex ( i ) ) ) ;
segs . emplace_back ( SEG ( aPoly . CVertex ( aPoly . VertexCount ( ) - 1 ) , aPoly . CVertex ( 0 ) ) ) ;
return segs ;
} ;
BOARD_COMMIT commit ( m_frame ) ;
PCB_BASE_EDIT_FRAME * frame = getEditFrame < PCB_BASE_EDIT_FRAME > ( ) ;
FOOTPRINT_EDIT_FRAME * fpEditor = dynamic_cast < FOOTPRINT_EDIT_FRAME * > ( m_frame ) ;
@ -1064,6 +1011,129 @@ int CONVERT_TOOL::CreateLines( const TOOL_EVENT& aEvent )
return false ;
} ;
auto addGraphicChain =
[ & ] ( const SHAPE_LINE_CHAIN & aChain , std : : optional < int > aWidth )
{
for ( size_t si = 0 ; si < aChain . GetSegmentCount ( ) ; + + si )
{
const SEG seg = aChain . GetSegment ( si ) ;
if ( seg . Length ( ) = = 0 )
continue ;
if ( aChain . IsArcSegment ( si ) )
continue ;
PCB_SHAPE * graphic = new PCB_SHAPE ( footprint , SHAPE_T : : SEGMENT ) ;
graphic - > SetLayer ( targetLayer ) ;
graphic - > SetStart ( seg . A ) ;
graphic - > SetEnd ( seg . B ) ;
if ( aWidth & & * aWidth > 0 )
graphic - > SetWidth ( * aWidth ) ;
commit . Add ( graphic ) ;
}
for ( size_t ai = 0 ; ai < aChain . ArcCount ( ) ; + + ai )
{
const SHAPE_ARC & arc = aChain . Arc ( ai ) ;
if ( arc . GetP0 ( ) = = arc . GetP1 ( ) )
continue ;
PCB_SHAPE * graphic = new PCB_SHAPE ( footprint , SHAPE_T : : ARC ) ;
graphic - > SetLayer ( targetLayer ) ;
graphic - > SetFilled ( false ) ;
graphic - > SetArcGeometry ( arc . GetP0 ( ) , arc . GetArcMid ( ) , arc . GetP1 ( ) ) ;
if ( aWidth & & * aWidth > 0 )
graphic - > SetWidth ( * aWidth ) ;
commit . Add ( graphic ) ;
}
} ;
auto addTrackChain =
[ & ] ( const SHAPE_LINE_CHAIN & aChain , std : : optional < int > aWidth )
{
for ( size_t si = 0 ; si < aChain . GetSegmentCount ( ) ; + + si )
{
const SEG seg = aChain . GetSegment ( si ) ;
if ( seg . Length ( ) = = 0 )
continue ;
if ( aChain . IsArcSegment ( si ) )
continue ;
PCB_TRACK * track = new PCB_TRACK ( parent ) ;
track - > SetLayer ( targetLayer ) ;
track - > SetStart ( seg . A ) ;
track - > SetEnd ( seg . B ) ;
if ( aWidth & & * aWidth > 0 )
track - > SetWidth ( * aWidth ) ;
commit . Add ( track ) ;
}
for ( size_t ai = 0 ; ai < aChain . ArcCount ( ) ; + + ai )
{
const SHAPE_ARC & arc = aChain . Arc ( ai ) ;
if ( arc . GetP0 ( ) = = arc . GetP1 ( ) )
continue ;
PCB_ARC * trackArc = new PCB_ARC ( parent ) ;
trackArc - > SetLayer ( targetLayer ) ;
trackArc - > SetStart ( arc . GetP0 ( ) ) ;
trackArc - > SetEnd ( arc . GetP1 ( ) ) ;
trackArc - > SetMid ( arc . GetArcMid ( ) ) ;
if ( aWidth & & * aWidth > 0 )
trackArc - > SetWidth ( * aWidth ) ;
commit . Add ( trackArc ) ;
}
} ;
auto processChain =
[ & ] ( const SHAPE_LINE_CHAIN & aChain , std : : optional < int > aWidth )
{
if ( aChain . GetSegmentCount ( ) = = 0 & & aChain . ArcCount ( ) = = 0 )
return ;
if ( aEvent . IsAction ( & PCB_ACTIONS : : convertToLines ) )
{
addGraphicChain ( aChain , aWidth ) ;
}
else if ( fpEditor )
{
addGraphicChain ( aChain , aWidth ) ;
}
else
{
addTrackChain ( aChain , aWidth ) ;
}
} ;
auto processPolySet =
[ & ] ( const SHAPE_POLY_SET & aPoly , std : : optional < int > aWidth )
{
for ( int oi = 0 ; oi < aPoly . OutlineCount ( ) ; + + oi )
{
processChain ( aPoly . COutline ( oi ) , aWidth ) ;
for ( int hi = 0 ; hi < aPoly . HoleCount ( oi ) ; + + hi )
processChain ( aPoly . CHole ( oi , hi ) , aWidth ) ;
}
} ;
if ( aEvent . IsAction ( & PCB_ACTIONS : : convertToTracks ) )
{
if ( ! IsCopperLayer ( targetLayer ) )
@ -1090,62 +1160,43 @@ int CONVERT_TOOL::CreateLines( const TOOL_EVENT& aEvent )
if ( handleGraphicSeg ( item ) )
continue ;
BOARD_ITEM & boardItem = static_cast < BOARD_ITEM & > ( * item ) ;
SHAPE_POLY_SET polySet = getPolySet ( item ) ;
std : : vector < SEG > segs = getSegList ( polySet ) ;
BOARD_ITEM & boardItem = static_cast < BOARD_ITEM & > ( * item ) ;
std : : optional < int > itemWidth = GetBoardItemWidth ( boardItem ) ;
if ( aEvent . IsAction ( & PCB_ACTIONS : : convertToLines ) )
if ( boardItem . Type ( ) = = PCB_SHAPE_T )
{
for ( SEG & seg : segs )
PCB_SHAPE * graphic = static_cast < PCB_SHAPE * > ( item ) ;
switch ( graphic - > GetShape ( ) )
{
case SHAPE_T : : RECTANGLE :
{
PCB_SHAPE * graphic = new PCB_SHAPE ( footprint , SHAPE_T : : SEGMENT ) ;
SHAPE_RECT rect ( graphic - > GetStart ( ) , graphic - > GetEnd ( ) ) ;
ROUNDRECT rrect ( rect , graphic - > GetCornerRadius ( ) , true ) ;
SHAPE_POLY_SET poly ;
graphic - > SetLayer ( targetLayer ) ;
graphic - > SetStart ( VECTOR2I ( seg . A ) ) ;
graphic - > SetEnd ( VECTOR2I ( seg . B ) ) ;
rrect . TransformToPolygon ( poly ) ;
processPolySet ( poly , itemWidth ) ;
break ;
}
// The width can exist but be 0 for filled, unstroked shapes
if ( itemWidth & & * itemWidth > 0 )
graphic - > SetWidth ( * itemWidth ) ;
case SHAPE_T : : POLY :
processPolySet ( graphic - > GetPolyShape ( ) , itemWidth ) ;
break ;
commit . Add ( graphic ) ;
default :
wxFAIL_MSG ( wxT ( " Unhandled graphic shape type in PolyToLines " ) ) ;
break ;
}
}
else if ( boardItem . Type ( ) = = PCB_ZONE_T )
{
ZONE * zone = static_cast < ZONE * > ( item ) ;
processPolySet ( * zone - > Outline ( ) , itemWidth ) ;
}
else
{
// I am really unsure converting a polygon to "tracks" (i.e. segments on
// copper layers) make sense for footprints, but anyway this code exists
if ( fpEditor )
{
// Creating segments on copper layer
for ( SEG & seg : segs )
{
PCB_SHAPE * graphic = new PCB_SHAPE ( footprint , SHAPE_T : : SEGMENT ) ;
graphic - > SetLayer ( targetLayer ) ;
graphic - > SetStart ( VECTOR2I ( seg . A ) ) ;
graphic - > SetEnd ( VECTOR2I ( seg . B ) ) ;
if ( itemWidth )
graphic - > SetWidth ( * itemWidth ) ;
commit . Add ( graphic ) ;
}
}
else
{
// Creating tracks
for ( SEG & seg : segs )
{
PCB_TRACK * track = new PCB_TRACK ( parent ) ;
track - > SetLayer ( targetLayer ) ;
track - > SetStart ( VECTOR2I ( seg . A ) ) ;
track - > SetEnd ( VECTOR2I ( seg . B ) ) ;
commit . Add ( track ) ;
}
}
wxFAIL_MSG ( wxT ( " Unhandled type in PolyToLines " ) ) ;
}
}