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 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
|
||||
* between -1800 and 1800
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
m_menu = new CONDITIONAL_MENU( this );
|
||||
m_menu->SetIcon( refresh_xpm );
|
||||
m_menu->SetTitle( _( "Convert" ) );
|
||||
m_menu->SetTitle( _( "Convert..." ) );
|
||||
|
||||
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 ) ||
|
||||
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::convertToZone, anyLines );
|
||||
m_menu->AddItem( PCB_ACTIONS::convertToKeepout, anyLines );
|
||||
m_menu->AddItem( PCB_ACTIONS::convertToLines, 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() )
|
||||
{
|
||||
|
@ -491,13 +493,18 @@ int CONVERT_TOOL::SegmentToArc( const TOOL_EVENT& aEvent )
|
|||
} );
|
||||
|
||||
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 );
|
||||
end = wxPoint( optSeg->B );
|
||||
mid = wxPoint( optSeg->Center() );
|
||||
start = seg->A;
|
||||
end = seg->B;
|
||||
|
||||
VECTOR2I normal = ( seg->B - seg->A ).Perpendicular().Resize( offsetRatio * seg->Length() );
|
||||
mid = seg->Center() + normal;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
|
@ -517,16 +524,17 @@ int CONVERT_TOOL::SegmentToArc( const TOOL_EVENT& aEvent )
|
|||
DRAWSEGMENT* line = static_cast<DRAWSEGMENT*>( source );
|
||||
DRAWSEGMENT* arc = new DRAWSEGMENT( parent );
|
||||
|
||||
wxPoint center = GetArcCenter( start, mid, end );
|
||||
VECTOR2I center = GetArcCenter( start, mid, end );
|
||||
|
||||
arc->SetShape( S_ARC );
|
||||
arc->SetLayer( layer );
|
||||
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 );
|
||||
}
|
||||
else
|
||||
|
@ -537,9 +545,9 @@ int CONVERT_TOOL::SegmentToArc( const TOOL_EVENT& aEvent )
|
|||
|
||||
arc->SetLayer( layer );
|
||||
arc->SetWidth( line->GetWidth() );
|
||||
arc->SetStart( start );
|
||||
arc->SetMid( mid );
|
||||
arc->SetEnd( end );
|
||||
arc->SetStart( wxPoint( start ) );
|
||||
arc->SetMid( wxPoint( mid ) );
|
||||
arc->SetEnd( wxPoint( end ) );
|
||||
|
||||
commit.Add( arc );
|
||||
}
|
||||
|
|
|
@ -657,23 +657,7 @@ void POINT_EDITOR::updateItem() const
|
|||
segment->SetCenter( wxPoint( center.x, center.y ) );
|
||||
m_editPoints->Point( ARC_CENTER ).SetPosition( center );
|
||||
|
||||
// Check if the new arc is CW or CCW
|
||||
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;
|
||||
newAngle = GetArcAngle( start, mid, end );
|
||||
|
||||
// Accuracy test
|
||||
// First, get the angle
|
||||
|
|
Loading…
Reference in New Issue