Enable converting segments to arcs
Fixes https://gitlab.com/kicad/code/kicad/-/issues/1957
This commit is contained in:
parent
a390b19f97
commit
fa8655511e
|
@ -112,6 +112,11 @@ const VECTOR2I GetArcCenter( const VECTOR2I& aStart, const VECTOR2I& aMid, const
|
||||||
const VECTOR2D GetArcCenter( const VECTOR2D& aStart, const VECTOR2D& aMid, const VECTOR2D& aEnd );
|
const VECTOR2D GetArcCenter( const VECTOR2D& aStart, const VECTOR2D& aMid, const VECTOR2D& aEnd );
|
||||||
const wxPoint GetArcCenter( const wxPoint& aStart, const wxPoint& aMid, const wxPoint& aEnd );
|
const wxPoint GetArcCenter( const wxPoint& aStart, const wxPoint& aMid, const wxPoint& aEnd );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the subtended angle for a given arc
|
||||||
|
*/
|
||||||
|
double GetArcAngle( const VECTOR2I& aStart, const VECTOR2I& aMid, const VECTOR2I& aEnd );
|
||||||
|
|
||||||
/* Return the arc tangent of 0.1 degrees coord vector dx, dy
|
/* Return the arc tangent of 0.1 degrees coord vector dx, dy
|
||||||
* between -1800 and 1800
|
* between -1800 and 1800
|
||||||
* Equivalent to atan2 (but faster for calculations if
|
* Equivalent to atan2 (but faster for calculations if
|
||||||
|
|
|
@ -442,3 +442,32 @@ const wxPoint GetArcCenter( const wxPoint& aStart, const wxPoint& aMid, const wx
|
||||||
|
|
||||||
return iCenter;
|
return iCenter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double GetArcAngle( const VECTOR2I& aStart, const VECTOR2I& aMid, const VECTOR2I& aEnd )
|
||||||
|
{
|
||||||
|
VECTOR2I center = GetArcCenter( aStart, aMid, aEnd );
|
||||||
|
|
||||||
|
// Check if the new arc is CW or CCW
|
||||||
|
VECTOR2D startLine = aStart - center;
|
||||||
|
VECTOR2D endLine = aEnd - center;
|
||||||
|
double angle = RAD2DECIDEG( endLine.Angle() - startLine.Angle() );
|
||||||
|
|
||||||
|
VECTOR2D v1, v2;
|
||||||
|
v1 = aStart - aMid;
|
||||||
|
v2 = aEnd - aMid;
|
||||||
|
double theta = RAD2DECIDEG( v1.Angle() );
|
||||||
|
|
||||||
|
RotatePoint( &( v1.x ), &( v1.y ), theta );
|
||||||
|
RotatePoint( &( v2.x ), &( v2.y ), theta );
|
||||||
|
|
||||||
|
bool clockwise = ( ( v1.Angle() - v2.Angle() ) > 0 );
|
||||||
|
|
||||||
|
// Normalize the angle
|
||||||
|
if( clockwise && angle < 0.0 )
|
||||||
|
angle += 3600.0;
|
||||||
|
else if( !clockwise && angle > 0.0 )
|
||||||
|
angle -= 3600.0;
|
||||||
|
|
||||||
|
return angle;
|
||||||
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ bool CONVERT_TOOL::Init()
|
||||||
// Create a context menu and make it available through selection tool
|
// Create a context menu and make it available through selection tool
|
||||||
m_menu = new CONDITIONAL_MENU( this );
|
m_menu = new CONDITIONAL_MENU( this );
|
||||||
m_menu->SetIcon( refresh_xpm );
|
m_menu->SetIcon( refresh_xpm );
|
||||||
m_menu->SetTitle( _( "Convert" ) );
|
m_menu->SetTitle( _( "Convert..." ) );
|
||||||
|
|
||||||
static KICAD_T convertableTracks[] = { PCB_TRACE_T, PCB_ARC_T, EOT };
|
static KICAD_T convertableTracks[] = { PCB_TRACE_T, PCB_ARC_T, EOT };
|
||||||
|
|
||||||
|
@ -87,15 +87,17 @@ bool CONVERT_TOOL::Init()
|
||||||
auto anyPolys = ( S_C::OnlyType( PCB_ZONE_AREA_T ) ||
|
auto anyPolys = ( S_C::OnlyType( PCB_ZONE_AREA_T ) ||
|
||||||
P_S_C::OnlyGraphicShapeTypes( { S_POLYGON } ) );
|
P_S_C::OnlyGraphicShapeTypes( { S_POLYGON } ) );
|
||||||
|
|
||||||
auto showConvert = anyPolys || anyLines;
|
auto lineToArc = P_S_C::OnlyGraphicShapeTypes( { S_SEGMENT } ) ||
|
||||||
|
S_C::OnlyType( PCB_TRACE_T );
|
||||||
|
|
||||||
|
auto showConvert = anyPolys || anyLines || lineToArc;
|
||||||
|
|
||||||
m_menu->AddItem( PCB_ACTIONS::convertToPoly, anyLines );
|
m_menu->AddItem( PCB_ACTIONS::convertToPoly, anyLines );
|
||||||
m_menu->AddItem( PCB_ACTIONS::convertToZone, anyLines );
|
m_menu->AddItem( PCB_ACTIONS::convertToZone, anyLines );
|
||||||
m_menu->AddItem( PCB_ACTIONS::convertToKeepout, anyLines );
|
m_menu->AddItem( PCB_ACTIONS::convertToKeepout, anyLines );
|
||||||
m_menu->AddItem( PCB_ACTIONS::convertToLines, anyPolys );
|
m_menu->AddItem( PCB_ACTIONS::convertToLines, anyPolys );
|
||||||
m_menu->AddItem( PCB_ACTIONS::convertToTracks, anyPolys );
|
m_menu->AddItem( PCB_ACTIONS::convertToTracks, anyPolys );
|
||||||
// Not yet
|
m_menu->AddItem( PCB_ACTIONS::convertToArc, lineToArc );
|
||||||
// m_menu->AddItem( PCB_ACTIONS::convertToArc, lineToArc );
|
|
||||||
|
|
||||||
for( std::shared_ptr<ACTION_MENU>& subMenu : m_selectionTool->GetToolMenu().GetSubMenus() )
|
for( std::shared_ptr<ACTION_MENU>& subMenu : m_selectionTool->GetToolMenu().GetSubMenus() )
|
||||||
{
|
{
|
||||||
|
@ -491,13 +493,18 @@ int CONVERT_TOOL::SegmentToArc( const TOOL_EVENT& aEvent )
|
||||||
} );
|
} );
|
||||||
|
|
||||||
EDA_ITEM* source = selection.Front();
|
EDA_ITEM* source = selection.Front();
|
||||||
wxPoint start, end, mid;
|
VECTOR2I start, end, mid;
|
||||||
|
|
||||||
if( OPT<SEG> optSeg = getStartEndPoints( source ) )
|
// Offset the midpoint along the normal a little bit so that it's more obviously an arc
|
||||||
|
const double offsetRatio = 0.1;
|
||||||
|
|
||||||
|
if( OPT<SEG> seg = getStartEndPoints( source ) )
|
||||||
{
|
{
|
||||||
start = wxPoint( optSeg->A );
|
start = seg->A;
|
||||||
end = wxPoint( optSeg->B );
|
end = seg->B;
|
||||||
mid = wxPoint( optSeg->Center() );
|
|
||||||
|
VECTOR2I normal = ( seg->B - seg->A ).Perpendicular().Resize( offsetRatio * seg->Length() );
|
||||||
|
mid = seg->Center() + normal;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -517,16 +524,17 @@ int CONVERT_TOOL::SegmentToArc( const TOOL_EVENT& aEvent )
|
||||||
DRAWSEGMENT* line = static_cast<DRAWSEGMENT*>( source );
|
DRAWSEGMENT* line = static_cast<DRAWSEGMENT*>( source );
|
||||||
DRAWSEGMENT* arc = new DRAWSEGMENT( parent );
|
DRAWSEGMENT* arc = new DRAWSEGMENT( parent );
|
||||||
|
|
||||||
wxPoint center = GetArcCenter( start, mid, end );
|
VECTOR2I center = GetArcCenter( start, mid, end );
|
||||||
|
|
||||||
arc->SetShape( S_ARC );
|
arc->SetShape( S_ARC );
|
||||||
arc->SetLayer( layer );
|
arc->SetLayer( layer );
|
||||||
arc->SetWidth( line->GetWidth() );
|
arc->SetWidth( line->GetWidth() );
|
||||||
arc->SetArcStart( start );
|
|
||||||
arc->SetCenter( center );
|
|
||||||
// TODO(JE): once !325 is merged
|
|
||||||
//arc->SetArcEnd( end );
|
|
||||||
|
|
||||||
|
arc->SetCenter( wxPoint( center ) );
|
||||||
|
arc->SetArcStart( wxPoint( start ) );
|
||||||
|
arc->SetAngle( GetArcAngle( start, mid, end ) );
|
||||||
|
|
||||||
|
arc->SetArcEnd( wxPoint( end ) );
|
||||||
commit.Add( arc );
|
commit.Add( arc );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -537,9 +545,9 @@ int CONVERT_TOOL::SegmentToArc( const TOOL_EVENT& aEvent )
|
||||||
|
|
||||||
arc->SetLayer( layer );
|
arc->SetLayer( layer );
|
||||||
arc->SetWidth( line->GetWidth() );
|
arc->SetWidth( line->GetWidth() );
|
||||||
arc->SetStart( start );
|
arc->SetStart( wxPoint( start ) );
|
||||||
arc->SetMid( mid );
|
arc->SetMid( wxPoint( mid ) );
|
||||||
arc->SetEnd( end );
|
arc->SetEnd( wxPoint( end ) );
|
||||||
|
|
||||||
commit.Add( arc );
|
commit.Add( arc );
|
||||||
}
|
}
|
||||||
|
|
|
@ -657,23 +657,7 @@ void POINT_EDITOR::updateItem() const
|
||||||
segment->SetCenter( wxPoint( center.x, center.y ) );
|
segment->SetCenter( wxPoint( center.x, center.y ) );
|
||||||
m_editPoints->Point( ARC_CENTER ).SetPosition( center );
|
m_editPoints->Point( ARC_CENTER ).SetPosition( center );
|
||||||
|
|
||||||
// Check if the new arc is CW or CCW
|
newAngle = GetArcAngle( start, mid, end );
|
||||||
VECTOR2D startLine = start - center;
|
|
||||||
VECTOR2D endLine = end - center;
|
|
||||||
newAngle = RAD2DECIDEG( endLine.Angle() - startLine.Angle() );
|
|
||||||
VECTOR2D v1, v2;
|
|
||||||
v1 = start - mid;
|
|
||||||
v2 = end - mid;
|
|
||||||
double theta = RAD2DECIDEG( v1.Angle() );
|
|
||||||
RotatePoint( &( v1.x ), &( v1.y ), theta );
|
|
||||||
RotatePoint( &( v2.x ), &( v2.y ), theta );
|
|
||||||
clockwise = ( ( v1.Angle() - v2.Angle() ) > 0 );
|
|
||||||
|
|
||||||
// Normalize the angle
|
|
||||||
if( clockwise && newAngle < 0.0 )
|
|
||||||
newAngle += 3600.0;
|
|
||||||
else if( !clockwise && newAngle > 0.0 )
|
|
||||||
newAngle -= 3600.0;
|
|
||||||
|
|
||||||
// Accuracy test
|
// Accuracy test
|
||||||
// First, get the angle
|
// First, get the angle
|
||||||
|
|
Loading…
Reference in New Issue