mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-04-07 21:25:31 +00:00
Overhaul arc internal model to not over-specify information.
This commit is contained in:
parent
8b08c9e53f
commit
9b9e379aa0
3d-viewer/3d_canvas
common
eeschema
include
libs/kimath
pcbnew
autorouter
board_item.cppboard_items_to_polygon_shape_transform.cppconvert_shape_list_to_polygon.cppdialogs
exporters
fp_shape.cppfp_shape.hgraphics_cleaner.cppimport_gfx
microwave
pad_custom_shape_functions.cpppcb_painter.cpppcb_shape.cpppcb_shape.hpcb_track.cppplot_brditems_plotter.cppplugins
altium
cadstar
eagle
fabmaster
geda
kicad
legacy
pcad
specctra_import_export
tools
qa
@ -689,7 +689,7 @@ void BOARD_ADAPTER::addShapeWithClearance( const PCB_SHAPE* aShape,
|
||||
{
|
||||
unsigned int segCount = GetCircleSegmentCount( aShape->GetBoundingBox().GetSizeMax() );
|
||||
|
||||
transformArcToSegments( aShape->GetCenter(), aShape->GetArcStart(), aShape->GetAngle(),
|
||||
transformArcToSegments( aShape->GetCenter(), aShape->GetStart(), aShape->GetArcAngle(),
|
||||
segCount, linewidth, aDstContainer, *aShape );
|
||||
}
|
||||
break;
|
||||
|
@ -39,7 +39,7 @@ EDA_SHAPE::EDA_SHAPE( SHAPE_T aType, int aDefaultLineWidth ) :
|
||||
m_shape( aType ),
|
||||
m_width( aDefaultLineWidth )
|
||||
{
|
||||
m_angle = 0;
|
||||
m_arcAngle = 0;
|
||||
m_filled = false;
|
||||
}
|
||||
|
||||
@ -82,15 +82,17 @@ wxString EDA_SHAPE::SHAPE_T_asString() const
|
||||
}
|
||||
|
||||
|
||||
void EDA_SHAPE::SetShapePos( const wxPoint& aPos )
|
||||
void EDA_SHAPE::setPosition( const wxPoint& aPos )
|
||||
{
|
||||
m_start = aPos;
|
||||
move( aPos - getPosition() );
|
||||
}
|
||||
|
||||
|
||||
wxPoint EDA_SHAPE::GetShapePos() const
|
||||
wxPoint EDA_SHAPE::getPosition() const
|
||||
{
|
||||
if( m_shape == SHAPE_T::POLY )
|
||||
if( m_shape == SHAPE_T::ARC )
|
||||
return getCenter();
|
||||
else if( m_shape == SHAPE_T::POLY )
|
||||
return (wxPoint) m_poly.CVertex( 0 );
|
||||
else
|
||||
return m_start;
|
||||
@ -119,10 +121,10 @@ double EDA_SHAPE::GetLength() const
|
||||
return length;
|
||||
|
||||
case SHAPE_T::ARC:
|
||||
return 2 * M_PI * GetRadius() * ( GetAngle() / 3600.0 );
|
||||
return 2 * M_PI * GetRadius() * ( GetArcAngle() / 3600.0 );
|
||||
|
||||
default:
|
||||
wxFAIL_MSG( "EDA_SHAPE::GetLength not implemented for " + SHAPE_T_asString() );
|
||||
UNIMPLEMENTED_FOR( SHAPE_T_asString() );
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
@ -130,25 +132,24 @@ double EDA_SHAPE::GetLength() const
|
||||
|
||||
void EDA_SHAPE::move( const wxPoint& aMoveVector )
|
||||
{
|
||||
// Move vector should not affect start/end for polygon since it will
|
||||
// be applied directly to polygon outline.
|
||||
if( m_shape != SHAPE_T::POLY )
|
||||
{
|
||||
m_start += aMoveVector;
|
||||
m_end += aMoveVector;
|
||||
}
|
||||
|
||||
switch ( m_shape )
|
||||
{
|
||||
case SHAPE_T::ARC:
|
||||
case SHAPE_T::SEGMENT:
|
||||
case SHAPE_T::RECT:
|
||||
case SHAPE_T::CIRCLE:
|
||||
m_start += aMoveVector;
|
||||
m_end += aMoveVector;
|
||||
m_arcCenter += aMoveVector;
|
||||
break;
|
||||
|
||||
case SHAPE_T::POLY:
|
||||
m_poly.Move( VECTOR2I( aMoveVector ) );
|
||||
break;
|
||||
|
||||
case SHAPE_T::ARC:
|
||||
m_thirdPoint += aMoveVector;
|
||||
break;
|
||||
|
||||
case SHAPE_T::BEZIER:
|
||||
m_start += aMoveVector;
|
||||
m_end += aMoveVector;
|
||||
m_bezierC1 += aMoveVector;
|
||||
m_bezierC2 += aMoveVector;
|
||||
|
||||
@ -158,7 +159,7 @@ void EDA_SHAPE::move( const wxPoint& aMoveVector )
|
||||
break;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG( "EDA_SHAPE::ShapeMove not implemented for " + SHAPE_T_asString() );
|
||||
UNIMPLEMENTED_FOR( SHAPE_T_asString() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -174,22 +175,19 @@ void EDA_SHAPE::scale( double aScale )
|
||||
|
||||
int radius = GetRadius();
|
||||
|
||||
scalePt( m_start );
|
||||
scalePt( m_end );
|
||||
|
||||
// specific parameters:
|
||||
switch( m_shape )
|
||||
{
|
||||
case SHAPE_T::BEZIER:
|
||||
scalePt( m_bezierC1 );
|
||||
scalePt( m_bezierC2 );
|
||||
break;
|
||||
|
||||
case SHAPE_T::ARC:
|
||||
scalePt( m_thirdPoint );
|
||||
case SHAPE_T::SEGMENT:
|
||||
case SHAPE_T::RECT:
|
||||
scalePt( m_start );
|
||||
scalePt( m_end );
|
||||
scalePt( m_arcCenter );
|
||||
break;
|
||||
|
||||
case SHAPE_T::CIRCLE: // ring or circle
|
||||
scalePt( m_start );
|
||||
m_end.x = m_start.x + KiROUND( radius * aScale );
|
||||
m_end.y = m_start.y;
|
||||
break;
|
||||
@ -208,8 +206,15 @@ void EDA_SHAPE::scale( double aScale )
|
||||
}
|
||||
break;
|
||||
|
||||
case SHAPE_T::BEZIER:
|
||||
scalePt( m_start );
|
||||
scalePt( m_end );
|
||||
scalePt( m_bezierC1 );
|
||||
scalePt( m_bezierC2 );
|
||||
break;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG( "EDA_SHAPE::ShapeScale not implemented for " + SHAPE_T_asString() );
|
||||
UNIMPLEMENTED_FOR( SHAPE_T_asString() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -225,7 +230,7 @@ void EDA_SHAPE::rotate( const wxPoint& aRotCentre, double aAngle )
|
||||
// these can all be done by just rotating the constituent points
|
||||
RotatePoint( &m_start, aRotCentre, aAngle );
|
||||
RotatePoint( &m_end, aRotCentre, aAngle );
|
||||
RotatePoint( &m_thirdPoint, aRotCentre, aAngle );
|
||||
RotatePoint( &m_arcCenter, aRotCentre, aAngle );
|
||||
break;
|
||||
|
||||
case SHAPE_T::RECT:
|
||||
@ -263,7 +268,7 @@ void EDA_SHAPE::rotate( const wxPoint& aRotCentre, double aAngle )
|
||||
break;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG( "EDA_SHAPE::ShapeRotate not implemented for " + SHAPE_T_asString() );
|
||||
UNIMPLEMENTED_FOR( SHAPE_T_asString() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -271,26 +276,24 @@ void EDA_SHAPE::rotate( const wxPoint& aRotCentre, double aAngle )
|
||||
|
||||
void EDA_SHAPE::flip( const wxPoint& aCentre, bool aFlipLeftRight )
|
||||
{
|
||||
if( aFlipLeftRight )
|
||||
{
|
||||
m_start.x = aCentre.x - ( m_start.x - aCentre.x );
|
||||
m_end.x = aCentre.x - ( m_end.x - aCentre.x );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_start.y = aCentre.y - ( m_start.y - aCentre.y );
|
||||
m_end.y = aCentre.y - ( m_end.y - aCentre.y );
|
||||
}
|
||||
|
||||
switch ( m_shape )
|
||||
{
|
||||
case SHAPE_T::SEGMENT:
|
||||
case SHAPE_T::RECT:
|
||||
case SHAPE_T::CIRCLE:
|
||||
case SHAPE_T::ARC:
|
||||
if( aFlipLeftRight )
|
||||
m_thirdPoint.x = aCentre.x - ( m_thirdPoint.x - aCentre.x );
|
||||
{
|
||||
m_start.x = aCentre.x - ( m_start.x - aCentre.x );
|
||||
m_end.x = aCentre.x - ( m_end.x - aCentre.x );
|
||||
m_arcCenter.x = aCentre.x - ( m_arcCenter.x - aCentre.x );
|
||||
}
|
||||
else
|
||||
m_thirdPoint.y = aCentre.y - ( m_thirdPoint.y - aCentre.y );
|
||||
|
||||
m_angle = -m_angle;
|
||||
{
|
||||
m_start.y = aCentre.y - ( m_start.y - aCentre.y );
|
||||
m_end.y = aCentre.y - ( m_end.y - aCentre.y );
|
||||
m_arcCenter.y = aCentre.y - ( m_arcCenter.y - aCentre.y );
|
||||
}
|
||||
break;
|
||||
|
||||
case SHAPE_T::POLY:
|
||||
@ -301,11 +304,15 @@ void EDA_SHAPE::flip( const wxPoint& aCentre, bool aFlipLeftRight )
|
||||
{
|
||||
if( aFlipLeftRight )
|
||||
{
|
||||
m_start.x = aCentre.x - ( m_start.x - aCentre.x );
|
||||
m_end.x = aCentre.x - ( m_end.x - aCentre.x );
|
||||
m_bezierC1.x = aCentre.x - ( m_bezierC1.x - aCentre.x );
|
||||
m_bezierC2.x = aCentre.x - ( m_bezierC2.x - aCentre.x );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_start.y = aCentre.y - ( m_start.y - aCentre.y );
|
||||
m_end.y = aCentre.y - ( m_end.y - aCentre.y );
|
||||
m_bezierC1.y = aCentre.y - ( m_bezierC1.y - aCentre.y );
|
||||
m_bezierC2.y = aCentre.y - ( m_bezierC2.y - aCentre.y );
|
||||
}
|
||||
@ -317,13 +324,8 @@ void EDA_SHAPE::flip( const wxPoint& aCentre, bool aFlipLeftRight )
|
||||
}
|
||||
break;
|
||||
|
||||
case SHAPE_T::SEGMENT:
|
||||
case SHAPE_T::RECT:
|
||||
case SHAPE_T::CIRCLE:
|
||||
break;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG( "EDA_SHAPE::ShapeFlip not implemented for " + SHAPE_T_asString() );
|
||||
UNIMPLEMENTED_FOR( SHAPE_T_asString() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -358,78 +360,59 @@ const std::vector<wxPoint> EDA_SHAPE::buildBezierToSegmentsPointsList( int aMinS
|
||||
|
||||
wxPoint EDA_SHAPE::getCenter() const
|
||||
{
|
||||
wxPoint c;
|
||||
|
||||
switch( m_shape )
|
||||
{
|
||||
case SHAPE_T::ARC:
|
||||
return m_arcCenter;
|
||||
|
||||
case SHAPE_T::CIRCLE:
|
||||
c = m_start;
|
||||
break;
|
||||
return m_start;
|
||||
|
||||
case SHAPE_T::SEGMENT:
|
||||
// Midpoint of the line
|
||||
c = ( GetStart() + GetEnd() ) / 2;
|
||||
break;
|
||||
return ( m_start + m_end ) / 2;
|
||||
|
||||
case SHAPE_T::POLY:
|
||||
case SHAPE_T::RECT:
|
||||
case SHAPE_T::BEZIER:
|
||||
c = getBoundingBox().Centre();
|
||||
break;
|
||||
return getBoundingBox().Centre();
|
||||
|
||||
default:
|
||||
wxFAIL_MSG( "EDA_SHAPE::GetCentre not implemented for " + SHAPE_T_asString() );
|
||||
break;
|
||||
UNIMPLEMENTED_FOR( SHAPE_T_asString() );
|
||||
return wxPoint();
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
wxPoint EDA_SHAPE::GetArcEnd() const
|
||||
void EDA_SHAPE::SetCenter( const wxPoint& aCenter )
|
||||
{
|
||||
wxPoint endPoint( m_end ); // start of arc
|
||||
|
||||
switch( m_shape )
|
||||
{
|
||||
case SHAPE_T::ARC:
|
||||
endPoint = m_thirdPoint;
|
||||
m_arcCenter = aCenter;
|
||||
break;
|
||||
|
||||
case SHAPE_T::CIRCLE:
|
||||
m_start = aCenter;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
UNIMPLEMENTED_FOR( SHAPE_T_asString() );
|
||||
}
|
||||
|
||||
return endPoint; // after rotation, the end of the arc.
|
||||
}
|
||||
|
||||
|
||||
wxPoint EDA_SHAPE::GetArcMid() const
|
||||
{
|
||||
wxPoint endPoint( m_end );
|
||||
|
||||
switch( m_shape )
|
||||
{
|
||||
case SHAPE_T::ARC:
|
||||
// rotate the starting point of the arc, given by m_End, through half
|
||||
// the angle m_Angle to get the middle of the arc.
|
||||
// m_Start is the arc centre
|
||||
endPoint = m_end; // m_End = start point of arc
|
||||
RotatePoint( &endPoint, m_start, -m_angle / 2.0 );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return endPoint; // after rotation, the end of the arc.
|
||||
wxPoint mid = m_start;
|
||||
RotatePoint( &mid, m_arcCenter, -m_arcAngle / 2.0 );
|
||||
return mid;
|
||||
}
|
||||
|
||||
|
||||
double EDA_SHAPE::GetArcAngleStart() const
|
||||
{
|
||||
wxPoint arcStart = GetArcStart();
|
||||
wxPoint arcStart = GetStart();
|
||||
wxPoint center = getCenter();
|
||||
double angleStart = ArcTangente( arcStart.y - center.y, arcStart.x - center.x );
|
||||
|
||||
@ -441,9 +424,10 @@ double EDA_SHAPE::GetArcAngleStart() const
|
||||
return angleStart;
|
||||
}
|
||||
|
||||
|
||||
double EDA_SHAPE::GetArcAngleEnd() const
|
||||
{
|
||||
wxPoint arcEnd = GetArcEnd();
|
||||
wxPoint arcEnd = GetEnd();
|
||||
wxPoint center = getCenter();
|
||||
double angleStart = ArcTangente( arcEnd.y - center.y, arcEnd.x - center.x );
|
||||
|
||||
@ -458,46 +442,60 @@ double EDA_SHAPE::GetArcAngleEnd() const
|
||||
|
||||
int EDA_SHAPE::GetRadius() const
|
||||
{
|
||||
double radius = GetLineLength( m_start, m_end );
|
||||
double radius = 0.0;
|
||||
|
||||
// don't allow degenerate arcs
|
||||
switch( m_shape )
|
||||
{
|
||||
case SHAPE_T::ARC:
|
||||
radius = GetLineLength( m_arcCenter, m_start );
|
||||
break;
|
||||
|
||||
case SHAPE_T::CIRCLE:
|
||||
radius = GetLineLength( m_start, m_end );
|
||||
break;
|
||||
|
||||
default:
|
||||
UNIMPLEMENTED_FOR( SHAPE_T_asString() );
|
||||
}
|
||||
|
||||
// don't allow degenerate circles/arcs
|
||||
return std::max( 1, KiROUND( radius ) );
|
||||
}
|
||||
|
||||
|
||||
void EDA_SHAPE::SetArcGeometry( const wxPoint& aStart, const wxPoint& aMid, const wxPoint& aEnd )
|
||||
{
|
||||
SetArcStart( aStart );
|
||||
SetArcEnd( aEnd );
|
||||
m_start = aStart;
|
||||
m_end = aEnd;
|
||||
m_arcCenter = CalcArcCenter( aStart, aMid, aEnd );
|
||||
|
||||
// Sadly we currently store center and angle rather than mid. So we have to calculate
|
||||
// those.
|
||||
wxPoint center = GetArcCenter( aStart, aMid, aEnd );
|
||||
VECTOR2D startLine = aStart - center;
|
||||
VECTOR2D endLine = aEnd - center;
|
||||
bool clockwise = GetAngle() > 0;
|
||||
double angle = RAD2DECIDEG( endLine.Angle() - startLine.Angle() );
|
||||
VECTOR2D startLine = m_start - m_arcCenter;
|
||||
VECTOR2D endLine = aEnd - m_arcCenter;
|
||||
bool clockwise = m_arcAngle > 0;
|
||||
|
||||
if( clockwise && angle < 0.0 )
|
||||
angle += 3600.0;
|
||||
else if( !clockwise && angle > 0.0 )
|
||||
angle -= 3600.0;
|
||||
m_arcAngle = RAD2DECIDEG( endLine.Angle() - startLine.Angle() );
|
||||
|
||||
SetAngle( angle, false );
|
||||
SetArcCenter( center );
|
||||
if( clockwise && m_arcAngle < 0.0 )
|
||||
m_arcAngle += 3600.0;
|
||||
else if( !clockwise && m_arcAngle > 0.0 )
|
||||
m_arcAngle -= 3600.0;
|
||||
}
|
||||
|
||||
|
||||
void EDA_SHAPE::SetAngle( double aAngle, bool aUpdateEnd )
|
||||
void EDA_SHAPE::SetArcAngle( double aAngle )
|
||||
{
|
||||
// m_Angle must be >= -360 and <= +360 degrees
|
||||
m_angle = NormalizeAngle360Max( aAngle );
|
||||
m_arcAngle = NormalizeAngle360Max( aAngle );
|
||||
}
|
||||
|
||||
if( aUpdateEnd )
|
||||
{
|
||||
m_thirdPoint = m_end;
|
||||
RotatePoint( &m_thirdPoint, m_start, -m_angle );
|
||||
}
|
||||
|
||||
void EDA_SHAPE::SetArcAngleAndEnd( double aAngle )
|
||||
{
|
||||
// m_Angle must be >= -360 and <= +360 degrees
|
||||
m_arcAngle = NormalizeAngle360Max( aAngle );
|
||||
|
||||
m_end = m_start;
|
||||
RotatePoint( &m_end, m_arcCenter, -m_arcAngle );
|
||||
}
|
||||
|
||||
|
||||
@ -514,17 +512,17 @@ void EDA_SHAPE::ShapeGetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PA
|
||||
case SHAPE_T::CIRCLE:
|
||||
aList.emplace_back( shape, _( "Circle" ) );
|
||||
|
||||
msg = MessageTextFromValue( units, GetLineLength( m_start, m_end ) );
|
||||
msg = MessageTextFromValue( units, GetLineLength( GetStart(), GetEnd() ) );
|
||||
aList.emplace_back( _( "Radius" ), msg );
|
||||
break;
|
||||
|
||||
case SHAPE_T::ARC:
|
||||
aList.emplace_back( shape, _( "Arc" ) );
|
||||
|
||||
msg.Printf( wxT( "%.1f" ), m_angle / 10.0 );
|
||||
msg.Printf( wxT( "%.1f" ), m_arcAngle / 10.0 );
|
||||
aList.emplace_back( _( "Angle" ), msg );
|
||||
|
||||
msg = MessageTextFromValue( units, GetLineLength( m_start, m_end ) );
|
||||
msg = MessageTextFromValue( units, GetLineLength( getCenter(), GetStart() ) );
|
||||
aList.emplace_back( _( "Radius" ), msg );
|
||||
break;
|
||||
|
||||
@ -545,10 +543,10 @@ void EDA_SHAPE::ShapeGetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PA
|
||||
case SHAPE_T::RECT:
|
||||
aList.emplace_back( shape, _( "Rectangle" ) );
|
||||
|
||||
msg = MessageTextFromValue( units, std::abs( m_end.x - m_start.x ) );
|
||||
msg = MessageTextFromValue( units, std::abs( GetEnd().x - GetStart().x ) );
|
||||
aList.emplace_back( _( "Width" ), msg );
|
||||
|
||||
msg = MessageTextFromValue( units, std::abs( m_end.y - m_start.y ) );
|
||||
msg = MessageTextFromValue( units, std::abs( GetEnd().y - GetStart().y ) );
|
||||
aList.emplace_back( _( "Height" ), msg );
|
||||
break;
|
||||
|
||||
@ -556,12 +554,12 @@ void EDA_SHAPE::ShapeGetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PA
|
||||
{
|
||||
aList.emplace_back( shape, _( "Segment" ) );
|
||||
|
||||
msg = MessageTextFromValue( units, GetLineLength( m_start, m_end ) );
|
||||
msg = MessageTextFromValue( units, GetLineLength( GetStart(), GetEnd() ) );
|
||||
aList.emplace_back( _( "Length" ), msg );
|
||||
|
||||
// angle counter-clockwise from 3'o-clock
|
||||
const double deg = RAD2DEG( atan2( (double)( m_start.y - m_end.y ),
|
||||
(double)( m_end.x - m_start.x ) ) );
|
||||
const double deg = RAD2DEG( atan2( (double)( GetStart().y - GetEnd().y ),
|
||||
(double)( GetEnd().x - GetStart().x ) ) );
|
||||
aList.emplace_back( _( "Angle" ), wxString::Format( "%.1f", deg ) );
|
||||
}
|
||||
break;
|
||||
@ -579,23 +577,21 @@ const EDA_RECT EDA_SHAPE::getBoundingBox() const
|
||||
{
|
||||
EDA_RECT bbox;
|
||||
|
||||
bbox.SetOrigin( m_start );
|
||||
|
||||
switch( m_shape )
|
||||
{
|
||||
case SHAPE_T::RECT:
|
||||
bbox = EDA_RECT(); // re-init for merging
|
||||
|
||||
for( wxPoint& pt : GetRectCorners() )
|
||||
bbox.Merge( pt );
|
||||
|
||||
break;
|
||||
|
||||
case SHAPE_T::SEGMENT:
|
||||
bbox.SetEnd( m_end );
|
||||
bbox.SetOrigin( GetStart() );
|
||||
bbox.SetEnd( GetEnd() );
|
||||
break;
|
||||
|
||||
case SHAPE_T::CIRCLE:
|
||||
bbox.SetOrigin( GetStart() );
|
||||
bbox.Inflate( GetRadius() );
|
||||
break;
|
||||
|
||||
@ -607,8 +603,6 @@ const EDA_RECT EDA_SHAPE::getBoundingBox() const
|
||||
if( m_poly.IsEmpty() )
|
||||
break;
|
||||
|
||||
bbox = EDA_RECT(); // re-init for merging
|
||||
|
||||
for( auto iter = m_poly.CIterate(); iter; iter++ )
|
||||
{
|
||||
wxPoint pt( iter->x, iter->y );
|
||||
@ -622,13 +616,14 @@ const EDA_RECT EDA_SHAPE::getBoundingBox() const
|
||||
break;
|
||||
|
||||
case SHAPE_T::BEZIER:
|
||||
bbox.Merge( m_bezierC1 );
|
||||
bbox.Merge( m_bezierC2 );
|
||||
bbox.Merge( m_end );
|
||||
bbox.SetOrigin( GetStart() );
|
||||
bbox.Merge( GetBezierC1() );
|
||||
bbox.Merge( GetBezierC2() );
|
||||
bbox.Merge( GetEnd() );
|
||||
break;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG( "EDA_SHAPE::getBoundingBox not implemented for " + SHAPE_T_asString() );
|
||||
UNIMPLEMENTED_FOR( SHAPE_T_asString() );
|
||||
break;
|
||||
}
|
||||
|
||||
@ -682,10 +677,10 @@ bool EDA_SHAPE::hitTest( const wxPoint& aPosition, int aAccuracy ) const
|
||||
|
||||
// Check angle: inside the arc angle when it is > 0 and outside the not drawn arc when
|
||||
// it is < 0
|
||||
if( GetAngle() >= 0.0 )
|
||||
return arc_hittest <= GetAngle();
|
||||
if( GetArcAngle() >= 0.0 )
|
||||
return arc_hittest <= GetArcAngle();
|
||||
else
|
||||
return arc_hittest >= ( 3600.0 + GetAngle() );
|
||||
return arc_hittest >= ( 3600.0 + GetArcAngle() );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -705,7 +700,7 @@ bool EDA_SHAPE::hitTest( const wxPoint& aPosition, int aAccuracy ) const
|
||||
return false;
|
||||
|
||||
case SHAPE_T::SEGMENT:
|
||||
return TestSegmentHit( aPosition, m_start, m_end, maxdist );
|
||||
return TestSegmentHit( aPosition, GetStart(), GetEnd(), maxdist );
|
||||
|
||||
case SHAPE_T::RECT:
|
||||
if( IsFilled() ) // Filled rect hit-test
|
||||
@ -903,7 +898,7 @@ bool EDA_SHAPE::hitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy )
|
||||
}
|
||||
|
||||
default:
|
||||
wxFAIL_MSG( "EDA_SHAPE::hitTest(rect) not implemented for " + SHAPE_T_asString() );
|
||||
UNIMPLEMENTED_FOR( SHAPE_T_asString() );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -949,11 +944,8 @@ void EDA_SHAPE::computeArcBBox( EDA_RECT& aBBox ) const
|
||||
{
|
||||
// Do not include the center, which is not necessarily
|
||||
// inside the BB of a arc with a small angle
|
||||
aBBox.SetOrigin( m_end );
|
||||
|
||||
wxPoint end = m_end;
|
||||
RotatePoint( &end, m_start, -m_angle );
|
||||
aBBox.Merge( end );
|
||||
aBBox.SetOrigin( m_start );
|
||||
aBBox.Merge( m_end );
|
||||
|
||||
// Determine the starting quarter
|
||||
// 0 right-bottom
|
||||
@ -962,24 +954,24 @@ void EDA_SHAPE::computeArcBBox( EDA_RECT& aBBox ) const
|
||||
// 3 right-top
|
||||
unsigned int quarter = 0; // assume right-bottom
|
||||
|
||||
if( m_end.x < m_start.x )
|
||||
if( m_start.x < m_arcCenter.x )
|
||||
{
|
||||
if( m_end.y <= m_start.y )
|
||||
if( m_start.y <= m_arcCenter.y )
|
||||
quarter = 2;
|
||||
else // ( m_End.y > m_Start.y )
|
||||
else // ( m_start.y > m_arcCenter.y )
|
||||
quarter = 1;
|
||||
}
|
||||
else if( m_end.x >= m_start.x )
|
||||
else if( m_start.x >= m_arcCenter.x )
|
||||
{
|
||||
if( m_end.y < m_start.y )
|
||||
if( m_start.y < m_arcCenter.y )
|
||||
quarter = 3;
|
||||
else if( m_end.x == m_start.x )
|
||||
else if( m_start.x == m_arcCenter.x )
|
||||
quarter = 1;
|
||||
}
|
||||
|
||||
int radius = GetRadius();
|
||||
int angle = (int) GetArcAngleStart() % 900 + m_angle;
|
||||
bool directionCW = ( m_angle > 0 ); // Is the direction of arc clockwise?
|
||||
int angle = (int) GetArcAngleStart() % 900 + m_arcAngle;
|
||||
bool directionCW = ( m_arcAngle > 0 ); // Is the direction of arc clockwise?
|
||||
|
||||
// Make the angle positive, so we go clockwise and merge points belonging to the arc
|
||||
if( !directionCW )
|
||||
@ -992,10 +984,10 @@ void EDA_SHAPE::computeArcBBox( EDA_RECT& aBBox ) const
|
||||
{
|
||||
switch( quarter )
|
||||
{
|
||||
case 0: aBBox.Merge( wxPoint( m_start.x, m_start.y + radius ) ); break; // down
|
||||
case 1: aBBox.Merge( wxPoint( m_start.x - radius, m_start.y ) ); break; // left
|
||||
case 2: aBBox.Merge( wxPoint( m_start.x, m_start.y - radius ) ); break; // up
|
||||
case 3: aBBox.Merge( wxPoint( m_start.x + radius, m_start.y ) ); break; // right
|
||||
case 0: aBBox.Merge( wxPoint( m_arcCenter.x, m_arcCenter.y + radius ) ); break; // down
|
||||
case 1: aBBox.Merge( wxPoint( m_arcCenter.x - radius, m_arcCenter.y ) ); break; // left
|
||||
case 2: aBBox.Merge( wxPoint( m_arcCenter.x, m_arcCenter.y - radius ) ); break; // up
|
||||
case 3: aBBox.Merge( wxPoint( m_arcCenter.x + radius, m_arcCenter.y ) ); break; // right
|
||||
}
|
||||
|
||||
if( directionCW )
|
||||
@ -1030,12 +1022,12 @@ std::vector<SHAPE*> EDA_SHAPE::MakeEffectiveShapes() const
|
||||
switch( m_shape )
|
||||
{
|
||||
case SHAPE_T::ARC:
|
||||
effectiveShapes.emplace_back( new SHAPE_ARC( getCenter(), GetArcStart(),
|
||||
GetAngle() / 10.0, m_width ) );
|
||||
effectiveShapes.emplace_back( new SHAPE_ARC( m_arcCenter, m_start, m_arcAngle / 10.0,
|
||||
m_width ) );
|
||||
break;
|
||||
|
||||
case SHAPE_T::SEGMENT:
|
||||
effectiveShapes.emplace_back( new SHAPE_SEGMENT( GetStart(), GetEnd(), m_width ) );
|
||||
effectiveShapes.emplace_back( new SHAPE_SEGMENT( m_start, m_end, m_width ) );
|
||||
break;
|
||||
|
||||
case SHAPE_T::RECT:
|
||||
@ -1068,8 +1060,8 @@ std::vector<SHAPE*> EDA_SHAPE::MakeEffectiveShapes() const
|
||||
|
||||
for( int i = 0; i < l.SegmentCount(); i++ )
|
||||
{
|
||||
effectiveShapes.emplace_back( new SHAPE_SEGMENT( l.Segment( i ).A,
|
||||
l.Segment( i ).B, m_width ) );
|
||||
effectiveShapes.emplace_back( new SHAPE_SEGMENT( l.Segment( i ).A, l.Segment( i ).B,
|
||||
m_width ) );
|
||||
}
|
||||
}
|
||||
|
||||
@ -1110,7 +1102,7 @@ std::vector<SHAPE*> EDA_SHAPE::MakeEffectiveShapes() const
|
||||
break;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG( "EDA_SHAPE::MakeEffectiveShapes not implemented for " + SHAPE_T_asString() );
|
||||
UNIMPLEMENTED_FOR( SHAPE_T_asString() );
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1166,9 +1158,9 @@ void EDA_SHAPE::SwapShape( EDA_SHAPE* aImage )
|
||||
std::swap( m_width, image->m_width );
|
||||
std::swap( m_start, image->m_start );
|
||||
std::swap( m_end, image->m_end );
|
||||
std::swap( m_thirdPoint, image->m_thirdPoint );
|
||||
std::swap( m_arcCenter, image->m_arcCenter );
|
||||
std::swap( m_shape, image->m_shape );
|
||||
std::swap( m_angle, image->m_angle );
|
||||
std::swap( m_arcAngle, image->m_arcAngle );
|
||||
std::swap( m_bezierC1, image->m_bezierC1 );
|
||||
std::swap( m_bezierC2, image->m_bezierC2 );
|
||||
std::swap( m_bezierPoints, image->m_bezierPoints );
|
||||
@ -1184,11 +1176,11 @@ int EDA_SHAPE::Compare( const EDA_SHAPE* aOther ) const
|
||||
TEST_PT( m_start, aOther->m_start );
|
||||
TEST_PT( m_end, aOther->m_end );
|
||||
|
||||
TEST( (int) m_shape, (int) aOther->m_shape );
|
||||
TEST( m_shape, aOther->m_shape );
|
||||
|
||||
if( m_shape == SHAPE_T::ARC )
|
||||
{
|
||||
TEST_PT( m_thirdPoint, aOther->m_thirdPoint );
|
||||
TEST_PT( m_arcCenter, aOther->m_arcCenter );
|
||||
}
|
||||
else if( m_shape == SHAPE_T::BEZIER )
|
||||
{
|
||||
@ -1198,11 +1190,14 @@ int EDA_SHAPE::Compare( const EDA_SHAPE* aOther ) const
|
||||
else if( m_shape == SHAPE_T::POLY )
|
||||
{
|
||||
TEST( m_poly.TotalVertices(), aOther->m_poly.TotalVertices() );
|
||||
|
||||
for( int ii = 0; ii < m_poly.TotalVertices(); ++ii )
|
||||
TEST_PT( m_poly.CVertex( ii ), aOther->m_poly.CVertex( ii ) );
|
||||
}
|
||||
|
||||
for( size_t ii = 0; ii < m_bezierPoints.size(); ++ii )
|
||||
TEST_PT( m_bezierPoints[ii], aOther->m_bezierPoints[ii] );
|
||||
|
||||
for( int ii = 0; ii < m_poly.TotalVertices(); ++ii )
|
||||
TEST_PT( m_poly.CVertex( ii ), aOther->m_poly.CVertex( ii ) );
|
||||
|
||||
TEST( m_width, aOther->m_width );
|
||||
|
||||
return 0;
|
||||
|
@ -138,33 +138,44 @@ size_t hash_fp_item( const EDA_ITEM* aItem, int aFlags )
|
||||
|
||||
case PCB_FP_SHAPE_T:
|
||||
{
|
||||
const FP_SHAPE* segment = static_cast<const FP_SHAPE*>( aItem );
|
||||
ret = hash_board_item( segment, aFlags );
|
||||
hash_combine( ret, segment->GetShape() );
|
||||
hash_combine( ret, segment->GetWidth() );
|
||||
hash_combine( ret, segment->IsFilled() );
|
||||
hash_combine( ret, segment->GetRadius() );
|
||||
const FP_SHAPE* shape = static_cast<const FP_SHAPE*>( aItem );
|
||||
ret = hash_board_item( shape, aFlags );
|
||||
hash_combine( ret, shape->GetShape() );
|
||||
hash_combine( ret, shape->GetWidth() );
|
||||
hash_combine( ret, shape->IsFilled() );
|
||||
hash_combine( ret, shape->GetRadius() );
|
||||
|
||||
if( aFlags & HASH_POS )
|
||||
{
|
||||
if( aFlags & REL_COORD )
|
||||
{
|
||||
hash_combine( ret, segment->GetStart0().x );
|
||||
hash_combine( ret, segment->GetStart0().y );
|
||||
hash_combine( ret, segment->GetEnd0().x );
|
||||
hash_combine( ret, segment->GetEnd0().y );
|
||||
hash_combine( ret, shape->GetStart0().x );
|
||||
hash_combine( ret, shape->GetStart0().y );
|
||||
hash_combine( ret, shape->GetEnd0().x );
|
||||
hash_combine( ret, shape->GetEnd0().y );
|
||||
|
||||
if( shape->GetShape() == SHAPE_T::ARC )
|
||||
{
|
||||
hash_combine( ret, shape->GetCenter0().x );
|
||||
hash_combine( ret, shape->GetCenter0().y );
|
||||
hash_combine( ret, shape->GetArcAngle() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hash_combine( ret, segment->GetStart().x );
|
||||
hash_combine( ret, segment->GetStart().y );
|
||||
hash_combine( ret, segment->GetEnd().x );
|
||||
hash_combine( ret, segment->GetEnd().y );
|
||||
hash_combine( ret, shape->GetStart().x );
|
||||
hash_combine( ret, shape->GetStart().y );
|
||||
hash_combine( ret, shape->GetEnd().x );
|
||||
hash_combine( ret, shape->GetEnd().y );
|
||||
|
||||
if( shape->GetShape() == SHAPE_T::ARC )
|
||||
{
|
||||
hash_combine( ret, shape->GetCenter().x );
|
||||
hash_combine( ret, shape->GetCenter().y );
|
||||
hash_combine( ret, shape->GetArcAngle() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( aFlags & HASH_ROT )
|
||||
hash_combine( ret, segment->GetAngle() );
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -46,9 +46,6 @@ static inline wxPoint twoPointVector( const wxPoint &startPoint, const wxPoint &
|
||||
|
||||
LIB_ARC::LIB_ARC( LIB_SYMBOL* aParent ) : LIB_ITEM( LIB_ARC_T, aParent )
|
||||
{
|
||||
m_Radius = 0;
|
||||
m_t1 = 0;
|
||||
m_t2 = 0;
|
||||
m_Width = 0;
|
||||
m_fill = FILL_TYPE::NO_FILL;
|
||||
m_isFillable = true;
|
||||
@ -56,6 +53,12 @@ LIB_ARC::LIB_ARC( LIB_SYMBOL* aParent ) : LIB_ITEM( LIB_ARC_T, aParent )
|
||||
}
|
||||
|
||||
|
||||
int LIB_ARC::GetRadius() const
|
||||
{
|
||||
return KiROUND( GetLineLength( GetCenter(), GetStart() ) );
|
||||
}
|
||||
|
||||
|
||||
bool LIB_ARC::HitTest( const wxPoint& aRefPoint, int aAccuracy ) const
|
||||
{
|
||||
int mindist = std::max( aAccuracy + GetPenWidth() / 2,
|
||||
@ -66,7 +69,7 @@ bool LIB_ARC::HitTest( const wxPoint& aRefPoint, int aAccuracy ) const
|
||||
|
||||
int distance = KiROUND( GetLineLength( m_Pos, relativePosition ) );
|
||||
|
||||
if( abs( distance - m_Radius ) > mindist )
|
||||
if( abs( distance - GetRadius() ) > mindist )
|
||||
return false;
|
||||
|
||||
// We are on the circle, ensure we are only on the arc, i.e. between
|
||||
@ -147,12 +150,6 @@ int LIB_ARC::compare( const LIB_ITEM& aOther, LIB_ITEM::COMPARE_FLAGS aCompareFl
|
||||
if( m_Pos.y != tmp->m_Pos.y )
|
||||
return m_Pos.y - tmp->m_Pos.y;
|
||||
|
||||
if( m_t1 != tmp->m_t1 )
|
||||
return m_t1 - tmp->m_t1;
|
||||
|
||||
if( m_t2 != tmp->m_t2 )
|
||||
return m_t2 - tmp->m_t2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -186,20 +183,6 @@ void LIB_ARC::MirrorHorizontal( const wxPoint& aCenter )
|
||||
m_ArcEnd.x *= -1;
|
||||
m_ArcEnd.x += aCenter.x;
|
||||
std::swap( m_ArcStart, m_ArcEnd );
|
||||
std::swap( m_t1, m_t2 );
|
||||
m_t1 = 1800 - m_t1;
|
||||
m_t2 = 1800 - m_t2;
|
||||
|
||||
if( m_t1 > 3600 || m_t2 > 3600 )
|
||||
{
|
||||
m_t1 -= 3600;
|
||||
m_t2 -= 3600;
|
||||
}
|
||||
else if( m_t1 < -3600 || m_t2 < -3600 )
|
||||
{
|
||||
m_t1 += 3600;
|
||||
m_t2 += 3600;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -215,20 +198,6 @@ void LIB_ARC::MirrorVertical( const wxPoint& aCenter )
|
||||
m_ArcEnd.y *= -1;
|
||||
m_ArcEnd.y += aCenter.y;
|
||||
std::swap( m_ArcStart, m_ArcEnd );
|
||||
std::swap( m_t1, m_t2 );
|
||||
m_t1 = - m_t1;
|
||||
m_t2 = - m_t2;
|
||||
|
||||
if( m_t1 > 3600 || m_t2 > 3600 )
|
||||
{
|
||||
m_t1 -= 3600;
|
||||
m_t2 -= 3600;
|
||||
}
|
||||
else if( m_t1 < -3600 || m_t2 < -3600 )
|
||||
{
|
||||
m_t1 += 3600;
|
||||
m_t2 += 3600;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -238,19 +207,6 @@ void LIB_ARC::Rotate( const wxPoint& aCenter, bool aRotateCCW )
|
||||
RotatePoint( &m_Pos, aCenter, rot_angle );
|
||||
RotatePoint( &m_ArcStart, aCenter, rot_angle );
|
||||
RotatePoint( &m_ArcEnd, aCenter, rot_angle );
|
||||
m_t1 -= rot_angle;
|
||||
m_t2 -= rot_angle;
|
||||
|
||||
if( m_t1 > 3600 || m_t2 > 3600 )
|
||||
{
|
||||
m_t1 -= 3600;
|
||||
m_t2 -= 3600;
|
||||
}
|
||||
else if( m_t1 < -3600 || m_t2 < -3600 )
|
||||
{
|
||||
m_t1 += 3600;
|
||||
m_t2 += 3600;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -259,27 +215,30 @@ void LIB_ARC::Plot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
|
||||
{
|
||||
wxASSERT( aPlotter != nullptr );
|
||||
|
||||
int t1 = m_t1;
|
||||
int t2 = m_t2;
|
||||
wxPoint pos = aTransform.TransformCoordinate( m_Pos ) + aOffset;
|
||||
wxPoint center = aTransform.TransformCoordinate( GetCenter() ) + aOffset;
|
||||
int startAngle;
|
||||
int endAngle;
|
||||
int pen_size = GetEffectivePenWidth( aPlotter->RenderSettings() );
|
||||
FILL_TYPE fill = aFill ? m_fill : FILL_TYPE::NO_FILL;
|
||||
|
||||
aTransform.MapAngles( &t1, &t2 );
|
||||
CalcAngles( startAngle, endAngle );
|
||||
aTransform.MapAngles( &startAngle, &endAngle );
|
||||
|
||||
if( aFill && m_fill == FILL_TYPE::FILLED_WITH_BG_BODYCOLOR )
|
||||
if( fill == FILL_TYPE::FILLED_WITH_BG_BODYCOLOR )
|
||||
{
|
||||
aPlotter->SetColor( aPlotter->RenderSettings()->GetLayerColor( LAYER_DEVICE_BACKGROUND ) );
|
||||
aPlotter->Arc( pos, -t2, -t1, m_Radius, FILL_TYPE::FILLED_WITH_BG_BODYCOLOR, 0 );
|
||||
aPlotter->Arc( center, -endAngle, -startAngle, GetRadius(), fill, 0 );
|
||||
|
||||
if( pen_size <= 0 )
|
||||
return;
|
||||
else
|
||||
fill = FILL_TYPE::NO_FILL;
|
||||
}
|
||||
|
||||
bool already_filled = m_fill == FILL_TYPE::FILLED_WITH_BG_BODYCOLOR;
|
||||
int pen_size = GetEffectivePenWidth( aPlotter->RenderSettings() );
|
||||
pen_size = std::max( pen_size, aPlotter->RenderSettings()->GetMinPenWidth() );
|
||||
|
||||
if( !already_filled || pen_size > 0 )
|
||||
{
|
||||
aPlotter->SetColor( aPlotter->RenderSettings()->GetLayerColor( LAYER_DEVICE ) );
|
||||
aPlotter->Arc( pos, -t2, -t1, m_Radius, already_filled ? FILL_TYPE::NO_FILL : m_fill,
|
||||
pen_size );
|
||||
}
|
||||
aPlotter->SetColor( aPlotter->RenderSettings()->GetLayerColor( LAYER_DEVICE ) );
|
||||
aPlotter->Arc( center, -endAngle, -startAngle, GetRadius(), fill, pen_size );
|
||||
}
|
||||
|
||||
|
||||
@ -305,15 +264,12 @@ void LIB_ARC::print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset, v
|
||||
pos1 = aTransform.TransformCoordinate( m_ArcEnd ) + aOffset;
|
||||
pos2 = aTransform.TransformCoordinate( m_ArcStart ) + aOffset;
|
||||
posc = aTransform.TransformCoordinate( m_Pos ) + aOffset;
|
||||
int pt1 = m_t1;
|
||||
int pt2 = m_t2;
|
||||
bool swap = aTransform.MapAngles( &pt1, &pt2 );
|
||||
|
||||
if( swap )
|
||||
{
|
||||
std::swap( pos1.x, pos2.x );
|
||||
std::swap( pos1.y, pos2.y );
|
||||
}
|
||||
int t1;
|
||||
int t2;
|
||||
|
||||
CalcAngles( t1, t2 );
|
||||
aTransform.MapAngles( &t1, &t2 );
|
||||
|
||||
if( forceNoFill || m_fill == FILL_TYPE::NO_FILL )
|
||||
{
|
||||
@ -324,33 +280,29 @@ void LIB_ARC::print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset, v
|
||||
if( m_fill == FILL_TYPE::FILLED_WITH_BG_BODYCOLOR )
|
||||
color = aSettings->GetLayerColor( LAYER_DEVICE_BACKGROUND );
|
||||
|
||||
GRFilledArc( nullptr, DC, posc.x, posc.y, pt1, pt2, m_Radius, penWidth, color, color );
|
||||
GRFilledArc( nullptr, DC, posc.x, posc.y, t1, t2, GetRadius(), penWidth, color, color );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const EDA_RECT LIB_ARC::GetBoundingBox() const
|
||||
{
|
||||
int radius = GetRadius();
|
||||
int minX, minY, maxX, maxY, angleStart, angleEnd;
|
||||
EDA_RECT rect;
|
||||
wxPoint nullPoint, startPos, endPos, centerPos;
|
||||
wxPoint normStart = m_ArcStart - m_Pos;
|
||||
wxPoint normEnd = m_ArcEnd - m_Pos;
|
||||
|
||||
if( ( normStart == nullPoint ) || ( normEnd == nullPoint ) || ( m_Radius == 0 ) )
|
||||
if( normStart == nullPoint || normEnd == nullPoint || radius == 0 )
|
||||
return rect;
|
||||
|
||||
endPos = DefaultTransform.TransformCoordinate( m_ArcEnd );
|
||||
startPos = DefaultTransform.TransformCoordinate( m_ArcStart );
|
||||
centerPos = DefaultTransform.TransformCoordinate( m_Pos );
|
||||
angleStart = m_t1;
|
||||
angleEnd = m_t2;
|
||||
|
||||
if( DefaultTransform.MapAngles( &angleStart, &angleEnd ) )
|
||||
{
|
||||
std::swap( endPos.x, startPos.x );
|
||||
std::swap( endPos.y, startPos.y );
|
||||
}
|
||||
CalcAngles( angleStart, angleEnd );
|
||||
DefaultTransform.MapAngles( &angleStart, &angleEnd );
|
||||
|
||||
/* Start with the start and end point of the arc. */
|
||||
minX = std::min( startPos.x, endPos.x );
|
||||
@ -360,23 +312,23 @@ const EDA_RECT LIB_ARC::GetBoundingBox() const
|
||||
|
||||
/* Zero degrees is a special case. */
|
||||
if( angleStart == 0 )
|
||||
maxX = centerPos.x + m_Radius;
|
||||
maxX = centerPos.x + radius;
|
||||
|
||||
/* Arc end angle wrapped passed 360. */
|
||||
if( angleStart > angleEnd )
|
||||
angleEnd += 3600;
|
||||
|
||||
if( angleStart <= 900 && angleEnd >= 900 ) /* 90 deg */
|
||||
maxY = centerPos.y + m_Radius;
|
||||
maxY = centerPos.y + radius;
|
||||
|
||||
if( angleStart <= 1800 && angleEnd >= 1800 ) /* 180 deg */
|
||||
minX = centerPos.x - m_Radius;
|
||||
minX = centerPos.x - radius;
|
||||
|
||||
if( angleStart <= 2700 && angleEnd >= 2700 ) /* 270 deg */
|
||||
minY = centerPos.y - m_Radius;
|
||||
minY = centerPos.y - radius;
|
||||
|
||||
if( angleStart <= 3600 && angleEnd >= 3600 ) /* 0 deg */
|
||||
maxX = centerPos.x + m_Radius;
|
||||
maxX = centerPos.x + radius;
|
||||
|
||||
rect.SetOrigin( minX, minY );
|
||||
rect.SetEnd( maxX, maxY );
|
||||
@ -407,7 +359,7 @@ void LIB_ARC::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITE
|
||||
wxString LIB_ARC::GetSelectMenuText( EDA_UNITS aUnits ) const
|
||||
{
|
||||
return wxString::Format( _( "Arc, radius %s" ),
|
||||
MessageTextFromValue( aUnits, m_Radius ) );
|
||||
MessageTextFromValue( aUnits, GetRadius() ) );
|
||||
}
|
||||
|
||||
|
||||
@ -428,6 +380,8 @@ void LIB_ARC::CalcEdit( const wxPoint& aPosition )
|
||||
{
|
||||
#define sq( x ) pow( x, 2 )
|
||||
|
||||
int radius = GetRadius();
|
||||
|
||||
// Edit state 0: drawing: place ArcStart
|
||||
// Edit state 1: drawing: place ArcEnd (center calculated for 90-degree subtended angle)
|
||||
// Edit state 2: point editing: move ArcStart (center calculated for invariant subtended angle)
|
||||
@ -440,14 +394,12 @@ void LIB_ARC::CalcEdit( const wxPoint& aPosition )
|
||||
m_ArcStart = aPosition;
|
||||
m_ArcEnd = aPosition;
|
||||
m_Pos = aPosition;
|
||||
m_Radius = 0;
|
||||
m_t1 = 0;
|
||||
m_t2 = 0;
|
||||
radius = 0;
|
||||
return;
|
||||
|
||||
case 1:
|
||||
m_ArcEnd = aPosition;
|
||||
m_Radius = KiROUND( sqrt( pow( GetLineLength( m_ArcStart, m_ArcEnd ), 2 ) / 2.0 ) );
|
||||
radius = KiROUND( sqrt( sq( GetLineLength( m_ArcStart, m_ArcEnd ) ) / 2.0 ) );
|
||||
break;
|
||||
|
||||
case 2:
|
||||
@ -465,10 +417,10 @@ void LIB_ARC::CalcEdit( const wxPoint& aPosition )
|
||||
double chordAfter = sq( v.x ) + sq( v.y );
|
||||
double ratio = chordAfter / chordBefore;
|
||||
|
||||
if( ratio > 0 )
|
||||
if( ratio != 0 )
|
||||
{
|
||||
m_Radius = int( sqrt( m_Radius * m_Radius * ratio ) ) + 1;
|
||||
m_Radius = std::max( m_Radius, int( sqrt( chordAfter ) / 2 ) + 1 );
|
||||
radius = std::max( int( sqrt( sq( radius ) * ratio ) ) + 1,
|
||||
int( sqrt( chordAfter ) / 2 ) + 1 );
|
||||
}
|
||||
|
||||
break;
|
||||
@ -478,7 +430,7 @@ void LIB_ARC::CalcEdit( const wxPoint& aPosition )
|
||||
{
|
||||
double chordA = GetLineLength( m_ArcStart, aPosition );
|
||||
double chordB = GetLineLength( m_ArcEnd, aPosition );
|
||||
m_Radius = int( ( chordA + chordB ) / 2.0 ) + 1;
|
||||
radius = int( ( chordA + chordB ) / 2.0 ) + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -491,8 +443,8 @@ void LIB_ARC::CalcEdit( const wxPoint& aPosition )
|
||||
|
||||
// Calculate 'd', the vector from the chord midpoint to the center
|
||||
wxPoint d;
|
||||
d.x = KiROUND( sqrt( sq( m_Radius ) - sq( l/2 ) ) * ( m_ArcStart.y - m_ArcEnd.y ) / l );
|
||||
d.y = KiROUND( sqrt( sq( m_Radius ) - sq( l/2 ) ) * ( m_ArcEnd.x - m_ArcStart.x ) / l );
|
||||
d.x = KiROUND( sqrt( sq( radius ) - sq( l/2 ) ) * ( m_ArcStart.y - m_ArcEnd.y ) / l );
|
||||
d.y = KiROUND( sqrt( sq( radius ) - sq( l/2 ) ) * ( m_ArcEnd.x - m_ArcStart.x ) / l );
|
||||
|
||||
wxPoint c1 = m + d;
|
||||
wxPoint c2 = m - d;
|
||||
@ -525,63 +477,65 @@ void LIB_ARC::CalcEdit( const wxPoint& aPosition )
|
||||
m_Pos = ( GetLineLength( c1, aPosition ) < GetLineLength( c2, aPosition ) ) ? c1 : c2;
|
||||
break;
|
||||
}
|
||||
|
||||
CalcRadiusAngles();
|
||||
}
|
||||
|
||||
|
||||
void LIB_ARC::CalcRadiusAngles()
|
||||
void LIB_ARC::CalcAngles( int& aStartAngle, int& aEndAngle ) const
|
||||
{
|
||||
wxPoint centerStartVector = twoPointVector( m_Pos, m_ArcStart );
|
||||
wxPoint centerEndVector = twoPointVector( m_Pos, m_ArcEnd );
|
||||
|
||||
m_Radius = KiROUND( EuclideanNorm( centerStartVector ) );
|
||||
wxPoint centerStartVector = twoPointVector( GetCenter(), GetStart() );
|
||||
wxPoint centerEndVector = twoPointVector( GetCenter(), GetEnd() );
|
||||
|
||||
// Angles in Eeschema are still integers
|
||||
m_t1 = KiROUND( ArcTangente( centerStartVector.y, centerStartVector.x ) );
|
||||
m_t2 = KiROUND( ArcTangente( centerEndVector.y, centerEndVector.x ) );
|
||||
aStartAngle = KiROUND( ArcTangente( centerStartVector.y, centerStartVector.x ) );
|
||||
aEndAngle = KiROUND( ArcTangente( centerEndVector.y, centerEndVector.x ) );
|
||||
|
||||
NORMALIZE_ANGLE_POS( m_t1 );
|
||||
NORMALIZE_ANGLE_POS( m_t2 ); // angles = 0 .. 3600
|
||||
NORMALIZE_ANGLE_POS( aStartAngle );
|
||||
NORMALIZE_ANGLE_POS( aEndAngle ); // angles = 0 .. 3600
|
||||
|
||||
// Restrict angle to less than 180 to avoid PBS display mirror Trace because it is
|
||||
// assumed that the arc is less than 180 deg to find orientation after rotate or mirror.
|
||||
if( ( m_t2 - m_t1 ) > 1800 )
|
||||
m_t2 -= 3600;
|
||||
else if( ( m_t2 - m_t1 ) <= -1800 )
|
||||
m_t2 += 3600;
|
||||
if( ( aEndAngle - aStartAngle ) > 1800 )
|
||||
aEndAngle -= 3600;
|
||||
else if( ( aEndAngle - aStartAngle ) <= -1800 )
|
||||
aEndAngle += 3600;
|
||||
|
||||
while( ( m_t2 - m_t1 ) >= 1800 )
|
||||
while( ( aEndAngle - aStartAngle ) >= 1800 )
|
||||
{
|
||||
m_t2--;
|
||||
m_t1++;
|
||||
aEndAngle--;
|
||||
aStartAngle++;
|
||||
}
|
||||
|
||||
while( ( m_t1 - m_t2 ) >= 1800 )
|
||||
while( ( aStartAngle - aEndAngle ) >= 1800 )
|
||||
{
|
||||
m_t2++;
|
||||
m_t1--;
|
||||
aEndAngle++;
|
||||
aStartAngle--;
|
||||
}
|
||||
|
||||
NORMALIZE_ANGLE_POS( m_t1 );
|
||||
NORMALIZE_ANGLE_POS( aStartAngle );
|
||||
|
||||
if( !IsMoving() )
|
||||
NORMALIZE_ANGLE_POS( m_t2 );
|
||||
NORMALIZE_ANGLE_POS( aEndAngle );
|
||||
}
|
||||
|
||||
|
||||
VECTOR2I LIB_ARC::CalcMidPoint() const
|
||||
{
|
||||
VECTOR2D midPoint;
|
||||
double startAngle = static_cast<double>( m_t1 ) / 10.0;
|
||||
double endAngle = static_cast<double>( m_t2 ) / 10.0;
|
||||
int radius = GetRadius();
|
||||
int t1;
|
||||
int t2;
|
||||
|
||||
CalcAngles( t1, t2 );
|
||||
|
||||
double startAngle = static_cast<double>( t1 ) / 10.0;
|
||||
double endAngle = static_cast<double>( t2 ) / 10.0;
|
||||
|
||||
if( endAngle < startAngle )
|
||||
endAngle -= 360.0;
|
||||
|
||||
double midPointAngle = ( ( endAngle - startAngle ) / 2.0 ) + startAngle;
|
||||
double x = cos( DEG2RAD( midPointAngle ) ) * m_Radius;
|
||||
double y = sin( DEG2RAD( midPointAngle ) ) * m_Radius;
|
||||
double x = cos( DEG2RAD( midPointAngle ) ) * radius;
|
||||
double y = sin( DEG2RAD( midPointAngle ) ) * radius;
|
||||
|
||||
midPoint.x = KiROUND( x ) + m_Pos.x;
|
||||
midPoint.y = KiROUND( y ) + m_Pos.y;
|
||||
@ -589,15 +543,3 @@ VECTOR2I LIB_ARC::CalcMidPoint() const
|
||||
return midPoint;
|
||||
}
|
||||
|
||||
|
||||
void LIB_ARC::CalcEndPoints()
|
||||
{
|
||||
double startAngle = DEG2RAD( static_cast<double>( m_t1 ) / 10.0 );
|
||||
double endAngle = DEG2RAD( static_cast<double>( m_t2 ) / 10.0 );
|
||||
|
||||
m_ArcStart.x = KiROUND( cos( startAngle ) * m_Radius ) + m_Pos.x;
|
||||
m_ArcStart.y = KiROUND( sin( startAngle ) * m_Radius ) + m_Pos.y;
|
||||
|
||||
m_ArcEnd.x = KiROUND( cos( endAngle ) * m_Radius ) + m_Pos.x;
|
||||
m_ArcEnd.y = KiROUND( sin( endAngle ) * m_Radius ) + m_Pos.y;
|
||||
}
|
||||
|
@ -80,14 +80,7 @@ public:
|
||||
int GetWidth() const override { return m_Width; }
|
||||
void SetWidth( int aWidth ) override { m_Width = aWidth; }
|
||||
|
||||
void SetRadius( int aRadius ) { m_Radius = aRadius; }
|
||||
int GetRadius() const { return m_Radius; }
|
||||
|
||||
void SetFirstRadiusAngle( int aAngle ) { m_t1 = aAngle; }
|
||||
int GetFirstRadiusAngle() const { return m_t1; }
|
||||
|
||||
void SetSecondRadiusAngle( int aAngle ) { m_t2 = aAngle; }
|
||||
int GetSecondRadiusAngle() const { return m_t2; }
|
||||
int GetRadius() const;
|
||||
|
||||
wxPoint GetStart() const { return m_ArcStart; }
|
||||
void SetStart( const wxPoint& aPoint ) { m_ArcStart = aPoint; }
|
||||
@ -95,6 +88,10 @@ public:
|
||||
wxPoint GetEnd() const { return m_ArcEnd; }
|
||||
void SetEnd( const wxPoint& aPoint ) { m_ArcEnd = aPoint; }
|
||||
|
||||
wxPoint GetCenter() const { return m_Pos; }
|
||||
void SetCenter( const wxPoint& aPoint ) { m_Pos = aPoint; }
|
||||
|
||||
|
||||
/**
|
||||
* Calculate the arc mid point using the arc start and end angles and radius length.
|
||||
*
|
||||
@ -106,14 +103,9 @@ public:
|
||||
VECTOR2I CalcMidPoint() const;
|
||||
|
||||
/**
|
||||
* Calculate the start and end points using the center point and the two angles.
|
||||
* Calculate the start and end angles of an arc using the start, end, and center points.
|
||||
*/
|
||||
void CalcEndPoints();
|
||||
|
||||
/**
|
||||
* Calculate the radius and angle of an arc using the start, end, and center points.
|
||||
*/
|
||||
void CalcRadiusAngles();
|
||||
void CalcAngles( int& aStartAngle, int& aEndAngle ) const;
|
||||
|
||||
|
||||
wxString GetSelectMenuText( EDA_UNITS aUnits ) const override;
|
||||
@ -145,9 +137,6 @@ private:
|
||||
ARC_STATUS_OUTLINE,
|
||||
};
|
||||
|
||||
int m_Radius;
|
||||
int m_t1; // First radius angle of the arc in 0.1 degrees.
|
||||
int m_t2; /* Second radius angle of the arc in 0.1 degrees. */
|
||||
wxPoint m_ArcStart;
|
||||
wxPoint m_ArcEnd; /* Arc end position. */
|
||||
wxPoint m_Pos; /* Radius center point. */
|
||||
|
570
eeschema/lib_shape.cpp
Normal file
570
eeschema/lib_shape.cpp
Normal file
@ -0,0 +1,570 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2004-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <sch_draw_panel.h>
|
||||
#include <plotter.h>
|
||||
#include <base_units.h>
|
||||
#include <widgets/msgpanel.h>
|
||||
#include <bitmaps.h>
|
||||
#include <eda_draw_frame.h>
|
||||
#include <general.h>
|
||||
#include <lib_shape.h>
|
||||
|
||||
|
||||
LIB_SHAPE::LIB_SHAPE( LIB_SYMBOL* aParent, SHAPE_T aShape, int aDefaultLineWidth,
|
||||
FILL_T aFillType ) :
|
||||
LIB_ITEM( LIB_SHAPE_T, aParent ),
|
||||
EDA_SHAPE( aShape, aDefaultLineWidth, aFillType )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool LIB_SHAPE::HitTest( const wxPoint& aPosRef, int aAccuracy ) const
|
||||
{
|
||||
if( aAccuracy < Mils2iu( MINIMUM_SELECTION_DISTANCE ) )
|
||||
aAccuracy = Mils2iu( MINIMUM_SELECTION_DISTANCE );
|
||||
|
||||
return hitTest( DefaultTransform.TransformCoordinate( aPosRef ), aAccuracy );
|
||||
}
|
||||
|
||||
|
||||
bool LIB_SHAPE::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
|
||||
{
|
||||
if( m_flags & (STRUCT_DELETED | SKIP_STRUCT ) )
|
||||
return false;
|
||||
|
||||
return hitTest( aRect, aContained, aAccuracy );
|
||||
}
|
||||
|
||||
|
||||
EDA_ITEM* LIB_SHAPE::Clone() const
|
||||
{
|
||||
return new LIB_SHAPE( *this );
|
||||
}
|
||||
|
||||
|
||||
int LIB_SHAPE::compare( const LIB_ITEM& aOther, LIB_ITEM::COMPARE_FLAGS aCompareFlags ) const
|
||||
{
|
||||
int retv = LIB_ITEM::compare( aOther, aCompareFlags );
|
||||
|
||||
if( retv )
|
||||
return retv;
|
||||
|
||||
return EDA_SHAPE::Compare( &static_cast<const LIB_SHAPE&>( aOther ) );
|
||||
}
|
||||
|
||||
|
||||
void LIB_SHAPE::Offset( const wxPoint& aOffset )
|
||||
{
|
||||
move( aOffset );
|
||||
}
|
||||
|
||||
|
||||
void LIB_SHAPE::MoveTo( const wxPoint& aPosition )
|
||||
{
|
||||
setPosition( aPosition );
|
||||
}
|
||||
|
||||
|
||||
void LIB_SHAPE::MirrorHorizontal( const wxPoint& aCenter )
|
||||
{
|
||||
flip( aCenter, true );
|
||||
}
|
||||
|
||||
|
||||
void LIB_SHAPE::MirrorVertical( const wxPoint& aCenter )
|
||||
{
|
||||
flip( aCenter, false );
|
||||
}
|
||||
|
||||
|
||||
void LIB_SHAPE::Rotate( const wxPoint& aCenter, bool aRotateCCW )
|
||||
{
|
||||
int rot_angle = aRotateCCW ? -900 : 900;
|
||||
|
||||
rotate( aCenter, rot_angle );
|
||||
}
|
||||
|
||||
|
||||
void LIB_SHAPE::Plot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
|
||||
const TRANSFORM& aTransform ) const
|
||||
{
|
||||
wxPoint start = aTransform.TransformCoordinate( m_start ) + aOffset;
|
||||
wxPoint end = aTransform.TransformCoordinate( m_end ) + aOffset;
|
||||
wxPoint center;
|
||||
int startAngle;
|
||||
int endAngle;
|
||||
int pen_size = GetPenWidth();
|
||||
FILL_T fill = aFill ? m_fill : FILL_TYPE::NO_FILL;
|
||||
|
||||
static std::vector<wxPoint> cornerList;
|
||||
|
||||
if( GetShape() == SHAPE_T::POLYGON )
|
||||
{
|
||||
cornerList.clear();
|
||||
|
||||
for( const VECTOR2I& pt : m_poly.Outline( 0 ).CPoints() )
|
||||
cornerList.push_back( aTransform.TransformCoordinate( (wxPoint) pt ) + aOffset );
|
||||
}
|
||||
else if( GetShape() == SHAPE_T::CURVE )
|
||||
{
|
||||
cornerList.clear();
|
||||
|
||||
for( const wxPoint& pt : m_bezierPoints )
|
||||
cornerList.push_back( aTransform.TransformCoordinate( pt ) + aOffset );
|
||||
}
|
||||
else if( GetShape() == SHAPE_T::ARC )
|
||||
{
|
||||
center = aTransform.TransformCoordinate( getCenter() ) + aOffset;
|
||||
startAngle = GetArcAngleStart();
|
||||
endAngle = GetArcAngleEnd();
|
||||
aTransform.MapAngles( &startAngle, &endAngle );
|
||||
}
|
||||
|
||||
if( fill == FILL_T::FILLED_WITH_BG_BODYCOLOR )
|
||||
{
|
||||
aPlotter->SetColor( aPlotter->RenderSettings()->GetLayerColor( LAYER_DEVICE_BACKGROUND ) );
|
||||
|
||||
switch( GetShape() )
|
||||
{
|
||||
case SHAPE_T::ARC:
|
||||
aPlotter->Arc( center, -endAngle, -startAngle, GetRadius(), fill, 0 );
|
||||
break;
|
||||
|
||||
case SHAPE_T::CIRCLE:
|
||||
aPlotter->Circle( start, GetRadius() * 2, fill, 0 );
|
||||
break;
|
||||
|
||||
case SHAPE_T::RECT:
|
||||
aPlotter->Rect( start, end, fill, 0 );
|
||||
break;
|
||||
|
||||
case SHAPE_T::POLYGON:
|
||||
case SHAPE_T::CURVE:
|
||||
aPlotter->PlotPoly( cornerList, fill, 0 );
|
||||
break;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG( "LIB_SHAPE::Plot not implemented for " + SHAPE_T_asString() );
|
||||
}
|
||||
|
||||
if( pen_size <= 0 )
|
||||
return;
|
||||
else
|
||||
fill = FILL_T::NO_FILL;
|
||||
}
|
||||
|
||||
pen_size = std::max( pen_size, aPlotter->RenderSettings()->GetMinPenWidth() );
|
||||
|
||||
aPlotter->SetColor( aPlotter->RenderSettings()->GetLayerColor( LAYER_DEVICE ) );
|
||||
|
||||
switch( GetShape() )
|
||||
{
|
||||
case SHAPE_T::ARC:
|
||||
aPlotter->Arc( center, -endAngle, -startAngle, GetRadius(), fill, pen_size );
|
||||
break;
|
||||
|
||||
case SHAPE_T::CIRCLE:
|
||||
aPlotter->Circle( start, GetRadius() * 2, fill, pen_size );
|
||||
break;
|
||||
|
||||
case SHAPE_T::RECT:
|
||||
aPlotter->Rect( start, end, fill, pen_size );
|
||||
break;
|
||||
|
||||
case SHAPE_T::POLYGON:
|
||||
case SHAPE_T::CURVE:
|
||||
aPlotter->PlotPoly( cornerList, fill, pen_size );
|
||||
break;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG( "LIB_SHAPE::Plot not implemented for " + SHAPE_T_asString() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int LIB_SHAPE::GetPenWidth() const
|
||||
{
|
||||
// Historically 0 meant "default width" and negative numbers meant "don't stroke".
|
||||
if( GetWidth() < 0 && GetFillType() != FILL_T::NO_FILL )
|
||||
return 0;
|
||||
else
|
||||
return std::max( GetWidth(), 1 );
|
||||
}
|
||||
|
||||
|
||||
void LIB_SHAPE::print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset,
|
||||
void* aData, const TRANSFORM& aTransform )
|
||||
{
|
||||
bool forceNoFill = static_cast<bool>( aData );
|
||||
int penWidth = GetPenWidth();
|
||||
|
||||
if( forceNoFill && IsFilled() && penWidth == 0 )
|
||||
return;
|
||||
|
||||
wxDC* DC = aSettings->GetPrintDC();
|
||||
wxPoint pt1 = aTransform.TransformCoordinate( m_start ) + aOffset;
|
||||
wxPoint pt2 = aTransform.TransformCoordinate( m_end ) + aOffset;
|
||||
wxPoint c;
|
||||
int t1;
|
||||
int t2;
|
||||
COLOR4D color = aSettings->GetLayerColor( LAYER_DEVICE );
|
||||
|
||||
unsigned ptCount = 0;
|
||||
wxPoint* buffer = nullptr;
|
||||
|
||||
if( GetShape() == SHAPE_T::POLYGON )
|
||||
{
|
||||
SHAPE_LINE_CHAIN poly = m_poly.Outline( 0 );
|
||||
|
||||
ptCount = poly.GetPointCount();
|
||||
buffer = new wxPoint[ ptCount ];
|
||||
|
||||
for( unsigned ii = 0; ii < ptCount; ++ii )
|
||||
buffer[ii] = aTransform.TransformCoordinate( (wxPoint) poly.CPoint( ii ) ) + aOffset;
|
||||
}
|
||||
else if( GetShape() == SHAPE_T::CURVE )
|
||||
{
|
||||
ptCount = m_bezierPoints.size();
|
||||
buffer = new wxPoint[ ptCount ];
|
||||
|
||||
for( size_t ii = 0; ii < ptCount; ++ii )
|
||||
buffer[ii] = aTransform.TransformCoordinate( m_bezierPoints[ii] ) + aOffset;
|
||||
}
|
||||
else if( GetShape() == SHAPE_T::ARC )
|
||||
{
|
||||
c = aTransform.TransformCoordinate( getCenter() ) + aOffset;
|
||||
t1 = GetArcAngleStart();
|
||||
t2 = GetArcAngleEnd();
|
||||
aTransform.MapAngles( &t1, &t2 );
|
||||
}
|
||||
|
||||
if( forceNoFill || GetFillType() == FILL_T::NO_FILL )
|
||||
{
|
||||
penWidth = std::max( penWidth, aSettings->GetDefaultPenWidth() );
|
||||
|
||||
switch( GetShape() )
|
||||
{
|
||||
case SHAPE_T::ARC:
|
||||
GRArc1( nullptr, DC, pt2.x, pt2.y, pt1.x, pt1.y, c.x, c.y, penWidth, color );
|
||||
break;
|
||||
|
||||
case SHAPE_T::CIRCLE:
|
||||
GRCircle( nullptr, DC, pt1.x, pt1.y, GetRadius(), penWidth, color );
|
||||
break;
|
||||
|
||||
case SHAPE_T::RECT:
|
||||
GRRect( nullptr, DC, pt1.x, pt1.y, pt2.x, pt2.y, penWidth, color );
|
||||
break;
|
||||
|
||||
case SHAPE_T::POLYGON:
|
||||
GRPoly( nullptr, DC, ptCount, buffer, false, penWidth, color, color );
|
||||
break;
|
||||
|
||||
case SHAPE_T::CURVE:
|
||||
GRPoly( nullptr, DC, ptCount, buffer, false, penWidth, color, color );
|
||||
break;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG( "LIB_SHAPE::print not implemented for " + SHAPE_T_asString() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( GetFillType() == FILL_T::FILLED_WITH_BG_BODYCOLOR )
|
||||
color = aSettings->GetLayerColor( LAYER_DEVICE_BACKGROUND );
|
||||
|
||||
switch( GetShape() )
|
||||
{
|
||||
case SHAPE_T::ARC:
|
||||
GRFilledArc( nullptr, DC, c.x, c.y, t1, t2, GetRadius(), penWidth, color, color );
|
||||
break;
|
||||
|
||||
case SHAPE_T::CIRCLE:
|
||||
GRFilledCircle( nullptr, DC, pt1.x, pt1.y, GetRadius(), 0, color, color );
|
||||
break;
|
||||
|
||||
case SHAPE_T::RECT:
|
||||
GRFilledRect( nullptr, DC, pt1.x, pt1.y, pt2.x, pt2.y, penWidth, color, color );
|
||||
break;
|
||||
|
||||
case SHAPE_T::POLYGON:
|
||||
GRPoly( nullptr, DC, ptCount, buffer, true, penWidth, color, color );
|
||||
break;
|
||||
|
||||
case SHAPE_T::CURVE:
|
||||
GRPoly( nullptr, DC, ptCount, buffer, true, penWidth, color, color );
|
||||
break;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG( "LIB_SHAPE::print not implemented for " + SHAPE_T_asString() );
|
||||
}
|
||||
}
|
||||
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
|
||||
const EDA_RECT LIB_SHAPE::GetBoundingBox() const
|
||||
{
|
||||
EDA_RECT rect = getBoundingBox();
|
||||
|
||||
rect.RevertYAxis();
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
|
||||
void LIB_SHAPE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, MSG_PANEL_ITEMS& aList )
|
||||
{
|
||||
LIB_ITEM::GetMsgPanelInfo( aFrame, aList );
|
||||
|
||||
ShapeGetMsgPanelInfo( aFrame, aList );
|
||||
}
|
||||
|
||||
|
||||
wxString LIB_SHAPE::GetSelectMenuText( EDA_UNITS aUnits ) const
|
||||
{
|
||||
switch( GetShape() )
|
||||
{
|
||||
case SHAPE_T::ARC:
|
||||
return wxString::Format( _( "Arc, radius %s" ),
|
||||
MessageTextFromValue( aUnits, GetRadius() ) );
|
||||
|
||||
case SHAPE_T::CIRCLE:
|
||||
return wxString::Format( _( "Circle, radius %s" ),
|
||||
MessageTextFromValue( aUnits, GetRadius() ) );
|
||||
|
||||
case SHAPE_T::RECT:
|
||||
return wxString::Format( _( "Rectangle, width %s height %s" ),
|
||||
MessageTextFromValue( aUnits, std::abs( m_start.x - m_end.x ) ),
|
||||
MessageTextFromValue( aUnits, std::abs( m_start.y - m_end.y ) ) );
|
||||
|
||||
case SHAPE_T::POLYGON:
|
||||
return wxString::Format( _( "Polyline, %d points" ),
|
||||
int( m_poly.Outline( 0 ).GetPointCount() ) );
|
||||
|
||||
case SHAPE_T::CURVE:
|
||||
return wxString::Format( _( "Bezier Curve, %d points" ),
|
||||
int( m_bezierPoints.size() ) );
|
||||
|
||||
default:
|
||||
wxFAIL_MSG( "LIB_SHAPE::GetSelectMenuText unimplemented for " + SHAPE_T_asString() );
|
||||
return wxEmptyString;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BITMAPS LIB_SHAPE::GetMenuImage() const
|
||||
{
|
||||
switch( GetShape() )
|
||||
{
|
||||
case SHAPE_T::SEGMENT: return BITMAPS::add_line;
|
||||
case SHAPE_T::ARC: return BITMAPS::add_arc;
|
||||
case SHAPE_T::CIRCLE: return BITMAPS::add_circle;
|
||||
case SHAPE_T::RECT: return BITMAPS::add_rectangle;
|
||||
case SHAPE_T::POLYGON: return BITMAPS::add_graphical_segments;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG( "LIB_SHAPE::GetMenuImage unimplemented for " + SHAPE_T_asString() );
|
||||
return BITMAPS::question_mark;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LIB_SHAPE::BeginEdit( const wxPoint& aPosition )
|
||||
{
|
||||
switch( GetShape() )
|
||||
{
|
||||
case SHAPE_T::SEGMENT:
|
||||
case SHAPE_T::CIRCLE:
|
||||
case SHAPE_T::RECT:
|
||||
SetPosition( aPosition );
|
||||
SetEnd( aPosition );
|
||||
break;
|
||||
|
||||
case SHAPE_T::ARC:
|
||||
SetStart( aPosition );
|
||||
SetEnd( aPosition );
|
||||
SetEditState( 1 );
|
||||
break;
|
||||
|
||||
case SHAPE_T::POLYGON:
|
||||
// Start and end of the first segment (co-located for now)
|
||||
m_poly.Outline( 0 ).Append( aPosition );
|
||||
m_poly.Outline( 0 ).Append( aPosition, true );
|
||||
break;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG( "LIB_SHAPE::BeginEdit not implemented for " + SHAPE_T_asString() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool LIB_SHAPE::ContinueEdit( const wxPoint& aPosition )
|
||||
{
|
||||
switch( GetShape() )
|
||||
{
|
||||
case SHAPE_T::SEGMENT:
|
||||
case SHAPE_T::CIRCLE:
|
||||
case SHAPE_T::RECT:
|
||||
return false;
|
||||
|
||||
case SHAPE_T::POLYGON:
|
||||
{
|
||||
SHAPE_LINE_CHAIN& poly = m_poly.Outline( 0 );
|
||||
|
||||
// do not add zero-length segments
|
||||
if( poly.CPoint( poly.GetPointCount() - 2 ) != poly.CLastPoint() )
|
||||
poly.Append( aPosition );
|
||||
}
|
||||
return true;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG( "LIB_SHAPE::ContinueEdit not implemented for " + SHAPE_T_asString() );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LIB_SHAPE::CalcEdit( const wxPoint& aPosition )
|
||||
{
|
||||
#define sq( x ) pow( x, 2 )
|
||||
|
||||
switch( GetShape() )
|
||||
{
|
||||
case SHAPE_T::SEGMENT:
|
||||
case SHAPE_T::CIRCLE:
|
||||
case SHAPE_T::RECT:
|
||||
SetEnd( aPosition );
|
||||
break;
|
||||
|
||||
case SHAPE_T::POLYGON:
|
||||
m_poly.Outline( 0 ).SetPoint( m_poly.Outline( 0 ).GetPointCount() - 1, aPosition );
|
||||
break;
|
||||
|
||||
case SHAPE_T::ARC:
|
||||
// Edit state 0: drawing: place start
|
||||
// Edit state 1: drawing: place end (center calculated for 90-degree subtended angle)
|
||||
// Edit state 2: point edit: move start (center calculated for invariant subtended angle)
|
||||
// Edit state 3: point edit: move end (center calculated for invariant subtended angle)
|
||||
// Edit state 4: point edit: move center
|
||||
// Edit state 5: point edit: move arc-mid-point
|
||||
|
||||
switch( m_editState )
|
||||
{
|
||||
case 0:
|
||||
SetArcGeometry( aPosition, aPosition, aPosition );
|
||||
return;
|
||||
|
||||
case 1:
|
||||
{
|
||||
wxPoint start = GetStart();
|
||||
wxPoint end = aPosition;
|
||||
wxPoint center = CalcArcCenter( start, end, 90.0 );
|
||||
wxPoint mid = (wxPoint) CalcArcMid( start, end, center, true );
|
||||
|
||||
SetArcGeometry( start, mid, aPosition );
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
wxPoint delta = aPosition - GetStart();
|
||||
|
||||
SetArcGeometry( aPosition, GetArcMid() + delta/2, GetEnd() );
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
{
|
||||
wxPoint delta = aPosition - GetEnd();
|
||||
|
||||
SetArcGeometry( GetStart(), GetArcMid() + delta/2, aPosition );
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
MoveTo( aPosition );
|
||||
break;
|
||||
|
||||
case 5:
|
||||
SetArcGeometry( GetStart(), aPosition, GetEnd() );
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG( "LIB_SHAPE::CalcEdit not implemented for " + SHAPE_T_asString() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LIB_SHAPE::EndEdit()
|
||||
{
|
||||
switch( GetShape() )
|
||||
{
|
||||
case SHAPE_T::ARC:
|
||||
case SHAPE_T::SEGMENT:
|
||||
case SHAPE_T::CIRCLE:
|
||||
case SHAPE_T::RECT:
|
||||
break;
|
||||
|
||||
case SHAPE_T::POLYGON:
|
||||
{
|
||||
SHAPE_LINE_CHAIN& poly = m_poly.Outline( 0 );
|
||||
|
||||
// do not include last point twice
|
||||
if( poly.GetPointCount() > 2 )
|
||||
{
|
||||
if( poly.CPoint( poly.GetPointCount() - 2 ) == poly.CLastPoint() )
|
||||
poly.Remove( poly.GetPointCount() - 1 );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG( "LIB_SHAPE::EndEdit not implemented for " + SHAPE_T_asString() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LIB_SHAPE::AddPoint( const wxPoint& aPosition )
|
||||
{
|
||||
if( GetShape() == SHAPE_T::POLYGON )
|
||||
{
|
||||
if( m_poly.IsEmpty() )
|
||||
m_poly.NewOutline();
|
||||
|
||||
m_poly.Outline( 0 ).Append( aPosition, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
wxFAIL_MSG( "LIB_SHAPE::AddPoint not implemented for " + SHAPE_T_asString() );
|
||||
}
|
||||
}
|
||||
|
||||
|
108
eeschema/lib_shape.h
Normal file
108
eeschema/lib_shape.h
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
|
||||
* Copyright (C) 2004-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef LIB_SHAPE_H
|
||||
#define LIB_SHAPE_H
|
||||
|
||||
#include <lib_item.h>
|
||||
#include <eda_shape.h>
|
||||
|
||||
|
||||
class LIB_SHAPE : public LIB_ITEM, public EDA_SHAPE
|
||||
{
|
||||
public:
|
||||
LIB_SHAPE( LIB_SYMBOL* aParent, SHAPE_T aShape, int aLineWidth = 0,
|
||||
FILL_T aFillType = FILL_T::NO_FILL );
|
||||
|
||||
// Do not create a copy constructor. The one generated by the compiler is adequate.
|
||||
|
||||
~LIB_SHAPE() { }
|
||||
|
||||
wxString GetClass() const override
|
||||
{
|
||||
return wxT( "LIB_SHAPE" );
|
||||
}
|
||||
|
||||
wxString GetTypeName() const override
|
||||
{
|
||||
return ShowShape();
|
||||
}
|
||||
|
||||
bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override;
|
||||
bool HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy = 0 ) const override;
|
||||
|
||||
int GetPenWidth() const override;
|
||||
|
||||
const EDA_RECT GetBoundingBox() const override;
|
||||
|
||||
void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
|
||||
|
||||
void BeginEdit( const wxPoint& aStartPoint ) override;
|
||||
bool ContinueEdit( const wxPoint& aPosition ) override;
|
||||
void CalcEdit( const wxPoint& aPosition ) override;
|
||||
void EndEdit() override;
|
||||
|
||||
void AddPoint( const wxPoint& aPosition );
|
||||
|
||||
void Offset( const wxPoint& aOffset ) override;
|
||||
|
||||
void MoveTo( const wxPoint& aPosition ) override;
|
||||
|
||||
wxPoint GetPosition() const override { return getPosition(); }
|
||||
void SetPosition( const wxPoint& aPosition ) override { setPosition( aPosition ); }
|
||||
|
||||
void MirrorHorizontal( const wxPoint& aCenter ) override;
|
||||
void MirrorVertical( const wxPoint& aCenter ) override;
|
||||
void Rotate( const wxPoint& aCenter, bool aRotateCCW = true ) override;
|
||||
|
||||
void Plot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
|
||||
const TRANSFORM& aTransform ) const override;
|
||||
|
||||
wxString GetSelectMenuText( EDA_UNITS aUnits ) const override;
|
||||
|
||||
BITMAPS GetMenuImage() const override;
|
||||
|
||||
EDA_ITEM* Clone() const override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* @copydoc LIB_ITEM::compare()
|
||||
*
|
||||
* The circle specific sort order is as follows:
|
||||
* - Circle horizontal (X) position.
|
||||
* - Circle vertical (Y) position.
|
||||
* - Circle radius.
|
||||
*/
|
||||
int compare( const LIB_ITEM& aOther,
|
||||
LIB_ITEM::COMPARE_FLAGS aCompareFlags = LIB_ITEM::COMPARE_FLAGS::NORMAL ) const override;
|
||||
|
||||
void print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset, void* aData,
|
||||
const TRANSFORM& aTransform ) override;
|
||||
|
||||
double getParentOrientation() const override { return 0.0; }
|
||||
wxPoint getParentPosition() const override { return wxPoint(); }
|
||||
};
|
||||
|
||||
|
||||
#endif // LIB_SHAPE_H
|
@ -196,7 +196,7 @@ SCH_CONNECTION* SCH_ITEM::InitializeConnection( const SCH_SHEET_PATH& aSheet,
|
||||
|
||||
void SCH_ITEM::SwapData( SCH_ITEM* aItem )
|
||||
{
|
||||
wxFAIL_MSG( wxT( "SwapData() method not implemented for class " ) + GetClass() );
|
||||
UNIMPLEMENTED_FOR( GetClass() );
|
||||
}
|
||||
|
||||
|
||||
|
@ -579,37 +579,14 @@ void SCH_PAINTER::draw( const LIB_ARC *aArc, int aLayer )
|
||||
|
||||
if( setDeviceColors( aArc, aLayer ) )
|
||||
{
|
||||
int sai = aArc->GetFirstRadiusAngle();
|
||||
int eai = aArc->GetSecondRadiusAngle();
|
||||
int startAngle;
|
||||
int endAngle;
|
||||
aArc->CalcAngles( startAngle, endAngle );
|
||||
|
||||
/**
|
||||
* This accounts for an oddity in the old library format, where the symbol
|
||||
* is overdefined. The previous draw (based on wxwidgets) used start point and end
|
||||
* point and always drew counter-clockwise. The new GAL draw takes center, radius and
|
||||
* start/end angles. All of these points were stored in the file, so we need to mimic the
|
||||
* swapping of start/end points rather than using the stored angles in order to properly map
|
||||
* edge cases.
|
||||
*
|
||||
* todo(v6): Remove this hack when we update the file format and do translation on loading.
|
||||
*/
|
||||
if( !TRANSFORM().MapAngles( &sai, &eai ) )
|
||||
{
|
||||
LIB_ARC new_arc( *aArc );
|
||||
TRANSFORM().MapAngles( &startAngle, &endAngle );
|
||||
|
||||
new_arc.SetStart( aArc->GetEnd() );
|
||||
new_arc.SetEnd( aArc->GetStart() );
|
||||
new_arc.CalcRadiusAngles();
|
||||
sai = new_arc.GetFirstRadiusAngle();
|
||||
eai = new_arc.GetSecondRadiusAngle();
|
||||
TRANSFORM().MapAngles( &sai, &eai );
|
||||
}
|
||||
|
||||
double sa = (double) sai * M_PI / 1800.0;
|
||||
double ea = (double) eai * M_PI / 1800.0 ;
|
||||
|
||||
VECTOR2D pos = mapCoords( aArc->GetPosition() );
|
||||
|
||||
m_gal->DrawArc( pos, aArc->GetRadius(), sa, ea );
|
||||
m_gal->DrawArc( mapCoords( aArc->GetCenter() ), aArc->GetRadius(),
|
||||
DECIDEG2RAD( startAngle ), DECIDEG2RAD( endAngle ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,7 @@
|
||||
#include <wx/log.h>
|
||||
#include <wx/zstream.h>
|
||||
#include <wx/wfstream.h>
|
||||
|
||||
#include <trigo.h>
|
||||
|
||||
const wxPoint GetRelativePosition( const wxPoint& aPosition, const SCH_SYMBOL* aSymbol )
|
||||
{
|
||||
@ -1350,21 +1350,23 @@ void SCH_ALTIUM_PLUGIN::ParseArc( const std::map<wxString, wxString>& aPropertie
|
||||
}
|
||||
else
|
||||
{
|
||||
if( fmod( 360.0 + elem.endAngle - elem.startAngle, 360.0 ) > 180.0 )
|
||||
{
|
||||
m_reporter->Report( _( "Arcs in symbols cannot exceed 180 degrees." ),
|
||||
RPT_SEVERITY_ERROR );
|
||||
return;
|
||||
}
|
||||
|
||||
LIB_ARC* arc = new LIB_ARC( libSymbolIt->second );
|
||||
libSymbolIt->second->AddDrawItem( arc );
|
||||
arc->SetUnit( elem.ownerpartid );
|
||||
arc->SetPosition( GetRelativePosition( elem.center + m_sheetOffset, symbol ) );
|
||||
arc->SetRadius( elem.radius );
|
||||
arc->SetFirstRadiusAngle( elem.startAngle * 10. );
|
||||
arc->SetSecondRadiusAngle( elem.endAngle * 10. );
|
||||
arc->CalcEndPoints();
|
||||
|
||||
arc->SetCenter( GetRelativePosition( elem.center + m_sheetOffset, symbol ) );
|
||||
|
||||
wxPoint arcStart( elem.radius, 0 );
|
||||
RotatePoint( &arcStart.x, &arcStart.y, -elem.startAngle * 10.0 );
|
||||
arcStart += arc->GetCenter();
|
||||
arc->SetStart( arcStart );
|
||||
|
||||
wxPoint arcEnd( elem.radius, 0 );
|
||||
RotatePoint( &arcEnd.x, &arcEnd.y, -elem.endAngle * 10.0 );
|
||||
arcEnd += arc->GetCenter();
|
||||
arc->SetEnd( arcEnd );
|
||||
|
||||
arc->SetWidth( elem.lineWidth );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1590,15 +1590,16 @@ void CADSTAR_SCH_ARCHIVE_LOADER::loadSymDefIntoLibrary( const SYMDEF_ID& aSymdef
|
||||
}
|
||||
|
||||
|
||||
void CADSTAR_SCH_ARCHIVE_LOADER::loadLibrarySymbolShapeVertices(
|
||||
const std::vector<VERTEX>& aCadstarVertices, wxPoint aSymbolOrigin, LIB_SYMBOL* aSymbol,
|
||||
int aGateNumber, int aLineThickness )
|
||||
void CADSTAR_SCH_ARCHIVE_LOADER::loadLibrarySymbolShapeVertices( const std::vector<VERTEX>& aCadstarVertices,
|
||||
wxPoint aSymbolOrigin,
|
||||
LIB_SYMBOL* aSymbol,
|
||||
int aGateNumber,
|
||||
int aLineThickness )
|
||||
{
|
||||
const VERTEX* prev = &aCadstarVertices.at( 0 );
|
||||
const VERTEX* cur;
|
||||
|
||||
wxASSERT_MSG(
|
||||
prev->Type == VERTEX_TYPE::POINT, "First vertex should always be a point vertex" );
|
||||
wxASSERT_MSG( prev->Type == VERTEX_TYPE::POINT, "First vertex should always be a point." );
|
||||
|
||||
for( size_t i = 1; i < aCadstarVertices.size(); i++ )
|
||||
{
|
||||
@ -1651,7 +1652,6 @@ void CADSTAR_SCH_ARCHIVE_LOADER::loadLibrarySymbolShapeVertices(
|
||||
( (LIB_ARC*) segment )->SetEnd( endPoint );
|
||||
}
|
||||
|
||||
( (LIB_ARC*) segment )->CalcRadiusAngles();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2778,7 +2778,6 @@ LIB_SYMBOL* CADSTAR_SCH_ARCHIVE_LOADER::getScaledLibPart( const LIB_SYMBOL* aSym
|
||||
arc.SetPosition( scalePt( arc.GetPosition() ) );
|
||||
arc.SetStart( scalePt( arc.GetStart() ) );
|
||||
arc.SetEnd( scalePt( arc.GetEnd() ) );
|
||||
arc.CalcRadiusAngles(); // Maybe not needed?
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1581,7 +1581,7 @@ EAGLE_LIBRARY* SCH_EAGLE_PLUGIN::loadLibrary( wxXmlNode* aLibraryNode,
|
||||
|
||||
|
||||
bool SCH_EAGLE_PLUGIN::loadSymbol( wxXmlNode* aSymbolNode, std::unique_ptr<LIB_SYMBOL>& aSymbol,
|
||||
EDEVICE* aDevice, int aGateNumber, const wxString& aGateName )
|
||||
EDEVICE* aDevice, int aGateNumber, const wxString& aGateName )
|
||||
{
|
||||
wxString symbolName = aSymbolNode->GetAttribute( "name" );
|
||||
std::vector<LIB_ITEM*> items;
|
||||
@ -1831,8 +1831,6 @@ LIB_ITEM* SCH_EAGLE_PLUGIN::loadSymbolWire( std::unique_ptr<LIB_SYMBOL>& aSymbol
|
||||
arc->SetEnd( begin );
|
||||
}
|
||||
|
||||
arc->SetRadius( radius );
|
||||
arc->CalcRadiusAngles();
|
||||
arc->SetUnit( aGateNumber );
|
||||
|
||||
return (LIB_ITEM*) arc.release();
|
||||
@ -1891,25 +1889,11 @@ LIB_PIN* SCH_EAGLE_PLUGIN::loadPin( std::unique_ptr<LIB_SYMBOL>& aSymbol, wxXmlN
|
||||
|
||||
switch( roti )
|
||||
{
|
||||
default:
|
||||
wxASSERT_MSG( false, wxString::Format( "Unhandled orientation (%d degrees)", roti ) );
|
||||
KI_FALLTHROUGH;
|
||||
|
||||
case 0:
|
||||
pin->SetOrientation( 'R' );
|
||||
break;
|
||||
|
||||
case 90:
|
||||
pin->SetOrientation( 'U' );
|
||||
break;
|
||||
|
||||
case 180:
|
||||
pin->SetOrientation( 'L' );
|
||||
break;
|
||||
|
||||
case 270:
|
||||
pin->SetOrientation( 'D' );
|
||||
break;
|
||||
case 0: pin->SetOrientation( 'R' ); break;
|
||||
case 90: pin->SetOrientation( 'U' ); break;
|
||||
case 180: pin->SetOrientation( 'L' ); break;
|
||||
case 270: pin->SetOrientation( 'D' ); break;
|
||||
default: wxFAIL_MSG( wxString::Format( "Unhandled orientation (%d degrees).", roti ) );
|
||||
}
|
||||
|
||||
pin->SetLength( Mils2iu( 300 ) ); // Default pin length when not defined.
|
||||
@ -1959,17 +1943,11 @@ LIB_PIN* SCH_EAGLE_PLUGIN::loadPin( std::unique_ptr<LIB_SYMBOL>& aSymbol, wxXmlN
|
||||
wxString function = aEPin->function.Get();
|
||||
|
||||
if( function == "dot" )
|
||||
{
|
||||
pin->SetShape( GRAPHIC_PINSHAPE::INVERTED );
|
||||
}
|
||||
else if( function == "clk" )
|
||||
{
|
||||
pin->SetShape( GRAPHIC_PINSHAPE::CLOCK );
|
||||
}
|
||||
else if( function == "dotclk" )
|
||||
{
|
||||
pin->SetShape( GRAPHIC_PINSHAPE::INVERTED_CLOCK );
|
||||
}
|
||||
}
|
||||
|
||||
return pin.release();
|
||||
|
@ -916,6 +916,8 @@ LIB_ARC* SCH_SEXPR_PARSER::parseArc()
|
||||
wxPoint midPoint;
|
||||
wxPoint endPoint;
|
||||
wxPoint pos;
|
||||
int startAngle;
|
||||
int endAngle;
|
||||
FILL_PARAMS fill;
|
||||
bool hasMidPoint = false;
|
||||
std::unique_ptr<LIB_ARC> arc = std::make_unique<LIB_ARC>( nullptr );
|
||||
@ -964,19 +966,16 @@ LIB_ARC* SCH_SEXPR_PARSER::parseArc()
|
||||
break;
|
||||
|
||||
case T_length:
|
||||
arc->SetRadius( parseInternalUnits( "radius length" ) );
|
||||
parseInternalUnits( "radius length" );
|
||||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
case T_angles:
|
||||
{
|
||||
int angle1 = KiROUND( parseDouble( "start radius angle" ) * 10.0 );
|
||||
int angle2 = KiROUND( parseDouble( "end radius angle" ) * 10.0 );
|
||||
|
||||
NORMALIZE_ANGLE_POS( angle1 );
|
||||
NORMALIZE_ANGLE_POS( angle2 );
|
||||
arc->SetFirstRadiusAngle( angle1 );
|
||||
arc->SetSecondRadiusAngle( angle2 );
|
||||
startAngle = KiROUND( parseDouble( "start radius angle" ) * 10.0 );
|
||||
endAngle = KiROUND( parseDouble( "end radius angle" ) * 10.0 );
|
||||
NORMALIZE_ANGLE_POS( startAngle );
|
||||
NORMALIZE_ANGLE_POS( endAngle );
|
||||
NeedRIGHT();
|
||||
break;
|
||||
}
|
||||
@ -1016,13 +1015,25 @@ LIB_ARC* SCH_SEXPR_PARSER::parseArc()
|
||||
|
||||
if( hasMidPoint )
|
||||
{
|
||||
VECTOR2I center = GetArcCenter( arc->GetStart(), midPoint, arc->GetEnd() );
|
||||
VECTOR2I center = CalcArcCenter( arc->GetStart(), midPoint, arc->GetEnd());
|
||||
|
||||
arc->SetPosition( wxPoint( center.x, center.y ) );
|
||||
|
||||
// @todo Calculate the radius.
|
||||
|
||||
arc->CalcRadiusAngles();
|
||||
arc->SetCenter( (wxPoint) center );
|
||||
}
|
||||
else
|
||||
{
|
||||
/**
|
||||
* This accounts for an oddity in the old library format, where the symbol is overdefined.
|
||||
* The previous draw (based on wxwidgets) used start point and end point and always drew
|
||||
* counter-clockwise. The new GAL draw takes center, radius and start/end angles. All of
|
||||
* these points were stored in the file, so we need to mimic the swapping of start/end
|
||||
* points rather than using the stored angles in order to properly map edge cases.
|
||||
*/
|
||||
if( !TRANSFORM().MapAngles( &startAngle, &endAngle ) )
|
||||
{
|
||||
wxPoint temp = arc->GetStart();
|
||||
arc->SetStart( arc->GetEnd() );
|
||||
arc->SetEnd( temp );
|
||||
}
|
||||
}
|
||||
|
||||
return arc.release();
|
||||
|
@ -1810,13 +1810,14 @@ void SCH_SEXPR_PLUGIN_CACHE::saveArc( LIB_ARC* aArc, OUTPUTFORMATTER& aFormatter
|
||||
{
|
||||
wxCHECK_RET( aArc && aArc->Type() == LIB_ARC_T, "Invalid LIB_ARC object." );
|
||||
|
||||
int x1 = aArc->GetFirstRadiusAngle();
|
||||
int x1;
|
||||
int x2;
|
||||
|
||||
aArc->CalcAngles( x1, x2 );
|
||||
|
||||
if( x1 > 1800 )
|
||||
x1 -= 3600;
|
||||
|
||||
int x2 = aArc->GetSecondRadiusAngle();
|
||||
|
||||
if( x2 > 1800 )
|
||||
x2 -= 3600;
|
||||
|
||||
|
@ -3280,15 +3280,13 @@ LIB_ARC* SCH_LEGACY_PLUGIN_CACHE::loadArc( std::unique_ptr<LIB_SYMBOL>& aSymbol,
|
||||
center.y = Mils2Iu( parseInt( aReader, line, &line ) );
|
||||
|
||||
arc->SetPosition( center );
|
||||
arc->SetRadius( Mils2Iu( parseInt( aReader, line, &line ) ) );
|
||||
|
||||
int radius = Mils2Iu( parseInt( aReader, line, &line ) );
|
||||
int angle1 = parseInt( aReader, line, &line );
|
||||
int angle2 = parseInt( aReader, line, &line );
|
||||
|
||||
NORMALIZE_ANGLE_POS( angle1 );
|
||||
NORMALIZE_ANGLE_POS( angle2 );
|
||||
arc->SetFirstRadiusAngle( angle1 );
|
||||
arc->SetSecondRadiusAngle( angle2 );
|
||||
|
||||
arc->SetUnit( parseInt( aReader, line, &line ) );
|
||||
arc->SetConvert( parseInt( aReader, line, &line ) );
|
||||
@ -3316,17 +3314,31 @@ LIB_ARC* SCH_LEGACY_PLUGIN_CACHE::loadArc( std::unique_ptr<LIB_SYMBOL>& aSymbol,
|
||||
{
|
||||
// Actual Coordinates of arc ends are not read from file
|
||||
// (old library), calculate them
|
||||
wxPoint arcStart( arc->GetRadius(), 0 );
|
||||
wxPoint arcEnd( arc->GetRadius(), 0 );
|
||||
wxPoint arcStart( radius, 0 );
|
||||
wxPoint arcEnd( radius, 0 );
|
||||
|
||||
RotatePoint( &arcStart.x, &arcStart.y, -angle1 );
|
||||
arcStart += arc->GetPosition();
|
||||
arcStart += arc->GetCenter();
|
||||
arc->SetStart( arcStart );
|
||||
RotatePoint( &arcEnd.x, &arcEnd.y, -angle2 );
|
||||
arcEnd += arc->GetPosition();
|
||||
arcEnd += arc->GetCenter();
|
||||
arc->SetEnd( arcEnd );
|
||||
}
|
||||
|
||||
/**
|
||||
* This accounts for an oddity in the old library format, where the symbol is overdefined.
|
||||
* The previous draw (based on wxwidgets) used start point and end point and always drew
|
||||
* counter-clockwise. The new GAL draw takes center, radius and start/end angles. All of
|
||||
* these points were stored in the file, so we need to mimic the swapping of start/end
|
||||
* points rather than using the stored angles in order to properly map edge cases.
|
||||
*/
|
||||
if( !TRANSFORM().MapAngles( &angle1, &angle2 ) )
|
||||
{
|
||||
wxPoint temp = arc->GetStart();
|
||||
arc->SetStart( arc->GetEnd() );
|
||||
arc->SetEnd( temp );
|
||||
}
|
||||
|
||||
return arc;
|
||||
}
|
||||
|
||||
@ -3955,43 +3967,41 @@ void SCH_LEGACY_PLUGIN_CACHE::saveArc( LIB_ARC* aArc, OUTPUTFORMATTER& aFormatte
|
||||
{
|
||||
wxCHECK_RET( aArc && aArc->Type() == LIB_ARC_T, "Invalid LIB_ARC object." );
|
||||
|
||||
int x1 = aArc->GetFirstRadiusAngle();
|
||||
int x1;
|
||||
int x2;
|
||||
|
||||
aArc->CalcAngles( x1, x2 );
|
||||
|
||||
if( x1 > 1800 )
|
||||
x1 -= 3600;
|
||||
|
||||
int x2 = aArc->GetSecondRadiusAngle();
|
||||
|
||||
if( x2 > 1800 )
|
||||
x2 -= 3600;
|
||||
|
||||
aFormatter.Print( 0, "A %d %d %d %d %d %d %d %d %c %d %d %d %d\n",
|
||||
Iu2Mils( aArc->GetPosition().x ), Iu2Mils( aArc->GetPosition().y ),
|
||||
Iu2Mils( aArc->GetRadius() ), x1, x2, aArc->GetUnit(), aArc->GetConvert(),
|
||||
Iu2Mils( aArc->GetWidth() ),
|
||||
fill_tab[ static_cast<int>( aArc->GetFillMode() ) ],
|
||||
Iu2Mils( aArc->GetWidth() ), fill_tab[ (int) aArc->GetFillMode() ],
|
||||
Iu2Mils( aArc->GetStart().x ), Iu2Mils( aArc->GetStart().y ),
|
||||
Iu2Mils( aArc->GetEnd().x ), Iu2Mils( aArc->GetEnd().y ) );
|
||||
}
|
||||
|
||||
|
||||
void SCH_LEGACY_PLUGIN_CACHE::saveBezier( LIB_BEZIER* aBezier,
|
||||
OUTPUTFORMATTER& aFormatter )
|
||||
void SCH_LEGACY_PLUGIN_CACHE::saveBezier( LIB_BEZIER* aBezier, OUTPUTFORMATTER& aFormatter )
|
||||
{
|
||||
wxCHECK_RET( aBezier && aBezier->Type() == LIB_BEZIER_T, "Invalid LIB_BEZIER object." );
|
||||
|
||||
aFormatter.Print( 0, "B %u %d %d %d", (unsigned)aBezier->GetPoints().size(),
|
||||
aBezier->GetUnit(), aBezier->GetConvert(), Iu2Mils( aBezier->GetWidth() ) );
|
||||
|
||||
for( const auto& pt : aBezier->GetPoints() )
|
||||
for( const wxPoint& pt : aBezier->GetPoints() )
|
||||
aFormatter.Print( 0, " %d %d", Iu2Mils( pt.x ), Iu2Mils( pt.y ) );
|
||||
|
||||
aFormatter.Print( 0, " %c\n", fill_tab[static_cast<int>( aBezier->GetFillMode() )] );
|
||||
}
|
||||
|
||||
|
||||
void SCH_LEGACY_PLUGIN_CACHE::saveCircle( LIB_CIRCLE* aCircle,
|
||||
OUTPUTFORMATTER& aFormatter )
|
||||
void SCH_LEGACY_PLUGIN_CACHE::saveCircle( LIB_CIRCLE* aCircle, OUTPUTFORMATTER& aFormatter )
|
||||
{
|
||||
wxCHECK_RET( aCircle && aCircle->Type() == LIB_CIRCLE_T, "Invalid LIB_CIRCLE object." );
|
||||
|
||||
|
@ -92,28 +92,9 @@ public:
|
||||
void SetWidth( int aWidth ) { m_width = aWidth; }
|
||||
int GetWidth() const { return m_width; }
|
||||
|
||||
/**
|
||||
* Set the angle for arcs, and normalizes it within the range 0 - 360 degrees.
|
||||
*
|
||||
* @param aAngle is tenths of degrees, but will soon be degrees.
|
||||
* @param aUpdateEnd set to true to update also arc end coordinates m_thirdPoint, so must
|
||||
* be called after setting m_Start and m_End.
|
||||
*/
|
||||
virtual void SetAngle( double aAngle, bool aUpdateEnd = true );
|
||||
double GetAngle() const { return m_angle; }
|
||||
|
||||
void SetShape( SHAPE_T aShape ) { m_shape = aShape; }
|
||||
SHAPE_T GetShape() const { return m_shape; }
|
||||
|
||||
void SetBezierC1( const wxPoint& aPoint ) { m_bezierC1 = aPoint; }
|
||||
const wxPoint& GetBezierC1() const { return m_bezierC1; }
|
||||
|
||||
void SetBezierC2( const wxPoint& aPoint ) { m_bezierC2 = aPoint; }
|
||||
const wxPoint& GetBezierC2() const { return m_bezierC2; }
|
||||
|
||||
void SetShapePos( const wxPoint& aPos );
|
||||
wxPoint GetShapePos() const;
|
||||
|
||||
/**
|
||||
* Return the starting point of the graphic.
|
||||
*/
|
||||
@ -135,22 +116,26 @@ public:
|
||||
void SetEndX( int x ) { m_end.x = x; }
|
||||
|
||||
/**
|
||||
* Function GetThirdPoint
|
||||
* returns the third point point of the graphic
|
||||
* Set the angle for arcs, and normalizes it within the range 0 - 360 degrees.
|
||||
*
|
||||
* @param aAngle is tenths of degrees, but will soon be degrees.
|
||||
*/
|
||||
const wxPoint& GetThirdPoint() const { return m_thirdPoint; }
|
||||
int GetThirdPointY() { return m_thirdPoint.y; }
|
||||
int GetThirdPointX() { return m_thirdPoint.x; }
|
||||
void SetThirdPoint( const wxPoint& aPoint ) { m_thirdPoint = aPoint; }
|
||||
void SetThirdPointY( int y ) { m_thirdPoint.y = y; }
|
||||
void SetThirdPointX( int x ) { m_thirdPoint.x = x; }
|
||||
virtual void SetArcAngle( double aAngle );
|
||||
virtual void SetArcAngleAndEnd( double aAngle );
|
||||
double GetArcAngle() const { return m_arcAngle; }
|
||||
|
||||
void SetBezierC1( const wxPoint& aPt ) { m_bezierC1 = aPt; }
|
||||
const wxPoint& GetBezierC1() const { return m_bezierC1; }
|
||||
|
||||
void SetBezierC2( const wxPoint& aPt ) { m_bezierC2 = aPt; }
|
||||
const wxPoint& GetBezierC2() const { return m_bezierC2; }
|
||||
|
||||
wxPoint getCenter() const;
|
||||
void SetCenter( const wxPoint& aCenter );
|
||||
|
||||
// Some attributes are read only, since they are derived from m_Start, m_End, and m_Angle.
|
||||
// No Set...() function for these attributes.
|
||||
|
||||
wxPoint getCenter() const;
|
||||
wxPoint GetArcStart() const { return m_end; }
|
||||
wxPoint GetArcEnd() const;
|
||||
wxPoint GetArcMid() const;
|
||||
std::vector<wxPoint> GetRectCorners() const;
|
||||
|
||||
@ -164,35 +149,8 @@ public:
|
||||
*/
|
||||
double GetArcAngleEnd() const;
|
||||
|
||||
/**
|
||||
* Return the radius of this item.
|
||||
*
|
||||
* Has meaning only for arcs and circles.
|
||||
*/
|
||||
int GetRadius() const;
|
||||
|
||||
/**
|
||||
* Initialize the start arc point.
|
||||
*
|
||||
* Can be used for circles to initialize one point of the cicumference.
|
||||
*/
|
||||
void SetArcStart( const wxPoint& aArcStartPoint )
|
||||
{
|
||||
m_end = aArcStartPoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the end arc point.
|
||||
*
|
||||
* Can be used for circles to initialize one point of the cicumference.
|
||||
*/
|
||||
void SetArcEnd( const wxPoint& aArcEndPoint )
|
||||
{
|
||||
m_thirdPoint = aArcEndPoint;
|
||||
}
|
||||
|
||||
void SetArcCenter( const wxPoint& aCenterPoint ) { m_start = aCenterPoint; }
|
||||
|
||||
/**
|
||||
* Set the three controlling points for an arc.
|
||||
*
|
||||
@ -278,6 +236,9 @@ public:
|
||||
int Compare( const EDA_SHAPE* aOther ) const;
|
||||
|
||||
protected:
|
||||
void setPosition( const wxPoint& aPos );
|
||||
wxPoint getPosition() const;
|
||||
|
||||
void move( const wxPoint& aMoveVector );
|
||||
void rotate( const wxPoint& aRotCentre, double aAngle );
|
||||
void flip( const wxPoint& aCentre, bool aFlipLeftRight );
|
||||
@ -300,11 +261,11 @@ protected:
|
||||
SHAPE_T m_shape; // Shape: line, Circle, Arc
|
||||
int m_width; // thickness of lines ...
|
||||
bool m_filled; // Pretty much what it says on the tin...
|
||||
wxPoint m_start; // Line start point or Circle and Arc center
|
||||
wxPoint m_end; // Line end point or circle and arc start point
|
||||
wxPoint m_start; // Line start point or Circle center
|
||||
wxPoint m_end; // Line end point or Circle 3 o'clock point
|
||||
|
||||
wxPoint m_thirdPoint; // Used only for Arcs: arc end point
|
||||
double m_angle; // Used only for Arcs: Arc angle in 1/10 deg
|
||||
wxPoint m_arcCenter; // Used only for Arcs: arc end point
|
||||
double m_arcAngle; // Used only for Arcs: Arc angle in 1/10 deg
|
||||
|
||||
wxPoint m_bezierC1; // Bezier Control Point 1
|
||||
wxPoint m_bezierC2; // Bezier Control Point 2
|
||||
|
@ -117,4 +117,7 @@ static inline wxString FROM_UTF8( const char* cstring )
|
||||
return line;
|
||||
}
|
||||
|
||||
#define UNIMPLEMENTED_FOR( type ) \
|
||||
wxFAIL_MSG( wxString::Format( "%s: unimplemented for %s", __FUNCTION__, type ) )
|
||||
|
||||
#endif // MACROS_H
|
||||
|
@ -106,15 +106,15 @@ void RotatePoint( double *pX, double *pY, double cx, double cy, double angle );
|
||||
* @param aEnd The ending point of the circle (equivalent to aStart)
|
||||
* @return The center of the circle
|
||||
*/
|
||||
const VECTOR2I GetArcCenter( const VECTOR2I& aStart, const VECTOR2I& aMid, const VECTOR2I& 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 VECTOR2I& aStart, const VECTOR2I& aEnd, double aAngle );
|
||||
const VECTOR2I CalcArcCenter( const VECTOR2I& aStart, const VECTOR2I& aMid, const VECTOR2I& aEnd );
|
||||
const VECTOR2D CalcArcCenter( const VECTOR2D& aStart, const VECTOR2D& aMid, const VECTOR2D& aEnd );
|
||||
const wxPoint CalcArcCenter( const wxPoint& aStart, const wxPoint& aMid, const wxPoint& aEnd );
|
||||
const wxPoint CalcArcCenter( const VECTOR2I& aStart, const VECTOR2I& aEnd, double aAngle );
|
||||
|
||||
/**
|
||||
* Return the subtended angle for a given arc.
|
||||
*/
|
||||
double GetArcAngle( const VECTOR2I& aStart, const VECTOR2I& aMid, const VECTOR2I& aEnd );
|
||||
double CalcArcAngle( const VECTOR2I& aStart, const VECTOR2I& aMid, const VECTOR2I& aEnd );
|
||||
|
||||
/**
|
||||
* Return the middle point of an arc, half-way between aStart and aEnd. There are two possible
|
||||
@ -127,8 +127,8 @@ double GetArcAngle( const VECTOR2I& aStart, const VECTOR2I& aMid, const VECTOR2I
|
||||
* @param aMinArcAngle If true, returns the point that results in the smallest arc angle.
|
||||
* @return The middle point of the arc
|
||||
*/
|
||||
const VECTOR2I GetArcMid( const VECTOR2I& aStart, const VECTOR2I& aEnd, const VECTOR2I& aCenter,
|
||||
bool aMinArcAngle = true );
|
||||
const VECTOR2I CalcArcMid( const VECTOR2I& aStart, const VECTOR2I& aEnd, const VECTOR2I& aCenter,
|
||||
bool aMinArcAngle = true );
|
||||
|
||||
/* Return the arc tangent of 0.1 degrees coord vector dx, dy
|
||||
* between -1800 and 1800
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include <math/util.h> // for KiROUND
|
||||
#include <math/vector2d.h> // for VECTOR2I
|
||||
#include <math.h> // for sqrt
|
||||
#include <trigo.h> // for GetArcMid
|
||||
#include <trigo.h> // for CalcArcMid
|
||||
|
||||
|
||||
CIRCLE::CIRCLE()
|
||||
@ -126,7 +126,7 @@ CIRCLE& CIRCLE::ConstructFromTanTanPt( const SEG& aLineA, const SEG& aLineB, con
|
||||
// Calculate bisector
|
||||
VECTOR2I lineApt = furthestFromIntersect( aLineA.A, aLineA.B );
|
||||
VECTOR2I lineBpt = furthestFromIntersect( aLineB.A, aLineB.B );
|
||||
VECTOR2I bisectorPt = GetArcMid( lineApt, lineBpt, intersectPoint, true );
|
||||
VECTOR2I bisectorPt = CalcArcMid( lineApt, lineBpt, intersectPoint, true );
|
||||
|
||||
anglebisector.A = intersectPoint;
|
||||
anglebisector.B = bisectorPt;
|
||||
|
@ -188,7 +188,7 @@ SHAPE_ARC& SHAPE_ARC::ConstructFromStartEndAngle( const VECTOR2I& aStart, const
|
||||
m_end = aEnd;
|
||||
m_width = aWidth;
|
||||
|
||||
VECTOR2I center( GetArcCenter( aStart, aEnd, aAngle ) );
|
||||
VECTOR2I center( CalcArcCenter( aStart, aEnd, aAngle ) );
|
||||
|
||||
RotatePoint( m_mid, center, -aAngle * 10.0 / 2.0 );
|
||||
|
||||
@ -463,7 +463,7 @@ double SHAPE_ARC::GetEndAngle() const
|
||||
|
||||
VECTOR2I SHAPE_ARC::GetCenter() const
|
||||
{
|
||||
return GetArcCenter( m_start, m_mid, m_end );
|
||||
return CalcArcCenter( m_start, m_mid, m_end );
|
||||
}
|
||||
|
||||
|
||||
|
@ -38,7 +38,7 @@
|
||||
#include <math/box2.h> // for BOX2I
|
||||
#include <math/util.h> // for rescale
|
||||
#include <math/vector2d.h> // for VECTOR2, VECTOR2I
|
||||
#include <trigo.h> // for RAD2DECIDEG, GetArcAngle
|
||||
#include <trigo.h> // for RAD2DECIDEG, CalcArcAngle
|
||||
|
||||
class SHAPE;
|
||||
|
||||
|
@ -160,8 +160,8 @@ bool TestSegmentHit( const wxPoint& aRefPoint, const wxPoint& aStart, const wxPo
|
||||
}
|
||||
|
||||
|
||||
const VECTOR2I GetArcMid( const VECTOR2I& aStart, const VECTOR2I& aEnd, const VECTOR2I& aCenter,
|
||||
bool aMinArcAngle )
|
||||
const VECTOR2I CalcArcMid( const VECTOR2I& aStart, const VECTOR2I& aEnd, const VECTOR2I& aCenter,
|
||||
bool aMinArcAngle )
|
||||
{
|
||||
VECTOR2I startVector = aStart - aCenter;
|
||||
VECTOR2I endVector = aEnd - aCenter;
|
||||
@ -359,7 +359,7 @@ void RotatePoint( double* pX, double* pY, double angle )
|
||||
}
|
||||
|
||||
|
||||
const wxPoint GetArcCenter( const VECTOR2I& aStart, const VECTOR2I& aEnd, double aAngle )
|
||||
const wxPoint CalcArcCenter( const VECTOR2I& aStart, const VECTOR2I& aEnd, double aAngle )
|
||||
{
|
||||
VECTOR2I start = aStart;
|
||||
VECTOR2I end = aEnd;
|
||||
@ -387,7 +387,7 @@ const wxPoint GetArcCenter( const VECTOR2I& aStart, const VECTOR2I& aEnd, double
|
||||
}
|
||||
|
||||
|
||||
const VECTOR2D GetArcCenter( const VECTOR2D& aStart, const VECTOR2D& aMid, const VECTOR2D& aEnd )
|
||||
const VECTOR2D CalcArcCenter( const VECTOR2D& aStart, const VECTOR2D& aMid, const VECTOR2D& aEnd )
|
||||
{
|
||||
VECTOR2D center;
|
||||
double yDelta_21 = aMid.y - aStart.y;
|
||||
@ -451,12 +451,12 @@ const VECTOR2D GetArcCenter( const VECTOR2D& aStart, const VECTOR2D& aMid, const
|
||||
}
|
||||
|
||||
|
||||
const VECTOR2I GetArcCenter( const VECTOR2I& aStart, const VECTOR2I& aMid, const VECTOR2I& aEnd )
|
||||
const VECTOR2I CalcArcCenter( const VECTOR2I& aStart, const VECTOR2I& aMid, const VECTOR2I& aEnd )
|
||||
{
|
||||
VECTOR2D dStart( static_cast<double>( aStart.x ), static_cast<double>( aStart.y ) );
|
||||
VECTOR2D dMid( static_cast<double>( aMid.x ), static_cast<double>( aMid.y ) );
|
||||
VECTOR2D dEnd( static_cast<double>( aEnd.x ), static_cast<double>( aEnd.y ) );
|
||||
VECTOR2D dCenter = GetArcCenter( dStart, dMid, dEnd );
|
||||
VECTOR2D dCenter = CalcArcCenter( dStart, dMid, dEnd );
|
||||
|
||||
VECTOR2I iCenter;
|
||||
|
||||
@ -472,12 +472,12 @@ const VECTOR2I GetArcCenter( const VECTOR2I& aStart, const VECTOR2I& aMid, const
|
||||
}
|
||||
|
||||
|
||||
const wxPoint GetArcCenter( const wxPoint& aStart, const wxPoint& aMid, const wxPoint& aEnd )
|
||||
const wxPoint CalcArcCenter( const wxPoint& aStart, const wxPoint& aMid, const wxPoint& aEnd )
|
||||
{
|
||||
VECTOR2D dStart( static_cast<double>( aStart.x ), static_cast<double>( aStart.y ) );
|
||||
VECTOR2D dMid( static_cast<double>( aMid.x ), static_cast<double>( aMid.y ) );
|
||||
VECTOR2D dEnd( static_cast<double>( aEnd.x ), static_cast<double>( aEnd.y ) );
|
||||
VECTOR2D dCenter = GetArcCenter( dStart, dMid, dEnd );
|
||||
VECTOR2D dCenter = CalcArcCenter( dStart, dMid, dEnd );
|
||||
|
||||
wxPoint iCenter;
|
||||
|
||||
@ -493,9 +493,9 @@ const wxPoint GetArcCenter( const wxPoint& aStart, const wxPoint& aMid, const wx
|
||||
}
|
||||
|
||||
|
||||
double GetArcAngle( const VECTOR2I& aStart, const VECTOR2I& aMid, const VECTOR2I& aEnd )
|
||||
double CalcArcAngle( const VECTOR2I& aStart, const VECTOR2I& aMid, const VECTOR2I& aEnd )
|
||||
{
|
||||
VECTOR2I center = GetArcCenter( aStart, aMid, aEnd );
|
||||
VECTOR2I center = CalcArcCenter( aStart, aMid, aEnd );
|
||||
|
||||
// Check if the new arc is CW or CCW
|
||||
VECTOR2D startLine = aStart - center;
|
||||
|
@ -762,35 +762,34 @@ void AR_MATRIX::TraceFilledRectangle( int ux0, int uy0, int ux1, int uy1, LSET a
|
||||
}
|
||||
|
||||
|
||||
void AR_MATRIX::TraceSegmentPcb( PCB_SHAPE* pt_segm, int color, int marge,
|
||||
void AR_MATRIX::TraceSegmentPcb( PCB_SHAPE* aShape, int aColor, int aMargin,
|
||||
AR_MATRIX::CELL_OP op_logic )
|
||||
{
|
||||
int half_width = ( pt_segm->GetWidth() / 2 ) + marge;
|
||||
int half_width = ( aShape->GetWidth() / 2 ) + aMargin;
|
||||
|
||||
// Calculate the bounding rectangle of the segment (if H, V or Via)
|
||||
int ux0 = pt_segm->GetStart().x - GetBrdCoordOrigin().x;
|
||||
int uy0 = pt_segm->GetStart().y - GetBrdCoordOrigin().y;
|
||||
int ux1 = pt_segm->GetEnd().x - GetBrdCoordOrigin().x;
|
||||
int uy1 = pt_segm->GetEnd().y - GetBrdCoordOrigin().y;
|
||||
|
||||
LAYER_NUM layer = UNDEFINED_LAYER; // Draw on all layers
|
||||
|
||||
switch( pt_segm->GetShape() )
|
||||
if( aShape->GetShape() == SHAPE_T::CIRCLE || aShape->GetShape() == SHAPE_T::SEGMENT )
|
||||
{
|
||||
case SHAPE_T::CIRCLE:
|
||||
traceCircle( ux0, uy0, ux1, uy1, half_width, layer, color, op_logic );
|
||||
break;
|
||||
int ux0 = aShape->GetStart().x - GetBrdCoordOrigin().x;
|
||||
int uy0 = aShape->GetStart().y - GetBrdCoordOrigin().y;
|
||||
int ux1 = aShape->GetEnd().x - GetBrdCoordOrigin().x;
|
||||
int uy1 = aShape->GetEnd().y - GetBrdCoordOrigin().y;
|
||||
|
||||
case SHAPE_T::ARC:
|
||||
traceArc( ux0, uy0, ux1, uy1, pt_segm->GetAngle(), half_width, layer, color, op_logic );
|
||||
break;
|
||||
if( aShape->GetShape() == SHAPE_T::CIRCLE )
|
||||
traceCircle( ux0, uy0, ux1, uy1, half_width, layer, aColor, op_logic );
|
||||
else
|
||||
drawSegmentQcq( ux0, uy0, ux1, uy1, half_width, layer, aColor, op_logic );
|
||||
}
|
||||
else if( aShape->GetShape() == SHAPE_T::ARC )
|
||||
{
|
||||
int ux0 = aShape->GetCenter().x - GetBrdCoordOrigin().x;
|
||||
int uy0 = aShape->GetCenter().y - GetBrdCoordOrigin().y;
|
||||
int ux1 = aShape->GetStart().x - GetBrdCoordOrigin().x;
|
||||
int uy1 = aShape->GetStart().y - GetBrdCoordOrigin().y;
|
||||
|
||||
case SHAPE_T::SEGMENT:
|
||||
drawSegmentQcq( ux0, uy0, ux1, uy1, half_width, layer, color, op_logic );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
traceArc( ux0, uy0, ux1, uy1, aShape->GetArcAngle(), half_width, layer, aColor, op_logic );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,7 @@ public:
|
||||
DIST_CELL GetDist( int aRow, int aCol, int aSide );
|
||||
void SetDist( int aRow, int aCol, int aSide, DIST_CELL );
|
||||
|
||||
void TraceSegmentPcb( PCB_SHAPE* pt_segm, int color, int marge, AR_MATRIX::CELL_OP op_logic );
|
||||
void TraceSegmentPcb( PCB_SHAPE* aShape, int aColor, int aMargin, AR_MATRIX::CELL_OP op_logic );
|
||||
|
||||
void CreateKeepOutRectangle( int ux0, int uy0, int ux1, int uy1, int marge, int aKeepOut,
|
||||
LSET aLayerMask );
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <wx/debug.h>
|
||||
#include <wx/msgdlg.h>
|
||||
#include <i18n_utility.h>
|
||||
#include <macros.h>
|
||||
#include <board.h>
|
||||
#include <pcb_group.h>
|
||||
|
||||
@ -167,7 +168,7 @@ std::shared_ptr<SHAPE> BOARD_ITEM::GetEffectiveShape( PCB_LAYER_ID aLayer ) cons
|
||||
{
|
||||
std::shared_ptr<SHAPE> shape;
|
||||
|
||||
wxFAIL_MSG( "GetEffectiveShape() not implemented for " + GetClass() );
|
||||
UNIMPLEMENTED_FOR( GetClass() );
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user