diff --git a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp index f59b3a2295..4ddf4f4516 100644 --- a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp +++ b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp @@ -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; diff --git a/common/eda_shape.cpp b/common/eda_shape.cpp index 0114b28b1e..bc677b6fee 100644 --- a/common/eda_shape.cpp +++ b/common/eda_shape.cpp @@ -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 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::vectorx, 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 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 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 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; diff --git a/common/hash_eda.cpp b/common/hash_eda.cpp index 09345a8a99..69c00351b0 100644 --- a/common/hash_eda.cpp +++ b/common/hash_eda.cpp @@ -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( 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( 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; diff --git a/eeschema/lib_arc.cpp b/eeschema/lib_arc.cpp index b38f6a0755..c4abdee87f 100644 --- a/eeschema/lib_arc.cpp +++ b/eeschema/lib_arc.cpp @@ -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 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( m_t1 ) / 10.0; - double endAngle = static_cast( m_t2 ) / 10.0; + int radius = GetRadius(); + int t1; + int t2; + + CalcAngles( t1, t2 ); + + double startAngle = static_cast( t1 ) / 10.0; + double endAngle = static_cast( 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( m_t1 ) / 10.0 ); - double endAngle = DEG2RAD( static_cast( 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; -} diff --git a/eeschema/lib_arc.h b/eeschema/lib_arc.h index cb74aad590..07f7521f2f 100644 --- a/eeschema/lib_arc.h +++ b/eeschema/lib_arc.h @@ -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. */ diff --git a/eeschema/lib_shape.cpp b/eeschema/lib_shape.cpp new file mode 100644 index 0000000000..0ef902e5b6 --- /dev/null +++ b/eeschema/lib_shape.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include + + +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( 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 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( 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() ); + } +} + + diff --git a/eeschema/lib_shape.h b/eeschema/lib_shape.h new file mode 100644 index 0000000000..197e769857 --- /dev/null +++ b/eeschema/lib_shape.h @@ -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 +#include + + +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& 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 diff --git a/eeschema/sch_item.cpp b/eeschema/sch_item.cpp index 38d89e4824..166c5e10be 100644 --- a/eeschema/sch_item.cpp +++ b/eeschema/sch_item.cpp @@ -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() ); } diff --git a/eeschema/sch_painter.cpp b/eeschema/sch_painter.cpp index 77e5557251..a5b188ae84 100644 --- a/eeschema/sch_painter.cpp +++ b/eeschema/sch_painter.cpp @@ -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 ) ); } } diff --git a/eeschema/sch_plugins/altium/sch_altium_plugin.cpp b/eeschema/sch_plugins/altium/sch_altium_plugin.cpp index 4dc5733bdb..c14328d707 100644 --- a/eeschema/sch_plugins/altium/sch_altium_plugin.cpp +++ b/eeschema/sch_plugins/altium/sch_altium_plugin.cpp @@ -62,7 +62,7 @@ #include #include #include - +#include const wxPoint GetRelativePosition( const wxPoint& aPosition, const SCH_SYMBOL* aSymbol ) { @@ -1350,21 +1350,23 @@ void SCH_ALTIUM_PLUGIN::ParseArc( const std::map& 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 ); } } } diff --git a/eeschema/sch_plugins/cadstar/cadstar_sch_archive_loader.cpp b/eeschema/sch_plugins/cadstar/cadstar_sch_archive_loader.cpp index 7528ef7023..aa870f5370 100644 --- a/eeschema/sch_plugins/cadstar/cadstar_sch_archive_loader.cpp +++ b/eeschema/sch_plugins/cadstar/cadstar_sch_archive_loader.cpp @@ -1590,15 +1590,16 @@ void CADSTAR_SCH_ARCHIVE_LOADER::loadSymDefIntoLibrary( const SYMDEF_ID& aSymdef } -void CADSTAR_SCH_ARCHIVE_LOADER::loadLibrarySymbolShapeVertices( - const std::vector& aCadstarVertices, wxPoint aSymbolOrigin, LIB_SYMBOL* aSymbol, - int aGateNumber, int aLineThickness ) +void CADSTAR_SCH_ARCHIVE_LOADER::loadLibrarySymbolShapeVertices( const std::vector& 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; diff --git a/eeschema/sch_plugins/eagle/sch_eagle_plugin.cpp b/eeschema/sch_plugins/eagle/sch_eagle_plugin.cpp index 96dee2ce36..30658457a7 100644 --- a/eeschema/sch_plugins/eagle/sch_eagle_plugin.cpp +++ b/eeschema/sch_plugins/eagle/sch_eagle_plugin.cpp @@ -1581,7 +1581,7 @@ EAGLE_LIBRARY* SCH_EAGLE_PLUGIN::loadLibrary( wxXmlNode* aLibraryNode, bool SCH_EAGLE_PLUGIN::loadSymbol( wxXmlNode* aSymbolNode, std::unique_ptr& aSymbol, - EDEVICE* aDevice, int aGateNumber, const wxString& aGateName ) + EDEVICE* aDevice, int aGateNumber, const wxString& aGateName ) { wxString symbolName = aSymbolNode->GetAttribute( "name" ); std::vector items; @@ -1831,8 +1831,6 @@ LIB_ITEM* SCH_EAGLE_PLUGIN::loadSymbolWire( std::unique_ptr& 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& 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& 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(); diff --git a/eeschema/sch_plugins/kicad/sch_sexpr_parser.cpp b/eeschema/sch_plugins/kicad/sch_sexpr_parser.cpp index d9df85c580..f62c7530f9 100644 --- a/eeschema/sch_plugins/kicad/sch_sexpr_parser.cpp +++ b/eeschema/sch_plugins/kicad/sch_sexpr_parser.cpp @@ -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 arc = std::make_unique( 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(); diff --git a/eeschema/sch_plugins/kicad/sch_sexpr_plugin.cpp b/eeschema/sch_plugins/kicad/sch_sexpr_plugin.cpp index d3b24822dc..6bed63dac6 100644 --- a/eeschema/sch_plugins/kicad/sch_sexpr_plugin.cpp +++ b/eeschema/sch_plugins/kicad/sch_sexpr_plugin.cpp @@ -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; diff --git a/eeschema/sch_plugins/legacy/sch_legacy_plugin.cpp b/eeschema/sch_plugins/legacy/sch_legacy_plugin.cpp index 5e74497c72..bf4f4b6db1 100644 --- a/eeschema/sch_plugins/legacy/sch_legacy_plugin.cpp +++ b/eeschema/sch_plugins/legacy/sch_legacy_plugin.cpp @@ -3280,15 +3280,13 @@ LIB_ARC* SCH_LEGACY_PLUGIN_CACHE::loadArc( std::unique_ptr& 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& 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( 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( 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." ); diff --git a/include/eda_shape.h b/include/eda_shape.h index 2a4a6f33ae..1f3acf460f 100644 --- a/include/eda_shape.h +++ b/include/eda_shape.h @@ -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 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 diff --git a/include/macros.h b/include/macros.h index ff888f02f2..bc1d6d3d80 100644 --- a/include/macros.h +++ b/include/macros.h @@ -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 diff --git a/libs/kimath/include/trigo.h b/libs/kimath/include/trigo.h index 95f904085a..4d33746ce8 100644 --- a/libs/kimath/include/trigo.h +++ b/libs/kimath/include/trigo.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 diff --git a/libs/kimath/src/geometry/circle.cpp b/libs/kimath/src/geometry/circle.cpp index 291ac1fb72..cd5b52bd6f 100644 --- a/libs/kimath/src/geometry/circle.cpp +++ b/libs/kimath/src/geometry/circle.cpp @@ -24,7 +24,7 @@ #include // for KiROUND #include // for VECTOR2I #include // for sqrt -#include // for GetArcMid +#include // 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; diff --git a/libs/kimath/src/geometry/shape_arc.cpp b/libs/kimath/src/geometry/shape_arc.cpp index e1f1dd5026..5587a1fa8e 100644 --- a/libs/kimath/src/geometry/shape_arc.cpp +++ b/libs/kimath/src/geometry/shape_arc.cpp @@ -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 ); } diff --git a/libs/kimath/src/geometry/shape_line_chain.cpp b/libs/kimath/src/geometry/shape_line_chain.cpp index ce4f303d6a..77d7cb4f95 100644 --- a/libs/kimath/src/geometry/shape_line_chain.cpp +++ b/libs/kimath/src/geometry/shape_line_chain.cpp @@ -38,7 +38,7 @@ #include // for BOX2I #include // for rescale #include // for VECTOR2, VECTOR2I -#include // for RAD2DECIDEG, GetArcAngle +#include // for RAD2DECIDEG, CalcArcAngle class SHAPE; diff --git a/libs/kimath/src/trigo.cpp b/libs/kimath/src/trigo.cpp index c58bcb97aa..31043dfc9b 100644 --- a/libs/kimath/src/trigo.cpp +++ b/libs/kimath/src/trigo.cpp @@ -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( aStart.x ), static_cast( aStart.y ) ); VECTOR2D dMid( static_cast( aMid.x ), static_cast( aMid.y ) ); VECTOR2D dEnd( static_cast( aEnd.x ), static_cast( 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( aStart.x ), static_cast( aStart.y ) ); VECTOR2D dMid( static_cast( aMid.x ), static_cast( aMid.y ) ); VECTOR2D dEnd( static_cast( aEnd.x ), static_cast( 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; diff --git a/pcbnew/autorouter/ar_matrix.cpp b/pcbnew/autorouter/ar_matrix.cpp index 3bdcc1f44a..675aeae274 100644 --- a/pcbnew/autorouter/ar_matrix.cpp +++ b/pcbnew/autorouter/ar_matrix.cpp @@ -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 ); } } diff --git a/pcbnew/autorouter/ar_matrix.h b/pcbnew/autorouter/ar_matrix.h index 9f932b174a..3071441b35 100644 --- a/pcbnew/autorouter/ar_matrix.h +++ b/pcbnew/autorouter/ar_matrix.h @@ -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 ); diff --git a/pcbnew/board_item.cpp b/pcbnew/board_item.cpp index 8625b27a42..8a24f9fa84 100644 --- a/pcbnew/board_item.cpp +++ b/pcbnew/board_item.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -167,7 +168,7 @@ std::shared_ptr BOARD_ITEM::GetEffectiveShape( PCB_LAYER_ID aLayer ) cons { std::shared_ptr shape; - wxFAIL_MSG( "GetEffectiveShape() not implemented for " + GetClass() ); + UNIMPLEMENTED_FOR( GetClass() ); return shape; } diff --git a/pcbnew/board_items_to_polygon_shape_transform.cpp b/pcbnew/board_items_to_polygon_shape_transform.cpp index b8adc8501d..5baaab5187 100644 --- a/pcbnew/board_items_to_polygon_shape_transform.cpp +++ b/pcbnew/board_items_to_polygon_shape_transform.cpp @@ -23,6 +23,7 @@ */ #include +#include #include #include #include @@ -465,12 +466,12 @@ void EDA_SHAPE::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuf } case SHAPE_T::ARC: - TransformArcToPolygon( aCornerBuffer, GetArcStart(), GetArcMid(), GetArcEnd(), width, - aError, aErrorLoc ); + TransformArcToPolygon( aCornerBuffer, GetStart(), GetArcMid(), GetEnd(), width, aError, + aErrorLoc ); break; case SHAPE_T::SEGMENT: - TransformOvalToPolygon( aCornerBuffer, m_start, m_end, width, aError, aErrorLoc ); + TransformOvalToPolygon( aCornerBuffer, GetStart(), GetEnd(), width, aError, aErrorLoc ); break; case SHAPE_T::POLY: @@ -518,8 +519,8 @@ void EDA_SHAPE::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuf case SHAPE_T::BEZIER: { - std::vector ctrlPoints = { m_start, m_bezierC1, m_bezierC2, m_end }; - BEZIER_POLY converter( ctrlPoints ); + std::vector ctrlPts = { GetStart(), GetBezierC1(), GetBezierC2(), GetEnd() }; + BEZIER_POLY converter( ctrlPts ); std::vector< wxPoint> poly; converter.GetPoly( poly, m_width ); @@ -533,8 +534,7 @@ void EDA_SHAPE::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuf } default: - wxFAIL_MSG( "EDA_SHAPE::TransformShapeWithClearanceToPolygon not implemented for " - + SHAPE_T_asString() ); + UNIMPLEMENTED_FOR( SHAPE_T_asString() ); break; } } diff --git a/pcbnew/convert_shape_list_to_polygon.cpp b/pcbnew/convert_shape_list_to_polygon.cpp index d622963b98..707cdcafbc 100644 --- a/pcbnew/convert_shape_list_to_polygon.cpp +++ b/pcbnew/convert_shape_list_to_polygon.cpp @@ -95,18 +95,8 @@ static PCB_SHAPE* findNext( PCB_SHAPE* aShape, const wxPoint& aPoint, if( graphic == aShape || ( graphic->GetFlags() & SKIP_STRUCT ) != 0 ) continue; - switch( graphic->GetShape() ) - { - case SHAPE_T::ARC: - if( aPoint == graphic->GetArcStart() || aPoint == graphic->GetArcEnd() ) - return graphic; - - break; - - default: - if( aPoint == graphic->GetStart() || aPoint == graphic->GetEnd() ) - return graphic; - } + if( aPoint == graphic->GetStart() || aPoint == graphic->GetEnd() ) + return graphic; } // Search again for anything that's close, even something already used. (The latter is @@ -121,42 +111,20 @@ static PCB_SHAPE* findNext( PCB_SHAPE* aShape, const wxPoint& aPoint, if( graphic == aShape ) continue; - switch( graphic->GetShape() ) + d_sq = ( pt - graphic->GetStart() ).SquaredEuclideanNorm(); + + if( d_sq < closest_dist_sq ) { - case SHAPE_T::ARC: - d_sq = ( pt - graphic->GetArcStart() ).SquaredEuclideanNorm(); + closest_dist_sq = d_sq; + closest_graphic = graphic; + } - if( d_sq < closest_dist_sq ) - { - closest_dist_sq = d_sq; - closest_graphic = graphic; - } + d_sq = ( pt - graphic->GetEnd() ).SquaredEuclideanNorm(); - d_sq = ( pt - graphic->GetArcEnd() ).SquaredEuclideanNorm(); - - if( d_sq < closest_dist_sq ) - { - closest_dist_sq = d_sq; - closest_graphic = graphic; - } - break; - - default: - d_sq = ( pt - graphic->GetStart() ).SquaredEuclideanNorm(); - - if( d_sq < closest_dist_sq ) - { - closest_dist_sq = d_sq; - closest_graphic = graphic; - } - - d_sq = ( pt - graphic->GetEnd() ).SquaredEuclideanNorm(); - - if( d_sq < closest_dist_sq ) - { - closest_dist_sq = d_sq; - closest_graphic = graphic; - } + if( d_sq < closest_dist_sq ) + { + closest_dist_sq = d_sq; + closest_graphic = graphic; } } @@ -221,9 +189,9 @@ bool ConvertOutlineToPolygon( std::vector& aSegList, SHAPE_POLY_SET& case SHAPE_T::ARC: { - wxPoint pstart = graphic->GetArcStart(); + wxPoint pstart = graphic->GetStart(); wxPoint center = graphic->GetCenter(); - double angle = -graphic->GetAngle(); + double angle = -graphic->GetArcAngle(); double radius = graphic->GetRadius(); int steps = GetArcToSegmentCount( radius, aErrorMax, angle / 10.0 ); wxPoint pt; @@ -389,8 +357,7 @@ bool ConvertOutlineToPolygon( std::vector& aSegList, SHAPE_POLY_SET& // Polygon start point. Arbitrarily chosen end of the // segment and build the poly from here. - wxPoint startPt = graphic->GetShape() == SHAPE_T::ARC ? graphic->GetArcEnd() - : graphic->GetEnd(); + wxPoint startPt = graphic->GetEnd(); prevPt = startPt; aPolygons.NewOutline(); @@ -443,16 +410,16 @@ bool ConvertOutlineToPolygon( std::vector& aSegList, SHAPE_POLY_SET& // We do not support arcs in polygons, so approximate an arc with a series of // short lines and put those line segments into the !same! PATH. - wxPoint pstart = graphic->GetArcStart(); - wxPoint pend = graphic->GetArcEnd(); + wxPoint pstart = graphic->GetStart(); + wxPoint pend = graphic->GetEnd(); wxPoint pcenter = graphic->GetCenter(); - double angle = -graphic->GetAngle(); + double angle = -graphic->GetArcAngle(); double radius = graphic->GetRadius(); int steps = GetArcToSegmentCount( radius, aErrorMax, angle / 10.0 ); if( !close_enough( prevPt, pstart, aChainingEpsilon ) ) { - wxASSERT( close_enough( prevPt, graphic->GetArcEnd(), aChainingEpsilon ) ); + wxASSERT( close_enough( prevPt, graphic->GetEnd(), aChainingEpsilon ) ); angle = -angle; std::swap( pstart, pend ); @@ -535,8 +502,7 @@ bool ConvertOutlineToPolygon( std::vector& aSegList, SHAPE_POLY_SET& break; default: - wxFAIL_MSG( "ConvertOutlineToPolygon not implemented for " - + graphic->SHAPE_T_asString() ); + UNIMPLEMENTED_FOR( graphic->SHAPE_T_asString() ); return false; } @@ -668,8 +634,8 @@ bool ConvertOutlineToPolygon( std::vector& aSegList, SHAPE_POLY_SET& // Polygon start point. Arbitrarily chosen end of the segment and build the poly // from here. - wxPoint startPt( graphic->GetEnd() ); - prevPt = graphic->GetEnd(); + wxPoint startPt = graphic->GetEnd(); + prevPt = startPt; aPolygons.Append( prevPt, -1, hole ); // do not append the other end point yet, this first 'graphic' might be an arc @@ -700,17 +666,16 @@ bool ConvertOutlineToPolygon( std::vector& aSegList, SHAPE_POLY_SET& // We do not support arcs in polygons, so approximate an arc with a series of // short lines and put those line segments into the !same! PATH. { - wxPoint pstart = graphic->GetArcStart(); - wxPoint pend = graphic->GetArcEnd(); + wxPoint pstart = graphic->GetStart(); + wxPoint pend = graphic->GetEnd(); wxPoint pcenter = graphic->GetCenter(); - double angle = -graphic->GetAngle(); + double angle = -graphic->GetArcAngle(); int radius = graphic->GetRadius(); int steps = GetArcToSegmentCount( radius, aErrorMax, angle / 10.0 ); if( !close_enough( prevPt, pstart, aChainingEpsilon ) ) { - wxASSERT( close_enough( prevPt, graphic->GetArcEnd(), - aChainingEpsilon ) ); + wxASSERT( close_enough( prevPt, graphic->GetEnd(), aChainingEpsilon ) ); angle = -angle; std::swap( pstart, pend ); diff --git a/pcbnew/dialogs/dialog_graphic_item_properties.cpp b/pcbnew/dialogs/dialog_graphic_item_properties.cpp index 85d0ab1a60..d5b544f3bd 100644 --- a/pcbnew/dialogs/dialog_graphic_item_properties.cpp +++ b/pcbnew/dialogs/dialog_graphic_item_properties.cpp @@ -189,7 +189,7 @@ bool DIALOG_GRAPHIC_ITEM_PROPERTIES::TransferDataToWindow() case SHAPE_T::ARC: SetTitle( _( "Arc Properties" ) ); - m_AngleValue = m_item->GetAngle() / 10.0; + m_AngleValue = m_item->GetArcAngle() / 10.0; m_filledCtrl->Show( false ); break; @@ -220,12 +220,7 @@ bool DIALOG_GRAPHIC_ITEM_PROPERTIES::TransferDataToWindow() break; } - if( m_item->GetShape() == SHAPE_T::ARC ) - { - m_startX.SetValue( m_item->GetArcStart().x ); - m_startY.SetValue( m_item->GetArcStart().y ); - } - else if( m_flipStartEnd ) + if( m_flipStartEnd && m_item->GetShape() != SHAPE_T::ARC ) { m_startX.SetValue( m_item->GetEnd().x ); m_startY.SetValue( m_item->GetEnd().y ); @@ -240,12 +235,7 @@ bool DIALOG_GRAPHIC_ITEM_PROPERTIES::TransferDataToWindow() { m_endX.SetValue( m_item->GetRadius() ); } - else if( m_item->GetShape() == SHAPE_T::ARC ) - { - m_endX.SetValue( m_item->GetArcEnd().x ); - m_endY.SetValue( m_item->GetArcEnd().y ); - } - else if( m_flipStartEnd ) + else if( m_flipStartEnd && m_item->GetShape() != SHAPE_T::ARC ) { m_endX.SetValue( m_item->GetStart().x ); m_endY.SetValue( m_item->GetStart().y ); @@ -292,11 +282,7 @@ bool DIALOG_GRAPHIC_ITEM_PROPERTIES::TransferDataFromWindow() BOARD_COMMIT commit( m_parent ); commit.Modify( m_item ); - if( m_item->GetShape() == SHAPE_T::ARC ) - { - m_item->SetArcStart( wxPoint( m_startX.GetValue(), m_startY.GetValue() ) ); - } - else if( m_flipStartEnd ) + if( m_flipStartEnd && m_item->GetShape() != SHAPE_T::ARC ) { m_item->SetEndX( m_startX.GetValue() ); m_item->SetEndY( m_startY.GetValue() ); @@ -311,11 +297,7 @@ bool DIALOG_GRAPHIC_ITEM_PROPERTIES::TransferDataFromWindow() { m_item->SetEnd( m_item->GetStart() + wxPoint( m_endX.GetValue(), 0 ) ); } - else if( m_item->GetShape() == SHAPE_T::ARC ) - { - m_item->SetArcEnd( wxPoint( m_endX.GetValue(), m_endY.GetValue() ) ); - } - else if( m_flipStartEnd ) + else if( m_flipStartEnd && m_item->GetShape() != SHAPE_T::ARC ) { m_item->SetStartX( m_endX.GetValue() ); m_item->SetStartY( m_endY.GetValue() ); @@ -329,14 +311,14 @@ bool DIALOG_GRAPHIC_ITEM_PROPERTIES::TransferDataFromWindow() // For Bezier curve: Set the two control points if( m_item->GetShape() == SHAPE_T::BEZIER ) { - m_item->SetBezierC1( wxPoint( m_bezierCtrl1X.GetValue(), m_bezierCtrl1Y.GetValue())); - m_item->SetBezierC2( wxPoint( m_bezierCtrl2X.GetValue(), m_bezierCtrl2Y.GetValue())); + m_item->SetBezierC1( wxPoint( m_bezierCtrl1X.GetValue(), m_bezierCtrl1Y.GetValue() ) ); + m_item->SetBezierC2( wxPoint( m_bezierCtrl2X.GetValue(), m_bezierCtrl2Y.GetValue() ) ); } if( m_item->GetShape() == SHAPE_T::ARC ) { - m_item->SetArcCenter( GetArcCenter( m_item->GetArcStart(), m_item->GetArcEnd(), m_AngleValue )); - m_item->SetAngle( m_AngleValue * 10.0, false ); + m_item->SetCenter( CalcArcCenter( m_item->GetStart(), m_item->GetEnd(), m_AngleValue ) ); + m_item->SetArcAngle( m_AngleValue * 10.0 ); } if( m_fp_item ) @@ -345,10 +327,13 @@ bool DIALOG_GRAPHIC_ITEM_PROPERTIES::TransferDataFromWindow() m_fp_item->SetStart0( m_fp_item->GetStart() ); m_fp_item->SetEnd0( m_fp_item->GetEnd() ); - if( m_fp_item->GetShape() == SHAPE_T::BEZIER ) + if( m_item->GetShape() == SHAPE_T::ARC ) + m_fp_item->SetCenter0( m_fp_item->GetCenter() ); + + if( m_item->GetShape() == SHAPE_T::BEZIER ) { - m_fp_item->SetBezierC1_0( wxPoint( m_bezierCtrl1X.GetValue(), m_bezierCtrl1Y.GetValue())); - m_fp_item->SetBezierC2_0( wxPoint( m_bezierCtrl2X.GetValue(), m_bezierCtrl2Y.GetValue())); + m_fp_item->SetBezierC1_0( m_fp_item->GetBezierC1() ); + m_fp_item->SetBezierC2_0( m_fp_item->GetBezierC2() ); } } @@ -408,8 +393,7 @@ bool DIALOG_GRAPHIC_ITEM_PROPERTIES::Validate() break; default: - wxFAIL_MSG( "DIALOG_GRAPHIC_ITEM_PROPERTIES::Validate not implemented for shape " - + m_item->SHAPE_T_asString() ); + UNIMPLEMENTED_FOR( m_item->SHAPE_T_asString() ); break; } diff --git a/pcbnew/dialogs/dialog_pad_basicshapes_properties.cpp b/pcbnew/dialogs/dialog_pad_basicshapes_properties.cpp index 0b1e2c5230..bb6422d3f6 100644 --- a/pcbnew/dialogs/dialog_pad_basicshapes_properties.cpp +++ b/pcbnew/dialogs/dialog_pad_basicshapes_properties.cpp @@ -112,14 +112,14 @@ bool DIALOG_PAD_PRIMITIVES_PROPERTIES::TransferDataToWindow() case SHAPE_T::ARC: SetTitle( _( "Arc" ) ); - m_startX.SetValue( m_shape->GetEnd().x ); // confusingly, the start point of the arc - m_startY.SetValue( m_shape->GetEnd().y ); + m_startX.SetValue( m_shape->GetStart().x ); + m_startY.SetValue( m_shape->GetStart().y ); m_staticTextPosEnd->SetLabel( _( "Center" ) ); - m_endX.SetValue( m_shape->GetStart().x ); // arc center - m_endY.SetValue( m_shape->GetStart().y ); + m_endX.SetValue( m_shape->GetCenter().x ); + m_endY.SetValue( m_shape->GetCenter().y ); m_radiusLabel->SetLabel( _( "Angle:" ) ); m_radius.SetUnits( EDA_UNITS::DEGREES ); - m_radius.SetValue( m_shape->GetAngle() ); + m_radius.SetValue( m_shape->GetArcAngle() ); m_ctrl1X.Show( false, true ); m_ctrl1Y.Show( false, true ); m_ctrl2X.Show( false, true ); @@ -199,13 +199,9 @@ bool DIALOG_PAD_PRIMITIVES_PROPERTIES::TransferDataFromWindow() break; case SHAPE_T::ARC: - // NB: we store the center of the arc in m_Start, and, confusingly, - // the start point in m_End - m_shape->SetStart( wxPoint( m_endX.GetValue(), m_endY.GetValue() ) ); - m_shape->SetEnd( wxPoint( m_startX.GetValue(), m_startY.GetValue() ) ); - - // arc angle - m_shape->SetAngle( m_radius.GetValue() ); + m_shape->SetCenter( wxPoint( m_endX.GetValue(), m_endY.GetValue() ) ); + m_shape->SetStart( wxPoint( m_startX.GetValue(), m_startY.GetValue() ) ); + m_shape->SetArcAngleAndEnd( m_radius.GetValue() ); break; case SHAPE_T::CIRCLE: diff --git a/pcbnew/dialogs/dialog_pad_properties.cpp b/pcbnew/dialogs/dialog_pad_properties.cpp index 68a4963bb0..32853684a1 100644 --- a/pcbnew/dialogs/dialog_pad_properties.cpp +++ b/pcbnew/dialogs/dialog_pad_properties.cpp @@ -711,9 +711,8 @@ void DIALOG_PAD_PROPERTIES::displayPrimitivesList() case SHAPE_T::ARC: bs_info[0] = _( "Arc" ); bs_info[1] = _( "center" ) + wxS( " " )+ formatCoord( m_units, primitive->GetCenter() ); - bs_info[2] = _( "start" ) + wxS( " " )+ formatCoord( m_units, - primitive->GetArcStart() ); - bs_info[3] = _( "angle" ) + wxS( " " )+ FormatAngle( primitive->GetAngle() ); + bs_info[2] = _( "start" ) + wxS( " " )+ formatCoord( m_units, primitive->GetStart() ); + bs_info[3] = _( "angle" ) + wxS( " " )+ FormatAngle( primitive->GetArcAngle() ); break; case SHAPE_T::CIRCLE: diff --git a/pcbnew/exporters/export_gencad.cpp b/pcbnew/exporters/export_gencad.cpp index 04013c156e..0dd2ea9b99 100644 --- a/pcbnew/exporters/export_gencad.cpp +++ b/pcbnew/exporters/export_gencad.cpp @@ -1255,23 +1255,14 @@ static void FootprintWriteShape( FILE* aFile, FOOTPRINT* aFootprint, const wxStr } case SHAPE_T::ARC: - { - int arcendx, arcendy; - arcendx = shape->GetEnd0().x - shape->GetStart0().x; - arcendy = shape->GetEnd0().y - shape->GetStart0().y; - RotatePoint( &arcendx, &arcendy, -shape->GetAngle() ); - arcendx += shape->GetStart0().x; - arcendy += shape->GetStart0().y; - fprintf( aFile, "ARC %g %g %g %g %g %g\n", + shape->GetStart0().x / SCALE_FACTOR, + -shape->GetStart0().y / SCALE_FACTOR, shape->GetEnd0().x / SCALE_FACTOR, -shape->GetEnd0().y / SCALE_FACTOR, - arcendx / SCALE_FACTOR, - -arcendy / SCALE_FACTOR, - shape->GetStart0().x / SCALE_FACTOR, - -shape->GetStart0().y / SCALE_FACTOR ); + shape->GetCenter0().x / SCALE_FACTOR, + -shape->GetCenter0().y / SCALE_FACTOR ); break; - } case SHAPE_T::POLY: // Not exported (TODO) diff --git a/pcbnew/exporters/export_idf.cpp b/pcbnew/exporters/export_idf.cpp index 6490de3125..540738264e 100644 --- a/pcbnew/exporters/export_idf.cpp +++ b/pcbnew/exporters/export_idf.cpp @@ -91,11 +91,8 @@ static void idf_export_outline( BOARD* aPcb, IDF3_BOARD& aIDFBoard ) { case SHAPE_T::SEGMENT: { - if( ( graphic->GetStart().x == graphic->GetEnd().x ) - && ( graphic->GetStart().y == graphic->GetEnd().y ) ) - { + if( graphic->GetStart() == graphic->GetEnd() ) break; - } sp.x = graphic->GetStart().x * scale + offX; sp.y = -graphic->GetStart().y * scale + offY; @@ -111,11 +108,8 @@ static void idf_export_outline( BOARD* aPcb, IDF3_BOARD& aIDFBoard ) case SHAPE_T::RECT: { - if( ( graphic->GetStart().x == graphic->GetEnd().x ) - && ( graphic->GetStart().y == graphic->GetEnd().y ) ) - { + if( graphic->GetStart() == graphic->GetEnd() ) break; - } double top = graphic->GetStart().y * scale + offY; double left = graphic->GetStart().x * scale + offX; @@ -137,17 +131,14 @@ static void idf_export_outline( BOARD* aPcb, IDF3_BOARD& aIDFBoard ) case SHAPE_T::ARC: { - if( ( graphic->GetCenter().x == graphic->GetArcStart().x ) - && ( graphic->GetCenter().y == graphic->GetArcStart().y ) ) - { + if( graphic->GetCenter() == graphic->GetStart() ) break; - } sp.x = graphic->GetCenter().x * scale + offX; sp.y = -graphic->GetCenter().y * scale + offY; - ep.x = graphic->GetArcStart().x * scale + offX; - ep.y = -graphic->GetArcStart().y * scale + offY; - IDF_SEGMENT* seg = new IDF_SEGMENT( sp, ep, -graphic->GetAngle() / 10.0, true ); + ep.x = graphic->GetStart().x * scale + offX; + ep.y = -graphic->GetStart().y * scale + offY; + IDF_SEGMENT* seg = new IDF_SEGMENT( sp, ep, -graphic->GetArcAngle() / 10.0, true ); if( seg ) lines.push_back( seg ); diff --git a/pcbnew/fp_shape.cpp b/pcbnew/fp_shape.cpp index 1f2fbd140e..a4c6090103 100644 --- a/pcbnew/fp_shape.cpp +++ b/pcbnew/fp_shape.cpp @@ -57,7 +57,7 @@ void FP_SHAPE::SetLocalCoord() { m_start0 = m_start; m_end0 = m_end; - m_thirdPoint0 = m_thirdPoint; + m_arcCenter0 = m_arcCenter; m_bezierC1_0 = m_bezierC1; m_bezierC2_0 = m_bezierC2; return; @@ -65,13 +65,13 @@ void FP_SHAPE::SetLocalCoord() m_start0 = m_start - fp->GetPosition(); m_end0 = m_end - fp->GetPosition(); - m_thirdPoint0 = m_thirdPoint - fp->GetPosition(); + m_arcCenter0 = m_arcCenter - fp->GetPosition(); m_bezierC1_0 = m_bezierC1 - fp->GetPosition(); m_bezierC2_0 = m_bezierC2 - fp->GetPosition(); double angle = fp->GetOrientation(); RotatePoint( &m_start0.x, &m_start0.y, -angle ); RotatePoint( &m_end0.x, &m_end0.y, -angle ); - RotatePoint( &m_thirdPoint0.x, &m_thirdPoint0.y, -angle ); + RotatePoint( &m_arcCenter0.x, &m_arcCenter0.y, -angle ); RotatePoint( &m_bezierC1_0.x, &m_bezierC1_0.y, -angle ); RotatePoint( &m_bezierC2_0.x, &m_bezierC2_0.y, -angle ); } @@ -83,7 +83,7 @@ void FP_SHAPE::SetDrawCoord() m_start = m_start0; m_end = m_end0; - m_thirdPoint = m_thirdPoint0; + m_arcCenter = m_arcCenter0; m_bezierC1 = m_bezierC1_0; m_bezierC2 = m_bezierC2_0; @@ -91,13 +91,13 @@ void FP_SHAPE::SetDrawCoord() { RotatePoint( &m_start.x, &m_start.y, fp->GetOrientation() ); RotatePoint( &m_end.x, &m_end.y, fp->GetOrientation() ); - RotatePoint( &m_thirdPoint.x, &m_thirdPoint.y, fp->GetOrientation() ); + RotatePoint( &m_arcCenter.x, &m_arcCenter.y, fp->GetOrientation() ); RotatePoint( &m_bezierC1.x, &m_bezierC1.y, fp->GetOrientation() ); RotatePoint( &m_bezierC2.x, &m_bezierC2.y, fp->GetOrientation() ); m_start += fp->GetPosition(); m_end += fp->GetPosition(); - m_thirdPoint += fp->GetPosition(); + m_arcCenter += fp->GetPosition(); m_bezierC1 += fp->GetPosition(); m_bezierC2 += fp->GetPosition(); } @@ -137,22 +137,57 @@ EDA_ITEM* FP_SHAPE::Clone() const } -void FP_SHAPE::SetAngle( double aAngle, bool aUpdateEnd ) +wxPoint FP_SHAPE::GetCenter0() const { - // Mark as depreciated. - // m_Angle does not define the arc anymore - // Update the parent class (updates the global m_ThirdPoint) - PCB_SHAPE::SetAngle( aAngle, aUpdateEnd ); - - // Also update the local m_thirdPoint0 if requested - if( aUpdateEnd ) + switch( m_shape ) { - m_thirdPoint0 = m_end0; - RotatePoint( &m_thirdPoint0, m_start0, -m_angle ); + case SHAPE_T::ARC: + return m_arcCenter0; + + case SHAPE_T::CIRCLE: + return m_start0; + + default: + UNIMPLEMENTED_FOR( SHAPE_T_asString() ); + return wxPoint(); } } +void FP_SHAPE::SetCenter0( const wxPoint& aCenter ) +{ + switch( m_shape ) + { + case SHAPE_T::ARC: + m_arcCenter0 = aCenter; + break; + + case SHAPE_T::CIRCLE: + m_start0 = aCenter; + break; + + default: + UNIMPLEMENTED_FOR( SHAPE_T_asString() ); + } +} + + +void FP_SHAPE::SetArcAngle( double aAngle ) +{ + PCB_SHAPE::SetArcAngle( aAngle ); +} + + +void FP_SHAPE::SetArcAngleAndEnd0( double aAngle ) +{ + PCB_SHAPE::SetArcAngle( aAngle ); + + wxPoint end = GetStart0(); + RotatePoint( &end, GetCenter0(), -m_arcAngle ); + SetEnd0( end ); +} + + void FP_SHAPE::Flip( const wxPoint& aCentre, bool aFlipLeftRight ) { wxPoint pt( 0, 0 ); @@ -160,9 +195,9 @@ void FP_SHAPE::Flip( const wxPoint& aCentre, bool aFlipLeftRight ) switch( GetShape() ) { case SHAPE_T::ARC: - // Update arc angle but do not yet update m_ThirdPoint0 and m_thirdPoint, + // Update arc angle but do not yet update m_arcCenter0 and m_arcCenter, // arc center and start point must be updated before calculation arc end. - SetAngle( -GetAngle(), false ); + SetArcAngle( -GetArcAngle() ); KI_FALLTHROUGH; default: @@ -177,12 +212,12 @@ void FP_SHAPE::Flip( const wxPoint& aCentre, bool aFlipLeftRight ) { MIRROR( m_start.x, aCentre.x ); MIRROR( m_end.x, aCentre.x ); - MIRROR( m_thirdPoint.x, aCentre.x ); + MIRROR( m_arcCenter.x, aCentre.x ); MIRROR( m_bezierC1.x, aCentre.x ); MIRROR( m_bezierC2.x, aCentre.x ); MIRROR( m_start0.x, pt.x ); MIRROR( m_end0.x, pt.x ); - MIRROR( m_thirdPoint0.x, pt.x ); + MIRROR( m_arcCenter0.x, pt.x ); MIRROR( m_bezierC1_0.x, pt.x ); MIRROR( m_bezierC2_0.x, pt.x ); } @@ -190,12 +225,12 @@ void FP_SHAPE::Flip( const wxPoint& aCentre, bool aFlipLeftRight ) { MIRROR( m_start.y, aCentre.y ); MIRROR( m_end.y, aCentre.y ); - MIRROR( m_thirdPoint.y, aCentre.y ); + MIRROR( m_arcCenter.y, aCentre.y ); MIRROR( m_bezierC1.y, aCentre.y ); MIRROR( m_bezierC2.y, aCentre.y ); MIRROR( m_start0.y, pt.y ); MIRROR( m_end0.y, pt.y ); - MIRROR( m_thirdPoint0.y, pt.y ); + MIRROR( m_arcCenter0.y, pt.y ); MIRROR( m_bezierC1_0.y, pt.y ); MIRROR( m_bezierC2_0.y, pt.y ); } @@ -227,9 +262,9 @@ void FP_SHAPE::Mirror( const wxPoint& aCentre, bool aMirrorAroundXAxis ) switch( GetShape() ) { case SHAPE_T::ARC: - // Update arc angle but do not yet update m_ThirdPoint0 and m_thirdPoint, + // Update arc angle but do not yet update m_arcCenter0 and m_arcCenter, // arc center and start point must be updated before calculation arc end. - SetAngle( -GetAngle(), false ); + SetArcAngle( -GetArcAngle() ); KI_FALLTHROUGH; default: @@ -239,7 +274,7 @@ void FP_SHAPE::Mirror( const wxPoint& aCentre, bool aMirrorAroundXAxis ) { MIRROR( m_start0.y, aCentre.y ); MIRROR( m_end0.y, aCentre.y ); - MIRROR( m_thirdPoint0.y, aCentre.y ); + MIRROR( m_arcCenter0.y, aCentre.y ); MIRROR( m_bezierC1_0.y, aCentre.y ); MIRROR( m_bezierC2_0.y, aCentre.y ); } @@ -247,7 +282,7 @@ void FP_SHAPE::Mirror( const wxPoint& aCentre, bool aMirrorAroundXAxis ) { MIRROR( m_start0.x, aCentre.x ); MIRROR( m_end0.x, aCentre.x ); - MIRROR( m_thirdPoint0.x, aCentre.x ); + MIRROR( m_arcCenter0.x, aCentre.x ); MIRROR( m_bezierC1_0.x, aCentre.x ); MIRROR( m_bezierC2_0.x, aCentre.x ); } @@ -290,7 +325,7 @@ void FP_SHAPE::Move( const wxPoint& aMoveVector ) // This is a footprint shape modification. m_start0 += aMoveVector; m_end0 += aMoveVector; - m_thirdPoint0 += aMoveVector; + m_arcCenter0 += aMoveVector; m_bezierC1_0 += aMoveVector; m_bezierC2_0 += aMoveVector; diff --git a/pcbnew/fp_shape.h b/pcbnew/fp_shape.h index 8b1200e8cf..3e89087e9a 100644 --- a/pcbnew/fp_shape.h +++ b/pcbnew/fp_shape.h @@ -70,10 +70,9 @@ public: /** * Sets 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 = true to update also arc end coordinates m_thirdPoint and - * m_thirdPoint0, so must be called after setting m_Start, m_start0, m_End and m_end0 */ - void SetAngle( double aAngle, bool aUpdateEnd = true ) override; + void SetArcAngle( double aAngle ) override; + void SetArcAngleAndEnd0( double aAngle ); /** * Move an edge of the footprint. @@ -114,15 +113,15 @@ public: void SetEnd0( const wxPoint& aPoint ) { m_end0 = aPoint; } const wxPoint& GetEnd0() const { return m_end0; } - void SetThirdPoint0( const wxPoint& aPoint ){ m_thirdPoint0 = aPoint; } - const wxPoint& GetThirdPoint0() const { return m_thirdPoint0; } - void SetBezierC1_0( const wxPoint& aPoint ) { m_bezierC1_0 = aPoint; } const wxPoint& GetBezierC1_0() const { return m_bezierC1_0; } void SetBezierC2_0( const wxPoint& aPoint ) { m_bezierC2_0 = aPoint; } const wxPoint& GetBezierC2_0() const { return m_bezierC2_0; } + wxPoint GetCenter0() const; + void SetCenter0( const wxPoint& aPt ); + /** * Set relative coordinates from draw coordinates. * Call in only when the geometry or the footprint is modified and therefore the relative @@ -160,7 +159,7 @@ public: protected: wxPoint m_start0; ///< Start point or circle center, relative to footprint origin, orient 0. wxPoint m_end0; ///< End point or circle edge, relative to footprint origin, orient 0. - wxPoint m_thirdPoint0; ///< End point for an arc. + wxPoint m_arcCenter0; ///< Center of arc, relative to footprint origin, orient 0. wxPoint m_bezierC1_0; ///< Bezier Control Point 1, relative to footprint origin, orient 0. wxPoint m_bezierC2_0; ///< Bezier Control Point 2, relative to footprint origin, orient 0. }; diff --git a/pcbnew/graphics_cleaner.cpp b/pcbnew/graphics_cleaner.cpp index 0f552d7c30..53a63c947b 100644 --- a/pcbnew/graphics_cleaner.cpp +++ b/pcbnew/graphics_cleaner.cpp @@ -24,6 +24,7 @@ */ #include +#include #include #include #include @@ -71,14 +72,12 @@ bool GRAPHICS_CLEANER::isNullShape( PCB_SHAPE* aShape ) { case SHAPE_T::SEGMENT: case SHAPE_T::RECT: + case SHAPE_T::ARC: return aShape->GetStart() == aShape->GetEnd(); case SHAPE_T::CIRCLE: return aShape->GetRadius() == 0; - case SHAPE_T::ARC: - return aShape->GetCenter() == aShape->GetArcStart(); - case SHAPE_T::POLY: return aShape->GetPointCount() == 0; @@ -87,8 +86,7 @@ bool GRAPHICS_CLEANER::isNullShape( PCB_SHAPE* aShape ) return aShape->GetBezierPoints().empty(); default: - wxFAIL_MSG( "GRAPHICS_CLEANER::isNullSegment unsupported PCB_SHAPE shape: " - + aShape->SHAPE_T_asString() ); + UNIMPLEMENTED_FOR( aShape->SHAPE_T_asString() ); return false; } } @@ -113,8 +111,8 @@ bool GRAPHICS_CLEANER::areEquivalent( PCB_SHAPE* aShape1, PCB_SHAPE* aShape2 ) case SHAPE_T::ARC: return aShape1->GetCenter() == aShape2->GetCenter() - && aShape1->GetArcStart() == aShape2->GetArcStart() - && aShape1->GetAngle() == aShape2->GetAngle(); + && aShape1->GetStart() == aShape2->GetStart() + && aShape1->GetArcAngle() == aShape2->GetArcAngle(); case SHAPE_T::POLY: // TODO diff --git a/pcbnew/import_gfx/graphics_importer_pcbnew.cpp b/pcbnew/import_gfx/graphics_importer_pcbnew.cpp index b0d9f206cf..a0646ac435 100644 --- a/pcbnew/import_gfx/graphics_importer_pcbnew.cpp +++ b/pcbnew/import_gfx/graphics_importer_pcbnew.cpp @@ -82,8 +82,8 @@ void GRAPHICS_IMPORTER_PCBNEW::AddCircle( const VECTOR2D& aCenter, double aRadiu circle->SetFilled( aFilled ); circle->SetLayer( GetLayer() ); circle->SetWidth( MapLineWidth( aWidth ) ); - circle->SetArcCenter( MapCoordinate( aCenter )); - circle->SetArcStart( MapCoordinate( VECTOR2D( aCenter.x + aRadius, aCenter.y ) ) ); + circle->SetStart( MapCoordinate( aCenter )); + circle->SetEnd( MapCoordinate( VECTOR2D( aCenter.x + aRadius, aCenter.y ) ) ); if( circle->Type() == PCB_FP_SHAPE_T ) static_cast( circle.get() )->SetLocalCoord(); @@ -99,9 +99,9 @@ void GRAPHICS_IMPORTER_PCBNEW::AddArc( const VECTOR2D& aCenter, const VECTOR2D& arc->SetShape( SHAPE_T::ARC ); arc->SetLayer( GetLayer() ); arc->SetWidth( MapLineWidth( aWidth ) ); - arc->SetArcCenter( MapCoordinate( aCenter )); - arc->SetArcStart( MapCoordinate( aStart ) ); - arc->SetAngle( aAngle * 10.0 ); // Pcbnew uses the decidegree + arc->SetCenter( MapCoordinate( aCenter )); + arc->SetStart( MapCoordinate( aStart ) ); + arc->SetArcAngleAndEnd( aAngle * 10.0 ); // Pcbnew uses the decidegree if( arc->Type() == PCB_FP_SHAPE_T ) static_cast( arc.get() )->SetLocalCoord(); diff --git a/pcbnew/microwave/microwave_inductor.cpp b/pcbnew/microwave/microwave_inductor.cpp index 954a686acf..6e3dcf24fa 100644 --- a/pcbnew/microwave/microwave_inductor.cpp +++ b/pcbnew/microwave/microwave_inductor.cpp @@ -424,8 +424,7 @@ FOOTPRINT* MICROWAVE_TOOL::createMicrowaveInductor( MICROWAVE_INDUCTOR_PATTERN& // Generate segments for( unsigned jj = 1; jj < buffer.size(); jj++ ) { - FP_SHAPE* seg; - seg = new FP_SHAPE( footprint, SHAPE_T::SEGMENT ); + FP_SHAPE* seg = new FP_SHAPE( footprint, SHAPE_T::SEGMENT ); seg->SetStart( buffer[jj - 1] ); seg->SetEnd( buffer[jj] ); seg->SetWidth( aInductorPattern.m_Width ); diff --git a/pcbnew/pad_custom_shape_functions.cpp b/pcbnew/pad_custom_shape_functions.cpp index ccf18842b4..713a9add6d 100644 --- a/pcbnew/pad_custom_shape_functions.cpp +++ b/pcbnew/pad_custom_shape_functions.cpp @@ -85,9 +85,9 @@ void PAD::AddPrimitiveArc( const wxPoint& aCenter, const wxPoint& aStart, int aA { PCB_SHAPE* item = new PCB_SHAPE( nullptr, SHAPE_T::ARC ); item->SetFilled( false ); - item->SetArcCenter( aCenter ); - item->SetArcStart( aStart ); - item->SetAngle( aArcAngle ); + item->SetCenter( aCenter ); + item->SetStart( aStart ); + item->SetArcAngleAndEnd( aArcAngle ); item->SetWidth( aThickness ); item->SetParent( this ); m_editPrimitives.emplace_back( item ); diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp index 09a7e92847..4443be547c 100644 --- a/pcbnew/pcb_painter.cpp +++ b/pcbnew/pcb_painter.cpp @@ -1340,8 +1340,6 @@ void PCB_PAINTER::draw( const PCB_SHAPE* aShape, int aLayer ) const COLOR4D& color = m_pcbSettings.GetColor( aShape, aShape->GetLayer() ); bool sketch = m_pcbSettings.m_sketchGraphics; int thickness = getLineThickness( aShape->GetWidth() ); - VECTOR2D start( aShape->GetStart() ); - VECTOR2D end( aShape->GetEnd() ); if( sketch ) { @@ -1358,14 +1356,14 @@ void PCB_PAINTER::draw( const PCB_SHAPE* aShape, int aLayer ) case SHAPE_T::SEGMENT: if( sketch ) { - m_gal->DrawSegment( start, end, thickness ); + m_gal->DrawSegment( aShape->GetStart(), aShape->GetEnd(), thickness ); } else { m_gal->SetIsFill( true ); m_gal->SetIsStroke( false ); - m_gal->DrawSegment( start, end, thickness ); + m_gal->DrawSegment( aShape->GetStart(), aShape->GetEnd(), thickness ); } break; @@ -1412,28 +1410,28 @@ void PCB_PAINTER::draw( const PCB_SHAPE* aShape, int aLayer ) case SHAPE_T::ARC: if( sketch ) { - m_gal->DrawArcSegment( start, aShape->GetRadius(), - DECIDEG2RAD( aShape->GetArcAngleStart() ), - DECIDEG2RAD( aShape->GetArcAngleStart() + aShape->GetAngle() ), // Change this - thickness, m_maxError ); + m_gal->DrawArcSegment( aShape->GetCenter(), aShape->GetRadius(), + DECIDEG2RAD( aShape->GetArcAngleStart() ), + DECIDEG2RAD( aShape->GetArcAngleStart() + aShape->GetArcAngle() ), // Change this + thickness, m_maxError ); } else { m_gal->SetIsFill( true ); m_gal->SetIsStroke( false ); - m_gal->DrawArcSegment( start, aShape->GetRadius(), - DECIDEG2RAD( aShape->GetArcAngleStart() ), - DECIDEG2RAD( aShape->GetArcAngleStart() + aShape->GetAngle() ), // Change this - thickness, m_maxError ); + m_gal->DrawArcSegment( aShape->GetCenter(), aShape->GetRadius(), + DECIDEG2RAD( aShape->GetArcAngleStart() ), + DECIDEG2RAD( aShape->GetArcAngleStart() + aShape->GetArcAngle() ), // Change this + thickness, m_maxError ); } break; case SHAPE_T::CIRCLE: if( sketch ) { - m_gal->DrawCircle( start, aShape->GetRadius() - thickness / 2 ); - m_gal->DrawCircle( start, aShape->GetRadius() + thickness / 2 ); + m_gal->DrawCircle( aShape->GetStart(), aShape->GetRadius() - thickness / 2 ); + m_gal->DrawCircle( aShape->GetStart(), aShape->GetRadius() + thickness / 2 ); } else { @@ -1441,7 +1439,7 @@ void PCB_PAINTER::draw( const PCB_SHAPE* aShape, int aLayer ) m_gal->SetIsStroke( thickness > 0 ); m_gal->SetLineWidth( thickness ); - m_gal->DrawCircle( start, aShape->GetRadius() ); + m_gal->DrawCircle( aShape->GetStart(), aShape->GetRadius() ); } break; diff --git a/pcbnew/pcb_shape.cpp b/pcbnew/pcb_shape.cpp index 7c1d10de00..f5bb53f6d8 100644 --- a/pcbnew/pcb_shape.cpp +++ b/pcbnew/pcb_shape.cpp @@ -255,7 +255,7 @@ static struct PCB_SHAPE_DESC &EDA_SHAPE::SetWidth, &EDA_SHAPE::GetWidth, PROPERTY_DISPLAY::DISTANCE ) ); // TODO show certain properties depending on the shape //propMgr.AddProperty( new PROPERTY( _HKI( "Angle" ), - // &PCB_SHAPE::SetAngle, &PCB_SHAPE::GetAngle, PROPERTY_DISPLAY::DECIDEGREE ) ); + // &PCB_SHAPE::SetArcAngle, &PCB_SHAPE::GetAngle, PROPERTY_DISPLAY::DECIDEGREE ) ); // TODO or may have different names (arcs) // TODO type? propMgr.AddProperty( new PROPERTY( _HKI( "End X" ), diff --git a/pcbnew/pcb_shape.h b/pcbnew/pcb_shape.h index 3f3ff47163..da89061256 100644 --- a/pcbnew/pcb_shape.h +++ b/pcbnew/pcb_shape.h @@ -73,8 +73,8 @@ public: return false; } - void SetPosition( const wxPoint& aPos ) override { SetShapePos( aPos ); } - wxPoint GetPosition() const override { return GetShapePos(); } + void SetPosition( const wxPoint& aPos ) override { setPosition( aPos ); } + wxPoint GetPosition() const override { return getPosition(); } wxPoint GetCenter() const override { return getCenter(); } diff --git a/pcbnew/pcb_track.cpp b/pcbnew/pcb_track.cpp index 31ab30d6fe..8a2aa37596 100644 --- a/pcbnew/pcb_track.cpp +++ b/pcbnew/pcb_track.cpp @@ -956,13 +956,13 @@ void PCB_VIA::SwapData( BOARD_ITEM* aImage ) wxPoint PCB_ARC::GetPosition() const { - auto center = GetArcCenter( VECTOR2I( m_Start ), VECTOR2I( m_Mid ), VECTOR2I( m_End ) ); + auto center = CalcArcCenter( VECTOR2I( m_Start ), VECTOR2I( m_Mid ), VECTOR2I( m_End )); return wxPoint( center.x, center.y ); } double PCB_ARC::GetRadius() const { - auto center = GetArcCenter( VECTOR2I( m_Start ), VECTOR2I( m_Mid ), VECTOR2I( m_End ) ); + auto center = CalcArcCenter( VECTOR2I( m_Start ), VECTOR2I( m_Mid ), VECTOR2I( m_End )); return GetLineLength( wxPoint( center ), m_Start ); } diff --git a/pcbnew/plot_brditems_plotter.cpp b/pcbnew/plot_brditems_plotter.cpp index 34c49965c4..024aada574 100644 --- a/pcbnew/plot_brditems_plotter.cpp +++ b/pcbnew/plot_brditems_plotter.cpp @@ -541,10 +541,8 @@ void BRDITEMS_PLOTTER::PlotFootprintGraphicItem( const FP_SHAPE* aShape ) m_plotter->SetColor( getColor( aShape->GetLayer() ) ); - bool sketch = GetPlotMode() == SKETCH; - int thickness = aShape->GetWidth(); - wxPoint pos( aShape->GetStart() ); - wxPoint end( aShape->GetEnd() ); + bool sketch = GetPlotMode() == SKETCH; + int thickness = aShape->GetWidth(); GBR_METADATA gbr_metadata; gbr_metadata.SetNetAttribType( GBR_NETLIST_METADATA::GBR_NETINFO_CMP ); @@ -568,7 +566,8 @@ void BRDITEMS_PLOTTER::PlotFootprintGraphicItem( const FP_SHAPE* aShape ) switch( aShape->GetShape() ) { case SHAPE_T::SEGMENT: - m_plotter->ThickSegment( pos, end, thickness, GetPlotMode(), &gbr_metadata ); + m_plotter->ThickSegment( aShape->GetStart(), aShape->GetEnd(), thickness, GetPlotMode(), + &gbr_metadata ); break; case SHAPE_T::RECT: @@ -596,30 +595,38 @@ void BRDITEMS_PLOTTER::PlotFootprintGraphicItem( const FP_SHAPE* aShape ) break; case SHAPE_T::CIRCLE: - radius = KiROUND( GetLineLength( end, pos ) ); + radius = KiROUND( GetLineLength( aShape->GetStart(), aShape->GetEnd() ) ); if( aShape->IsFilled() ) - m_plotter->FilledCircle( pos, radius * 2 + thickness, GetPlotMode(), &gbr_metadata ); + { + m_plotter->FilledCircle( aShape->GetStart(), radius * 2 + thickness, GetPlotMode(), + &gbr_metadata ); + } else - m_plotter->ThickCircle( pos, radius * 2, thickness, GetPlotMode(), &gbr_metadata ); + { + m_plotter->ThickCircle( aShape->GetStart(), radius * 2, thickness, GetPlotMode(), + &gbr_metadata ); + } break; case SHAPE_T::ARC: { - radius = KiROUND( GetLineLength( end, pos ) ); - double startAngle = ArcTangente( end.y - pos.y, end.x - pos.x ); - double endAngle = startAngle + aShape->GetAngle(); + radius = KiROUND( GetLineLength( aShape->GetCenter(), aShape->GetStart() ) ); + double startAngle = ArcTangente( aShape->GetStart().y - aShape->GetCenter().y, + aShape->GetStart().x - aShape->GetCenter().x ); + double endAngle = startAngle + aShape->GetArcAngle(); // when startAngle == endAngle ThickArc() doesn't know whether it's 0 deg and 360 deg - if( std::abs( aShape->GetAngle() ) == 3600.0 ) + if( std::abs( aShape->GetArcAngle() ) == 3600.0 ) { - m_plotter->ThickCircle( pos, radius * 2, thickness, GetPlotMode(), &gbr_metadata ); + m_plotter->ThickCircle( aShape->GetCenter(), radius * 2, thickness, GetPlotMode(), + &gbr_metadata ); } else { - m_plotter->ThickArc( pos, -endAngle, -startAngle, radius, thickness, GetPlotMode(), - &gbr_metadata ); + m_plotter->ThickArc( aShape->GetCenter(), -endAngle, -startAngle, radius, thickness, + GetPlotMode(), &gbr_metadata ); } } break; @@ -865,16 +872,11 @@ void BRDITEMS_PLOTTER::PlotPcbShape( const PCB_SHAPE* aShape ) if( !m_layerMask[aShape->GetLayer()] ) return; - int radius = 0; - double StAngle = 0, EndAngle = 0; bool sketch = GetPlotMode() == SKETCH; int thickness = aShape->GetWidth(); m_plotter->SetColor( getColor( aShape->GetLayer() ) ); - wxPoint start( aShape->GetStart() ); - wxPoint end( aShape->GetEnd() ); - GBR_METADATA gbr_metadata; if( aShape->GetLayer() == Edge_Cuts ) @@ -889,34 +891,42 @@ void BRDITEMS_PLOTTER::PlotPcbShape( const PCB_SHAPE* aShape ) switch( aShape->GetShape() ) { case SHAPE_T::SEGMENT: - m_plotter->ThickSegment( start, end, thickness, GetPlotMode(), &gbr_metadata ); + m_plotter->ThickSegment( aShape->GetStart(), aShape->GetEnd(), thickness, GetPlotMode(), + &gbr_metadata ); break; case SHAPE_T::CIRCLE: - radius = KiROUND( GetLineLength( end, start ) ); - if( aShape->IsFilled() ) - m_plotter->FilledCircle( start, radius * 2 + thickness, GetPlotMode(), &gbr_metadata ); + { + m_plotter->FilledCircle( aShape->GetStart(), aShape->GetRadius() * 2 + thickness, + GetPlotMode(), &gbr_metadata ); + } else - m_plotter->ThickCircle( start, radius * 2, thickness, GetPlotMode(), &gbr_metadata ); + { + m_plotter->ThickCircle( aShape->GetStart(), aShape->GetRadius() * 2, thickness, + GetPlotMode(), &gbr_metadata ); + } break; case SHAPE_T::ARC: - radius = KiROUND( GetLineLength( end, start ) ); - StAngle = ArcTangente( end.y - start.y, end.x - start.x ); - EndAngle = StAngle + aShape->GetAngle(); + { + double startAngle = ArcTangente( aShape->GetStart().y - aShape->GetCenter().y, + aShape->GetStart().x - aShape->GetCenter().x ); + double endAngle = startAngle + aShape->GetArcAngle(); // when startAngle == endAngle ThickArc() doesn't know whether it's 0 deg and 360 deg - if( std::abs( aShape->GetAngle() ) == 3600.0 ) + if( std::abs( aShape->GetArcAngle() ) == 3600.0 ) { - m_plotter->ThickCircle( start, radius * 2, thickness, GetPlotMode(), &gbr_metadata ); + m_plotter->ThickCircle( aShape->GetCenter(), aShape->GetRadius() * 2, thickness, + GetPlotMode(), &gbr_metadata ); } else { - m_plotter->ThickArc( start, -EndAngle, -StAngle, radius, thickness, GetPlotMode(), - &gbr_metadata ); + m_plotter->ThickArc( aShape->GetCenter(), -endAngle, -startAngle, aShape->GetRadius(), + thickness, GetPlotMode(), &gbr_metadata ); } + } break; case SHAPE_T::BEZIER: @@ -984,8 +994,7 @@ void BRDITEMS_PLOTTER::PlotPcbShape( const PCB_SHAPE* aShape ) } default: - wxASSERT_MSG( false, "Unhandled PCB_SHAPE shape" ); - m_plotter->ThickSegment( start, end, thickness, GetPlotMode(), &gbr_metadata ); + UNIMPLEMENTED_FOR( aShape->SHAPE_T_asString() ); } } diff --git a/pcbnew/plugins/altium/altium_pcb.cpp b/pcbnew/plugins/altium/altium_pcb.cpp index 8572bd5dbe..522849cdc5 100644 --- a/pcbnew/plugins/altium/altium_pcb.cpp +++ b/pcbnew/plugins/altium/altium_pcb.cpp @@ -862,24 +862,25 @@ void ALTIUM_PCB::HelperCreateBoardOutline( const std::vector& aV else if( cur->isRound ) { shape->SetShape( SHAPE_T::ARC ); - shape->SetAngle( -NormalizeAngleDegreesPos( cur->endangle - cur->startangle ) * 10. ); + double includedAngle = cur->endangle - cur->startangle; double startradiant = DEG2RAD( cur->startangle ); wxPoint arcStartOffset = wxPoint( KiROUND( std::cos( startradiant ) * cur->radius ), - -KiROUND( std::sin( startradiant ) * cur->radius ) ); + -KiROUND( std::sin( startradiant ) * cur->radius ) ); wxPoint arcStart = cur->center + arcStartOffset; - shape->SetArcCenter( cur->center ); - shape->SetArcStart( arcStart ); + + shape->SetCenter( cur->center ); + shape->SetStart( arcStart ); + shape->SetArcAngleAndEnd( -NormalizeAngleDegreesPos( includedAngle ) * 10.0 ); if( !last->isRound ) { double endradiant = DEG2RAD( cur->endangle ); wxPoint arcEndOffset = wxPoint( KiROUND( std::cos( endradiant ) * cur->radius ), - -KiROUND( std::sin( endradiant ) * cur->radius ) ); + -KiROUND( std::sin( endradiant ) * cur->radius ) ); wxPoint arcEnd = cur->center + arcEndOffset; - PCB_SHAPE* shape2 = new PCB_SHAPE( m_board ); - shape2->SetShape( SHAPE_T::SEGMENT ); + PCB_SHAPE* shape2 = new PCB_SHAPE( m_board, SHAPE_T::SEGMENT ); m_board->Add( shape2, ADD_MODE::APPEND ); shape2->SetWidth( m_board->GetDesignSettings().GetLineThickness( Edge_Cuts ) ); shape2->SetLayer( Edge_Cuts ); @@ -888,14 +889,11 @@ void ALTIUM_PCB::HelperCreateBoardOutline( const std::vector& aV // TODO: this is more of a hack than the real solution double lineLengthStart = GetLineLength( last->position, arcStart ); double lineLengthEnd = GetLineLength( last->position, arcEnd ); + if( lineLengthStart > lineLengthEnd ) - { shape2->SetEnd( cur->center + arcEndOffset ); - } else - { shape2->SetEnd( cur->center + arcStartOffset ); - } } } last = cur; @@ -1922,22 +1920,25 @@ void ALTIUM_PCB::ParseArcs6Data( const CFB::CompoundFileReader& aReader, { PCB_SHAPE shape( nullptr ); // just a helper to get the graphic shape.SetWidth( elem.width ); - shape.SetArcCenter( elem.center ); if( elem.startangle == 0. && elem.endangle == 360. ) { // TODO: other variants to define circle? shape.SetShape( SHAPE_T::CIRCLE ); - shape.SetArcStart( elem.center - wxPoint( 0, elem.radius ) ); + shape.SetStart( elem.center ); + shape.SetEnd( elem.center - wxPoint( 0, elem.radius ) ); } else { shape.SetShape( SHAPE_T::ARC ); + double includedAngle = elem.endangle - elem.startangle; double startradiant = DEG2RAD( elem.startangle ); wxPoint arcStartOffset = wxPoint( KiROUND( std::cos( startradiant ) * elem.radius ), -KiROUND( std::sin( startradiant ) * elem.radius ) ); - shape.SetArcStart( elem.center + arcStartOffset ); - shape.SetAngle( -NormalizeAngleDegreesPos( elem.endangle - elem.startangle ) * 10. ); + + shape.SetCenter( elem.center ); + shape.SetStart( elem.center + arcStartOffset ); + shape.SetArcAngleAndEnd( -NormalizeAngleDegreesPos( includedAngle ) * 10.0 ); } ZONE* zone = new ZONE( m_board ); @@ -2023,24 +2024,27 @@ void ALTIUM_PCB::ParseArcs6Data( const CFB::CompoundFileReader& aReader, else { PCB_SHAPE* shape = HelperCreateAndAddShape( elem.component ); - shape->SetArcCenter( elem.center ); shape->SetWidth( elem.width ); shape->SetLayer( klayer ); if( elem.startangle == 0. && elem.endangle == 360. ) { // TODO: other variants to define circle? shape->SetShape( SHAPE_T::CIRCLE ); - shape->SetArcStart( elem.center - wxPoint( 0, elem.radius ) ); + shape->SetStart( elem.center ); + shape->SetEnd( elem.center - wxPoint( 0, elem.radius ) ); } else { shape->SetShape( SHAPE_T::ARC ); - shape->SetAngle( -NormalizeAngleDegreesPos( elem.endangle - elem.startangle ) * 10. ); + double includedAngle = elem.endangle - elem.startangle; double startradiant = DEG2RAD( elem.startangle ); wxPoint arcStartOffset = wxPoint( KiROUND( std::cos( startradiant ) * elem.radius ), -KiROUND( std::sin( startradiant ) * elem.radius ) ); - shape->SetArcStart( elem.center + arcStartOffset ); + + shape->SetCenter( elem.center ); + shape->SetStart( elem.center + arcStartOffset ); + shape->SetArcAngleAndEnd( -NormalizeAngleDegreesPos( includedAngle ) * 10.0 ); } HelperShapeSetLocalCoord( shape, elem.component ); @@ -2363,9 +2367,9 @@ void ALTIUM_PCB::HelperParsePad6NonCopper( const APAD6& aElem ) // circle shape->SetShape( SHAPE_T::CIRCLE ); shape->SetFilled( true ); - shape->SetArcCenter( aElem.position ); + shape->SetStart( aElem.position ); + shape->SetEnd( aElem.position - wxPoint( 0, aElem.topsize.x / 4 ) ); shape->SetWidth( aElem.topsize.x / 2 ); - shape->SetArcStart( aElem.position - wxPoint( 0, aElem.topsize.x / 4 ) ); } else if( aElem.topsize.x < aElem.topsize.y ) { @@ -2396,9 +2400,9 @@ void ALTIUM_PCB::HelperParsePad6NonCopper( const APAD6& aElem ) shape->SetShape( SHAPE_T::CIRCLE ); shape->SetFilled( true ); shape->SetLayer( klayer ); - shape->SetArcCenter( aElem.position ); + shape->SetStart( aElem.position ); + shape->SetEnd( aElem.position - wxPoint( 0, aElem.topsize.x / 4 ) ); shape->SetWidth( aElem.topsize.x / 2 ); - shape->SetArcStart( aElem.position - wxPoint( 0, aElem.topsize.x / 4 ) ); HelperShapeSetLocalCoord( shape, aElem.component ); } else diff --git a/pcbnew/plugins/cadstar/cadstar_pcb_archive_loader.cpp b/pcbnew/plugins/cadstar/cadstar_pcb_archive_loader.cpp index acde795e56..1abcdf7363 100644 --- a/pcbnew/plugins/cadstar/cadstar_pcb_archive_loader.cpp +++ b/pcbnew/plugins/cadstar/cadstar_pcb_archive_loader.cpp @@ -2818,8 +2818,8 @@ PCB_SHAPE* CADSTAR_PCB_ARCHIVE_LOADER::getShapeFromVertex( const POINT& aCadstar else shape = new PCB_SHAPE( aContainer, SHAPE_T::ARC ); - shape->SetArcStart( startPoint ); - shape->SetArcCenter( centerPoint ); + shape->SetCenter( centerPoint ); + shape->SetStart( startPoint ); arcStartAngle = getPolarAngle( startPoint - centerPoint ); arcEndAngle = getPolarAngle( endPoint - centerPoint ); @@ -2828,9 +2828,9 @@ PCB_SHAPE* CADSTAR_PCB_ARCHIVE_LOADER::getShapeFromVertex( const POINT& aCadstar // with opposite start/end points and same centre point) if( cw ) - shape->SetAngle( NormalizeAnglePos( arcAngle ) ); + shape->SetArcAngleAndEnd( NormalizeAnglePos( arcAngle ) ); else - shape->SetAngle( NormalizeAngleNeg( arcAngle ) ); + shape->SetArcAngleAndEnd( NormalizeAngleNeg( arcAngle ) ); break; } @@ -2960,12 +2960,12 @@ SHAPE_LINE_CHAIN CADSTAR_PCB_ARCHIVE_LOADER::getLineChainFromShapes( const std:: if( shape->GetClass() == wxT( "MGRAPHIC" ) ) { FP_SHAPE* fp_shape = (FP_SHAPE*) shape; - SHAPE_ARC arc( fp_shape->GetStart0(), fp_shape->GetEnd0(), (double) fp_shape->GetAngle() / 10.0 ); + SHAPE_ARC arc( fp_shape->GetCenter0(), fp_shape->GetStart0(), fp_shape->GetArcAngle() / 10.0 ); lineChain.Append( arc ); } else { - SHAPE_ARC arc( shape->GetCenter(), shape->GetArcStart(), (double) shape->GetAngle() / 10.0 ); + SHAPE_ARC arc( shape->GetCenter(), shape->GetStart(), shape->GetArcAngle() / 10.0 ); lineChain.Append( arc ); } } @@ -3041,15 +3041,13 @@ std::vector CADSTAR_PCB_ARCHIVE_LOADER::makeTracksFromShapes( if( shape->GetClass() == wxT( "MGRAPHIC" ) ) { FP_SHAPE* fp_shape = (FP_SHAPE*) shape; - SHAPE_ARC arc( fp_shape->GetStart0(), fp_shape->GetEnd0(), - (double) fp_shape->GetAngle() / 10.0 ); - SHAPE_ARC arc( fp_shape->GetStart0(), fp_shape->GetEnd0(), - fp_shape->GetAngle() / 10.0 ); + SHAPE_ARC arc( fp_shape->GetCenter0(), fp_shape->GetStart0(), + fp_shape->GetArcAngle() / 10.0 ); track = new PCB_ARC( aParentContainer, &arc ); } else { - SHAPE_ARC arc( shape->GetCenter(), shape->GetArcStart(), (double) shape->GetAngle() / 10.0 ); + SHAPE_ARC arc( shape->GetCenter(), shape->GetStart(), shape->GetArcAngle() / 10.0 ); track = new PCB_ARC( aParentContainer, &arc ); } break; diff --git a/pcbnew/plugins/eagle/eagle_plugin.cpp b/pcbnew/plugins/eagle/eagle_plugin.cpp index 8d0f0cdcb5..7462cb5dc1 100644 --- a/pcbnew/plugins/eagle/eagle_plugin.cpp +++ b/pcbnew/plugins/eagle/eagle_plugin.cpp @@ -715,6 +715,7 @@ void EAGLE_PLUGIN::loadPlain( wxXmlNode* aGraphics ) if( !w.curve ) { + shape->SetShape( SHAPE_T::SEGMENT ); shape->SetStart( start ); shape->SetEnd( end ); } @@ -723,9 +724,9 @@ void EAGLE_PLUGIN::loadPlain( wxXmlNode* aGraphics ) wxPoint center = ConvertArcCenter( start, end, *w.curve ); shape->SetShape( SHAPE_T::ARC ); - shape->SetStart( center ); - shape->SetEnd( start ); - shape->SetAngle( *w.curve * -10.0 ); // KiCad rotates the other way + shape->SetCenter( center ); + shape->SetStart( start ); + shape->SetArcAngleAndEnd( *w.curve * -10.0 ); // KiCad rotates the other way } shape->SetLayer( layer ); @@ -1773,9 +1774,9 @@ void EAGLE_PLUGIN::packageWire( FOOTPRINT* aFootprint, wxXmlNode* aTree ) const dwg = new FP_SHAPE( aFootprint, SHAPE_T::ARC ); wxPoint center = ConvertArcCenter( start, end, *w.curve ); - dwg->SetStart0( center ); - dwg->SetEnd0( start ); - dwg->SetAngle( *w.curve * -10.0 ); // KiCad rotates the other way + dwg->SetCenter0( center ); + dwg->SetStart0( start ); + dwg->SetArcAngleAndEnd0( *w.curve * -10.0 ); // KiCad rotates the other way } dwg->SetLayer( layer ); diff --git a/pcbnew/plugins/fabmaster/import_fabmaster.cpp b/pcbnew/plugins/fabmaster/import_fabmaster.cpp index 255e2d838f..f1d3111372 100644 --- a/pcbnew/plugins/fabmaster/import_fabmaster.cpp +++ b/pcbnew/plugins/fabmaster/import_fabmaster.cpp @@ -2120,16 +2120,16 @@ bool FABMASTER::loadFootprints( BOARD* aBoard ) if( src->mirror ) { arc->SetLayer( FlipLayer( layer ) ); - arc->SetArcCenter( wxPoint( lsrc->center_x, 2 * src->y - lsrc->center_y )); - arc->SetArcStart( wxPoint( lsrc->end_x, 2 * src->y - lsrc->end_y ) ); - arc->SetAngle( lsrc->result.GetCentralAngle() * 10.0 ); + arc->SetCenter( wxPoint( lsrc->center_x, 2 * src->y - lsrc->center_y ) ); + arc->SetStart( wxPoint( lsrc->end_x, 2 * src->y - lsrc->end_y ) ); + arc->SetArcAngleAndEnd0( lsrc->result.GetCentralAngle() * 10.0 ); } else { arc->SetLayer( layer ); - arc->SetArcCenter( wxPoint( lsrc->center_x, lsrc->center_y )); - arc->SetArcStart( wxPoint( lsrc->end_x, lsrc->end_y ) ); - arc->SetAngle( -lsrc->result.GetCentralAngle() * 10.0 ); + arc->SetCenter( wxPoint( lsrc->center_x, lsrc->center_y ) ); + arc->SetStart( wxPoint( lsrc->end_x, lsrc->end_y ) ); + arc->SetArcAngleAndEnd0( -lsrc->result.GetCentralAngle() * 10.0 ); } arc->SetWidth( lsrc->width ); @@ -2773,9 +2773,9 @@ bool FABMASTER::loadOutline( BOARD* aBoard, const std::unique_ptrSetLayer( layer ); - arc->SetArcCenter( wxPoint( src->center_x, src->center_y )); - arc->SetArcStart( wxPoint( src->start_x, src->start_y ) ); - arc->SetAngle( src->result.GetCentralAngle() * 10.0 ); + arc->SetCenter( wxPoint( src->center_x, src->center_y ) ); + arc->SetStart( wxPoint( src->start_x, src->start_y ) ); + arc->SetArcAngleAndEnd( src->result.GetCentralAngle() * 10.0 ); arc->SetWidth( src->width ); if( arc->GetWidth() == 0 ) @@ -2888,9 +2888,9 @@ bool FABMASTER::loadGraphics( BOARD* aBoard ) PCB_SHAPE* arc = new PCB_SHAPE( aBoard, SHAPE_T::ARC ); arc->SetLayer( layer ); - arc->SetArcCenter( wxPoint( src->center_x, src->center_y )); - arc->SetArcStart( wxPoint( src->start_x, src->start_y ) ); - arc->SetAngle( src->result.GetCentralAngle() * 10.0 ); + arc->SetCenter( wxPoint( src->center_x, src->center_y ) ); + arc->SetStart( wxPoint( src->start_x, src->start_y ) ); + arc->SetArcAngleAndEnd( src->result.GetCentralAngle() * 10.0 ); arc->SetWidth( src->width ); aBoard->Add( arc, ADD_MODE::APPEND ); diff --git a/pcbnew/plugins/geda/gpcb_plugin.cpp b/pcbnew/plugins/geda/gpcb_plugin.cpp index f5684a2710..f898dfda90 100644 --- a/pcbnew/plugins/geda/gpcb_plugin.cpp +++ b/pcbnew/plugins/geda/gpcb_plugin.cpp @@ -497,7 +497,7 @@ FOOTPRINT* GPCB_FPL_CACHE::parseFOOTPRINT( LINE_READER* aLineReader ) wxPoint centre( parseInt( parameters[2], conv_unit ), parseInt( parameters[3], conv_unit ) ); - shape->SetStart0( centre ); + shape->SetCenter0( centre ); // Pcbnew start angles are inverted and 180 degrees from Geda PCB angles. double start_angle = parseInt( parameters[6], -10.0 ) + 1800.0; @@ -509,14 +509,14 @@ FOOTPRINT* GPCB_FPL_CACHE::parseFOOTPRINT( LINE_READER* aLineReader ) if( sweep_angle == -3600.0 ) shape->SetShape( SHAPE_T::CIRCLE ); - // Angle value is clockwise in gpcb and Pcbnew. - shape->SetAngle( sweep_angle ); - shape->SetEnd0( wxPoint( radius, 0 ) ); - // Calculate start point coordinate of arc - wxPoint arcStart( shape->GetEnd0() ); + wxPoint arcStart( radius, 0 ); RotatePoint( &arcStart, -start_angle ); - shape->SetEnd0( centre + arcStart ); + shape->SetStart0( arcStart + centre ); + + // Angle value is clockwise in gpcb and Pcbnew. + shape->SetArcAngleAndEnd0( sweep_angle ); + shape->SetWidth( parseInt( parameters[8], conv_unit ) ); shape->SetDrawCoord(); continue; diff --git a/pcbnew/plugins/kicad/kicad_plugin.cpp b/pcbnew/plugins/kicad/kicad_plugin.cpp index a518c34caa..bbe2ee5014 100644 --- a/pcbnew/plugins/kicad/kicad_plugin.cpp +++ b/pcbnew/plugins/kicad/kicad_plugin.cpp @@ -803,10 +803,6 @@ void PCB_IO::format( const PCB_SHAPE* aShape, int aNestLevel ) const locked.c_str(), FormatInternalUnits( aShape->GetStart() ).c_str(), FormatInternalUnits( aShape->GetEnd() ).c_str() ); - - if( aShape->GetAngle() != 0.0 ) - m_out->Print( 0, " (angle %s)", FormatAngle( aShape->GetAngle() ).c_str() ); - break; case SHAPE_T::RECT: @@ -826,9 +822,9 @@ void PCB_IO::format( const PCB_SHAPE* aShape, int aNestLevel ) const case SHAPE_T::ARC: m_out->Print( aNestLevel, "(gr_arc%s (start %s) (end %s) (angle %s)", locked.c_str(), + FormatInternalUnits( aShape->GetCenter() ).c_str(), FormatInternalUnits( aShape->GetStart() ).c_str(), - FormatInternalUnits( aShape->GetEnd() ).c_str(), - FormatAngle( aShape->GetAngle() ).c_str() ); + FormatAngle( aShape->GetArcAngle() ).c_str() ); break; case SHAPE_T::POLY: @@ -905,7 +901,7 @@ void PCB_IO::format( const PCB_SHAPE* aShape, int aNestLevel ) const break; default: - wxFAIL_MSG( "PCB_IO::format not implemented for " + aShape->SHAPE_T_asString() ); + UNIMPLEMENTED_FOR( aShape->SHAPE_T_asString() ); return; }; @@ -960,9 +956,9 @@ void PCB_IO::format( const FP_SHAPE* aFPShape, int aNestLevel ) const case SHAPE_T::ARC: m_out->Print( aNestLevel, "(fp_arc%s (start %s) (end %s) (angle %s)", locked.c_str(), + FormatInternalUnits( aFPShape->GetCenter0() ).c_str(), FormatInternalUnits( aFPShape->GetStart0() ).c_str(), - FormatInternalUnits( aFPShape->GetEnd0() ).c_str(), - FormatAngle( aFPShape->GetAngle() ).c_str() ); + FormatAngle( aFPShape->GetArcAngle() ).c_str() ); break; case SHAPE_T::POLY: @@ -1635,9 +1631,9 @@ void PCB_IO::format( const PAD* aPad, int aNestLevel ) const case SHAPE_T::ARC: m_out->Print( nested_level, "(gr_arc (start %s) (end %s) (angle %s)", + FormatInternalUnits( primitive->GetCenter() ).c_str(), FormatInternalUnits( primitive->GetStart() ).c_str(), - FormatInternalUnits( primitive->GetEnd() ).c_str(), - FormatAngle( primitive->GetAngle() ).c_str() ); + FormatAngle( primitive->GetArcAngle() ).c_str() ); break; case SHAPE_T::CIRCLE: diff --git a/pcbnew/plugins/kicad/pcb_parser.cpp b/pcbnew/plugins/kicad/pcb_parser.cpp index 117d0380e5..b809dcb4d8 100644 --- a/pcbnew/plugins/kicad/pcb_parser.cpp +++ b/pcbnew/plugins/kicad/pcb_parser.cpp @@ -2392,7 +2392,7 @@ PCB_SHAPE* PCB_PARSER::parsePCB_SHAPE() pt.x = parseBoardUnits( "X coordinate" ); pt.y = parseBoardUnits( "Y coordinate" ); - shape->SetArcCenter( pt ); + shape->SetCenter( pt ); NeedRIGHT(); NeedLEFT(); token = NextTok(); @@ -2402,7 +2402,7 @@ PCB_SHAPE* PCB_PARSER::parsePCB_SHAPE() pt.x = parseBoardUnits( "X coordinate" ); pt.y = parseBoardUnits( "Y coordinate" ); - shape->SetArcStart( pt ); + shape->SetStart( pt ); NeedRIGHT(); break; @@ -2426,7 +2426,7 @@ PCB_SHAPE* PCB_PARSER::parsePCB_SHAPE() pt.x = parseBoardUnits( "X coordinate" ); pt.y = parseBoardUnits( "Y coordinate" ); - shape->SetArcCenter( pt ); + shape->SetStart( pt ); NeedRIGHT(); NeedLEFT(); @@ -2570,7 +2570,8 @@ PCB_SHAPE* PCB_PARSER::parsePCB_SHAPE() Expecting( "gr_arc, gr_circle, gr_curve, gr_line, gr_poly, or gp_rect" ); } - bool foundFill = false; + bool foundFill = false; + double angle; for( token = NextTok(); token != T_RIGHT; token = NextTok() ) { @@ -2582,7 +2583,11 @@ PCB_SHAPE* PCB_PARSER::parsePCB_SHAPE() switch( token ) { case T_angle: - shape->SetAngle( parseDouble( "segment angle" ) * 10.0 ); + angle = parseDouble( "segment angle" ) * 10.0; + + if( shape->GetShape() == SHAPE_T::ARC ) + shape->SetArcAngleAndEnd( angle ); + NeedRIGHT(); break; @@ -3419,7 +3424,7 @@ FOOTPRINT* PCB_PARSER::parseFOOTPRINT_unchecked( wxArrayString* aInitialComments FP_SHAPE* shape = parseFP_SHAPE(); // Drop 0 and NaN angles as these can corrupt/crash the schematic - if( std::isnormal( shape->GetAngle() ) ) + if( std::isnormal( shape->GetArcAngle() ) ) { shape->SetParent( footprint.get() ); shape->SetDrawCoord(); @@ -3654,7 +3659,7 @@ FP_SHAPE* PCB_PARSER::parseFP_SHAPE() pt.x = parseBoardUnits( "X coordinate" ); pt.y = parseBoardUnits( "Y coordinate" ); - shape->SetStart0( pt ); + shape->SetCenter0( pt ); NeedRIGHT(); NeedLEFT(); token = NextTok(); @@ -3664,7 +3669,7 @@ FP_SHAPE* PCB_PARSER::parseFP_SHAPE() pt.x = parseBoardUnits( "X coordinate" ); pt.y = parseBoardUnits( "Y coordinate" ); - shape->SetEnd0( pt ); + shape->SetStart0( pt ); NeedRIGHT(); NeedLEFT(); token = NextTok(); @@ -3672,9 +3677,7 @@ FP_SHAPE* PCB_PARSER::parseFP_SHAPE() if( token != T_angle ) Expecting( T_angle ); - // Setting angle will set m_thirdPoint0, so must be done after setting - // m_start0 and m_end0 - shape->SetAngle( parseDouble( "segment angle" ) * 10.0 ); + shape->SetArcAngleAndEnd0( parseDouble( "segment angle" ) * 10.0 ); NeedRIGHT(); break; @@ -4346,8 +4349,8 @@ PAD* PCB_PARSER::parsePAD( FOOTPRINT* aParent ) { case T_gr_arc: dummyShape = parsePCB_SHAPE(); - pad->AddPrimitiveArc( dummyShape->GetCenter(), dummyShape->GetArcStart(), - dummyShape->GetAngle(), dummyShape->GetWidth() ); + pad->AddPrimitiveArc( dummyShape->GetCenter(), dummyShape->GetStart(), + dummyShape->GetArcAngle(), dummyShape->GetWidth() ); break; case T_gr_line: diff --git a/pcbnew/plugins/legacy/legacy_plugin.cpp b/pcbnew/plugins/legacy/legacy_plugin.cpp index 9af1eda3cf..129cb8797f 100644 --- a/pcbnew/plugins/legacy/legacy_plugin.cpp +++ b/pcbnew/plugins/legacy/legacy_plugin.cpp @@ -1582,21 +1582,18 @@ void LEGACY_PLUGIN::loadFP_SHAPE( FOOTPRINT* aFootprint ) { case SHAPE_T::ARC: { - BIU start0_x = biuParse( line + SZ( "DA" ), &data ); - BIU start0_y = biuParse( data, &data ); - BIU end0_x = biuParse( data, &data ); - BIU end0_y = biuParse( data, &data ); - double angle = degParse( data, &data ); + BIU center0_x = biuParse( line + SZ( "DA" ), &data ); + BIU center0_y = biuParse( data, &data ); + BIU start0_x = biuParse( data, &data ); + BIU start0_y = biuParse( data, &data ); + double angle = degParse( data, &data ); width = biuParse( data, &data ); layer = layerParse( data ); + dwg->SetCenter0( wxPoint( center0_x, center0_y ) ); dwg->SetStart0( wxPoint( start0_x, start0_y ) ); - dwg->SetEnd0( wxPoint( end0_x, end0_y ) ); - - // Setting angle will set m_thirdPoint0, so must be done after setting - // m_start0 and m_end0 - dwg->SetAngle( angle ); + dwg->SetArcAngleAndEnd0( angle ); break; } @@ -1882,7 +1879,7 @@ void LEGACY_PLUGIN::loadPCB_LINE() case 2: double angle; angle = degParse( data ); - dseg->SetAngle( angle ); // m_Angle + dseg->SetArcAngleAndEnd( angle ); // m_Angle break; case 3: const_cast( dseg->m_Uuid ) = KIID( data ); diff --git a/pcbnew/plugins/pcad/pcb_arc.cpp b/pcbnew/plugins/pcad/pcb_arc.cpp index 27addbaa59..18208f7f41 100644 --- a/pcbnew/plugins/pcad/pcb_arc.cpp +++ b/pcbnew/plugins/pcad/pcb_arc.cpp @@ -174,12 +174,9 @@ void PCB_ARC::AddToFootprint( FOOTPRINT* aFootprint ) FP_SHAPE* arc = new FP_SHAPE( aFootprint, IsCircle() ? SHAPE_T::CIRCLE : SHAPE_T::ARC ); aFootprint->Add( arc ); - arc->SetStart0( wxPoint( m_positionX, m_positionY ) ); - arc->SetEnd0( wxPoint( m_StartX, m_StartY ) ); - - // Setting angle will set m_thirdPoint0, so must be done after setting - // m_start0 and m_end0 - arc->SetAngle( -m_Angle ); + arc->SetCenter0( wxPoint( m_positionX, m_positionY ) ); + arc->SetStart0( wxPoint( m_StartX, m_StartY ) ); + arc->SetArcAngleAndEnd0( -m_Angle ); arc->SetWidth( m_Width ); arc->SetLayer( m_KiCadLayer ); @@ -197,9 +194,9 @@ void PCB_ARC::AddToBoard() arc->SetFilled( false ); arc->SetLayer( m_KiCadLayer ); - arc->SetStart( wxPoint( m_positionX, m_positionY ) ); - arc->SetEnd( wxPoint( m_StartX, m_StartY ) ); - arc->SetAngle( -m_Angle ); + arc->SetCenter( wxPoint( m_positionX, m_positionY ) ); + arc->SetStart( wxPoint( m_StartX, m_StartY ) ); + arc->SetArcAngleAndEnd( -m_Angle ); arc->SetWidth( m_Width ); } diff --git a/pcbnew/plugins/pcad/pcb_line.cpp b/pcbnew/plugins/pcad/pcb_line.cpp index b6a112d9c1..cf143df363 100644 --- a/pcbnew/plugins/pcad/pcb_line.cpp +++ b/pcbnew/plugins/pcad/pcb_line.cpp @@ -150,7 +150,7 @@ void PCB_LINE::AddToBoard() } else { - PCB_SHAPE* segment = new PCB_SHAPE( m_board ); + PCB_SHAPE* segment = new PCB_SHAPE( m_board, SHAPE_T::SEGMENT ); m_board->Add( segment, ADD_MODE::APPEND ); segment->SetLayer( m_KiCadLayer ); diff --git a/pcbnew/specctra_import_export/specctra_export.cpp b/pcbnew/specctra_import_export/specctra_export.cpp index 6d222d2835..ef399c22f0 100644 --- a/pcbnew/specctra_import_export/specctra_export.cpp +++ b/pcbnew/specctra_import_export/specctra_export.cpp @@ -802,10 +802,10 @@ IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, FOOTPRINT* aFootprint ) path->SetAperture( 0 );//scale( graphic->GetWidth() ) ); path->SetLayerId( "signal" ); - wxPoint arc_centre = graphic->GetStart0(); - double radius = graphic->GetRadius() + graphic->GetWidth() / 2; - double arcStartDeg = graphic->GetArcAngleStart() / 10.0; - double arcAngleDeg = graphic->GetAngle() / 10.0; + wxPoint arc_centre = graphic->GetCenter0(); + double radius = graphic->GetRadius() + graphic->GetWidth()/2; + double arcStartDeg = graphic->GetArcAngleStart() / 10.0; + double arcAngleDeg = graphic->GetArcAngle() / 10.0; // For some obscure reason, FreeRouter does not show the same polygonal // shape for polygons CW and CCW. So used only the order of corners @@ -841,10 +841,10 @@ IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, FOOTPRINT* aFootprint ) wxPoint move = graphic->GetCenter() - arc_centre; - TransformCircleToPolygon( polyBuffer, graphic->GetArcStart() - move, + TransformCircleToPolygon( polyBuffer, graphic->GetStart() - move, graphic->GetWidth() / 2, ARC_HIGH_DEF, ERROR_INSIDE ); - TransformCircleToPolygon( polyBuffer, graphic->GetArcEnd() - move, + TransformCircleToPolygon( polyBuffer, graphic->GetEnd() - move, graphic->GetWidth() / 2, ARC_HIGH_DEF, ERROR_INSIDE ); polyBuffer.Simplify( SHAPE_POLY_SET::PM_FAST ); diff --git a/pcbnew/tools/convert_tool.cpp b/pcbnew/tools/convert_tool.cpp index c150818465..9bb1dc6895 100644 --- a/pcbnew/tools/convert_tool.cpp +++ b/pcbnew/tools/convert_tool.cpp @@ -321,7 +321,7 @@ SHAPE_POLY_SET CONVERT_TOOL::makePolysFromSegs( const std::deque& aIt else { PCB_SHAPE* ps = static_cast( aItem ); - arc = SHAPE_ARC( ps->GetArcStart(), ps->GetArcMid(), ps->GetArcEnd(), + arc = SHAPE_ARC( ps->GetStart(), ps->GetArcMid(), ps->GetEnd(), ps->GetWidth() ); } @@ -653,8 +653,8 @@ int CONVERT_TOOL::CreateLines( const TOOL_EVENT& aEvent ) PCB_ARC* arc = new PCB_ARC( parent ); arc->SetLayer( targetLayer ); - arc->SetStart( graphic->GetArcStart() ); - arc->SetEnd( graphic->GetArcEnd() ); + arc->SetStart( graphic->GetStart() ); + arc->SetEnd( graphic->GetEnd() ); arc->SetMid( graphic->GetArcMid() ); commit.Add( arc ); @@ -804,20 +804,19 @@ int CONVERT_TOOL::SegmentToArc( const TOOL_EVENT& aEvent ) if( source->Type() == PCB_SHAPE_T || source->Type() == PCB_FP_SHAPE_T ) { PCB_SHAPE* line = static_cast( source ); - PCB_SHAPE* arc = new PCB_SHAPE( parent ); + PCB_SHAPE* arc = new PCB_SHAPE( parent, SHAPE_T::ARC ); - VECTOR2I center = GetArcCenter( start, mid, end ); + VECTOR2I center = CalcArcCenter( start, mid, end ); - arc->SetShape( SHAPE_T::ARC ); arc->SetFilled( false ); arc->SetLayer( layer ); arc->SetWidth( line->GetWidth() ); - arc->SetArcCenter( wxPoint( center )); - arc->SetArcStart( wxPoint( start ) ); - arc->SetAngle( GetArcAngle( start, mid, end ) ); + arc->SetCenter( wxPoint( center ) ); + arc->SetStart( wxPoint( start ) ); + arc->SetEnd( wxPoint( end ) ); + arc->SetArcAngle( CalcArcAngle( start, mid, end ) ); - arc->SetArcEnd( wxPoint( end ) ); commit.Add( arc ); } else @@ -848,21 +847,13 @@ OPT CONVERT_TOOL::getStartEndPoints( EDA_ITEM* aItem, int* aWidth ) case PCB_SHAPE_T: case PCB_FP_SHAPE_T: { - PCB_SHAPE* line = static_cast( aItem ); + PCB_SHAPE* shape = static_cast( aItem ); if( aWidth ) - *aWidth = line->GetWidth(); + *aWidth = shape->GetWidth(); - if( line->GetShape() == SHAPE_T::SEGMENT ) - { - return boost::make_optional( { VECTOR2I( line->GetStart() ), - VECTOR2I( line->GetEnd() ) } ); - } - else - { - return boost::make_optional( { VECTOR2I( line->GetArcStart() ), - VECTOR2I( line->GetArcEnd() ) } ); - } + return boost::make_optional( { VECTOR2I( shape->GetStart() ), + VECTOR2I( shape->GetEnd() ) } ); } case PCB_TRACE_T: diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp index cdce6f07ab..78df65bd1e 100644 --- a/pcbnew/tools/drawing_tool.cpp +++ b/pcbnew/tools/drawing_tool.cpp @@ -1713,17 +1713,16 @@ bool DRAWING_TOOL::drawSegment( const std::string& aTool, PCB_SHAPE** aGraphic, static void updateArcFromConstructionMgr( const KIGFX::PREVIEW::ARC_GEOM_MANAGER& aMgr, PCB_SHAPE& aArc ) { - auto vec = aMgr.GetOrigin(); + VECTOR2I vec = aMgr.GetOrigin(); - aArc.SetArcCenter( { vec.x, vec.y } ); + aArc.SetCenter( (wxPoint) vec ); vec = aMgr.GetStartRadiusEnd(); - aArc.SetArcStart( { vec.x, vec.y } ); - - aArc.SetAngle( RAD2DECIDEG( -aMgr.GetSubtended() ) ); - + aArc.SetStart( (wxPoint) vec ); vec = aMgr.GetEndRadiusEnd(); - aArc.SetArcEnd( { vec.x, vec.y } ); + aArc.SetEnd( (wxPoint) vec ); + + aArc.SetArcAngle( RAD2DECIDEG( -aMgr.GetSubtended() ) ); } @@ -1892,7 +1891,7 @@ bool DRAWING_TOOL::drawArc( const std::string& aTool, PCB_SHAPE** aGraphic, bool { if( arcManager.GetStep() == KIGFX::PREVIEW::ARC_GEOM_MANAGER::SET_START ) { - graphic->SetAngle( 900, true ); + graphic->SetArcAngleAndEnd( 900 ); frame()->OnEditItemRequest( graphic ); m_view->Update( &preview ); frame()->SetMsgPanel( graphic ); diff --git a/pcbnew/tools/edit_tool.cpp b/pcbnew/tools/edit_tool.cpp index e4be983355..5b976f2a17 100644 --- a/pcbnew/tools/edit_tool.cpp +++ b/pcbnew/tools/edit_tool.cpp @@ -555,7 +555,7 @@ int EDIT_TOOL::DragArcTrack( const TOOL_EVENT& aEvent ) VECTOR2I newCenter = circlehelper.Center; VECTOR2I newStart = cSegTanStart.LineProject( newCenter ); VECTOR2I newEnd = cSegTanEnd.LineProject( newCenter ); - VECTOR2I newMid = GetArcMid( newStart, newEnd, newCenter ); + VECTOR2I newMid = CalcArcMid( newStart, newEnd, newCenter ); // Update objects theArc->SetStart( (wxPoint) newStart ); diff --git a/pcbnew/tools/pad_tool.cpp b/pcbnew/tools/pad_tool.cpp index e65645f4ce..8dd753d5c3 100644 --- a/pcbnew/tools/pad_tool.cpp +++ b/pcbnew/tools/pad_tool.cpp @@ -23,6 +23,7 @@ #include "pad_tool.h" +#include #include #include #include @@ -612,12 +613,38 @@ PCB_LAYER_ID PAD_TOOL::explodePad( PAD* aPad ) shape->SetShape( primitive->GetShape() ); shape->SetFilled( primitive->IsFilled() ); shape->SetWidth( primitive->GetWidth() ); - shape->SetStart( primitive->GetStart() ); - shape->SetEnd( primitive->GetEnd() ); - shape->SetBezierC1( primitive->GetBezierC1()); - shape->SetBezierC2( primitive->GetBezierC2()); - shape->SetAngle( primitive->GetAngle() ); - shape->SetPolyShape( primitive->GetPolyShape() ); + + switch( shape->GetShape() ) + { + case SHAPE_T::SEGMENT: + case SHAPE_T::RECT: + case SHAPE_T::CIRCLE: + shape->SetStart( primitive->GetStart() ); + shape->SetEnd( primitive->GetEnd() ); + break; + + case SHAPE_T::ARC: + shape->SetStart( primitive->GetStart() ); + shape->SetEnd( primitive->GetEnd() ); + shape->SetCenter( primitive->GetCenter() ); + shape->SetArcAngle( primitive->GetArcAngle() ); + break; + + case SHAPE_T::BEZIER: + shape->SetStart( primitive->GetStart() ); + shape->SetEnd( primitive->GetEnd() ); + shape->SetBezierC1( primitive->GetBezierC1() ); + shape->SetBezierC2( primitive->GetBezierC2() ); + break; + + case SHAPE_T::POLY: + shape->SetPolyShape( primitive->GetPolyShape() ); + break; + + default: + UNIMPLEMENTED_FOR( shape->SHAPE_T_asString() ); + } + shape->SetLocalCoord(); shape->Move( aPad->GetPosition() ); shape->Rotate( aPad->GetPosition(), aPad->GetOrientation() ); @@ -724,12 +751,38 @@ void PAD_TOOL::recombinePad( PAD* aPad ) pcbShape->SetShape( fpShape->GetShape() ); pcbShape->SetFilled( fpShape->IsFilled() ); pcbShape->SetWidth( fpShape->GetWidth() ); - pcbShape->SetStart( fpShape->GetStart() ); - pcbShape->SetEnd( fpShape->GetEnd() ); - pcbShape->SetBezierC1( fpShape->GetBezierC1()); - pcbShape->SetBezierC2( fpShape->GetBezierC2()); - pcbShape->SetAngle( fpShape->GetAngle() ); - pcbShape->SetPolyShape( fpShape->GetPolyShape() ); + + + switch( pcbShape->GetShape() ) + { + case SHAPE_T::SEGMENT: + case SHAPE_T::RECT: + case SHAPE_T::CIRCLE: + pcbShape->SetStart( fpShape->GetStart() ); + pcbShape->SetEnd( fpShape->GetEnd() ); + break; + + case SHAPE_T::ARC: + pcbShape->SetStart( fpShape->GetStart() ); + pcbShape->SetEnd( fpShape->GetEnd() ); + pcbShape->SetCenter( fpShape->GetCenter() ); + pcbShape->SetArcAngle( fpShape->GetArcAngle() ); + break; + + case SHAPE_T::BEZIER: + pcbShape->SetStart( fpShape->GetStart() ); + pcbShape->SetEnd( fpShape->GetEnd() ); + pcbShape->SetBezierC1( fpShape->GetBezierC1() ); + pcbShape->SetBezierC2( fpShape->GetBezierC2() ); + break; + + case SHAPE_T::POLY: + pcbShape->SetPolyShape( fpShape->GetPolyShape() ); + break; + + default: + UNIMPLEMENTED_FOR( pcbShape->SHAPE_T_asString() ); + } pcbShape->Move( - aPad->GetPosition() ); pcbShape->Rotate( wxPoint( 0, 0 ), - aPad->GetOrientation() ); diff --git a/pcbnew/tools/pcb_grid_helper.cpp b/pcbnew/tools/pcb_grid_helper.cpp index d2456045f0..dd4472b83a 100644 --- a/pcbnew/tools/pcb_grid_helper.cpp +++ b/pcbnew/tools/pcb_grid_helper.cpp @@ -543,8 +543,8 @@ void PCB_GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos } case SHAPE_T::ARC: - addAnchor( shape->GetArcStart(), CORNER | SNAPPABLE, shape ); - addAnchor( shape->GetArcEnd(), CORNER | SNAPPABLE, shape ); + addAnchor( shape->GetStart(), CORNER | SNAPPABLE, shape ); + addAnchor( shape->GetEnd(), CORNER | SNAPPABLE, shape ); addAnchor( shape->GetArcMid(), CORNER | SNAPPABLE, shape ); addAnchor( shape->GetCenter(), ORIGIN | SNAPPABLE, shape ); break; @@ -598,7 +598,7 @@ void PCB_GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos KI_FALLTHROUGH; default: - addAnchor( shape->GetStart(), ORIGIN | SNAPPABLE, shape ); + addAnchor( shape->GetPosition(), ORIGIN | SNAPPABLE, shape ); break; } break; diff --git a/pcbnew/tools/pcb_point_editor.cpp b/pcbnew/tools/pcb_point_editor.cpp index 9e39bb5bbe..0f8b12e3d6 100644 --- a/pcbnew/tools/pcb_point_editor.cpp +++ b/pcbnew/tools/pcb_point_editor.cpp @@ -215,9 +215,9 @@ std::shared_ptr PCB_POINT_EDITOR::makePoints( EDA_ITEM* aItem ) case SHAPE_T::ARC: points->AddPoint( shape->GetCenter() ); - points->AddPoint( shape->GetArcStart() ); + points->AddPoint( shape->GetStart() ); points->AddPoint( shape->GetArcMid() ); - points->AddPoint( shape->GetArcEnd() ); + points->AddPoint( shape->GetEnd() ); points->Point( ARC_MID ).SetGridConstraint( IGNORE_GRID ); points->Point( ARC_START ).SetGridConstraint( SNAP_TO_GRID ); @@ -613,7 +613,7 @@ void PCB_POINT_EDITOR::editArcEndpointKeepTangent( PCB_SHAPE* aArc, const VECTOR VECTOR2I p1, p2, p3; // p1 does not move, p2 does. - if( aStart != aArc->GetArcStart() ) + if( aStart != aArc->GetStart() ) { start = aCursor; p1 = aEnd; @@ -621,7 +621,7 @@ void PCB_POINT_EDITOR::editArcEndpointKeepTangent( PCB_SHAPE* aArc, const VECTOR p3 = aMid; movingStart = true; } - else if( aEnd != aArc->GetArcEnd() ) + else if( aEnd != aArc->GetEnd() ) { end = aCursor; p1 = aStart; @@ -736,7 +736,7 @@ void PCB_POINT_EDITOR::editArcEndpointKeepTangent( PCB_SHAPE* aArc, const VECTOR // v4 is the new center v4 = ( !transformCircle ) ? VECTOR2D( -delta, 0 ) : VECTOR2D( 2 * R + delta, 0 ); - clockwise = aArc->GetAngle() > 0; + clockwise = aArc->GetArcAngle() > 0; if( transformCircle ) clockwise = !clockwise; @@ -759,13 +759,13 @@ void PCB_POINT_EDITOR::editArcEndpointKeepTangent( PCB_SHAPE* aArc, const VECTOR if( arcValid ) { - aArc->SetAngle( newAngle, false ); - aArc->SetArcCenter( ( wxPoint ) center ); + aArc->SetCenter( (wxPoint) aCenter ); + aArc->SetArcAngle( newAngle ); if( movingStart ) - aArc->SetArcStart( ( wxPoint ) start ); + aArc->SetStart( (wxPoint) aStart ); else - aArc->SetArcEnd( ( wxPoint ) end ); + aArc->SetEnd( (wxPoint) aEnd ); } } } @@ -886,7 +886,7 @@ void PCB_POINT_EDITOR::editArcEndpointKeepCenter( PCB_SHAPE* aArc, const VECTOR2 // p1 does not move, p2 does. - if( aStart != aArc->GetArcStart() ) + if( aStart != aArc->GetStart() ) { p1 = aEnd; p2 = aStart; @@ -932,7 +932,7 @@ void PCB_POINT_EDITOR::editArcEndpointKeepCenter( PCB_SHAPE* aArc, const VECTOR2 p1 = p1 + aCenter; p2 = p2 + aCenter; - clockwise = aArc->GetAngle() > 0; + clockwise = aArc->GetArcAngle() > 0; VECTOR2D startLine = aStart - aCenter; VECTOR2D endLine = aEnd - aCenter; @@ -943,13 +943,13 @@ void PCB_POINT_EDITOR::editArcEndpointKeepCenter( PCB_SHAPE* aArc, const VECTOR2 else if( !clockwise && newAngle > 0.0 ) newAngle -= 3600.0; - aArc->SetAngle( newAngle, false ); - aArc->SetArcCenter((wxPoint) aCenter ); + aArc->SetCenter( (wxPoint) aCenter ); + aArc->SetArcAngle( newAngle ); if( movingStart ) - aArc->SetArcStart( (wxPoint) aStart ); + aArc->SetStart( (wxPoint) aStart ); else - aArc->SetArcEnd( (wxPoint) aEnd ); + aArc->SetEnd( (wxPoint) aEnd ); } @@ -1009,8 +1009,8 @@ void PCB_POINT_EDITOR::editArcMidKeepCenter( PCB_SHAPE* aArc, const VECTOR2I& aC start = start + aCenter; end = end + aCenter; - aArc->SetArcStart( (wxPoint) start ); - aArc->SetArcEnd( (wxPoint) end ); + aArc->SetStart( (wxPoint) start ); + aArc->SetEnd( (wxPoint) end ); } @@ -1577,9 +1577,9 @@ void PCB_POINT_EDITOR::updatePoints() case SHAPE_T::ARC: m_editPoints->Point( ARC_CENTER ).SetPosition( shape->GetCenter() ); - m_editPoints->Point( ARC_START ).SetPosition( shape->GetArcStart() ); + m_editPoints->Point( ARC_START ).SetPosition( shape->GetStart() ); m_editPoints->Point( ARC_MID ).SetPosition( shape->GetArcMid() ); - m_editPoints->Point( ARC_END ).SetPosition( shape->GetArcEnd() ); + m_editPoints->Point( ARC_END ).SetPosition( shape->GetEnd() ); break; case SHAPE_T::CIRCLE: diff --git a/qa/eeschema/CMakeLists.txt b/qa/eeschema/CMakeLists.txt index 254e6fbce2..552097d214 100644 --- a/qa/eeschema/CMakeLists.txt +++ b/qa/eeschema/CMakeLists.txt @@ -51,7 +51,6 @@ set( QA_EESCHEMA_SRCS sch_plugins/altium/test_altium_parser_sch.cpp test_eagle_plugin.cpp - test_lib_arc.cpp test_lib_part.cpp test_netlists.cpp test_sch_pin.cpp diff --git a/qa/eeschema/test_lib_arc.cpp b/qa/eeschema/test_lib_arc.cpp deleted file mode 100644 index 6dfc256159..0000000000 --- a/qa/eeschema/test_lib_arc.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2020 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 - */ - -/** - * @file - * Test suite for LIB_ARC - */ - -#include -#include -#include - -// Code under test -#include - -class TEST_LIB_ARC_FIXTURE -{ -public: - TEST_LIB_ARC_FIXTURE() : - m_arc( nullptr ) - { - } - - ///> Part with no extra data set - LIB_ARC m_arc; -}; - - -/** - * Declare the test suite - */ -BOOST_FIXTURE_TEST_SUITE( LibArc, TEST_LIB_ARC_FIXTURE ) - - -/** - * Check that we can get the default properties out as expected - */ -BOOST_AUTO_TEST_CASE( DefaultProperties ) -{ - BOOST_CHECK_EQUAL( m_arc.Type(), LIB_ARC_T ); - BOOST_CHECK_EQUAL( m_arc.GetClass(), "LIB_ARC" ); - BOOST_CHECK_EQUAL( m_arc.GetPosition(), wxPoint( 0, 0 ) ); -} - - -/** - * Test the function that calculates the radius angles based on the center, start, and end points. - */ -BOOST_AUTO_TEST_CASE( TestCalcRadiusAngles ) -{ - double radius = 5.0; // Use millimeters and convert to internal units. - int startX = Millimeter2iu( radius * cos( DEG2RAD( 10.0 ) ) ); - int startY = Millimeter2iu( radius * sin( DEG2RAD( 10.0 ) ) ); - int endX = Millimeter2iu( radius * cos( DEG2RAD( 45.0 ) ) ); - int endY = Millimeter2iu( radius * sin( DEG2RAD( 45.0 ) ) ); - - m_arc.SetStart( wxPoint( startX, startY ) ); - m_arc.SetEnd( wxPoint( endX, endY ) ); - - m_arc.CalcRadiusAngles(); - BOOST_CHECK_EQUAL( m_arc.GetFirstRadiusAngle(), 100 ); - BOOST_CHECK_EQUAL( m_arc.GetSecondRadiusAngle(), 450 ); - - // Set arc end point in the second quadrant. - endX = Millimeter2iu( radius * cos( DEG2RAD( 145.0 ) ) ); - endY = Millimeter2iu( radius * sin( DEG2RAD( 145.0 ) ) ); - m_arc.SetEnd( wxPoint( endX, endY ) ); - m_arc.CalcRadiusAngles(); - BOOST_CHECK_EQUAL( m_arc.GetFirstRadiusAngle(), 100 ); - BOOST_CHECK_EQUAL( m_arc.GetSecondRadiusAngle(), 1450 ); -} - - -/** - * Test the function that calculates the mid point based on the start and end angles and - * radius length. - */ -BOOST_AUTO_TEST_CASE( TestCalcMidPoint ) -{ - // Midpoint angle is 77.5 degrees. - m_arc.SetRadius( Millimeter2iu( 5.0 ) ); - m_arc.SetFirstRadiusAngle( 100 ); - m_arc.SetSecondRadiusAngle( 1450 ); - BOOST_CHECK_EQUAL( m_arc.CalcMidPoint(), VECTOR2I( 10822, 48815 ) ); - m_arc.SetFirstRadiusAngle( 850 ); - m_arc.SetSecondRadiusAngle( 950 ); - BOOST_CHECK_EQUAL( m_arc.CalcMidPoint(), VECTOR2I( 0, 50000 ) ); - m_arc.SetFirstRadiusAngle( 1700 ); - m_arc.SetSecondRadiusAngle( 1900 ); - BOOST_CHECK_EQUAL( m_arc.CalcMidPoint(), VECTOR2I( -50000, 0 ) ); - m_arc.SetFirstRadiusAngle( 2500 ); - m_arc.SetSecondRadiusAngle( 2900 ); - BOOST_CHECK_EQUAL( m_arc.CalcMidPoint(), VECTOR2I( 0, -50000 ) ); - m_arc.SetFirstRadiusAngle( 3500 ); - m_arc.SetSecondRadiusAngle( 100 ); - BOOST_CHECK_EQUAL( m_arc.CalcMidPoint(), VECTOR2I( 50000, 0 ) ); -} - - -BOOST_AUTO_TEST_SUITE_END() diff --git a/qa/pcbnew_utils/board_construction_utils.cpp b/qa/pcbnew_utils/board_construction_utils.cpp index 78e65c1fee..98d1bf5298 100644 --- a/qa/pcbnew_utils/board_construction_utils.cpp +++ b/qa/pcbnew_utils/board_construction_utils.cpp @@ -61,9 +61,9 @@ void DrawArc( FOOTPRINT& aFootprint, const VECTOR2I& aCentre, const VECTOR2I& aS { auto seg = std::make_unique( &aFootprint, SHAPE_T::ARC ); - seg->SetStart0( (wxPoint) aCentre ); - seg->SetEnd0( (wxPoint) aStart ); - seg->SetAngle( aAngle * 10 ); + seg->SetCenter0( (wxPoint) aCentre ); + seg->SetStart0( (wxPoint) aStart ); + seg->SetArcAngleAndEnd0( aAngle * 10 ); seg->SetWidth( aWidth ); seg->SetLayer( aLayer );