Replace individual LIB_* shapes with LIB_SHAPE (based on EDA_SHAPE).

Also moves to more capable FILL_T model that can be shared.
This commit is contained in:
Jeff Young 2021-07-19 00:08:54 +01:00
parent 9b9e379aa0
commit b52529521e
73 changed files with 1344 additions and 4235 deletions

View File

@ -295,12 +295,8 @@ static struct EDA_ITEM_DESC
.Map( LIB_SYMBOL_T, _HKI( "Symbol" ) ) .Map( LIB_SYMBOL_T, _HKI( "Symbol" ) )
.Map( LIB_ALIAS_T, _HKI( "Alias" ) ) .Map( LIB_ALIAS_T, _HKI( "Alias" ) )
.Map( LIB_ARC_T, _HKI( "Arc" ) ) .Map( LIB_SHAPE_T, _HKI( "Graphic" ) )
.Map( LIB_CIRCLE_T, _HKI( "Circle" ) )
.Map( LIB_TEXT_T, _HKI( "Text" ) ) .Map( LIB_TEXT_T, _HKI( "Text" ) )
.Map( LIB_RECTANGLE_T, _HKI( "Rectangle" ) )
.Map( LIB_POLYLINE_T, _HKI( "Polyline" ) )
.Map( LIB_BEZIER_T, _HKI( "Bezier" ) )
.Map( LIB_PIN_T, _HKI( "Pin" ) ) .Map( LIB_PIN_T, _HKI( "Pin" ) )
.Map( LIB_FIELD_T, _HKI( "Symbol Field" ) ) .Map( LIB_FIELD_T, _HKI( "Symbol Field" ) )

View File

@ -35,12 +35,11 @@
#include <eda_shape.h> #include <eda_shape.h>
EDA_SHAPE::EDA_SHAPE( SHAPE_T aType, int aDefaultLineWidth ) : EDA_SHAPE::EDA_SHAPE( SHAPE_T aType, int aLineWidth, FILL_T aFill ) :
m_shape( aType ), m_shape( aType ),
m_width( aDefaultLineWidth ) m_width( aLineWidth ),
m_fill( aFill )
{ {
m_arcAngle = 0;
m_filled = false;
} }
@ -173,9 +172,6 @@ void EDA_SHAPE::scale( double aScale )
pt.y = KiROUND( pt.y * aScale ); pt.y = KiROUND( pt.y * aScale );
}; };
int radius = GetRadius();
// specific parameters:
switch( m_shape ) switch( m_shape )
{ {
case SHAPE_T::ARC: case SHAPE_T::ARC:
@ -188,7 +184,7 @@ void EDA_SHAPE::scale( double aScale )
case SHAPE_T::CIRCLE: // ring or circle case SHAPE_T::CIRCLE: // ring or circle
scalePt( m_start ); scalePt( m_start );
m_end.x = m_start.x + KiROUND( radius * aScale ); m_end.x = m_start.x + KiROUND( GetRadius() * aScale );
m_end.y = m_start.y; m_end.y = m_start.y;
break; break;
@ -224,10 +220,13 @@ void EDA_SHAPE::rotate( const wxPoint& aRotCentre, double aAngle )
{ {
switch( m_shape ) switch( m_shape )
{ {
case SHAPE_T::ARC:
case SHAPE_T::SEGMENT: case SHAPE_T::SEGMENT:
case SHAPE_T::CIRCLE: case SHAPE_T::CIRCLE:
// these can all be done by just rotating the constituent points RotatePoint( &m_start, aRotCentre, aAngle );
RotatePoint( &m_end, aRotCentre, aAngle );
break;
case SHAPE_T::ARC:
RotatePoint( &m_start, aRotCentre, aAngle ); RotatePoint( &m_start, aRotCentre, aAngle );
RotatePoint( &m_end, aRotCentre, aAngle ); RotatePoint( &m_end, aRotCentre, aAngle );
RotatePoint( &m_arcCenter, aRotCentre, aAngle ); RotatePoint( &m_arcCenter, aRotCentre, aAngle );
@ -280,7 +279,33 @@ void EDA_SHAPE::flip( const wxPoint& aCentre, bool aFlipLeftRight )
{ {
case SHAPE_T::SEGMENT: case SHAPE_T::SEGMENT:
case SHAPE_T::RECT: case SHAPE_T::RECT:
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 );
}
std::swap( m_start, m_end );
break;
case SHAPE_T::CIRCLE: case SHAPE_T::CIRCLE:
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 );
}
break;
case SHAPE_T::ARC: case SHAPE_T::ARC:
if( aFlipLeftRight ) if( aFlipLeftRight )
{ {
@ -294,6 +319,8 @@ void EDA_SHAPE::flip( const wxPoint& aCentre, bool aFlipLeftRight )
m_end.y = aCentre.y - ( m_end.y - aCentre.y ); m_end.y = aCentre.y - ( m_end.y - aCentre.y );
m_arcCenter.y = aCentre.y - ( m_arcCenter.y - aCentre.y ); m_arcCenter.y = aCentre.y - ( m_arcCenter.y - aCentre.y );
} }
std::swap( m_start, m_end );
break; break;
case SHAPE_T::POLY: case SHAPE_T::POLY:
@ -301,7 +328,6 @@ void EDA_SHAPE::flip( const wxPoint& aCentre, bool aFlipLeftRight )
break; break;
case SHAPE_T::BEZIER: case SHAPE_T::BEZIER:
{
if( aFlipLeftRight ) if( aFlipLeftRight )
{ {
m_start.x = aCentre.x - ( m_start.x - aCentre.x ); m_start.x = aCentre.x - ( m_start.x - aCentre.x );
@ -318,6 +344,7 @@ void EDA_SHAPE::flip( const wxPoint& aCentre, bool aFlipLeftRight )
} }
// Rebuild the poly points shape // Rebuild the poly points shape
{
std::vector<wxPoint> ctrlPoints = { m_start, m_bezierC1, m_bezierC2, m_end }; std::vector<wxPoint> ctrlPoints = { m_start, m_bezierC1, m_bezierC2, m_end };
BEZIER_POLY converter( ctrlPoints ); BEZIER_POLY converter( ctrlPoints );
converter.GetPoly( m_bezierPoints, m_width ); converter.GetPoly( m_bezierPoints, m_width );
@ -512,17 +539,17 @@ void EDA_SHAPE::ShapeGetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PA
case SHAPE_T::CIRCLE: case SHAPE_T::CIRCLE:
aList.emplace_back( shape, _( "Circle" ) ); aList.emplace_back( shape, _( "Circle" ) );
msg = MessageTextFromValue( units, GetLineLength( GetStart(), GetEnd() ) ); msg = MessageTextFromValue( units, GetRadius() );
aList.emplace_back( _( "Radius" ), msg ); aList.emplace_back( _( "Radius" ), msg );
break; break;
case SHAPE_T::ARC: case SHAPE_T::ARC:
aList.emplace_back( shape, _( "Arc" ) ); aList.emplace_back( shape, _( "Arc" ) );
msg.Printf( wxT( "%.1f" ), m_arcAngle / 10.0 ); msg.Printf( wxT( "%.1f" ), GetArcAngle() / 10.0 );
aList.emplace_back( _( "Angle" ), msg ); aList.emplace_back( _( "Angle" ), msg );
msg = MessageTextFromValue( units, GetLineLength( getCenter(), GetStart() ) ); msg = MessageTextFromValue( units, GetRadius() );
aList.emplace_back( _( "Radius" ), msg ); aList.emplace_back( _( "Radius" ), msg );
break; break;
@ -636,7 +663,10 @@ const EDA_RECT EDA_SHAPE::getBoundingBox() const
bool EDA_SHAPE::hitTest( const wxPoint& aPosition, int aAccuracy ) const bool EDA_SHAPE::hitTest( const wxPoint& aPosition, int aAccuracy ) const
{ {
int maxdist = aAccuracy + ( m_width / 2 ); int maxdist = aAccuracy;
if( m_width > 0 )
maxdist += m_width / 2;
switch( m_shape ) switch( m_shape )
{ {
@ -666,6 +696,7 @@ bool EDA_SHAPE::hitTest( const wxPoint& aPosition, int aAccuracy ) const
// this relative arc should be < arc angle if arc angle > 0 (CW arc) // this relative arc should be < arc angle if arc angle > 0 (CW arc)
// and > arc angle if arc angle < 0 (CCW arc) // and > arc angle if arc angle < 0 (CCW arc)
double arc_angle_start = GetArcAngleStart(); // Always 0.0 ... 360 deg, in 0.1 deg double arc_angle_start = GetArcAngleStart(); // Always 0.0 ... 360 deg, in 0.1 deg
double arc_swept_angle = GetArcAngleEnd() - arc_angle_start;
double arc_hittest = ArcTangente( relPos.y, relPos.x ); double arc_hittest = ArcTangente( relPos.y, relPos.x );
@ -677,10 +708,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 // Check angle: inside the arc angle when it is > 0 and outside the not drawn arc when
// it is < 0 // it is < 0
if( GetArcAngle() >= 0.0 ) if( arc_swept_angle >= 0.0 )
return arc_hittest <= GetArcAngle(); return arc_hittest <= arc_swept_angle;
else else
return arc_hittest >= ( 3600.0 + GetArcAngle() ); return arc_hittest >= ( 3600.0 + arc_swept_angle );
} }
else else
{ {
@ -735,7 +766,7 @@ bool EDA_SHAPE::hitTest( const wxPoint& aPosition, int aAccuracy ) const
} }
default: default:
wxFAIL_MSG( "EDA_SHAPE::hitTest(point) not implemented for " + SHAPE_T_asString() ); UNIMPLEMENTED_FOR( SHAPE_T_asString() );
return false; return false;
} }
} }
@ -841,25 +872,37 @@ bool EDA_SHAPE::hitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy )
if( getParentOrientation() ) if( getParentOrientation() )
orientation = -DECIDEG2RAD( getParentOrientation() ); orientation = -DECIDEG2RAD( getParentOrientation() );
SHAPE_POLY_SET poly{ m_poly }; SHAPE_LINE_CHAIN poly = m_poly.Outline( 0 );
poly.Rotate( orientation ); poly.Rotate( orientation );
poly.Move( offset ); poly.Move( offset );
int count = poly.TotalVertices(); int count = poly.GetPointCount();
for( int ii = 0; ii < count; ii++ ) for( int ii = 0; ii < count; ii++ )
{ {
VECTOR2I vertex = poly.CVertex( ii ); VECTOR2I vertex = poly.GetPoint( ii );
VECTOR2I vertexNext = poly.CVertex( ( ii + 1 ) % count );
// Test if the point is within aRect // Test if the point is within aRect
if( arect.Contains( ( wxPoint ) vertex ) ) if( arect.Contains( ( wxPoint ) vertex ) )
return true; return true;
if( ii + 1 < count )
{
VECTOR2I vertexNext = poly.GetPoint( ii + 1 );
// Test if this edge intersects aRect // Test if this edge intersects aRect
if( arect.Intersects( ( wxPoint ) vertex, ( wxPoint ) vertexNext ) ) if( arect.Intersects( ( wxPoint ) vertex, ( wxPoint ) vertexNext ) )
return true; return true;
} }
else if( poly.IsClosed() )
{
VECTOR2I vertexNext = poly.GetPoint( 0 );
// Test if this edge intersects aRect
if( arect.Intersects( ( wxPoint ) vertex, ( wxPoint ) vertexNext ) )
return true;
}
}
return false; return false;
} }
@ -1170,13 +1213,13 @@ void EDA_SHAPE::SwapShape( EDA_SHAPE* aImage )
int EDA_SHAPE::Compare( const EDA_SHAPE* aOther ) const int EDA_SHAPE::Compare( const EDA_SHAPE* aOther ) const
{ {
#define TEST( a, b ) { if( a != b ) return a < b; } #define TEST( a, b ) { if( a != b ) return a - b; }
#define TEST_PT( a, b ) { TEST( a.x, b.x ); TEST( a.y, b.y ); } #define TEST_PT( a, b ) { TEST( a.x, b.x ); TEST( a.y, b.y ); }
TEST_PT( m_start, aOther->m_start ); TEST_PT( m_start, aOther->m_start );
TEST_PT( m_end, aOther->m_end ); TEST_PT( m_end, aOther->m_end );
TEST( m_shape, aOther->m_shape ); TEST( (int) m_shape, (int) aOther->m_shape );
if( m_shape == SHAPE_T::ARC ) if( m_shape == SHAPE_T::ARC )
{ {
@ -1190,15 +1233,13 @@ int EDA_SHAPE::Compare( const EDA_SHAPE* aOther ) const
else if( m_shape == SHAPE_T::POLY ) else if( m_shape == SHAPE_T::POLY )
{ {
TEST( m_poly.TotalVertices(), aOther->m_poly.TotalVertices() ); TEST( m_poly.TotalVertices(), aOther->m_poly.TotalVertices() );
}
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 ) for( int ii = 0; ii < m_poly.TotalVertices(); ++ii )
TEST_PT( m_poly.CVertex( ii ), aOther->m_poly.CVertex( ii ) ); TEST_PT( m_poly.CVertex( ii ), aOther->m_poly.CVertex( ii ) );
}
TEST( m_width, aOther->m_width ); TEST( m_width, aOther->m_width );
TEST( (int) m_fill, (int) aOther->m_fill );
return 0; return 0;
} }

View File

@ -651,7 +651,7 @@ double EDA_TEXT::GetDrawRotation() const
int EDA_TEXT::Compare( const EDA_TEXT* aOther ) const int EDA_TEXT::Compare( const EDA_TEXT* aOther ) const
{ {
#define TEST( a, b ) { if( a != b ) return a < b; } #define TEST( a, b ) { if( a != b ) return a - b; }
#define TEST_PT( a, b ) { TEST( a.x, b.x ); TEST( a.y, b.y ); } #define TEST_PT( a, b ) { TEST( a.x, b.x ); TEST( a.y, b.y ); }
TEST_PT( m_e.pos, aOther->m_e.pos ); TEST_PT( m_e.pos, aOther->m_e.pos );

View File

@ -409,7 +409,7 @@ void DXF_PLOTTER::SetColor( const COLOR4D& color )
} }
void DXF_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, int width ) void DXF_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill, int width )
{ {
wxASSERT( m_outputFile ); wxASSERT( m_outputFile );
MoveTo( p1 ); MoveTo( p1 );
@ -420,7 +420,7 @@ void DXF_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, in
} }
void DXF_PLOTTER::Circle( const wxPoint& centre, int diameter, FILL_TYPE fill, int width ) void DXF_PLOTTER::Circle( const wxPoint& centre, int diameter, FILL_T fill, int width )
{ {
wxASSERT( m_outputFile ); wxASSERT( m_outputFile );
double radius = userToDeviceSize( diameter / 2 ); double radius = userToDeviceSize( diameter / 2 );
@ -430,14 +430,13 @@ void DXF_PLOTTER::Circle( const wxPoint& centre, int diameter, FILL_TYPE fill, i
{ {
wxString cname = getDXFColorName( m_currentColor ); wxString cname = getDXFColorName( m_currentColor );
if( fill == FILL_TYPE::NO_FILL ) if( fill == FILL_T::NO_FILL )
{ {
fprintf( m_outputFile, "0\nCIRCLE\n8\n%s\n10\n%g\n20\n%g\n40\n%g\n", fprintf( m_outputFile, "0\nCIRCLE\n8\n%s\n10\n%g\n20\n%g\n40\n%g\n",
TO_UTF8( cname ), TO_UTF8( cname ),
centre_dev.x, centre_dev.y, radius ); centre_dev.x, centre_dev.y, radius );
} }
else if( fill == FILL_T::FILLED_SHAPE )
if( fill == FILL_TYPE::FILLED_SHAPE )
{ {
double r = radius*0.5; double r = radius*0.5;
fprintf( m_outputFile, "0\nPOLYLINE\n" ); fprintf( m_outputFile, "0\nPOLYLINE\n" );
@ -455,8 +454,8 @@ void DXF_PLOTTER::Circle( const wxPoint& centre, int diameter, FILL_TYPE fill, i
} }
void DXF_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList, void DXF_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList, FILL_T aFill, int aWidth,
FILL_TYPE aFill, int aWidth, void* aData ) void* aData )
{ {
if( aCornerList.size() <= 1 ) if( aCornerList.size() <= 1 )
return; return;
@ -472,7 +471,7 @@ void DXF_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList,
LineTo( aCornerList[ii] ); LineTo( aCornerList[ii] );
// Close polygon if 'fill' requested // Close polygon if 'fill' requested
if( aFill != FILL_TYPE::NO_FILL ) if( aFill != FILL_T::NO_FILL )
{ {
if( aCornerList[last] != aCornerList[0] ) if( aCornerList[last] != aCornerList[0] )
LineTo( aCornerList[0] ); LineTo( aCornerList[0] );
@ -485,7 +484,7 @@ void DXF_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList,
// if the polygon outline has thickness, and is not filled // if the polygon outline has thickness, and is not filled
// (i.e. is a polyline) plot outlines with thick segments // (i.e. is a polyline) plot outlines with thick segments
if( aWidth > 0 && aFill == FILL_TYPE::NO_FILL ) if( aWidth > 0 && aFill == FILL_T::NO_FILL )
{ {
MoveTo( aCornerList[0] ); MoveTo( aCornerList[0] );
@ -610,7 +609,7 @@ void DXF_PLOTTER::ThickSegment( const wxPoint& aStart, const wxPoint& aEnd, int
if( cornerList[0] != cornerList[cornerList.size() - 1] ) if( cornerList[0] != cornerList[cornerList.size() - 1] )
cornerList.push_back( cornerList[0] ); cornerList.push_back( cornerList[0] );
PlotPoly( cornerList, FILL_TYPE::NO_FILL ); PlotPoly( cornerList, FILL_T::NO_FILL );
} }
else else
{ {
@ -621,7 +620,7 @@ void DXF_PLOTTER::ThickSegment( const wxPoint& aStart, const wxPoint& aEnd, int
void DXF_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int radius, void DXF_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int radius,
FILL_TYPE fill, int width ) FILL_T fill, int width )
{ {
wxASSERT( m_outputFile ); wxASSERT( m_outputFile );
@ -671,7 +670,7 @@ void DXF_PLOTTER::FlashPadCircle( const wxPoint& pos, int diametre,
OUTLINE_MODE trace_mode, void* aData ) OUTLINE_MODE trace_mode, void* aData )
{ {
wxASSERT( m_outputFile ); wxASSERT( m_outputFile );
Circle( pos, diametre, FILL_TYPE::NO_FILL ); Circle( pos, diametre, FILL_T::NO_FILL );
} }

View File

@ -793,7 +793,7 @@ void GERBER_PLOTTER::PenTo( const wxPoint& aPos, char plume )
} }
void GERBER_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, int width ) void GERBER_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill, int width )
{ {
std::vector< wxPoint > cornerList; std::vector< wxPoint > cornerList;
@ -811,15 +811,15 @@ void GERBER_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill,
} }
void GERBER_PLOTTER::Circle( const wxPoint& aCenter, int aDiameter, FILL_TYPE aFill, int aWidth ) void GERBER_PLOTTER::Circle( const wxPoint& aCenter, int aDiameter, FILL_T aFill, int aWidth )
{ {
Arc( aCenter, 0, 3600, aDiameter / 2, aFill, aWidth ); Arc( aCenter, 0, 3600, aDiameter / 2, aFill, aWidth );
} }
void GERBER_PLOTTER::Arc( const wxPoint& aCenter, double aStAngle, double aEndAngle, void GERBER_PLOTTER::Arc( const wxPoint& aCenter, double aStAngle, double aEndAngle, int aRadius,
int aRadius, FILL_TYPE aFill, int aWidth ) FILL_T aFill, int aWidth )
{ {
SetCurrentLineWidth( aWidth ); SetCurrentLineWidth( aWidth );
@ -920,7 +920,7 @@ void GERBER_PLOTTER::PlotGerberRegion( const SHAPE_LINE_CHAIN& aPoly, void* aDat
} }
} }
PlotPoly( aPoly, FILL_TYPE::FILLED_SHAPE, 0 , gbr_metadata ); PlotPoly( aPoly, FILL_T::FILLED_SHAPE, 0 , gbr_metadata );
// Clear the TA attribute, to avoid the next item to inherit it: // Clear the TA attribute, to avoid the next item to inherit it:
if( clearTA_AperFunction ) if( clearTA_AperFunction )
@ -957,7 +957,7 @@ void GERBER_PLOTTER::PlotGerberRegion( const std::vector< wxPoint >& aCornerList
} }
} }
PlotPoly( aCornerList, FILL_TYPE::FILLED_SHAPE, 0, gbr_metadata ); PlotPoly( aCornerList, FILL_T::FILLED_SHAPE, 0, gbr_metadata );
// Clear the TA attribute, to avoid the next item to inherit it: // Clear the TA attribute, to avoid the next item to inherit it:
if( clearTA_AperFunction ) if( clearTA_AperFunction )
@ -974,7 +974,7 @@ void GERBER_PLOTTER::PlotGerberRegion( const std::vector< wxPoint >& aCornerList
} }
void GERBER_PLOTTER::PlotPoly( const SHAPE_LINE_CHAIN& aPoly, FILL_TYPE aFill, int aWidth, void GERBER_PLOTTER::PlotPoly( const SHAPE_LINE_CHAIN& aPoly, FILL_T aFill, int aWidth,
void* aData ) void* aData )
{ {
if( aPoly.CPoints().size() <= 1 ) if( aPoly.CPoints().size() <= 1 )
@ -988,7 +988,7 @@ void GERBER_PLOTTER::PlotPoly( const SHAPE_LINE_CHAIN& aPoly, FILL_TYPE aFill, i
if( gbr_metadata ) if( gbr_metadata )
formatNetAttribute( &gbr_metadata->m_NetlistMetadata ); formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
if( aFill != FILL_TYPE::NO_FILL ) if( aFill != FILL_T::NO_FILL )
{ {
fputs( "G36*\n", m_outputFile ); fputs( "G36*\n", m_outputFile );
@ -1045,15 +1045,15 @@ void GERBER_PLOTTER::PlotPoly( const SHAPE_LINE_CHAIN& aPoly, FILL_TYPE aFill, i
// Ensure the thick outline is closed for filled polygons // Ensure the thick outline is closed for filled polygons
// (if not filled, could be only a polyline) // (if not filled, could be only a polyline)
if( aFill != FILL_TYPE::NO_FILL && ( aPoly.CPoint( 0 ) != aPoly.CPoint( -1 ) ) ) if( aFill != FILL_T::NO_FILL && ( aPoly.CPoint( 0 ) != aPoly.CPoint( -1 ) ) )
LineTo( wxPoint( aPoly.CPoint( 0 ) ) ); LineTo( wxPoint( aPoly.CPoint( 0 ) ) );
PenFinish(); PenFinish();
} }
} }
void GERBER_PLOTTER::PlotPoly( const std::vector< wxPoint >& aCornerList, void GERBER_PLOTTER::PlotPoly( const std::vector< wxPoint >& aCornerList, FILL_T aFill, int aWidth,
FILL_TYPE aFill, int aWidth, void * aData ) void * aData )
{ {
if( aCornerList.size() <= 1 ) if( aCornerList.size() <= 1 )
return; return;
@ -1066,7 +1066,7 @@ void GERBER_PLOTTER::PlotPoly( const std::vector< wxPoint >& aCornerList,
if( gbr_metadata ) if( gbr_metadata )
formatNetAttribute( &gbr_metadata->m_NetlistMetadata ); formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
if( aFill != FILL_TYPE::NO_FILL ) if( aFill != FILL_T::NO_FILL )
{ {
fputs( "G36*\n", m_outputFile ); fputs( "G36*\n", m_outputFile );
@ -1094,7 +1094,7 @@ void GERBER_PLOTTER::PlotPoly( const std::vector< wxPoint >& aCornerList,
// Ensure the thick outline is closed for filled polygons // Ensure the thick outline is closed for filled polygons
// (if not filled, could be only a polyline) // (if not filled, could be only a polyline)
if( aFill != FILL_TYPE::NO_FILL &&( aCornerList[aCornerList.size() - 1] != aCornerList[0] ) ) if( aFill != FILL_T::NO_FILL && ( aCornerList[aCornerList.size() - 1] != aCornerList[0] ) )
LineTo( aCornerList[0] ); LineTo( aCornerList[0] );
PenFinish(); PenFinish();
@ -1134,16 +1134,15 @@ void GERBER_PLOTTER::ThickArc( const wxPoint& centre, double StAngle, double End
if( tracemode == FILLED ) if( tracemode == FILLED )
{ {
Arc( centre, StAngle, EndAngle, radius, FILL_TYPE::NO_FILL, DO_NOT_SET_LINE_WIDTH ); Arc( centre, StAngle, EndAngle, radius, FILL_T::NO_FILL, DO_NOT_SET_LINE_WIDTH );
} }
else else
{ {
SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH );
Arc( centre, StAngle, EndAngle, Arc( centre, StAngle, EndAngle, radius - ( width - m_currentPenWidth ) / 2, FILL_T::NO_FILL,
radius - ( width - m_currentPenWidth ) / 2, FILL_TYPE::NO_FILL, DO_NOT_SET_LINE_WIDTH );
Arc( centre, StAngle, EndAngle, radius + ( width - m_currentPenWidth ) / 2, FILL_T::NO_FILL,
DO_NOT_SET_LINE_WIDTH ); DO_NOT_SET_LINE_WIDTH );
Arc( centre, StAngle, EndAngle, radius + ( width - m_currentPenWidth ) / 2,
FILL_TYPE::NO_FILL, DO_NOT_SET_LINE_WIDTH );
} }
} }
@ -1159,7 +1158,7 @@ void GERBER_PLOTTER::ThickRect( const wxPoint& p1, const wxPoint& p2, int width,
if( tracemode == FILLED ) if( tracemode == FILLED )
{ {
Rect( p1, p2, FILL_TYPE::NO_FILL, DO_NOT_SET_LINE_WIDTH ); Rect( p1, p2, FILL_T::NO_FILL, DO_NOT_SET_LINE_WIDTH );
} }
else else
{ {
@ -1168,12 +1167,12 @@ void GERBER_PLOTTER::ThickRect( const wxPoint& p1, const wxPoint& p2, int width,
p1.y - (width - m_currentPenWidth) / 2 ); p1.y - (width - m_currentPenWidth) / 2 );
wxPoint offsetp2( p2.x + (width - m_currentPenWidth) / 2, wxPoint offsetp2( p2.x + (width - m_currentPenWidth) / 2,
p2.y + (width - m_currentPenWidth) / 2 ); p2.y + (width - m_currentPenWidth) / 2 );
Rect( offsetp1, offsetp2, FILL_TYPE::NO_FILL, -1 ); Rect( offsetp1, offsetp2, FILL_T::NO_FILL, -1 );
offsetp1.x += (width - m_currentPenWidth); offsetp1.x += (width - m_currentPenWidth);
offsetp1.y += (width - m_currentPenWidth); offsetp1.y += (width - m_currentPenWidth);
offsetp2.x -= (width - m_currentPenWidth); offsetp2.x -= (width - m_currentPenWidth);
offsetp2.y -= (width - m_currentPenWidth); offsetp2.y -= (width - m_currentPenWidth);
Rect( offsetp1, offsetp2, FILL_TYPE::NO_FILL, DO_NOT_SET_LINE_WIDTH ); Rect( offsetp1, offsetp2, FILL_T::NO_FILL, DO_NOT_SET_LINE_WIDTH );
} }
} }
@ -1189,15 +1188,15 @@ void GERBER_PLOTTER::ThickCircle( const wxPoint& pos, int diametre, int width,
if( tracemode == FILLED ) if( tracemode == FILLED )
{ {
Circle( pos, diametre, FILL_TYPE::NO_FILL, DO_NOT_SET_LINE_WIDTH ); Circle( pos, diametre, FILL_T::NO_FILL, DO_NOT_SET_LINE_WIDTH );
} }
else else
{ {
SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH, gbr_metadata ); SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH, gbr_metadata );
Circle( pos, diametre - (width - m_currentPenWidth), Circle( pos, diametre - (width - m_currentPenWidth), FILL_T::NO_FILL,
FILL_TYPE::NO_FILL, DO_NOT_SET_LINE_WIDTH ); DO_NOT_SET_LINE_WIDTH );
Circle( pos, diametre + (width - m_currentPenWidth), Circle( pos, diametre + (width - m_currentPenWidth), FILL_T::NO_FILL,
FILL_TYPE::NO_FILL, DO_NOT_SET_LINE_WIDTH ); DO_NOT_SET_LINE_WIDTH );
} }
} }
@ -1217,17 +1216,18 @@ void GERBER_PLOTTER::FilledCircle( const wxPoint& pos, int diametre,
// Draw a circle of diameter = diameter/2 with a line thickness = radius, // Draw a circle of diameter = diameter/2 with a line thickness = radius,
// To create a filled circle // To create a filled circle
SetCurrentLineWidth( diametre/2, gbr_metadata ); SetCurrentLineWidth( diametre/2, gbr_metadata );
Circle( pos, diametre/2, FILL_TYPE::NO_FILL, DO_NOT_SET_LINE_WIDTH ); Circle( pos, diametre/2, FILL_T::NO_FILL, DO_NOT_SET_LINE_WIDTH );
} }
else else
{ {
SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH, gbr_metadata ); SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH, gbr_metadata );
Circle( pos, diametre, FILL_TYPE::NO_FILL, DO_NOT_SET_LINE_WIDTH ); Circle( pos, diametre, FILL_T::NO_FILL, DO_NOT_SET_LINE_WIDTH );
} }
} }
void GERBER_PLOTTER::FlashPadCircle( const wxPoint& pos, int diametre, OUTLINE_MODE trace_mode, void* aData ) void GERBER_PLOTTER::FlashPadCircle( const wxPoint& pos, int diametre, OUTLINE_MODE trace_mode,
void* aData )
{ {
wxSize size( diametre, diametre ); wxSize size( diametre, diametre );
GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData ); GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
@ -1239,7 +1239,7 @@ void GERBER_PLOTTER::FlashPadCircle( const wxPoint& pos, int diametre, OUTLINE_M
SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH );
Circle( pos, diametre - m_currentPenWidth, FILL_TYPE::NO_FILL, DO_NOT_SET_LINE_WIDTH ); Circle( pos, diametre - m_currentPenWidth, FILL_T::NO_FILL, DO_NOT_SET_LINE_WIDTH );
} }
else else
{ {
@ -1363,7 +1363,7 @@ void GERBER_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& aSize,
pos.y - (size.y - GetCurrentLineWidth()) / 2 ), pos.y - (size.y - GetCurrentLineWidth()) / 2 ),
wxPoint( pos.x + (size.x - GetCurrentLineWidth()) / 2, wxPoint( pos.x + (size.x - GetCurrentLineWidth()) / 2,
pos.y + (size.y - GetCurrentLineWidth()) / 2 ), pos.y + (size.y - GetCurrentLineWidth()) / 2 ),
FILL_TYPE::NO_FILL, GetCurrentLineWidth() ); FILL_T::NO_FILL, GetCurrentLineWidth() );
} }
else else
{ {
@ -1446,7 +1446,7 @@ void GERBER_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aS
cornerList.push_back( cornerList[0] ); cornerList.push_back( cornerList[0] );
// plot outlines // plot outlines
PlotPoly( cornerList, FILL_TYPE::NO_FILL, GetCurrentLineWidth(), gbr_metadata ); PlotPoly( cornerList, FILL_T::NO_FILL, GetCurrentLineWidth(), gbr_metadata );
} }
else else
{ {
@ -1663,7 +1663,7 @@ void GERBER_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize
if( aTraceMode == SKETCH ) if( aTraceMode == SKETCH )
{ {
PlotPoly( cornerList, FILL_TYPE::NO_FILL, GetCurrentLineWidth(), &gbr_metadata ); PlotPoly( cornerList, FILL_T::NO_FILL, GetCurrentLineWidth(), &gbr_metadata );
} }
else else
{ {
@ -1734,7 +1734,7 @@ void GERBER_PLOTTER::FlashPadChamferRoundRect( const wxPoint& aShapePos, const w
cornerList.push_back( cornerList[0] ); cornerList.push_back( cornerList[0] );
if( aPlotMode == SKETCH ) if( aPlotMode == SKETCH )
PlotPoly( cornerList, FILL_TYPE::NO_FILL, GetCurrentLineWidth(), &gbr_metadata ); PlotPoly( cornerList, FILL_T::NO_FILL, GetCurrentLineWidth(), &gbr_metadata );
else else
{ {
#ifdef GBR_USE_MACROS_FOR_CHAMFERED_ROUND_RECT #ifdef GBR_USE_MACROS_FOR_CHAMFERED_ROUND_RECT
@ -1847,7 +1847,7 @@ void GERBER_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint* aCo
if( aTrace_Mode == SKETCH ) if( aTrace_Mode == SKETCH )
{ {
PlotPoly( cornerList, FILL_TYPE::NO_FILL, GetCurrentLineWidth(), &metadata ); PlotPoly( cornerList, FILL_T::NO_FILL, GetCurrentLineWidth(), &metadata );
return; return;
} }
@ -1903,7 +1903,7 @@ void GERBER_PLOTTER::FlashRegularPolygon( const wxPoint& aShapePos, int aDiamete
cornerList.push_back( cornerList[0] ); // Close the shape cornerList.push_back( cornerList[0] ); // Close the shape
PlotPoly( cornerList, FILL_TYPE::NO_FILL, GetCurrentLineWidth(), &gbr_metadata ); PlotPoly( cornerList, FILL_T::NO_FILL, GetCurrentLineWidth(), &gbr_metadata );
} }
else else
{ {

View File

@ -383,7 +383,7 @@ void HPGL_PLOTTER::SetPenDiameter( double diameter )
} }
void HPGL_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, int width ) void HPGL_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill, int width )
{ {
wxASSERT( m_outputFile ); wxASSERT( m_outputFile );
@ -392,7 +392,7 @@ void HPGL_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, i
MoveTo( p1 ); MoveTo( p1 );
if( fill == FILL_TYPE::FILLED_SHAPE ) if( fill == FILL_T::FILLED_SHAPE )
{ {
startOrAppendItem( p1dev, wxString::Format( "RA %.0f,%.0f;", p2dev.x, p2dev.y ) ); startOrAppendItem( p1dev, wxString::Format( "RA %.0f,%.0f;", p2dev.x, p2dev.y ) );
} }
@ -405,7 +405,7 @@ void HPGL_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, i
} }
void HPGL_PLOTTER::Circle( const wxPoint& centre, int diameter, FILL_TYPE fill, int width ) void HPGL_PLOTTER::Circle( const wxPoint& centre, int diameter, FILL_T fill, int width )
{ {
wxASSERT( m_outputFile ); wxASSERT( m_outputFile );
double radius = userToDeviceSize( diameter / 2 ); double radius = userToDeviceSize( diameter / 2 );
@ -425,7 +425,7 @@ void HPGL_PLOTTER::Circle( const wxPoint& centre, int diameter, FILL_TYPE fill,
chord_degrees = 45; chord_degrees = 45;
} }
if( fill == FILL_TYPE::FILLED_SHAPE ) if( fill == FILL_T::FILLED_SHAPE )
{ {
// Draw the filled area // Draw the filled area
MoveTo( centre ); MoveTo( centre );
@ -451,8 +451,8 @@ void HPGL_PLOTTER::Circle( const wxPoint& centre, int diameter, FILL_TYPE fill,
} }
void HPGL_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList, FILL_TYPE aFill, void HPGL_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList, FILL_T aFill, int aWidth,
int aWidth, void* aData ) void* aData )
{ {
if( aCornerList.size() <= 1 ) if( aCornerList.size() <= 1 )
return; return;
@ -468,7 +468,7 @@ void HPGL_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList, FILL_TYPE
MoveTo( aCornerList[0] ); MoveTo( aCornerList[0] );
startItem( userToDeviceCoordinates( aCornerList[0] ) ); startItem( userToDeviceCoordinates( aCornerList[0] ) );
if( aFill == FILL_TYPE::FILLED_SHAPE ) if( aFill == FILL_T::FILLED_SHAPE )
{ {
// Draw the filled area // Draw the filled area
SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH );
@ -493,7 +493,7 @@ void HPGL_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList, FILL_TYPE
LineTo( aCornerList[ii] ); LineTo( aCornerList[ii] );
// Always close polygon if filled. // Always close polygon if filled.
if( aFill != FILL_TYPE::NO_FILL ) if( aFill != FILL_T::NO_FILL )
{ {
int ii = aCornerList.size() - 1; int ii = aCornerList.size() - 1;
@ -563,7 +563,7 @@ void HPGL_PLOTTER::ThickSegment( const wxPoint& start, const wxPoint& end,
void HPGL_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int radius, void HPGL_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int radius,
FILL_TYPE fill, int width ) FILL_T fill, int width )
{ {
wxASSERT( m_outputFile ); wxASSERT( m_outputFile );
double angle; double angle;
@ -725,7 +725,7 @@ void HPGL_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& padsize,
corners[ii] += pos; corners[ii] += pos;
} }
PlotPoly( corners, trace_mode == FILLED ? FILL_TYPE::FILLED_SHAPE : FILL_TYPE::NO_FILL ); PlotPoly( corners, trace_mode == FILLED ? FILL_T::FILLED_SHAPE : FILL_T::NO_FILL );
} }
@ -763,7 +763,7 @@ void HPGL_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSiz
if( cornerList.back() != cornerList.front() ) if( cornerList.back() != cornerList.front() )
cornerList.push_back( cornerList.front() ); cornerList.push_back( cornerList.front() );
PlotPoly( cornerList, aTraceMode == FILLED ? FILL_TYPE::FILLED_SHAPE : FILL_TYPE::NO_FILL ); PlotPoly( cornerList, aTraceMode == FILLED ? FILL_T::FILLED_SHAPE : FILL_T::NO_FILL );
} }
@ -785,7 +785,7 @@ void HPGL_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize,
if( cornerList.back() != cornerList.front() ) if( cornerList.back() != cornerList.front() )
cornerList.push_back( cornerList.front() ); cornerList.push_back( cornerList.front() );
PlotPoly( cornerList, aTraceMode == FILLED ? FILL_TYPE::FILLED_SHAPE : FILL_TYPE::NO_FILL ); PlotPoly( cornerList, aTraceMode == FILLED ? FILL_T::FILLED_SHAPE : FILL_T::NO_FILL );
} }
} }
@ -807,7 +807,7 @@ void HPGL_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint* aCorne
// Close polygon // Close polygon
cornerList.push_back( cornerList.front() ); cornerList.push_back( cornerList.front() );
PlotPoly( cornerList, aTraceMode == FILLED ? FILL_TYPE::FILLED_SHAPE : FILL_TYPE::NO_FILL ); PlotPoly( cornerList, aTraceMode == FILLED ? FILL_T::FILLED_SHAPE : FILL_T::NO_FILL );
} }

View File

@ -190,7 +190,7 @@ void PDF_PLOTTER::SetDash( PLOT_DASH_TYPE dashed )
} }
void PDF_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, int width ) void PDF_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill, int width )
{ {
wxASSERT( workFile ); wxASSERT( workFile );
DPOINT p1_dev = userToDeviceCoordinates( p1 ); DPOINT p1_dev = userToDeviceCoordinates( p1 );
@ -198,11 +198,11 @@ void PDF_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, in
SetCurrentLineWidth( width ); SetCurrentLineWidth( width );
fprintf( workFile, "%g %g %g %g re %c\n", p1_dev.x, p1_dev.y, fprintf( workFile, "%g %g %g %g re %c\n", p1_dev.x, p1_dev.y,
p2_dev.x - p1_dev.x, p2_dev.y - p1_dev.y, fill == FILL_TYPE::NO_FILL ? 'S' : 'B' ); p2_dev.x - p1_dev.x, p2_dev.y - p1_dev.y, fill == FILL_T::NO_FILL ? 'S' : 'B' );
} }
void PDF_PLOTTER::Circle( const wxPoint& pos, int diametre, FILL_TYPE aFill, int width ) void PDF_PLOTTER::Circle( const wxPoint& pos, int diametre, FILL_T aFill, int width )
{ {
wxASSERT( workFile ); wxASSERT( workFile );
DPOINT pos_dev = userToDeviceCoordinates( pos ); DPOINT pos_dev = userToDeviceCoordinates( pos );
@ -217,9 +217,9 @@ void PDF_PLOTTER::Circle( const wxPoint& pos, int diametre, FILL_TYPE aFill, int
SetCurrentLineWidth( width ); SetCurrentLineWidth( width );
// If diameter is less than width, switch to filled mode // If diameter is less than width, switch to filled mode
if( aFill == FILL_TYPE::NO_FILL && diametre < width ) if( aFill == FILL_T::NO_FILL && diametre < width )
{ {
aFill = FILL_TYPE::FILLED_SHAPE; aFill = FILL_T::FILLED_SHAPE;
SetCurrentLineWidth( 0 ); SetCurrentLineWidth( 0 );
radius = userToDeviceSize( ( diametre / 2.0 ) + ( width / 2.0 ) ); radius = userToDeviceSize( ( diametre / 2.0 ) + ( width / 2.0 ) );
@ -251,18 +251,18 @@ void PDF_PLOTTER::Circle( const wxPoint& pos, int diametre, FILL_TYPE aFill, int
pos_dev.x - radius, pos_dev.y - magic, pos_dev.x - radius, pos_dev.y - magic,
pos_dev.x - radius, pos_dev.y, pos_dev.x - radius, pos_dev.y,
aFill == FILL_TYPE::NO_FILL ? 's' : 'b' ); aFill == FILL_T::NO_FILL ? 's' : 'b' );
} }
void PDF_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int radius, void PDF_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int radius,
FILL_TYPE fill, int width ) FILL_T fill, int width )
{ {
wxASSERT( workFile ); wxASSERT( workFile );
if( radius <= 0 ) if( radius <= 0 )
{ {
Circle( centre, width, FILL_TYPE::FILLED_SHAPE, 0 ); Circle( centre, width, FILL_T::FILLED_SHAPE, 0 );
return; return;
} }
@ -297,7 +297,7 @@ void PDF_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, i
// The arc is drawn... if not filled we stroke it, otherwise we finish // The arc is drawn... if not filled we stroke it, otherwise we finish
// closing the pie at the center // closing the pie at the center
if( fill == FILL_TYPE::NO_FILL ) if( fill == FILL_T::NO_FILL )
{ {
fputs( "S\n", workFile ); fputs( "S\n", workFile );
} }
@ -309,8 +309,8 @@ void PDF_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, i
} }
void PDF_PLOTTER::PlotPoly( const std::vector< wxPoint >& aCornerList, void PDF_PLOTTER::PlotPoly( const std::vector< wxPoint >& aCornerList, FILL_T aFill, int aWidth,
FILL_TYPE aFill, int aWidth, void* aData ) void* aData )
{ {
wxASSERT( workFile ); wxASSERT( workFile );
@ -329,7 +329,7 @@ void PDF_PLOTTER::PlotPoly( const std::vector< wxPoint >& aCornerList,
} }
// Close path and stroke(/fill) // Close path and stroke(/fill)
fprintf( workFile, "%c\n", aFill == FILL_TYPE::NO_FILL ? 'S' : 'b' ); fprintf( workFile, "%c\n", aFill == FILL_T::NO_FILL ? 'S' : 'b' );
} }

View File

@ -47,12 +47,12 @@ const double PSLIKE_PLOTTER::postscriptTextAscent = 0.718;
// return a id used to select a ps macro (see StartPlot() ) from a FILL_TYPE // return a id used to select a ps macro (see StartPlot() ) from a FILL_TYPE
// fill mode, for arc, rect, circle and poly draw primitives // fill mode, for arc, rect, circle and poly draw primitives
static int getFillId( FILL_TYPE aFill ) static int getFillId( FILL_T aFill )
{ {
if( aFill == FILL_TYPE::NO_FILL ) if( aFill == FILL_T::NO_FILL )
return 0; return 0;
if( aFill == FILL_TYPE::FILLED_SHAPE ) if( aFill == FILL_T::FILLED_SHAPE )
return 1; return 1;
return 2; return 2;
@ -122,7 +122,7 @@ void PSLIKE_PLOTTER::FlashPadCircle( const wxPoint& aPadPos, int aDiameter,
{ {
if( aTraceMode == FILLED ) if( aTraceMode == FILLED )
{ {
Circle( aPadPos, aDiameter, FILL_TYPE::FILLED_SHAPE, 0 ); Circle( aPadPos, aDiameter, FILL_T::FILLED_SHAPE, 0 );
} }
else // Plot a ring: else // Plot a ring:
{ {
@ -133,7 +133,7 @@ void PSLIKE_PLOTTER::FlashPadCircle( const wxPoint& aPadPos, int aDiameter,
if( linewidth > aDiameter-2 ) if( linewidth > aDiameter-2 )
linewidth = aDiameter-2; linewidth = aDiameter-2;
Circle( aPadPos, aDiameter - linewidth, FILL_TYPE::NO_FILL, linewidth ); Circle( aPadPos, aDiameter - linewidth, FILL_T::NO_FILL, linewidth );
} }
SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH );
@ -185,7 +185,7 @@ void PSLIKE_PLOTTER::FlashPadRect( const wxPoint& aPadPos, const wxSize& aSize,
cornerList.push_back( cornerList[0] ); cornerList.push_back( cornerList[0] );
PlotPoly( cornerList, ( aTraceMode == FILLED ) ? FILL_TYPE::FILLED_SHAPE : FILL_TYPE::NO_FILL, PlotPoly( cornerList, ( aTraceMode == FILLED ) ? FILL_T::FILLED_SHAPE : FILL_T::NO_FILL,
GetCurrentLineWidth() ); GetCurrentLineWidth() );
} }
@ -225,7 +225,7 @@ void PSLIKE_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aS
// Close polygon // Close polygon
cornerList.push_back( cornerList[0] ); cornerList.push_back( cornerList[0] );
PlotPoly( cornerList, ( aTraceMode == FILLED ) ? FILL_TYPE::FILLED_SHAPE : FILL_TYPE::NO_FILL, PlotPoly( cornerList, ( aTraceMode == FILLED ) ? FILL_T::FILLED_SHAPE : FILL_T::NO_FILL,
GetCurrentLineWidth() ); GetCurrentLineWidth() );
} }
@ -261,7 +261,7 @@ void PSLIKE_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize
// Close polygon // Close polygon
cornerList.push_back( cornerList[0] ); cornerList.push_back( cornerList[0] );
PlotPoly( cornerList, ( aTraceMode == FILLED ) ? FILL_TYPE::FILLED_SHAPE : FILL_TYPE::NO_FILL, PlotPoly( cornerList, ( aTraceMode == FILLED ) ? FILL_T::FILLED_SHAPE : FILL_T::NO_FILL,
GetCurrentLineWidth() ); GetCurrentLineWidth() );
} }
} }
@ -309,7 +309,7 @@ void PSLIKE_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCor
} }
cornerList.push_back( cornerList[0] ); cornerList.push_back( cornerList[0] );
PlotPoly( cornerList, ( aTraceMode == FILLED ) ? FILL_TYPE::FILLED_SHAPE : FILL_TYPE::NO_FILL, PlotPoly( cornerList, ( aTraceMode == FILLED ) ? FILL_T::FILLED_SHAPE : FILL_T::NO_FILL,
GetCurrentLineWidth() ); GetCurrentLineWidth() );
} }
@ -577,7 +577,7 @@ void PS_PLOTTER::SetDash( PLOT_DASH_TYPE dashed )
} }
void PS_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, int width ) void PS_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill, int width )
{ {
DPOINT p1_dev = userToDeviceCoordinates( p1 ); DPOINT p1_dev = userToDeviceCoordinates( p1 );
DPOINT p2_dev = userToDeviceCoordinates( p2 ); DPOINT p2_dev = userToDeviceCoordinates( p2 );
@ -588,7 +588,7 @@ void PS_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, int
} }
void PS_PLOTTER::Circle( const wxPoint& pos, int diametre, FILL_TYPE fill, int width ) void PS_PLOTTER::Circle( const wxPoint& pos, int diametre, FILL_T fill, int width )
{ {
wxASSERT( m_outputFile ); wxASSERT( m_outputFile );
DPOINT pos_dev = userToDeviceCoordinates( pos ); DPOINT pos_dev = userToDeviceCoordinates( pos );
@ -599,8 +599,8 @@ void PS_PLOTTER::Circle( const wxPoint& pos, int diametre, FILL_TYPE fill, int w
} }
void PS_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, void PS_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int radius,
int radius, FILL_TYPE fill, int width ) FILL_T fill, int width )
{ {
wxASSERT( m_outputFile ); wxASSERT( m_outputFile );
@ -636,8 +636,8 @@ void PS_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle,
} }
void PS_PLOTTER::PlotPoly( const std::vector< wxPoint >& aCornerList, void PS_PLOTTER::PlotPoly( const std::vector< wxPoint >& aCornerList, FILL_T aFill,
FILL_TYPE aFill, int aWidth, void * aData ) int aWidth, void * aData )
{ {
if( aCornerList.size() <= 1 ) if( aCornerList.size() <= 1 )
return; return;

View File

@ -93,6 +93,7 @@
#include <base64.h> #include <base64.h>
#include <eda_rect.h> #include <eda_rect.h>
#include <eda_shape.h>
#include <string_utils.h> #include <string_utils.h>
#include <macros.h> #include <macros.h>
#include <trigo.h> #include <trigo.h>
@ -163,7 +164,7 @@ SVG_PLOTTER::SVG_PLOTTER()
{ {
m_graphics_changed = true; m_graphics_changed = true;
SetTextMode( PLOT_TEXT_MODE::STROKE ); SetTextMode( PLOT_TEXT_MODE::STROKE );
m_fillMode = FILL_TYPE::NO_FILL; // or FILLED_SHAPE or FILLED_WITH_BG_BODYCOLOR m_fillMode = FILL_T::NO_FILL; // or FILLED_SHAPE or FILLED_WITH_BG_BODYCOLOR
m_pen_rgb_color = 0; // current color value (black) m_pen_rgb_color = 0; // current color value (black)
m_brush_rgb_color = 0; // current color value (black) m_brush_rgb_color = 0; // current color value (black)
m_dashed = PLOT_DASH_TYPE::SOLID; m_dashed = PLOT_DASH_TYPE::SOLID;
@ -215,7 +216,7 @@ void SVG_PLOTTER::SetColor( const COLOR4D& color )
} }
void SVG_PLOTTER::setFillMode( FILL_TYPE fill ) void SVG_PLOTTER::setFillMode( FILL_T fill )
{ {
if( m_fillMode != fill ) if( m_fillMode != fill )
{ {
@ -235,20 +236,11 @@ void SVG_PLOTTER::setSVGPlotStyle( bool aIsGroup, const std::string& aExtraStyle
switch( m_fillMode ) switch( m_fillMode )
{ {
case FILL_TYPE::NO_FILL: case FILL_T::NO_FILL: fputs( "fill-opacity:0.0; ", m_outputFile ); break;
fputs( "fill-opacity:0.0; ", m_outputFile ); case FILL_T::FILLED_SHAPE: fputs( "fill-opacity:1.0; ", m_outputFile ); break;
break; case FILL_T::FILLED_WITH_BG_BODYCOLOR: fputs( "fill-opacity:0.6; ", m_outputFile ); break;
case FILL_T::FILLED_WITH_COLOR:
case FILL_TYPE::FILLED_SHAPE: UNIMPLEMENTED_FOR( "FILLED_WITH_COLOR" );
fputs( "fill-opacity:1.0; ", m_outputFile );
break;
case FILL_TYPE::FILLED_WITH_BG_BODYCOLOR:
fputs( "fill-opacity:0.6; ", m_outputFile );
break;
case FILL_TYPE::FILLED_WITH_COLOR:
wxFAIL_MSG( "FILLED_WITH_COLOR not implemented" );
break; break;
} }
@ -373,7 +365,7 @@ void SVG_PLOTTER::SetDash( PLOT_DASH_TYPE dashed )
} }
void SVG_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, int width ) void SVG_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill, int width )
{ {
EDA_RECT rect( p1, wxSize( p2.x -p1.x, p2.y -p1.y ) ); EDA_RECT rect( p1, wxSize( p2.x -p1.x, p2.y -p1.y ) );
rect.Normalize(); rect.Normalize();
@ -410,7 +402,7 @@ void SVG_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, in
} }
void SVG_PLOTTER::Circle( const wxPoint& pos, int diametre, FILL_TYPE fill, int width ) void SVG_PLOTTER::Circle( const wxPoint& pos, int diametre, FILL_T fill, int width )
{ {
DPOINT pos_dev = userToDeviceCoordinates( pos ); DPOINT pos_dev = userToDeviceCoordinates( pos );
double radius = userToDeviceSize( diametre / 2.0 ); double radius = userToDeviceSize( diametre / 2.0 );
@ -419,9 +411,9 @@ void SVG_PLOTTER::Circle( const wxPoint& pos, int diametre, FILL_TYPE fill, int
SetCurrentLineWidth( width ); SetCurrentLineWidth( width );
// If diameter is less than width, switch to filled mode // If diameter is less than width, switch to filled mode
if( fill == FILL_TYPE::NO_FILL && diametre < width ) if( fill == FILL_T::NO_FILL && diametre < width )
{ {
setFillMode( FILL_TYPE::FILLED_SHAPE ); setFillMode( FILL_T::FILLED_SHAPE );
SetCurrentLineWidth( 0 ); SetCurrentLineWidth( 0 );
radius = userToDeviceSize( ( diametre / 2.0 ) + ( width / 2.0 ) ); radius = userToDeviceSize( ( diametre / 2.0 ) + ( width / 2.0 ) );
@ -434,7 +426,7 @@ void SVG_PLOTTER::Circle( const wxPoint& pos, int diametre, FILL_TYPE fill, int
void SVG_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int radius, void SVG_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int radius,
FILL_TYPE fill, int width ) FILL_T fill, int width )
{ {
/* Draws an arc of a circle, centered on (xc,yc), with starting point /* Draws an arc of a circle, centered on (xc,yc), with starting point
* (x1, y1) and ending at (x2, y2). The current pen is used for the outline * (x1, y1) and ending at (x2, y2). The current pen is used for the outline
@ -446,7 +438,7 @@ void SVG_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, i
if( radius <= 0 ) if( radius <= 0 )
{ {
Circle( centre, width, FILL_TYPE::FILLED_SHAPE, 0 ); Circle( centre, width, FILL_T::FILLED_SHAPE, 0 );
return; return;
} }
@ -513,7 +505,7 @@ void SVG_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, i
// flag arc size (0 = small arc > 180 deg, 1 = large arc > 180 deg), // flag arc size (0 = small arc > 180 deg, 1 = large arc > 180 deg),
// sweep arc ( 0 = CCW, 1 = CW), // sweep arc ( 0 = CCW, 1 = CW),
// end point // end point
if( fill != FILL_TYPE::NO_FILL ) if( fill != FILL_T::NO_FILL )
{ {
// Filled arcs (in Eeschema) consist of the pie wedge and a stroke only on the arc // Filled arcs (in Eeschema) consist of the pie wedge and a stroke only on the arc
// This needs to be drawn in two steps. // This needs to be drawn in two steps.
@ -526,7 +518,7 @@ void SVG_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, i
end.x, end.y, centre_dev.x, centre_dev.y ); end.x, end.y, centre_dev.x, centre_dev.y );
} }
setFillMode( FILL_TYPE::NO_FILL ); setFillMode( FILL_T::NO_FILL );
SetCurrentLineWidth( width ); SetCurrentLineWidth( width );
fprintf( m_outputFile, "<path d=\"M%f %f A%f %f 0.0 %d %d %f %f\" />\n", fprintf( m_outputFile, "<path d=\"M%f %f A%f %f 0.0 %d %d %f %f\" />\n",
start.x, start.y, radius_dev, radius_dev, start.x, start.y, radius_dev, radius_dev,
@ -540,7 +532,7 @@ void SVG_PLOTTER::BezierCurve( const wxPoint& aStart, const wxPoint& aControl1,
int aTolerance, int aLineThickness ) int aTolerance, int aLineThickness )
{ {
#if 1 #if 1
setFillMode( FILL_TYPE::NO_FILL ); setFillMode( FILL_T::NO_FILL );
SetCurrentLineWidth( aLineThickness ); SetCurrentLineWidth( aLineThickness );
DPOINT start = userToDeviceCoordinates( aStart ); DPOINT start = userToDeviceCoordinates( aStart );
@ -558,7 +550,7 @@ void SVG_PLOTTER::BezierCurve( const wxPoint& aStart, const wxPoint& aControl1,
} }
void SVG_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList, FILL_TYPE aFill, void SVG_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList, FILL_T aFill,
int aWidth, void* aData ) int aWidth, void* aData )
{ {
if( aCornerList.size() <= 1 ) if( aCornerList.size() <= 1 )
@ -570,16 +562,16 @@ void SVG_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList, FILL_TYPE a
switch( aFill ) switch( aFill )
{ {
case FILL_TYPE::NO_FILL: case FILL_T::NO_FILL:
setSVGPlotStyle( false, "fill:none" ); setSVGPlotStyle( false, "fill:none" );
break; break;
case FILL_TYPE::FILLED_WITH_BG_BODYCOLOR: case FILL_T::FILLED_WITH_BG_BODYCOLOR:
case FILL_TYPE::FILLED_SHAPE: case FILL_T::FILLED_SHAPE:
setSVGPlotStyle( false, "fill-rule:evenodd;" ); setSVGPlotStyle( false, "fill-rule:evenodd;" );
break; break;
case FILL_TYPE::FILLED_WITH_COLOR: case FILL_T::FILLED_WITH_COLOR:
wxFAIL_MSG( "FILLED_WITH_COLOR not implemented" ); wxFAIL_MSG( "FILLED_WITH_COLOR not implemented" );
break; break;
} }
@ -673,9 +665,9 @@ void SVG_PLOTTER::PenTo( const wxPoint& pos, char plume )
// Ensure we do not use a fill mode when moving the pen, // Ensure we do not use a fill mode when moving the pen,
// in SVG mode (i;e. we are plotting only basic lines, not a filled area // in SVG mode (i;e. we are plotting only basic lines, not a filled area
if( m_fillMode != FILL_TYPE::NO_FILL ) if( m_fillMode != FILL_T::NO_FILL )
{ {
setFillMode( FILL_TYPE::NO_FILL ); setFillMode( FILL_T::NO_FILL );
setSVGPlotStyle(); setSVGPlotStyle();
} }
@ -773,7 +765,7 @@ void SVG_PLOTTER::Text( const wxPoint& aPos,
bool aMultilineAllowed, bool aMultilineAllowed,
void* aData ) void* aData )
{ {
setFillMode( FILL_TYPE::NO_FILL ); setFillMode( FILL_T::NO_FILL );
SetColor( aColor ); SetColor( aColor );
SetCurrentLineWidth( aWidth ); SetCurrentLineWidth( aWidth );

View File

@ -109,7 +109,7 @@ void PlotDrawingSheet( PLOTTER* plotter, const PROJECT* aProject, const TITLE_BL
{ {
DS_DRAW_ITEM_RECT* rect = (DS_DRAW_ITEM_RECT*) item; DS_DRAW_ITEM_RECT* rect = (DS_DRAW_ITEM_RECT*) item;
int penWidth = std::max( rect->GetPenWidth(), defaultPenWidth ); int penWidth = std::max( rect->GetPenWidth(), defaultPenWidth );
plotter->Rect( rect->GetStart(), rect->GetEnd(), FILL_TYPE::NO_FILL, penWidth ); plotter->Rect( rect->GetStart(), rect->GetEnd(), FILL_T::NO_FILL, penWidth );
} }
break; break;
@ -138,7 +138,7 @@ void PlotDrawingSheet( PLOTTER* plotter, const PROJECT* aProject, const TITLE_BL
for( int ii = 0; ii < outline.PointCount(); ii++ ) for( int ii = 0; ii < outline.PointCount(); ii++ )
points.emplace_back( outline.CPoint( ii ).x, outline.CPoint( ii ).y ); points.emplace_back( outline.CPoint( ii ).x, outline.CPoint( ii ).y );
plotter->PlotPoly( points, FILL_TYPE::FILLED_SHAPE, penWidth ); plotter->PlotPoly( points, FILL_T::FILLED_SHAPE, penWidth );
} }
} }
break; break;

View File

@ -157,12 +157,12 @@ double PLOTTER::GetDashGapLenIU() const
void PLOTTER::Arc( const SHAPE_ARC& aArc ) void PLOTTER::Arc( const SHAPE_ARC& aArc )
{ {
Arc( wxPoint( aArc.GetCenter() ), aArc.GetStartAngle(), aArc.GetEndAngle(), aArc.GetRadius(), Arc( wxPoint( aArc.GetCenter() ), aArc.GetStartAngle(), aArc.GetEndAngle(), aArc.GetRadius(),
FILL_TYPE::NO_FILL, aArc.GetWidth() ); FILL_T::NO_FILL, aArc.GetWidth() );
} }
void PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int radius, void PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int radius,
FILL_TYPE fill, int width ) FILL_T fill, int width )
{ {
wxPoint start, end; wxPoint start, end;
const int delta = 50; // increment (in 0.1 degrees) to draw circles const int delta = 50; // increment (in 0.1 degrees) to draw circles
@ -176,7 +176,7 @@ void PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int r
start.x = centre.x + KiROUND( cosdecideg( radius, -StAngle ) ); start.x = centre.x + KiROUND( cosdecideg( radius, -StAngle ) );
start.y = centre.y + KiROUND( sindecideg( radius, -StAngle ) ); start.y = centre.y + KiROUND( sindecideg( radius, -StAngle ) );
if( fill != FILL_TYPE::NO_FILL ) if( fill != FILL_T::NO_FILL )
{ {
MoveTo( centre ); MoveTo( centre );
LineTo( start ); LineTo( start );
@ -196,7 +196,7 @@ void PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int r
end.x = centre.x + KiROUND( cosdecideg( radius, -EndAngle ) ); end.x = centre.x + KiROUND( cosdecideg( radius, -EndAngle ) );
end.y = centre.y + KiROUND( sindecideg( radius, -EndAngle ) ); end.y = centre.y + KiROUND( sindecideg( radius, -EndAngle ) );
if( fill != FILL_TYPE::NO_FILL ) if( fill != FILL_T::NO_FILL )
{ {
LineTo( end ); LineTo( end );
FinishTo( centre ); FinishTo( centre );
@ -248,7 +248,7 @@ void PLOTTER::PlotImage(const wxImage& aImage, const wxPoint& aPos, double aScal
end.x += size.x; end.x += size.x;
end.y += size.y; end.y += size.y;
Rect( start, end, FILL_TYPE::NO_FILL ); Rect( start, end, FILL_T::NO_FILL );
} }
@ -273,13 +273,13 @@ void PLOTTER::markerSquare( const wxPoint& position, int radius )
corner.y = position.y + r; corner.y = position.y + r;
corner_list.push_back( corner ); corner_list.push_back( corner );
PlotPoly( corner_list, FILL_TYPE::NO_FILL, GetCurrentLineWidth() ); PlotPoly( corner_list, FILL_T::NO_FILL, GetCurrentLineWidth() );
} }
void PLOTTER::markerCircle( const wxPoint& position, int radius ) void PLOTTER::markerCircle( const wxPoint& position, int radius )
{ {
Circle( position, radius * 2, FILL_TYPE::NO_FILL, GetCurrentLineWidth() ); Circle( position, radius * 2, FILL_T::NO_FILL, GetCurrentLineWidth() );
} }
@ -303,7 +303,7 @@ void PLOTTER::markerLozenge( const wxPoint& position, int radius )
corner.y = position.y + radius; corner.y = position.y + radius;
corner_list.push_back( corner ); corner_list.push_back( corner );
PlotPoly( corner_list, FILL_TYPE::NO_FILL, GetCurrentLineWidth() ); PlotPoly( corner_list, FILL_T::NO_FILL, GetCurrentLineWidth() );
} }
@ -514,15 +514,11 @@ void PLOTTER::sketchOval( const wxPoint& pos, const wxSize& aSize, double orient
cx = 0; cx = 0;
cy = deltaxy / 2; cy = deltaxy / 2;
RotatePoint( &cx, &cy, orient ); RotatePoint( &cx, &cy, orient );
Arc( wxPoint( cx + pos.x, cy + pos.y ), Arc( wxPoint( cx + pos.x, cy + pos.y ), orient + 1800, orient + 3600, radius, FILL_T::NO_FILL );
orient + 1800, orient + 3600,
radius, FILL_TYPE::NO_FILL );
cx = 0; cx = 0;
cy = -deltaxy / 2; cy = -deltaxy / 2;
RotatePoint( &cx, &cy, orient ); RotatePoint( &cx, &cy, orient );
Arc( wxPoint( cx + pos.x, cy + pos.y ), Arc( wxPoint( cx + pos.x, cy + pos.y ), orient, orient + 1800, radius, FILL_T::NO_FILL );
orient, orient + 1800,
radius, FILL_TYPE::NO_FILL );
} }
@ -533,7 +529,7 @@ void PLOTTER::ThickSegment( const wxPoint& start, const wxPoint& end, int width,
{ {
if( start == end ) if( start == end )
{ {
Circle( start, width, FILL_TYPE::FILLED_SHAPE, 0 ); Circle( start, width, FILL_T::FILLED_SHAPE, 0 );
} }
else else
{ {
@ -555,15 +551,15 @@ void PLOTTER::ThickArc( const wxPoint& centre, double StAngle, double EndAngle,
{ {
if( tracemode == FILLED ) if( tracemode == FILLED )
{ {
Arc( centre, StAngle, EndAngle, radius, FILL_TYPE::NO_FILL, width ); Arc( centre, StAngle, EndAngle, radius, FILL_T::NO_FILL, width );
} }
else else
{ {
SetCurrentLineWidth( -1 ); SetCurrentLineWidth( -1 );
Arc( centre, StAngle, EndAngle, Arc( centre, StAngle, EndAngle, radius - ( width - m_currentPenWidth ) / 2,
radius - ( width - m_currentPenWidth ) / 2, FILL_TYPE::NO_FILL, -1 ); FILL_T::NO_FILL, -1 );
Arc( centre, StAngle, EndAngle, Arc( centre, StAngle, EndAngle, radius + ( width - m_currentPenWidth ) / 2,
radius + ( width - m_currentPenWidth ) / 2, FILL_TYPE::NO_FILL, -1 ); FILL_T::NO_FILL, -1 );
} }
} }
@ -573,7 +569,7 @@ void PLOTTER::ThickRect( const wxPoint& p1, const wxPoint& p2, int width,
{ {
if( tracemode == FILLED ) if( tracemode == FILLED )
{ {
Rect( p1, p2, FILL_TYPE::NO_FILL, width ); Rect( p1, p2, FILL_T::NO_FILL, width );
} }
else else
{ {
@ -582,12 +578,12 @@ void PLOTTER::ThickRect( const wxPoint& p1, const wxPoint& p2, int width,
p1.y - (width - m_currentPenWidth) / 2 ); p1.y - (width - m_currentPenWidth) / 2 );
wxPoint offsetp2( p2.x + (width - m_currentPenWidth) / 2, wxPoint offsetp2( p2.x + (width - m_currentPenWidth) / 2,
p2.y + (width - m_currentPenWidth) / 2 ); p2.y + (width - m_currentPenWidth) / 2 );
Rect( offsetp1, offsetp2, FILL_TYPE::NO_FILL, -1 ); Rect( offsetp1, offsetp2, FILL_T::NO_FILL, -1 );
offsetp1.x += ( width - m_currentPenWidth ); offsetp1.x += ( width - m_currentPenWidth );
offsetp1.y += ( width - m_currentPenWidth ); offsetp1.y += ( width - m_currentPenWidth );
offsetp2.x -= ( width - m_currentPenWidth ); offsetp2.x -= ( width - m_currentPenWidth );
offsetp2.y -= ( width - m_currentPenWidth ); offsetp2.y -= ( width - m_currentPenWidth );
Rect( offsetp1, offsetp2, FILL_TYPE::NO_FILL, -1 ); Rect( offsetp1, offsetp2, FILL_T::NO_FILL, -1 );
} }
} }
@ -597,13 +593,13 @@ void PLOTTER::ThickCircle( const wxPoint& pos, int diametre, int width, OUTLINE_
{ {
if( tracemode == FILLED ) if( tracemode == FILLED )
{ {
Circle( pos, diametre, FILL_TYPE::NO_FILL, width ); Circle( pos, diametre, FILL_T::NO_FILL, width );
} }
else else
{ {
SetCurrentLineWidth( -1 ); SetCurrentLineWidth( -1 );
Circle( pos, diametre - width + m_currentPenWidth, FILL_TYPE::NO_FILL, -1 ); Circle( pos, diametre - width + m_currentPenWidth, FILL_T::NO_FILL, -1 );
Circle( pos, diametre + width - m_currentPenWidth, FILL_TYPE::NO_FILL, -1 ); Circle( pos, diametre + width - m_currentPenWidth, FILL_T::NO_FILL, -1 );
} }
} }
@ -612,18 +608,17 @@ void PLOTTER::FilledCircle( const wxPoint& pos, int diametre, OUTLINE_MODE trace
{ {
if( tracemode == FILLED ) if( tracemode == FILLED )
{ {
Circle( pos, diametre, FILL_TYPE::FILLED_SHAPE, 0 ); Circle( pos, diametre, FILL_T::FILLED_SHAPE, 0 );
} }
else else
{ {
SetCurrentLineWidth( -1 ); SetCurrentLineWidth( -1 );
Circle( pos, diametre, FILL_TYPE::NO_FILL, -1 ); Circle( pos, diametre, FILL_T::NO_FILL, -1 );
} }
} }
void PLOTTER::PlotPoly( const SHAPE_LINE_CHAIN& aCornerList, FILL_TYPE aFill, void PLOTTER::PlotPoly( const SHAPE_LINE_CHAIN& aCornerList, FILL_T aFill, int aWidth, void* aData )
int aWidth, void* aData )
{ {
std::vector<wxPoint> cornerList; std::vector<wxPoint> cornerList;
cornerList.reserve( aCornerList.PointCount() ); cornerList.reserve( aCornerList.PointCount() );

View File

@ -177,14 +177,10 @@ set( EESCHEMA_SRCS
generate_alias_info.cpp generate_alias_info.cpp
getpart.cpp getpart.cpp
hierarch.cpp hierarch.cpp
lib_arc.cpp lib_shape.cpp
lib_bezier.cpp
lib_circle.cpp
lib_item.cpp lib_item.cpp
lib_field.cpp lib_field.cpp
lib_pin.cpp lib_pin.cpp
lib_polyline.cpp
lib_rectangle.cpp
lib_symbol.cpp lib_symbol.cpp
lib_text.cpp lib_text.cpp
symbol_viewer_frame.cpp symbol_viewer_frame.cpp
@ -274,6 +270,7 @@ set( EESCHEMA_COMMON_SRCS
${CMAKE_SOURCE_DIR}/common/base_screen.cpp ${CMAKE_SOURCE_DIR}/common/base_screen.cpp
${CMAKE_SOURCE_DIR}/common/base_units.cpp ${CMAKE_SOURCE_DIR}/common/base_units.cpp
${CMAKE_SOURCE_DIR}/common/eda_text.cpp ${CMAKE_SOURCE_DIR}/common/eda_text.cpp
${CMAKE_SOURCE_DIR}/common/eda_shape.cpp
${CMAKE_SOURCE_DIR}/common/page_info.cpp ${CMAKE_SOURCE_DIR}/common/page_info.cpp
) )

View File

@ -63,8 +63,11 @@ bool DIALOG_LIB_SHAPE_PROPERTIES::TransferDataToWindow()
return false; return false;
LIB_SYMBOL* symbol = m_item->GetParent(); LIB_SYMBOL* symbol = m_item->GetParent();
EDA_SHAPE* shape = dynamic_cast<EDA_SHAPE*>( m_item );
if( shape )
m_lineWidth.SetValue( shape->GetWidth() );
m_lineWidth.SetValue( m_item->GetWidth() );
m_checkApplyToAllUnits->SetValue( m_item->GetUnit() == 0 ); m_checkApplyToAllUnits->SetValue( m_item->GetUnit() == 0 );
m_checkApplyToAllUnits->Enable( symbol && symbol->GetUnitCount() > 1 ); m_checkApplyToAllUnits->Enable( symbol && symbol->GetUnitCount() > 1 );
m_checkApplyToAllConversions->SetValue( m_item->GetConvert() == 0 ); m_checkApplyToAllConversions->SetValue( m_item->GetConvert() == 0 );
@ -80,8 +83,10 @@ bool DIALOG_LIB_SHAPE_PROPERTIES::TransferDataToWindow()
m_checkApplyToAllConversions->Enable( enblConvOptStyle ); m_checkApplyToAllConversions->Enable( enblConvOptStyle );
m_fillCtrl->SetSelection( static_cast<int>( m_item->GetFillMode() ) ); if( shape )
m_fillCtrl->Enable( m_item->IsFillable() ); m_fillCtrl->SetSelection( static_cast<int>( shape->GetFillType() ) );
m_fillCtrl->Enable( shape != nullptr );
return true; return true;
} }
@ -92,10 +97,13 @@ bool DIALOG_LIB_SHAPE_PROPERTIES::TransferDataFromWindow()
if( !wxDialog::TransferDataFromWindow() ) if( !wxDialog::TransferDataFromWindow() )
return false; return false;
if( m_item->IsFillable() ) EDA_SHAPE* shape = dynamic_cast<EDA_SHAPE*>( m_item );
m_item->SetFillMode( (FILL_TYPE) std::max( m_fillCtrl->GetSelection(), 0 ) );
m_item->SetWidth( m_lineWidth.GetValue() ); if( shape )
shape->SetFillMode((FILL_T) std::max( m_fillCtrl->GetSelection(), 0 ));
if( shape )
shape->SetWidth( m_lineWidth.GetValue() );
if( GetApplyToAllConversions() ) if( GetApplyToAllConversions() )
m_item->SetConvert( 0 ); m_item->SetConvert( 0 );

View File

@ -898,7 +898,7 @@ void DIALOG_PLOT_SCHEMATIC::plotOneSheetPDF( PLOTTER* aPlotter, SCH_SCREEN* aScr
aPlotter->SetColor( aPlotter->RenderSettings()->GetBackgroundColor() ); aPlotter->SetColor( aPlotter->RenderSettings()->GetBackgroundColor() );
wxPoint end( aPlotter->PageSettings().GetWidthIU(), wxPoint end( aPlotter->PageSettings().GetWidthIU(),
aPlotter->PageSettings().GetHeightIU() ); aPlotter->PageSettings().GetHeightIU() );
aPlotter->Rect( wxPoint( 0, 0 ), end, FILL_TYPE::FILLED_SHAPE, 1.0 ); aPlotter->Rect( wxPoint( 0, 0 ), end, FILL_T::FILLED_SHAPE, 1.0 );
} }
if( aPlotDrawingSheet ) if( aPlotDrawingSheet )
@ -1088,7 +1088,7 @@ bool DIALOG_PLOT_SCHEMATIC::plotOneSheetPS( const wxString& aFileName,
{ {
plotter->SetColor( plotter->RenderSettings()->GetLayerColor( LAYER_SCHEMATIC_BACKGROUND ) ); plotter->SetColor( plotter->RenderSettings()->GetLayerColor( LAYER_SCHEMATIC_BACKGROUND ) );
wxPoint end( plotter->PageSettings().GetWidthIU(), plotter->PageSettings().GetHeightIU() ); wxPoint end( plotter->PageSettings().GetWidthIU(), plotter->PageSettings().GetHeightIU() );
plotter->Rect( wxPoint( 0, 0 ), end, FILL_TYPE::FILLED_SHAPE, 1.0 ); plotter->Rect( wxPoint( 0, 0 ), end, FILL_T::FILLED_SHAPE, 1.0 );
} }
if( aPlotFrameRef ) if( aPlotFrameRef )
@ -1218,7 +1218,7 @@ bool DIALOG_PLOT_SCHEMATIC::plotOneSheetSVG( const wxString& aFileName,
plotter->SetColor( plotter->RenderSettings()->GetLayerColor( LAYER_SCHEMATIC_BACKGROUND ) ); plotter->SetColor( plotter->RenderSettings()->GetLayerColor( LAYER_SCHEMATIC_BACKGROUND ) );
wxPoint end( plotter->PageSettings().GetWidthIU(), wxPoint end( plotter->PageSettings().GetWidthIU(),
plotter->PageSettings().GetHeightIU() ); plotter->PageSettings().GetHeightIU() );
plotter->Rect( wxPoint( 0, 0 ), end, FILL_TYPE::FILLED_SHAPE, 1.0 ); plotter->Rect( wxPoint( 0, 0 ), end, FILL_T::FILLED_SHAPE, 1.0 );
} }
if( aPlotFrameRef ) if( aPlotFrameRef )

View File

@ -24,7 +24,7 @@
#include <eeschema_settings.h> #include <eeschema_settings.h>
#include <gal/gal_display_options.h> #include <gal/gal_display_options.h>
#include <layer_ids.h> #include <layer_ids.h>
#include <lib_polyline.h> #include <lib_shape.h>
#include <page_info.h> #include <page_info.h>
#include <panel_eeschema_color_settings.h> #include <panel_eeschema_color_settings.h>
#include <pgm_base.h> #include <pgm_base.h>
@ -347,12 +347,12 @@ void PANEL_EESCHEMA_COLOR_SETTINGS::createPreviewItems()
symbol->SetShowPinNumbers( true ); symbol->SetShowPinNumbers( true );
symbol->SetPinNameOffset( 0 ); symbol->SetPinNameOffset( 0 );
LIB_POLYLINE* comp_body = new LIB_POLYLINE( symbol ); LIB_SHAPE* comp_body = new LIB_SHAPE( symbol, SHAPE_T::POLY );
comp_body->SetUnit( 0 ); comp_body->SetUnit( 0 );
comp_body->SetConvert( 0 ); comp_body->SetConvert( 0 );
comp_body->SetWidth( Mils2iu( 10 ) ); comp_body->SetWidth( Mils2iu( 10 ) );
comp_body->SetFillMode( FILL_TYPE::FILLED_WITH_BG_BODYCOLOR ); comp_body->SetFillMode( FILL_T::FILLED_WITH_BG_BODYCOLOR );
comp_body->AddPoint( MILS_POINT( p.x - 200, p.y + 200 ) ); comp_body->AddPoint( MILS_POINT( p.x - 200, p.y + 200 ) );
comp_body->AddPoint( MILS_POINT( p.x + 200, p.y ) ); comp_body->AddPoint( MILS_POINT( p.x + 200, p.y ) );
comp_body->AddPoint( MILS_POINT( p.x - 200, p.y - 200 ) ); comp_body->AddPoint( MILS_POINT( p.x - 200, p.y - 200 ) );

View File

@ -1,545 +1 @@
/*
* 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.
* Copyright (C) 2019 CERN
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <sch_draw_panel.h>
#include <plotters/plotter.h>
#include <trigo.h>
#include <base_units.h>
#include <widgets/msgpanel.h>
#include <bitmaps.h>
#include <math/util.h> // for KiROUND
#include <eda_draw_frame.h>
#include <general.h>
#include <lib_arc.h>
#include <transform.h>
#include <settings/color_settings.h>
#include <status_popup.h>
// Helper function
static inline wxPoint twoPointVector( const wxPoint &startPoint, const wxPoint &endPoint )
{
return endPoint - startPoint;
}
LIB_ARC::LIB_ARC( LIB_SYMBOL* aParent ) : LIB_ITEM( LIB_ARC_T, aParent )
{
m_Width = 0;
m_fill = FILL_TYPE::NO_FILL;
m_isFillable = true;
m_editState = 0;
}
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,
Mils2iu( MINIMUM_SELECTION_DISTANCE ) );
wxPoint relativePosition = aRefPoint;
relativePosition.y = -relativePosition.y; // reverse Y axis
int distance = KiROUND( GetLineLength( m_Pos, relativePosition ) );
if( abs( distance - GetRadius() ) > mindist )
return false;
// We are on the circle, ensure we are only on the arc, i.e. between
// m_ArcStart and m_ArcEnd
wxPoint startEndVector = twoPointVector( m_ArcStart, m_ArcEnd );
wxPoint startRelativePositionVector = twoPointVector( m_ArcStart, relativePosition );
wxPoint centerStartVector = twoPointVector( m_Pos, m_ArcStart );
wxPoint centerEndVector = twoPointVector( m_Pos, m_ArcEnd );
wxPoint centerRelativePositionVector = twoPointVector( m_Pos, relativePosition );
// Compute the cross product to check if the point is in the sector
double crossProductStart = CrossProduct( centerStartVector, centerRelativePositionVector );
double crossProductEnd = CrossProduct( centerEndVector, centerRelativePositionVector );
// The cross products need to be exchanged, depending on which side the center point
// relative to the start point to end point vector lies
if( CrossProduct( startEndVector, startRelativePositionVector ) < 0 )
{
std::swap( crossProductStart, crossProductEnd );
}
// When the cross products have a different sign, the point lies in sector
// also check, if the reference is near start or end point
return HitTestPoints( m_ArcStart, relativePosition, MINIMUM_SELECTION_DISTANCE ) ||
HitTestPoints( m_ArcEnd, relativePosition, MINIMUM_SELECTION_DISTANCE ) ||
( crossProductStart <= 0 && crossProductEnd >= 0 );
}
bool LIB_ARC::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
{
if( m_flags & (STRUCT_DELETED | SKIP_STRUCT ) )
return false;
wxPoint center = DefaultTransform.TransformCoordinate( GetPosition() );
int radius = GetRadius();
int lineWidth = GetWidth();
EDA_RECT sel = aRect ;
if ( aAccuracy )
sel.Inflate( aAccuracy );
if( aContained )
return sel.Contains( GetBoundingBox() );
EDA_RECT arcRect = GetBoundingBox().Common( sel );
/* All following tests must pass:
* 1. Rectangle must intersect arc BoundingBox
* 2. Rectangle must cross the outside of the arc
*/
return arcRect.Intersects( sel ) && arcRect.IntersectsCircleEdge( center, radius, lineWidth );
}
EDA_ITEM* LIB_ARC::Clone() const
{
return new LIB_ARC( *this );
}
int LIB_ARC::compare( const LIB_ITEM& aOther, LIB_ITEM::COMPARE_FLAGS aCompareFlags ) const
{
wxASSERT( aOther.Type() == LIB_ARC_T );
int retv = LIB_ITEM::compare( aOther );
if( retv )
return retv;
const LIB_ARC* tmp = ( LIB_ARC* ) &aOther;
if( m_Pos.x != tmp->m_Pos.x )
return m_Pos.x - tmp->m_Pos.x;
if( m_Pos.y != tmp->m_Pos.y )
return m_Pos.y - tmp->m_Pos.y;
return 0;
}
void LIB_ARC::Offset( const wxPoint& aOffset )
{
m_Pos += aOffset;
m_ArcStart += aOffset;
m_ArcEnd += aOffset;
}
void LIB_ARC::MoveTo( const wxPoint& aPosition )
{
wxPoint offset = aPosition - m_Pos;
m_Pos = aPosition;
m_ArcStart += offset;
m_ArcEnd += offset;
}
void LIB_ARC::MirrorHorizontal( const wxPoint& aCenter )
{
m_Pos.x -= aCenter.x;
m_Pos.x *= -1;
m_Pos.x += aCenter.x;
m_ArcStart.x -= aCenter.x;
m_ArcStart.x *= -1;
m_ArcStart.x += aCenter.x;
m_ArcEnd.x -= aCenter.x;
m_ArcEnd.x *= -1;
m_ArcEnd.x += aCenter.x;
std::swap( m_ArcStart, m_ArcEnd );
}
void LIB_ARC::MirrorVertical( const wxPoint& aCenter )
{
m_Pos.y -= aCenter.y;
m_Pos.y *= -1;
m_Pos.y += aCenter.y;
m_ArcStart.y -= aCenter.y;
m_ArcStart.y *= -1;
m_ArcStart.y += aCenter.y;
m_ArcEnd.y -= aCenter.y;
m_ArcEnd.y *= -1;
m_ArcEnd.y += aCenter.y;
std::swap( m_ArcStart, m_ArcEnd );
}
void LIB_ARC::Rotate( const wxPoint& aCenter, bool aRotateCCW )
{
int rot_angle = aRotateCCW ? -900 : 900;
RotatePoint( &m_Pos, aCenter, rot_angle );
RotatePoint( &m_ArcStart, aCenter, rot_angle );
RotatePoint( &m_ArcEnd, aCenter, rot_angle );
}
void LIB_ARC::Plot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
const TRANSFORM& aTransform ) const
{
wxASSERT( aPlotter != nullptr );
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;
CalcAngles( startAngle, endAngle );
aTransform.MapAngles( &startAngle, &endAngle );
if( fill == FILL_TYPE::FILLED_WITH_BG_BODYCOLOR )
{
aPlotter->SetColor( aPlotter->RenderSettings()->GetLayerColor( LAYER_DEVICE_BACKGROUND ) );
aPlotter->Arc( center, -endAngle, -startAngle, GetRadius(), fill, 0 );
if( pen_size <= 0 )
return;
else
fill = FILL_TYPE::NO_FILL;
}
pen_size = std::max( pen_size, aPlotter->RenderSettings()->GetMinPenWidth() );
aPlotter->SetColor( aPlotter->RenderSettings()->GetLayerColor( LAYER_DEVICE ) );
aPlotter->Arc( center, -endAngle, -startAngle, GetRadius(), fill, pen_size );
}
int LIB_ARC::GetPenWidth() const
{
return m_Width;
}
void LIB_ARC::print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset, void* aData,
const TRANSFORM& aTransform )
{
bool forceNoFill = static_cast<bool>( aData );
int penWidth = GetEffectivePenWidth( aSettings );
if( forceNoFill && m_fill != FILL_TYPE::NO_FILL && penWidth == 0 )
return;
wxDC* DC = aSettings->GetPrintDC();
wxPoint pos1, pos2, posc;
COLOR4D color = aSettings->GetLayerColor( LAYER_DEVICE );
pos1 = aTransform.TransformCoordinate( m_ArcEnd ) + aOffset;
pos2 = aTransform.TransformCoordinate( m_ArcStart ) + aOffset;
posc = aTransform.TransformCoordinate( m_Pos ) + aOffset;
int t1;
int t2;
CalcAngles( t1, t2 );
aTransform.MapAngles( &t1, &t2 );
if( forceNoFill || m_fill == FILL_TYPE::NO_FILL )
{
GRArc1( nullptr, DC, pos1.x, pos1.y, pos2.x, pos2.y, posc.x, posc.y, penWidth, color );
}
else
{
if( m_fill == FILL_TYPE::FILLED_WITH_BG_BODYCOLOR )
color = aSettings->GetLayerColor( LAYER_DEVICE_BACKGROUND );
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 || radius == 0 )
return rect;
endPos = DefaultTransform.TransformCoordinate( m_ArcEnd );
startPos = DefaultTransform.TransformCoordinate( m_ArcStart );
centerPos = DefaultTransform.TransformCoordinate( m_Pos );
CalcAngles( angleStart, angleEnd );
DefaultTransform.MapAngles( &angleStart, &angleEnd );
/* Start with the start and end point of the arc. */
minX = std::min( startPos.x, endPos.x );
minY = std::min( startPos.y, endPos.y );
maxX = std::max( startPos.x, endPos.x );
maxY = std::max( startPos.y, endPos.y );
/* Zero degrees is a special case. */
if( angleStart == 0 )
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 + radius;
if( angleStart <= 1800 && angleEnd >= 1800 ) /* 180 deg */
minX = centerPos.x - radius;
if( angleStart <= 2700 && angleEnd >= 2700 ) /* 270 deg */
minY = centerPos.y - radius;
if( angleStart <= 3600 && angleEnd >= 3600 ) /* 0 deg */
maxX = centerPos.x + radius;
rect.SetOrigin( minX, minY );
rect.SetEnd( maxX, maxY );
rect.Inflate( ( GetPenWidth() / 2 ) + 1 );
return rect;
}
void LIB_ARC::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
{
wxString msg;
EDA_RECT bBox = GetBoundingBox();
LIB_ITEM::GetMsgPanelInfo( aFrame, aList );
msg = MessageTextFromValue( aFrame->GetUserUnits(), m_Width );
aList.emplace_back( _( "Line Width" ), msg );
msg.Printf( wxT( "(%d, %d, %d, %d)" ), bBox.GetOrigin().x,
bBox.GetOrigin().y, bBox.GetEnd().x, bBox.GetEnd().y );
aList.emplace_back( _( "Bounding Box" ), msg );
}
wxString LIB_ARC::GetSelectMenuText( EDA_UNITS aUnits ) const
{
return wxString::Format( _( "Arc, radius %s" ),
MessageTextFromValue( aUnits, GetRadius() ) );
}
BITMAPS LIB_ARC::GetMenuImage() const
{
return BITMAPS::add_arc;
}
void LIB_ARC::BeginEdit( const wxPoint& aPosition )
{
m_ArcStart = m_ArcEnd = aPosition;
m_editState = 1;
}
void LIB_ARC::CalcEdit( const wxPoint& aPosition )
{
#define sq( x ) pow( x, 2 )
int radius = GetRadius();
// Edit state 0: drawing: place ArcStart
// Edit state 1: drawing: place ArcEnd (center calculated for 90-degree subtended angle)
// Edit state 2: point editing: move ArcStart (center calculated for invariant subtended angle)
// Edit state 3: point editing: move ArcEnd (center calculated for invariant subtended angle)
// Edit state 4: point editing: move center
switch( m_editState )
{
case 0:
m_ArcStart = aPosition;
m_ArcEnd = aPosition;
m_Pos = aPosition;
radius = 0;
return;
case 1:
m_ArcEnd = aPosition;
radius = KiROUND( sqrt( sq( GetLineLength( m_ArcStart, m_ArcEnd ) ) / 2.0 ) );
break;
case 2:
case 3:
{
wxPoint v = m_ArcStart - m_ArcEnd;
double chordBefore = sq( v.x ) + sq( v.y );
if( m_editState == 2 )
m_ArcStart = aPosition;
else
m_ArcEnd = aPosition;
v = m_ArcStart - m_ArcEnd;
double chordAfter = sq( v.x ) + sq( v.y );
double ratio = chordAfter / chordBefore;
if( ratio != 0 )
{
radius = std::max( int( sqrt( sq( radius ) * ratio ) ) + 1,
int( sqrt( chordAfter ) / 2 ) + 1 );
}
break;
}
case 4:
{
double chordA = GetLineLength( m_ArcStart, aPosition );
double chordB = GetLineLength( m_ArcEnd, aPosition );
radius = int( ( chordA + chordB ) / 2.0 ) + 1;
break;
}
}
// Calculate center based on start, end, and radius
//
// Let 'l' be the length of the chord and 'm' the middle point of the chord
double l = GetLineLength( m_ArcStart, m_ArcEnd );
wxPoint m = ( m_ArcStart + m_ArcEnd ) / 2;
// Calculate 'd', the vector from the chord midpoint to the center
wxPoint d;
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;
// Solution gives us 2 centers; we need to pick one:
switch( m_editState )
{
case 1:
{
// Keep center clockwise from chord while drawing
wxPoint chordVector = twoPointVector( m_ArcStart, m_ArcEnd );
double chordAngle = ArcTangente( chordVector.y, chordVector.x );
NORMALIZE_ANGLE_POS( chordAngle );
wxPoint c1Test = c1;
RotatePoint( &c1Test, m_ArcStart, -chordAngle );
m_Pos = c1Test.x > 0 ? c2 : c1;
}
break;
case 2:
case 3:
// Pick the one closer to the old center
m_Pos = ( GetLineLength( c1, m_Pos ) < GetLineLength( c2, m_Pos ) ) ? c1 : c2;
break;
case 4:
// Pick the one closer to the mouse position
m_Pos = ( GetLineLength( c1, aPosition ) < GetLineLength( c2, aPosition ) ) ? c1 : c2;
break;
}
}
void LIB_ARC::CalcAngles( int& aStartAngle, int& aEndAngle ) const
{
wxPoint centerStartVector = twoPointVector( GetCenter(), GetStart() );
wxPoint centerEndVector = twoPointVector( GetCenter(), GetEnd() );
// Angles in Eeschema are still integers
aStartAngle = KiROUND( ArcTangente( centerStartVector.y, centerStartVector.x ) );
aEndAngle = KiROUND( ArcTangente( centerEndVector.y, centerEndVector.x ) );
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( ( aEndAngle - aStartAngle ) > 1800 )
aEndAngle -= 3600;
else if( ( aEndAngle - aStartAngle ) <= -1800 )
aEndAngle += 3600;
while( ( aEndAngle - aStartAngle ) >= 1800 )
{
aEndAngle--;
aStartAngle++;
}
while( ( aStartAngle - aEndAngle ) >= 1800 )
{
aEndAngle++;
aStartAngle--;
}
NORMALIZE_ANGLE_POS( aStartAngle );
if( !IsMoving() )
NORMALIZE_ANGLE_POS( aEndAngle );
}
VECTOR2I LIB_ARC::CalcMidPoint() const
{
VECTOR2D midPoint;
int radius = GetRadius();
int t1;
int t2;
CalcAngles( t1, t2 );
double startAngle = static_cast<double>( t1 ) / 10.0;
double endAngle = static_cast<double>( t2 ) / 10.0;
if( endAngle < startAngle )
endAngle -= 360.0;
double midPointAngle = ( ( endAngle - startAngle ) / 2.0 ) + startAngle;
double x = cos( DEG2RAD( midPointAngle ) ) * radius;
double y = sin( DEG2RAD( midPointAngle ) ) * radius;
midPoint.x = KiROUND( x ) + m_Pos.x;
midPoint.y = KiROUND( y ) + m_Pos.y;
return midPoint;
}

View File

@ -1,148 +0,0 @@
/*
* 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 change_log.txt for contributors.
* Copyright (C) 2019 CERN
*
* 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_ARC_H
#define LIB_ARC_H
#include <lib_item.h>
#include <math/vector2d.h>
class TRANSFORM;
class LIB_ARC : public LIB_ITEM
{
public:
LIB_ARC( LIB_SYMBOL* aParent );
// Do not create a copy constructor. The one generated by the compiler is adequate.
~LIB_ARC() { }
wxString GetClass() const override
{
return wxT( "LIB_ARC" );
}
wxString GetTypeName() const override
{
return _( "Arc" );
}
bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override;
bool HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy = 0 ) const override;
const EDA_RECT GetBoundingBox() const override;
void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
int GetPenWidth() const override;
void BeginEdit( const wxPoint& aStartPoint ) override;
void CalcEdit( const wxPoint& aPosition ) override;
void SetEditState( int aState ) { m_editState = aState; }
void Offset( const wxPoint& aOffset ) override;
void MoveTo( const wxPoint& aPosition ) override;
wxPoint GetPosition() const override { return m_Pos; }
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;
int GetWidth() const override { return m_Width; }
void SetWidth( int aWidth ) override { m_Width = aWidth; }
int GetRadius() const;
wxPoint GetStart() const { return m_ArcStart; }
void SetStart( const wxPoint& aPoint ) { m_ArcStart = aPoint; }
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.
*
* @note This is not a general purpose trigonometric arc midpoint calculation. It is
* limited to the less than 180.0 degree arcs used in symbols.
*
* @return A #VECTOR2I object containing the midpoint of the arc.
*/
VECTOR2I CalcMidPoint() const;
/**
* Calculate the start and end angles of an arc using the start, end, and center points.
*/
void CalcAngles( int& aStartAngle, int& aEndAngle ) const;
wxString GetSelectMenuText( EDA_UNITS aUnits ) const override;
BITMAPS GetMenuImage() const override;
EDA_ITEM* Clone() const override;
private:
void print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset, void* aData,
const TRANSFORM& aTransform ) override;
/**
* @copydoc LIB_ITEM::compare()
*
* The arc specific sort order is as follows:
* - Arc horizontal (X) position.
* - Arc vertical (Y) position.
* - Arc start angle.
* - Arc end angle.
*/
int compare( const LIB_ITEM& aOther,
LIB_ITEM::COMPARE_FLAGS aCompareFlags = LIB_ITEM::COMPARE_FLAGS::NORMAL ) const override;
enum SELECT_T // When creating an arc: status of arc
{
ARC_STATUS_START,
ARC_STATUS_END,
ARC_STATUS_OUTLINE,
};
wxPoint m_ArcStart;
wxPoint m_ArcEnd; /* Arc end position. */
wxPoint m_Pos; /* Radius center point. */
int m_Width; /* Line width */
int m_editState;
};
#endif // LIB_ARC_H

View File

@ -1,353 +0,0 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2004-2021 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <sch_draw_panel.h>
#include <plotters/plotter.h>
#include <trigo.h>
#include <bezier_curves.h>
#include <base_units.h>
#include <eda_draw_frame.h>
#include <widgets/msgpanel.h>
#include <eda_draw_frame.h>
#include <general.h>
#include <lib_bezier.h>
#include <transform.h>
#include <settings/color_settings.h>
LIB_BEZIER::LIB_BEZIER( LIB_SYMBOL* aParent ) :
LIB_ITEM( LIB_BEZIER_T, aParent )
{
m_fill = FILL_TYPE::NO_FILL;
m_Width = 0;
m_isFillable = true;
}
EDA_ITEM* LIB_BEZIER::Clone() const
{
return new LIB_BEZIER( *this );
}
int LIB_BEZIER::compare( const LIB_ITEM& aOther, LIB_ITEM::COMPARE_FLAGS aCompareFlags ) const
{
wxASSERT( aOther.Type() == LIB_BEZIER_T );
int retv = LIB_ITEM::compare( aOther );
if( retv )
return retv;
const LIB_BEZIER* tmp = ( LIB_BEZIER* ) &aOther;
if( m_BezierPoints.size() != tmp->m_BezierPoints.size() )
return m_BezierPoints.size() - tmp->m_BezierPoints.size();
for( size_t i = 0; i < m_BezierPoints.size(); i++ )
{
if( m_BezierPoints[i].x != tmp->m_BezierPoints[i].x )
return m_BezierPoints[i].x - tmp->m_BezierPoints[i].x;
if( m_BezierPoints[i].y != tmp->m_BezierPoints[i].y )
return m_BezierPoints[i].y - tmp->m_BezierPoints[i].y;
}
return 0;
}
void LIB_BEZIER::Offset( const wxPoint& aOffset )
{
size_t i;
for( i = 0; i < m_BezierPoints.size(); i++ )
m_BezierPoints[i] += aOffset;
for( i = 0; i < m_PolyPoints.size(); i++ )
m_PolyPoints[i] += aOffset;
}
void LIB_BEZIER::MoveTo( const wxPoint& aPosition )
{
if ( !m_PolyPoints.size() )
m_PolyPoints.emplace_back(0, 0 );
Offset( aPosition - m_PolyPoints[ 0 ] );
}
const wxPoint LIB_BEZIER::GetOffset() const
{
if ( !m_PolyPoints.size() )
return wxPoint(0, 0);
return m_PolyPoints[0];
}
void LIB_BEZIER::MirrorHorizontal( const wxPoint& aCenter )
{
size_t i, imax = m_PolyPoints.size();
for( i = 0; i < imax; i++ )
{
m_PolyPoints[i].x -= aCenter.x;
m_PolyPoints[i].x *= -1;
m_PolyPoints[i].x += aCenter.x;
}
imax = m_BezierPoints.size();
for( i = 0; i < imax; i++ )
{
m_BezierPoints[i].x -= aCenter.x;
m_BezierPoints[i].x *= -1;
m_BezierPoints[i].x += aCenter.x;
}
}
void LIB_BEZIER::MirrorVertical( const wxPoint& aCenter )
{
size_t i, imax = m_PolyPoints.size();
for( i = 0; i < imax; i++ )
{
m_PolyPoints[i].y -= aCenter.y;
m_PolyPoints[i].y *= -1;
m_PolyPoints[i].y += aCenter.y;
}
imax = m_BezierPoints.size();
for( i = 0; i < imax; i++ )
{
m_BezierPoints[i].y -= aCenter.y;
m_BezierPoints[i].y *= -1;
m_BezierPoints[i].y += aCenter.y;
}
}
void LIB_BEZIER::Rotate( const wxPoint& aCenter, bool aRotateCCW )
{
int rot_angle = aRotateCCW ? -900 : 900;
for( wxPoint& point : m_PolyPoints )
RotatePoint( &point, aCenter, rot_angle );
for( wxPoint& bezierPoint : m_BezierPoints )
RotatePoint( &bezierPoint, aCenter, rot_angle );
}
void LIB_BEZIER::Plot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
const TRANSFORM& aTransform ) const
{
wxASSERT( aPlotter != nullptr );
static std::vector< wxPoint > cornerList;
cornerList.clear();
for( wxPoint pos : m_PolyPoints )
{
pos = aTransform.TransformCoordinate( pos ) + aOffset;
cornerList.push_back( pos );
}
if( aFill && m_fill == FILL_TYPE::FILLED_WITH_BG_BODYCOLOR )
{
aPlotter->SetColor( aPlotter->RenderSettings()->GetLayerColor( LAYER_DEVICE_BACKGROUND ) );
aPlotter->PlotPoly( cornerList, FILL_TYPE::FILLED_WITH_BG_BODYCOLOR, 0 );
}
bool already_filled = m_fill == FILL_TYPE::FILLED_WITH_BG_BODYCOLOR;
int pen_size = GetEffectivePenWidth( aPlotter->RenderSettings() );
if( !already_filled || pen_size > 0 )
{
aPlotter->SetColor( aPlotter->RenderSettings()->GetLayerColor( LAYER_DEVICE ) );
aPlotter->PlotPoly( cornerList, already_filled ? FILL_TYPE::NO_FILL : m_fill, pen_size );
}
}
int LIB_BEZIER::GetPenWidth() const
{
return m_Width;
}
void LIB_BEZIER::print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset, void* aData,
const TRANSFORM& aTransform )
{
bool forceNoFill = static_cast<bool>( aData );
int penWidth = GetEffectivePenWidth( aSettings );
if( forceNoFill && m_fill != FILL_TYPE::NO_FILL && penWidth == 0 )
return;
std::vector<wxPoint> PolyPointsTraslated;
wxDC* DC = aSettings->GetPrintDC();
COLOR4D color = aSettings->GetLayerColor( LAYER_DEVICE );
BEZIER_POLY converter( m_BezierPoints );
converter.GetPoly( m_PolyPoints );
PolyPointsTraslated.clear();
for( wxPoint& point : m_PolyPoints )
PolyPointsTraslated.push_back( aTransform.TransformCoordinate( point ) + aOffset );
if( forceNoFill || m_fill == FILL_TYPE::NO_FILL )
{
GRPoly( nullptr, DC, m_PolyPoints.size(), &PolyPointsTraslated[0], false, penWidth,
color, color );
}
else
{
if( m_fill == FILL_TYPE::FILLED_WITH_BG_BODYCOLOR )
color = aSettings->GetLayerColor( LAYER_DEVICE_BACKGROUND );
GRPoly( nullptr, DC, m_PolyPoints.size(), &PolyPointsTraslated[0], true, penWidth,
color, color );
}
}
bool LIB_BEZIER::HitTest( const wxPoint& aRefPos, int aAccuracy ) const
{
int mindist = std::max( aAccuracy + GetPenWidth() / 2,
Mils2iu( MINIMUM_SELECTION_DISTANCE ) );
wxPoint start, end;
for( unsigned ii = 1; ii < GetCornerCount(); ii++ )
{
start = DefaultTransform.TransformCoordinate( m_PolyPoints[ii - 1] );
end = DefaultTransform.TransformCoordinate( m_PolyPoints[ii] );
if ( TestSegmentHit( aRefPos, start, end, mindist ) )
return true;
}
return false;
}
bool LIB_BEZIER::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
{
if( m_flags & (STRUCT_DELETED | SKIP_STRUCT ) )
return false;
EDA_RECT sel = aRect;
if ( aAccuracy )
sel.Inflate( aAccuracy );
if( aContained )
return sel.Contains( GetBoundingBox() );
// Fast test: if aRect is outside the polygon bounding box, rectangles cannot intersect
if( !sel.Intersects( GetBoundingBox() ) )
return false;
// Account for the width of the line
sel.Inflate( GetWidth() / 2 );
unsigned count = m_BezierPoints.size();
for( unsigned ii = 1; ii < count; ii++ )
{
wxPoint vertex = DefaultTransform.TransformCoordinate( m_BezierPoints[ii-1] );
wxPoint vertexNext = DefaultTransform.TransformCoordinate( m_BezierPoints[ii] );
// Test if the point is within aRect
if( sel.Contains( vertex ) )
return true;
// Test if this edge intersects aRect
if( sel.Intersects( vertex, vertexNext ) )
return true;
}
return false;
}
const EDA_RECT LIB_BEZIER::GetBoundingBox() const
{
EDA_RECT rect;
int xmin, xmax, ymin, ymax;
if( !GetCornerCount() )
return rect;
xmin = xmax = m_PolyPoints[0].x;
ymin = ymax = m_PolyPoints[0].y;
for( unsigned ii = 1; ii < GetCornerCount(); ii++ )
{
xmin = std::min( xmin, m_PolyPoints[ii].x );
xmax = std::max( xmax, m_PolyPoints[ii].x );
ymin = std::min( ymin, m_PolyPoints[ii].y );
ymax = std::max( ymax, m_PolyPoints[ii].y );
}
rect.SetOrigin( xmin, ymin );
rect.SetEnd( xmax, ymax );
rect.Inflate( ( GetPenWidth() / 2 ) + 1 );
rect.RevertYAxis();
return rect;
}
void LIB_BEZIER::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
{
wxString msg;
EDA_RECT bBox = GetBoundingBox();
LIB_ITEM::GetMsgPanelInfo( aFrame, aList );
msg = MessageTextFromValue( aFrame->GetUserUnits(), m_Width );
aList.emplace_back( _( "Line Width" ), msg );
msg.Printf( wxT( "(%d, %d, %d, %d)" ),
bBox.GetOrigin().x,
bBox.GetOrigin().y,
bBox.GetEnd().x,
bBox.GetEnd().y );
aList.emplace_back( _( "Bounding Box" ), msg );
}
wxPoint LIB_BEZIER::GetPosition() const
{
if( !m_PolyPoints.size() )
return wxPoint(0, 0);
return m_PolyPoints[0];
}

View File

@ -1,111 +0,0 @@
/*
* 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 change_log.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_BEZIER_H
#define LIB_BEZIER_H
#include <lib_item.h>
/**
* Define a bezier curve graphic body item.
*/
class LIB_BEZIER : public LIB_ITEM
{
public:
LIB_BEZIER( LIB_SYMBOL* aParent );
// Do not create a copy constructor. The one generated by the compiler is adequate.
~LIB_BEZIER() { }
wxString GetClass() const override
{
return wxT( "LIB_BEZIER" );
}
wxString GetTypeName() const override
{
return _( "Bezier" );
}
void Reserve( size_t aCount ) { m_BezierPoints.reserve( aCount ); }
void AddPoint( const wxPoint& aPoint ) { m_BezierPoints.push_back( aPoint ); }
void Offset( const wxPoint& aOffset ) override;
const wxPoint GetOffset() const;
/**
* @return the number of corners
*/
unsigned GetCornerCount() const { return m_PolyPoints.size(); }
const std::vector< wxPoint >& GetPoints() const { return m_BezierPoints; }
bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override;
bool HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy = 0 ) const override;
const EDA_RECT GetBoundingBox() const override;
void MoveTo( const wxPoint& aPosition ) override;
wxPoint GetPosition() const override;
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;
int GetWidth() const override { return m_Width; }
void SetWidth( int aWidth ) override { m_Width = aWidth; }
int GetPenWidth() const override;
void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
EDA_ITEM* Clone() const override;
private:
/**
* @copydoc LIB_ITEM::compare()
*
* The bezier curve specific sort order for each curve segment point is as follows:
* - Bezier horizontal (X) point position.
* - Bezier vertical (Y) point position.
*/
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;
int m_Width; // Line width
std::vector<wxPoint> m_BezierPoints; // list of parameter (3|4)
std::vector<wxPoint> m_PolyPoints; // list of points (>= 2)
};
#endif // LIB_BEZIER_H

View File

@ -1,285 +0,0 @@
/*
* 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 <eda_draw_frame.h>
#include <sch_draw_panel.h>
#include <plotters/plotter.h>
#include <trigo.h>
#include <base_units.h>
#include <widgets/msgpanel.h>
#include <bitmaps.h>
#include <math/util.h> // for KiROUND
#include <eda_draw_frame.h>
#include <general.h>
#include <lib_circle.h>
#include <settings/color_settings.h>
#include <transform.h>
LIB_CIRCLE::LIB_CIRCLE( LIB_SYMBOL* aParent ) :
LIB_ITEM( LIB_CIRCLE_T, aParent )
{
m_Width = 0;
m_fill = FILL_TYPE::NO_FILL;
m_isFillable = true;
}
bool LIB_CIRCLE::HitTest( const wxPoint& aPosRef, int aAccuracy ) const
{
int mindist = std::max( aAccuracy + GetPenWidth() / 2,
Mils2iu( MINIMUM_SELECTION_DISTANCE ) );
int dist = KiROUND( GetLineLength( aPosRef, DefaultTransform.TransformCoordinate( m_Pos ) ) );
if( abs( dist - GetRadius() ) <= mindist )
return true;
if( m_fill == FILL_TYPE::NO_FILL )
return false;
return dist <= GetRadius();
}
bool LIB_CIRCLE::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
{
if( m_flags & (STRUCT_DELETED | SKIP_STRUCT ) )
return false;
wxPoint center = DefaultTransform.TransformCoordinate( GetPosition() );
int radius = GetRadius();
int lineWidth = GetWidth();
EDA_RECT sel = aRect ;
if ( aAccuracy )
sel.Inflate( aAccuracy );
if( aContained )
return sel.Contains( GetBoundingBox() );
// If the rectangle does not intersect the bounding box, this is a much quicker test
if( !sel.Intersects( GetBoundingBox() ) )
return false;
else
return sel.IntersectsCircleEdge( center, radius, lineWidth );
}
EDA_ITEM* LIB_CIRCLE::Clone() const
{
return new LIB_CIRCLE( *this );
}
int LIB_CIRCLE::compare( const LIB_ITEM& aOther, LIB_ITEM::COMPARE_FLAGS aCompareFlags ) const
{
wxASSERT( aOther.Type() == LIB_CIRCLE_T );
int retv = LIB_ITEM::compare( aOther, aCompareFlags );
if( retv )
return retv;
const LIB_CIRCLE* tmp = ( LIB_CIRCLE* ) &aOther;
if( m_Pos.x != tmp->m_Pos.x )
return m_Pos.x - tmp->m_Pos.x;
if( m_Pos.y != tmp->m_Pos.y )
return m_Pos.y - tmp->m_Pos.y;
if( m_EndPos.x != tmp->m_EndPos.x )
return m_EndPos.x - tmp->m_EndPos.x;
if( m_EndPos.y != tmp->m_EndPos.y )
return m_EndPos.y - tmp->m_EndPos.y;
return 0;
}
void LIB_CIRCLE::Offset( const wxPoint& aOffset )
{
m_Pos += aOffset;
m_EndPos += aOffset;
}
void LIB_CIRCLE::MoveTo( const wxPoint& aPosition )
{
Offset( aPosition - m_Pos );
}
void LIB_CIRCLE::MirrorHorizontal( const wxPoint& aCenter )
{
m_Pos.x -= aCenter.x;
m_Pos.x *= -1;
m_Pos.x += aCenter.x;
m_EndPos.x -= aCenter.x;
m_EndPos.x *= -1;
m_EndPos.x += aCenter.x;
}
void LIB_CIRCLE::MirrorVertical( const wxPoint& aCenter )
{
m_Pos.y -= aCenter.y;
m_Pos.y *= -1;
m_Pos.y += aCenter.y;
m_EndPos.y -= aCenter.y;
m_EndPos.y *= -1;
m_EndPos.y += aCenter.y;
}
void LIB_CIRCLE::Rotate( const wxPoint& aCenter, bool aRotateCCW )
{
int rot_angle = aRotateCCW ? -900 : 900;
RotatePoint( &m_Pos, aCenter, rot_angle );
RotatePoint( &m_EndPos, aCenter, rot_angle );
}
void LIB_CIRCLE::Plot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
const TRANSFORM& aTransform ) const
{
wxPoint pos = aTransform.TransformCoordinate( m_Pos ) + aOffset;
if( aFill && m_fill == FILL_TYPE::FILLED_WITH_BG_BODYCOLOR )
{
aPlotter->SetColor( aPlotter->RenderSettings()->GetLayerColor( LAYER_DEVICE_BACKGROUND ) );
aPlotter->Circle( pos, GetRadius() * 2, FILL_TYPE::FILLED_WITH_BG_BODYCOLOR, 0 );
}
bool already_filled = m_fill == FILL_TYPE::FILLED_WITH_BG_BODYCOLOR;
int pen_size = GetEffectivePenWidth( aPlotter->RenderSettings() );
if( !already_filled || pen_size > 0 )
{
aPlotter->SetColor( aPlotter->RenderSettings()->GetLayerColor( LAYER_DEVICE ) );
aPlotter->Circle( pos, GetRadius() * 2, already_filled ? FILL_TYPE::NO_FILL : m_fill,
pen_size );
}
}
int LIB_CIRCLE::GetPenWidth() const
{
return m_Width;
}
void LIB_CIRCLE::print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset,
void* aData, const TRANSFORM& aTransform )
{
bool forceNoFill = static_cast<bool>( aData );
int penWidth = GetEffectivePenWidth( aSettings );
if( forceNoFill && m_fill != FILL_TYPE::NO_FILL && penWidth == 0 )
return;
wxDC* DC = aSettings->GetPrintDC();
wxPoint pos1 = aTransform.TransformCoordinate( m_Pos ) + aOffset;
COLOR4D color = aSettings->GetLayerColor( LAYER_DEVICE );
if( forceNoFill || m_fill == FILL_TYPE::NO_FILL )
{
GRCircle( nullptr, DC, pos1.x, pos1.y, GetRadius(), penWidth, color );
}
else
{
if( m_fill == FILL_TYPE::FILLED_WITH_BG_BODYCOLOR )
color = aSettings->GetLayerColor( LAYER_DEVICE_BACKGROUND );
GRFilledCircle( nullptr, DC, pos1.x, pos1.y, GetRadius(), 0, color, color );
}
}
const EDA_RECT LIB_CIRCLE::GetBoundingBox() const
{
EDA_RECT rect;
int radius = GetRadius();
rect.SetOrigin( m_Pos.x - radius, m_Pos.y - radius );
rect.SetEnd( m_Pos.x + radius, m_Pos.y + radius );
rect.Inflate( ( GetPenWidth() / 2 ) + 1 );
rect.RevertYAxis();
return rect;
}
void LIB_CIRCLE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
{
EDA_RECT bBox = GetBoundingBox();
LIB_ITEM::GetMsgPanelInfo( aFrame, aList );
aList.emplace_back( _( "Line Width" ), MessageTextFromValue( aFrame->GetUserUnits(),
m_Width ) );
aList.emplace_back( _( "Radius" ), MessageTextFromValue( aFrame->GetUserUnits(),
GetRadius() ) );
aList.emplace_back( _( "Bounding Box" ), wxString::Format( wxT( "(%d, %d, %d, %d)" ),
bBox.GetOrigin().x,
bBox.GetOrigin().y,
bBox.GetEnd().x,
bBox.GetEnd().y ) );
}
int LIB_CIRCLE::GetRadius() const
{
return KiROUND( GetLineLength( m_EndPos, m_Pos ) );
}
wxString LIB_CIRCLE::GetSelectMenuText( EDA_UNITS aUnits ) const
{
return wxString::Format( _( "Circle, radius %s" ),
MessageTextFromValue( aUnits, GetRadius() ) );
}
BITMAPS LIB_CIRCLE::GetMenuImage() const
{
return BITMAPS::add_circle;
}
void LIB_CIRCLE::BeginEdit( const wxPoint& aPosition )
{
m_Pos = aPosition;
}
void LIB_CIRCLE::CalcEdit( const wxPoint& aPosition )
{
SetEnd( aPosition );
}

View File

@ -1,111 +0,0 @@
/*
* 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_CIRCLE_H
#define LIB_CIRCLE_H
#include <lib_item.h>
class LIB_CIRCLE : public LIB_ITEM
{
public:
LIB_CIRCLE( LIB_SYMBOL* aParent );
// Do not create a copy constructor. The one generated by the compiler is adequate.
~LIB_CIRCLE() { }
wxString GetClass() const override
{
return wxT( "LIB_CIRCLE" );
}
wxString GetTypeName() const override
{
return _( "Circle" );
}
bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override;
bool HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy = 0 ) const override;
int GetPenWidth() const override;
const EDA_RECT GetBoundingBox() const override;
void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
void BeginEdit( const wxPoint& aStartPoint ) override;
void CalcEdit( const wxPoint& aPosition ) override;
void Offset( const wxPoint& aOffset ) override;
void MoveTo( const wxPoint& aPosition ) override;
wxPoint GetPosition() const override { return m_Pos; }
void SetEnd( const wxPoint& aPosition ) { m_EndPos = aPosition; }
wxPoint GetEnd() const { return m_EndPos; }
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;
int GetWidth() const override { return m_Width; }
void SetWidth( int aWidth ) override { m_Width = aWidth; }
void SetRadius( int aRadius ) { m_EndPos = wxPoint( m_Pos.x + aRadius, m_Pos.y ); }
int GetRadius() const;
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;
wxPoint m_Pos; // Position or centre (Arc and Circle) or start point (segments).
wxPoint m_EndPos; // A point on the circumference of the circle.
int m_Width; // Line width.
};
#endif // LIB_CIRCLE_H

View File

@ -163,9 +163,6 @@ public:
void Plot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, void Plot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
const TRANSFORM& aTransform ) const override; const TRANSFORM& aTransform ) const override;
int GetWidth() const override { return GetTextThickness(); }
void SetWidth( int aWidth ) override { SetTextThickness( aWidth ); }
wxString GetSelectMenuText( EDA_UNITS aUnits ) const override; wxString GetSelectMenuText( EDA_UNITS aUnits ) const override;
BITMAPS GetMenuImage() const override; BITMAPS GetMenuImage() const override;

View File

@ -3,7 +3,7 @@
* *
* Copyright (C) 2015 Jean-Pierre Charras, jaen-pierre.charras at wanadoo.fr * Copyright (C) 2015 Jean-Pierre Charras, jaen-pierre.charras at wanadoo.fr
* Copyright (C) 2015 Wayne Stambaugh <stambaughw@verizon.net> * Copyright (C) 2015 Wayne Stambaugh <stambaughw@verizon.net>
* Copyright (C) 2004-2019 KiCad Developers, see change_log.txt for contributors. * Copyright (C) 2004-2021 KiCad Developers, see change_log.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -25,25 +25,19 @@
#include <sch_draw_panel.h> #include <sch_draw_panel.h>
#include <widgets/msgpanel.h> #include <widgets/msgpanel.h>
#include <lib_symbol.h>
#include <general.h> #include <general.h>
#include <lib_item.h> #include <lib_item.h>
const int fill_tab[3] = { 'N', 'F', 'f' }; const int fill_tab[3] = { 'N', 'F', 'f' };
LIB_ITEM::LIB_ITEM( KICAD_T aType, LIB_ITEM::LIB_ITEM( KICAD_T aType, LIB_SYMBOL* aSymbol, int aUnit, int aConvert ) :
LIB_SYMBOL* aSymbol, EDA_ITEM( aSymbol, aType ),
int aUnit, m_unit( aUnit ),
int aConvert, m_convert( aConvert ),
FILL_TYPE aFillType ) : m_editState( 0 )
EDA_ITEM( aType )
{ {
m_unit = aUnit;
m_convert = aConvert;
m_fill = aFillType;
m_parent = (EDA_ITEM*) aSymbol;
m_isFillable = false;
} }
@ -83,9 +77,6 @@ int LIB_ITEM::compare( const LIB_ITEM& aOther, LIB_ITEM::COMPARE_FLAGS aCompareF
if( !( aCompareFlags & COMPARE_FLAGS::UNIT ) && m_convert != aOther.m_convert ) if( !( aCompareFlags & COMPARE_FLAGS::UNIT ) && m_convert != aOther.m_convert )
return m_convert - aOther.m_convert; return m_convert - aOther.m_convert;
if( m_fill != aOther.m_fill )
return static_cast<int>( m_fill ) - static_cast<int>( aOther.m_fill );
return 0; return 0;
} }

View File

@ -28,7 +28,7 @@
#include <eda_item.h> #include <eda_item.h>
#include <eda_rect.h> #include <eda_rect.h>
#include <fill_type.h> #include <eda_shape.h>
#include <transform.h> #include <transform.h>
#include <render_settings.h> #include <render_settings.h>
@ -61,8 +61,7 @@ typedef std::vector< LIB_PIN* > LIB_PINS;
class LIB_ITEM : public EDA_ITEM class LIB_ITEM : public EDA_ITEM
{ {
public: public:
LIB_ITEM( KICAD_T aType, LIB_SYMBOL* aSymbol = nullptr, int aUnit = 0, int aConvert = 0, LIB_ITEM( KICAD_T aType, LIB_SYMBOL* aSymbol = nullptr, int aUnit = 0, int aConvert = 0 );
FILL_TYPE aFillType = FILL_TYPE::NO_FILL );
// Do not create a copy constructor. The one generated by the compiler is adequate. // Do not create a copy constructor. The one generated by the compiler is adequate.
@ -127,6 +126,12 @@ public:
*/ */
virtual void CalcEdit( const wxPoint& aPosition ) {} virtual void CalcEdit( const wxPoint& aPosition ) {}
/**
* For use by more complex editing routines that need to indicate what phase they are in.
* @param aState
*/
virtual void SetEditState( int aState ) { m_editState = aState; }
/** /**
* Draw an item * Draw an item
* *
@ -148,9 +153,7 @@ public:
// For historical reasons, a stored value of 0 means "default width" and negative // For historical reasons, a stored value of 0 means "default width" and negative
// numbers meant "don't stroke". // numbers meant "don't stroke".
if( GetPenWidth() < 0 && GetFillMode() != FILL_TYPE::NO_FILL ) if( GetPenWidth() <= 0 )
return 0;
else if( GetPenWidth() == 0 )
return aSettings->GetDefaultPenWidth(); return aSettings->GetDefaultPenWidth();
else else
return std::max( GetPenWidth(), aSettings->GetMinPenWidth() ); return std::max( GetPenWidth(), aSettings->GetMinPenWidth() );
@ -257,26 +260,12 @@ public:
virtual void Plot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, virtual void Plot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
const TRANSFORM& aTransform ) const = 0; const TRANSFORM& aTransform ) const = 0;
virtual int GetWidth() const = 0;
virtual void SetWidth( int aWidth ) = 0;
/**
* Check if draw object can be filled.
*
* The default setting is false. If the derived object support filling, set the
* m_isFillable member to true.
*/
bool IsFillable() const { return m_isFillable; }
void SetUnit( int aUnit ) { m_unit = aUnit; } void SetUnit( int aUnit ) { m_unit = aUnit; }
int GetUnit() const { return m_unit; } int GetUnit() const { return m_unit; }
void SetConvert( int aConvert ) { m_convert = aConvert; } void SetConvert( int aConvert ) { m_convert = aConvert; }
int GetConvert() const { return m_convert; } int GetConvert() const { return m_convert; }
void SetFillMode( FILL_TYPE aFillMode ) { m_fill = aFillMode; }
FILL_TYPE GetFillMode() const { return m_fill; }
#if defined(DEBUG) #if defined(DEBUG)
void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); } void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
#endif #endif
@ -332,12 +321,7 @@ protected:
*/ */
int m_convert; int m_convert;
/** int m_editState;
* The body fill type. This has meaning only for some items. For a list of fill types
* see #FILL_TYPE.
*/
FILL_TYPE m_fill;
bool m_isFillable;
}; };

View File

@ -571,7 +571,7 @@ void LIB_PIN::PlotSymbol( PLOTTER* aPlotter, const wxPoint& aPosition, int aOrie
{ {
const int radius = externalPinDecoSize( aPlotter->RenderSettings(), *this ); const int radius = externalPinDecoSize( aPlotter->RenderSettings(), *this );
aPlotter->Circle( wxPoint( MapX1 * radius + x1, MapY1 * radius + y1 ), radius * 2, aPlotter->Circle( wxPoint( MapX1 * radius + x1, MapY1 * radius + y1 ), radius * 2,
FILL_TYPE::NO_FILL, penWidth ); FILL_T::NO_FILL, penWidth );
aPlotter->MoveTo( wxPoint( MapX1 * radius * 2 + x1, MapY1 * radius * 2 + y1 ) ); aPlotter->MoveTo( wxPoint( MapX1 * radius * 2 + x1, MapY1 * radius * 2 + y1 ) );
aPlotter->FinishTo( aPosition ); aPlotter->FinishTo( aPosition );

View File

@ -219,10 +219,6 @@ public:
void Plot( PLOTTER* aPlotter, const wxPoint& aPffset, bool aFill, void Plot( PLOTTER* aPlotter, const wxPoint& aPffset, bool aFill,
const TRANSFORM& aTransform ) const override; const TRANSFORM& aTransform ) const override;
// Get/SetWidth() not used for pins. Use GetPenWidth() for drawing.
int GetWidth() const override { return 1; }
void SetWidth( int aWidth ) override { };
BITMAPS GetMenuImage() const override; BITMAPS GetMenuImage() const override;
wxString GetSelectMenuText( EDA_UNITS aUnits ) const override; wxString GetSelectMenuText( EDA_UNITS aUnits ) const override;

View File

@ -1,390 +0,0 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2004-2021 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <sch_draw_panel.h>
#include <plotters/plotter.h>
#include <trigo.h>
#include <base_units.h>
#include <widgets/msgpanel.h>
#include <bitmaps.h>
#include <eda_draw_frame.h>
#include <general.h>
#include <lib_polyline.h>
#include <settings/color_settings.h>
#include <transform.h>
LIB_POLYLINE::LIB_POLYLINE( LIB_SYMBOL* aParent ) :
LIB_ITEM( LIB_POLYLINE_T, aParent )
{
m_fill = FILL_TYPE::NO_FILL;
m_Width = 0;
m_isFillable = true;
}
EDA_ITEM* LIB_POLYLINE::Clone() const
{
return new LIB_POLYLINE( *this );
}
int LIB_POLYLINE::compare( const LIB_ITEM& aOther, LIB_ITEM::COMPARE_FLAGS aCompareFlags ) const
{
wxASSERT( aOther.Type() == LIB_POLYLINE_T );
int retv = LIB_ITEM::compare( aOther );
if( retv )
return retv;
const LIB_POLYLINE* tmp = (LIB_POLYLINE*) &aOther;
if( m_PolyPoints.size() != tmp->m_PolyPoints.size() )
return m_PolyPoints.size() - tmp->m_PolyPoints.size();
for( size_t i = 0; i < m_PolyPoints.size(); i++ )
{
if( m_PolyPoints[i].x != tmp->m_PolyPoints[i].x )
return m_PolyPoints[i].x - tmp->m_PolyPoints[i].x;
if( m_PolyPoints[i].y != tmp->m_PolyPoints[i].y )
return m_PolyPoints[i].y - tmp->m_PolyPoints[i].y;
}
return 0;
}
void LIB_POLYLINE::Offset( const wxPoint& aOffset )
{
for( wxPoint& point : m_PolyPoints )
point += aOffset;
}
void LIB_POLYLINE::MoveTo( const wxPoint& aPosition )
{
Offset( aPosition - m_PolyPoints[ 0 ] );
}
void LIB_POLYLINE::MirrorHorizontal( const wxPoint& aCenter )
{
for( wxPoint& point : m_PolyPoints )
{
point.x -= aCenter.x;
point.x *= -1;
point.x += aCenter.x;
}
}
void LIB_POLYLINE::MirrorVertical( const wxPoint& aCenter )
{
for( wxPoint& point : m_PolyPoints )
{
point.y -= aCenter.y;
point.y *= -1;
point.y += aCenter.y;
}
}
void LIB_POLYLINE::Rotate( const wxPoint& aCenter, bool aRotateCCW )
{
for( wxPoint& point : m_PolyPoints )
RotatePoint( &point, aCenter, aRotateCCW ? -900 : 900 );
}
void LIB_POLYLINE::Plot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
const TRANSFORM& aTransform ) const
{
wxASSERT( aPlotter != nullptr );
static std::vector< wxPoint > cornerList;
cornerList.clear();
for( wxPoint pos : m_PolyPoints )
{
pos = aTransform.TransformCoordinate( pos ) + aOffset;
cornerList.push_back( pos );
}
if( aFill && m_fill == FILL_TYPE::FILLED_WITH_BG_BODYCOLOR )
{
aPlotter->SetColor( aPlotter->RenderSettings()->GetLayerColor( LAYER_DEVICE_BACKGROUND ) );
aPlotter->PlotPoly( cornerList, FILL_TYPE::FILLED_WITH_BG_BODYCOLOR, 0 );
}
bool already_filled = m_fill == FILL_TYPE::FILLED_WITH_BG_BODYCOLOR;
int pen_size = GetEffectivePenWidth( aPlotter->RenderSettings() );
if( !already_filled || pen_size > 0 )
{
aPlotter->SetColor( aPlotter->RenderSettings()->GetLayerColor( LAYER_DEVICE ) );
aPlotter->PlotPoly( cornerList, already_filled ? FILL_TYPE::NO_FILL : m_fill, pen_size );
}
}
void LIB_POLYLINE::AddPoint( const wxPoint& aPosition )
{
m_PolyPoints.push_back( aPosition );
}
void LIB_POLYLINE::AddCorner( const wxPoint& aPosition )
{
int currentMinDistance = INT_MAX;
int closestLineStart = 0;
for( unsigned i = 0; i < m_PolyPoints.size() - 1; ++i )
{
int distance = (int) DistanceLinePoint( m_PolyPoints[i], m_PolyPoints[i + 1], aPosition );
if( distance < currentMinDistance )
{
currentMinDistance = distance;
closestLineStart = i;
}
}
m_PolyPoints.insert( m_PolyPoints.begin() + closestLineStart, aPosition );
}
void LIB_POLYLINE::RemoveCorner( int aIdx )
{
m_PolyPoints.erase( m_PolyPoints.begin() + aIdx );
}
int LIB_POLYLINE::GetPenWidth() const
{
return m_Width;
}
void LIB_POLYLINE::print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset, void* aData,
const TRANSFORM& aTransform )
{
bool forceNoFill = static_cast<bool>( aData );
int penWidth = GetEffectivePenWidth( aSettings );
if( forceNoFill && m_fill != FILL_TYPE::NO_FILL && penWidth == 0 )
return;
wxDC* DC = aSettings->GetPrintDC();
COLOR4D color = aSettings->GetLayerColor( LAYER_DEVICE );
wxPoint* buffer = new wxPoint[ m_PolyPoints.size() ];
for( unsigned ii = 0; ii < m_PolyPoints.size(); ii++ )
buffer[ii] = aTransform.TransformCoordinate( m_PolyPoints[ii] ) + aOffset;
if( forceNoFill || m_fill == FILL_TYPE::NO_FILL )
{
GRPoly( nullptr, DC, m_PolyPoints.size(), buffer, false, penWidth, color, color );
}
else
{
if( m_fill == FILL_TYPE::FILLED_WITH_BG_BODYCOLOR )
color = aSettings->GetLayerColor( LAYER_DEVICE_BACKGROUND );
GRPoly( nullptr, DC, m_PolyPoints.size(), buffer, true, penWidth, color, color );
}
delete[] buffer;
}
bool LIB_POLYLINE::HitTest( const wxPoint& aPosition, int aAccuracy ) const
{
int delta = std::max( aAccuracy + GetPenWidth() / 2, Mils2iu( MINIMUM_SELECTION_DISTANCE ) );
SHAPE_LINE_CHAIN shape;
for( wxPoint pt : m_PolyPoints )
shape.Append( DefaultTransform.TransformCoordinate( pt ) );
if( m_fill != FILL_TYPE::NO_FILL && m_PolyPoints.size() > 2 )
{
shape.SetClosed( true );
return shape.PointInside( aPosition, delta );
}
else
return shape.PointOnEdge( aPosition, delta );
}
bool LIB_POLYLINE::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
{
if( m_flags & (STRUCT_DELETED | SKIP_STRUCT ) )
return false;
EDA_RECT sel = aRect;
if ( aAccuracy )
sel.Inflate( aAccuracy );
if( aContained )
return sel.Contains( GetBoundingBox() );
// Fast test: if rect is outside the polygon bounding box, then they cannot intersect
if( !sel.Intersects( GetBoundingBox() ) )
return false;
// Account for the width of the line
sel.Inflate( ( GetPenWidth() / 2 ) + 1 );
for( size_t ii = 0; ii < m_PolyPoints.size(); ii++ )
{
wxPoint pt = DefaultTransform.TransformCoordinate( m_PolyPoints[ ii ] );
// Test if the point is within aRect
if( sel.Contains( pt ) )
return true;
if( ii + 1 < m_PolyPoints.size() )
{
wxPoint ptNext = DefaultTransform.TransformCoordinate( m_PolyPoints[ ii + 1 ] );
// Test if this edge intersects aRect
if( sel.Intersects( pt, ptNext ) )
return true;
}
else if( m_fill != FILL_TYPE::NO_FILL )
{
wxPoint ptNext = DefaultTransform.TransformCoordinate( m_PolyPoints[ 0 ] );
// Test if this edge intersects aRect
if( sel.Intersects( pt, ptNext ) )
return true;
}
}
return false;
}
const EDA_RECT LIB_POLYLINE::GetBoundingBox() const
{
EDA_RECT rect;
int xmin, xmax, ymin, ymax;
xmin = xmax = m_PolyPoints[0].x;
ymin = ymax = m_PolyPoints[0].y;
for( unsigned ii = 1; ii < GetCornerCount(); ii++ )
{
xmin = std::min( xmin, m_PolyPoints[ii].x );
xmax = std::max( xmax, m_PolyPoints[ii].x );
ymin = std::min( ymin, m_PolyPoints[ii].y );
ymax = std::max( ymax, m_PolyPoints[ii].y );
}
rect.SetOrigin( xmin, ymin );
rect.SetEnd( xmax, ymax );
rect.Inflate( ( GetPenWidth() / 2 ) + 1 );
rect.RevertYAxis();
return rect;
}
void LIB_POLYLINE::DeleteSegment( const wxPoint aPosition )
{
// First segment is kept, only its end point is changed
while( GetCornerCount() > 2 )
{
m_PolyPoints.pop_back();
if( m_PolyPoints[ GetCornerCount() - 1 ] != aPosition )
{
m_PolyPoints[ GetCornerCount() - 1 ] = aPosition;
break;
}
}
}
void LIB_POLYLINE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
{
EDA_RECT bBox = GetBoundingBox();
LIB_ITEM::GetMsgPanelInfo( aFrame, aList );
aList.emplace_back( _( "Line Width" ), MessageTextFromValue( aFrame->GetUserUnits(), m_Width ) );
aList.emplace_back( _( "Bounding Box" ), wxString::Format( wxT( "(%d, %d, %d, %d)" ),
bBox.GetOrigin().x,
bBox.GetOrigin().y,
bBox.GetEnd().x,
bBox.GetEnd().y ) );
}
wxString LIB_POLYLINE::GetSelectMenuText( EDA_UNITS aUnits ) const
{
return wxString::Format( _( "Polyline, %d points" ), int( m_PolyPoints.size() ) );
}
BITMAPS LIB_POLYLINE::GetMenuImage() const
{
return BITMAPS::add_graphical_segments;
}
void LIB_POLYLINE::BeginEdit( const wxPoint& aPosition )
{
m_PolyPoints.push_back( aPosition ); // Start point of first segment.
m_PolyPoints.push_back( aPosition ); // End point of first segment.
}
bool LIB_POLYLINE::ContinueEdit( const wxPoint& aPosition )
{
// do not add zero length segments
if( m_PolyPoints[m_PolyPoints.size() - 2] != m_PolyPoints.back() )
m_PolyPoints.push_back( aPosition );
return true;
}
void LIB_POLYLINE::EndEdit()
{
// do not include last point twice
if( m_PolyPoints.size() > 2 )
{
if( m_PolyPoints[ m_PolyPoints.size() - 2 ] == m_PolyPoints.back() )
m_PolyPoints.pop_back();
}
}
void LIB_POLYLINE::CalcEdit( const wxPoint& aPosition )
{
m_PolyPoints[ GetCornerCount() - 1 ] = aPosition;
}

View File

@ -1,125 +0,0 @@
/*
* 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_POLYLINE_H_
#define _LIB_POLYLINE_H_
#include <lib_item.h>
class LIB_POLYLINE : public LIB_ITEM
{
public:
LIB_POLYLINE( LIB_SYMBOL* aParent );
// Do not create a copy constructor. The one generated by the compiler is adequate.
~LIB_POLYLINE() { }
wxString GetClass() const override
{
return wxT( "LIB_POLYLINE" );
}
wxString GetTypeName() const override
{
return _( "PolyLine" );
}
void ClearPoints() { m_PolyPoints.clear(); }
void Reserve( size_t aPointCount ) { m_PolyPoints.reserve( aPointCount ); }
void AddPoint( const wxPoint& aPoint );
const std::vector< wxPoint >& GetPolyPoints() const { return m_PolyPoints; }
/**
* Delete the segment at \a aPosition.
*/
void DeleteSegment( const wxPoint aPosition );
void AddCorner( const wxPoint& aPosition );
void RemoveCorner( int aIdx );
/**
* @return the number of corners
*/
unsigned GetCornerCount() const { return m_PolyPoints.size(); }
bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override;
bool HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy = 0 ) const override;
const EDA_RECT GetBoundingBox() const override;
int GetPenWidth() const override;
void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
void BeginEdit( const wxPoint& aStartPoint ) override;
void CalcEdit( const wxPoint& aPosition ) override;
bool ContinueEdit( const wxPoint& aNextPoint ) override;
void EndEdit() override;
void Offset( const wxPoint& aOffset ) override;
void MoveTo( const wxPoint& aPosition ) override;
wxPoint GetPosition() const override { return m_PolyPoints[0]; }
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;
int GetWidth() const override { return m_Width; }
void SetWidth( int aWidth ) override { m_Width = aWidth; }
wxString GetSelectMenuText( EDA_UNITS aUnits ) const override;
BITMAPS GetMenuImage() const override;
EDA_ITEM* Clone() const override;
private:
/**
* @copydoc LIB_ITEM::compare()
*
* The sort order for specific to each polyline segment point is as follows:
* - Line segment point horizontal (X) position.
* - Line segment point vertical (Y) position.
*/
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;
int m_Width; // Line width
std::vector<wxPoint> m_PolyPoints; // list of points (>= 2)
};
#endif // _LIB_POLYLINE_H_

View File

@ -1,292 +0,0 @@
/*
* 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 <eda_draw_frame.h>
#include <sch_draw_panel.h>
#include <plotters/plotter.h>
#include <trigo.h>
#include <base_units.h>
#include <widgets/msgpanel.h>
#include <bitmaps.h>
#include <general.h>
#include <lib_rectangle.h>
#include <settings/color_settings.h>
#include <transform.h>
LIB_RECTANGLE::LIB_RECTANGLE( LIB_SYMBOL* aParent ) : LIB_ITEM( LIB_RECTANGLE_T, aParent )
{
m_Width = 0;
m_fill = FILL_TYPE::NO_FILL;
m_isFillable = true;
}
EDA_ITEM* LIB_RECTANGLE::Clone() const
{
return new LIB_RECTANGLE( *this );
}
int LIB_RECTANGLE::compare( const LIB_ITEM& aOther, LIB_ITEM::COMPARE_FLAGS aCompareFlags ) const
{
wxASSERT( aOther.Type() == LIB_RECTANGLE_T );
int retv = LIB_ITEM::compare( aOther );
if( retv )
return retv;
const LIB_RECTANGLE* tmp = ( LIB_RECTANGLE* ) &aOther;
if( m_Pos.x != tmp->m_Pos.x )
return m_Pos.x - tmp->m_Pos.x;
if( m_Pos.y != tmp->m_Pos.y )
return m_Pos.y - tmp->m_Pos.y;
if( m_End.x != tmp->m_End.x )
return m_End.x - tmp->m_End.x;
if( m_End.y != tmp->m_End.y )
return m_End.y - tmp->m_End.y;
return 0;
}
void LIB_RECTANGLE::Offset( const wxPoint& aOffset )
{
m_Pos += aOffset;
m_End += aOffset;
}
void LIB_RECTANGLE::MoveTo( const wxPoint& aPosition )
{
wxPoint size = m_End - m_Pos;
m_Pos = aPosition;
m_End = aPosition + size;
}
void LIB_RECTANGLE::MirrorHorizontal( const wxPoint& aCenter )
{
m_Pos.x -= aCenter.x;
m_Pos.x *= -1;
m_Pos.x += aCenter.x;
m_End.x -= aCenter.x;
m_End.x *= -1;
m_End.x += aCenter.x;
}
void LIB_RECTANGLE::MirrorVertical( const wxPoint& aCenter )
{
m_Pos.y -= aCenter.y;
m_Pos.y *= -1;
m_Pos.y += aCenter.y;
m_End.y -= aCenter.y;
m_End.y *= -1;
m_End.y += aCenter.y;
}
void LIB_RECTANGLE::Rotate( const wxPoint& aCenter, bool aRotateCCW )
{
int rot_angle = aRotateCCW ? -900 : 900;
RotatePoint( &m_Pos, aCenter, rot_angle );
RotatePoint( &m_End, aCenter, rot_angle );
}
void LIB_RECTANGLE::Plot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
const TRANSFORM& aTransform ) const
{
wxASSERT( aPlotter != nullptr );
wxPoint pos = aTransform.TransformCoordinate( m_Pos ) + aOffset;
wxPoint end = aTransform.TransformCoordinate( m_End ) + aOffset;
if( aFill && m_fill == FILL_TYPE::FILLED_WITH_BG_BODYCOLOR )
{
aPlotter->SetColor( aPlotter->RenderSettings()->GetLayerColor( LAYER_DEVICE_BACKGROUND ) );
aPlotter->Rect( pos, end, FILL_TYPE::FILLED_WITH_BG_BODYCOLOR, 0 );
}
bool already_filled = m_fill == FILL_TYPE::FILLED_WITH_BG_BODYCOLOR;
int pen_size = GetEffectivePenWidth( aPlotter->RenderSettings() );
if( !already_filled || pen_size > 0 )
{
aPlotter->SetColor( aPlotter->RenderSettings()->GetLayerColor( LAYER_DEVICE ) );
aPlotter->Rect( pos, end, already_filled ? FILL_TYPE::NO_FILL : m_fill, pen_size );
}
}
int LIB_RECTANGLE::GetPenWidth() const
{
return m_Width;
}
void LIB_RECTANGLE::print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset,
void* aData, const TRANSFORM& aTransform )
{
bool forceNoFill = static_cast<bool>( aData );
int penWidth = GetEffectivePenWidth( aSettings );
if( forceNoFill && m_fill != FILL_TYPE::NO_FILL && penWidth == 0 )
return;
wxDC* DC = aSettings->GetPrintDC();
COLOR4D color = aSettings->GetLayerColor( LAYER_DEVICE );
wxPoint pt1 = aTransform.TransformCoordinate( m_Pos ) + aOffset;
wxPoint pt2 = aTransform.TransformCoordinate( m_End ) + aOffset;
if( forceNoFill || m_fill == FILL_TYPE::NO_FILL )
{
GRRect( nullptr, DC, pt1.x, pt1.y, pt2.x, pt2.y, penWidth, color );
}
else
{
if( m_fill == FILL_TYPE::FILLED_WITH_BG_BODYCOLOR )
color = aSettings->GetLayerColor( LAYER_DEVICE_BACKGROUND );
GRFilledRect( nullptr, DC, pt1.x, pt1.y, pt2.x, pt2.y, penWidth, color, color );
}
}
void LIB_RECTANGLE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
{
LIB_ITEM::GetMsgPanelInfo( aFrame, aList );
aList.emplace_back( _( "Line Width" ), MessageTextFromValue( aFrame->GetUserUnits(), m_Width ) );
}
const EDA_RECT LIB_RECTANGLE::GetBoundingBox() const
{
EDA_RECT rect;
rect.SetOrigin( m_Pos );
rect.SetEnd( m_End );
rect.Inflate( ( GetPenWidth() / 2 ) + 1 );
rect.RevertYAxis();
return rect;
}
bool LIB_RECTANGLE::HitTest( const wxPoint& aPosition, int aAccuracy ) const
{
int mindist = std::max( aAccuracy + GetPenWidth() / 2,
Mils2iu( MINIMUM_SELECTION_DISTANCE ) );
wxPoint actualStart = DefaultTransform.TransformCoordinate( m_Pos );
wxPoint actualEnd = DefaultTransform.TransformCoordinate( m_End );
// locate lower segment
wxPoint start, end;
start = actualStart;
end.x = actualEnd.x;
end.y = actualStart.y;
if( TestSegmentHit( aPosition, start, end, mindist ) )
return true;
// locate right segment
start.x = actualEnd.x;
end.y = actualEnd.y;
if( TestSegmentHit( aPosition, start, end, mindist ) )
return true;
// locate upper segment
start.y = actualEnd.y;
end.x = actualStart.x;
if( TestSegmentHit( aPosition, start, end, mindist ) )
return true;
// locate left segment
start = actualStart;
end.x = actualStart.x;
end.y = actualEnd.y;
if( TestSegmentHit( aPosition, start, end, mindist ) )
return true;
if( m_fill == FILL_TYPE::NO_FILL )
return false;
return GetBoundingBox().Contains( aPosition );
}
bool LIB_RECTANGLE::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
{
if( m_flags & (STRUCT_DELETED | SKIP_STRUCT ) )
return false;
EDA_RECT sel = aRect;
if ( aAccuracy )
sel.Inflate( aAccuracy );
if( aContained )
return sel.Contains( GetBoundingBox() );
return sel.Intersects( GetBoundingBox() );
}
wxString LIB_RECTANGLE::GetSelectMenuText( EDA_UNITS aUnits ) const
{
return wxString::Format( _( "Rectangle, width %s height %s" ),
MessageTextFromValue( aUnits, std::abs( m_Pos.x - m_End.x ) ),
MessageTextFromValue( aUnits, std::abs( m_Pos.y - m_End.y ) ) );
}
BITMAPS LIB_RECTANGLE::GetMenuImage() const
{
return BITMAPS::add_rectangle;
}
void LIB_RECTANGLE::BeginEdit( const wxPoint& aPosition )
{
m_Pos = m_End = aPosition;
}
void LIB_RECTANGLE::CalcEdit( const wxPoint& aPosition )
{
m_End = aPosition;
}

View File

@ -1,112 +0,0 @@
/*
* 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 AUTHOR.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_RECTANGLE_H
#define LIB_RECTANGLE_H
#include <lib_item.h>
class LIB_RECTANGLE : public LIB_ITEM
{
public:
LIB_RECTANGLE( LIB_SYMBOL* aParent );
// Do not create a copy constructor. The one generated by the compiler is adequate.
~LIB_RECTANGLE() { }
wxString GetClass() const override
{
return wxT( "LIB_RECTANGLE" );
}
wxString GetTypeName() const override
{
return _( "Rectangle" );
}
void SetEndPosition( const wxPoint& aPosition ) { m_End = aPosition; }
bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override;
bool HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy = 0 ) const override;
int GetPenWidth() const override;
const EDA_RECT GetBoundingBox() const override;
void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
void BeginEdit( const wxPoint& aStartPoint ) override;
void CalcEdit( const wxPoint& aPosition ) override;
void Offset( const wxPoint& aOffset ) override;
void MoveTo( const wxPoint& aPosition ) override;
wxPoint GetPosition() const override { return m_Pos; }
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;
int GetWidth() const override { return m_Width; }
void SetWidth( int aWidth ) override { m_Width = aWidth; }
void SetEnd( const wxPoint& aEnd ) { m_End = aEnd; }
wxPoint GetEnd() const { return m_End; }
wxString GetSelectMenuText( EDA_UNITS aUnits ) const override;
BITMAPS GetMenuImage() const override;
EDA_ITEM* Clone() const override;
private:
/**
* @copydoc LIB_ITEM::compare()
*
* The rectangle specific sort order is as follows:
* - Rectangle horizontal (X) start position.
* - Rectangle vertical (Y) start position.
* - Rectangle horizontal (X) end position.
* - Rectangle vertical (Y) end position.
*/
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;
wxPoint m_End; // Rectangle end point.
wxPoint m_Pos; // Rectangle start point.
int m_Width; // Line width
};
#endif // LIB_RECTANGLE_H

View File

@ -23,7 +23,8 @@
*/ */
#include <sch_draw_panel.h> #include <sch_draw_panel.h>
#include <plotter.h> #include <plotters/plotter.h>
#include <macros.h>
#include <base_units.h> #include <base_units.h>
#include <widgets/msgpanel.h> #include <widgets/msgpanel.h>
#include <bitmaps.h> #include <bitmaps.h>
@ -37,6 +38,7 @@ LIB_SHAPE::LIB_SHAPE( LIB_SYMBOL* aParent, SHAPE_T aShape, int aDefaultLineWidth
LIB_ITEM( LIB_SHAPE_T, aParent ), LIB_ITEM( LIB_SHAPE_T, aParent ),
EDA_SHAPE( aShape, aDefaultLineWidth, aFillType ) EDA_SHAPE( aShape, aDefaultLineWidth, aFillType )
{ {
m_editState = 0;
} }
@ -54,7 +56,7 @@ bool LIB_SHAPE::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy )
if( m_flags & (STRUCT_DELETED | SKIP_STRUCT ) ) if( m_flags & (STRUCT_DELETED | SKIP_STRUCT ) )
return false; return false;
return hitTest( aRect, aContained, aAccuracy ); return hitTest( DefaultTransform.TransformCoordinate( aRect ), aContained, aAccuracy );
} }
@ -115,19 +117,20 @@ void LIB_SHAPE::Plot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
wxPoint center; wxPoint center;
int startAngle; int startAngle;
int endAngle; int endAngle;
int pen_size = GetPenWidth(); int pen_size = GetEffectivePenWidth( aPlotter->RenderSettings() );
FILL_T fill = aFill ? m_fill : FILL_TYPE::NO_FILL; FILL_T fill = aFill ? m_fill : FILL_T::NO_FILL;
static std::vector<wxPoint> cornerList; static std::vector<wxPoint> cornerList;
if( GetShape() == SHAPE_T::POLYGON ) if( GetShape() == SHAPE_T::POLY )
{ {
const SHAPE_LINE_CHAIN& poly = m_poly.Outline( 0 );
cornerList.clear(); cornerList.clear();
for( const VECTOR2I& pt : m_poly.Outline( 0 ).CPoints() ) for( const VECTOR2I& pt : poly.CPoints() )
cornerList.push_back( aTransform.TransformCoordinate( (wxPoint) pt ) + aOffset ); cornerList.push_back( aTransform.TransformCoordinate( (wxPoint) pt ) + aOffset );
} }
else if( GetShape() == SHAPE_T::CURVE ) else if( GetShape() == SHAPE_T::BEZIER )
{ {
cornerList.clear(); cornerList.clear();
@ -137,8 +140,8 @@ void LIB_SHAPE::Plot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
else if( GetShape() == SHAPE_T::ARC ) else if( GetShape() == SHAPE_T::ARC )
{ {
center = aTransform.TransformCoordinate( getCenter() ) + aOffset; center = aTransform.TransformCoordinate( getCenter() ) + aOffset;
startAngle = GetArcAngleStart();
endAngle = GetArcAngleEnd(); CalcArcAngles( startAngle, endAngle );
aTransform.MapAngles( &startAngle, &endAngle ); aTransform.MapAngles( &startAngle, &endAngle );
} }
@ -160,13 +163,13 @@ void LIB_SHAPE::Plot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
aPlotter->Rect( start, end, fill, 0 ); aPlotter->Rect( start, end, fill, 0 );
break; break;
case SHAPE_T::POLYGON: case SHAPE_T::POLY:
case SHAPE_T::CURVE: case SHAPE_T::BEZIER:
aPlotter->PlotPoly( cornerList, fill, 0 ); aPlotter->PlotPoly( cornerList, fill, 0 );
break; break;
default: default:
wxFAIL_MSG( "LIB_SHAPE::Plot not implemented for " + SHAPE_T_asString() ); UNIMPLEMENTED_FOR( SHAPE_T_asString() );
} }
if( pen_size <= 0 ) if( pen_size <= 0 )
@ -175,8 +178,6 @@ void LIB_SHAPE::Plot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
fill = FILL_T::NO_FILL; fill = FILL_T::NO_FILL;
} }
pen_size = std::max( pen_size, aPlotter->RenderSettings()->GetMinPenWidth() );
aPlotter->SetColor( aPlotter->RenderSettings()->GetLayerColor( LAYER_DEVICE ) ); aPlotter->SetColor( aPlotter->RenderSettings()->GetLayerColor( LAYER_DEVICE ) );
switch( GetShape() ) switch( GetShape() )
@ -193,24 +194,20 @@ void LIB_SHAPE::Plot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
aPlotter->Rect( start, end, fill, pen_size ); aPlotter->Rect( start, end, fill, pen_size );
break; break;
case SHAPE_T::POLYGON: case SHAPE_T::POLY:
case SHAPE_T::CURVE: case SHAPE_T::BEZIER:
aPlotter->PlotPoly( cornerList, fill, pen_size ); aPlotter->PlotPoly( cornerList, fill, pen_size );
break; break;
default: default:
wxFAIL_MSG( "LIB_SHAPE::Plot not implemented for " + SHAPE_T_asString() ); UNIMPLEMENTED_FOR( SHAPE_T_asString() );
} }
} }
int LIB_SHAPE::GetPenWidth() const int LIB_SHAPE::GetPenWidth() const
{ {
// Historically 0 meant "default width" and negative numbers meant "don't stroke". return GetWidth();
if( GetWidth() < 0 && GetFillType() != FILL_T::NO_FILL )
return 0;
else
return std::max( GetWidth(), 1 );
} }
@ -234,9 +231,9 @@ void LIB_SHAPE::print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset,
unsigned ptCount = 0; unsigned ptCount = 0;
wxPoint* buffer = nullptr; wxPoint* buffer = nullptr;
if( GetShape() == SHAPE_T::POLYGON ) if( GetShape() == SHAPE_T::POLY )
{ {
SHAPE_LINE_CHAIN poly = m_poly.Outline( 0 ); const SHAPE_LINE_CHAIN& poly = m_poly.Outline( 0 );
ptCount = poly.GetPointCount(); ptCount = poly.GetPointCount();
buffer = new wxPoint[ ptCount ]; buffer = new wxPoint[ ptCount ];
@ -244,7 +241,7 @@ void LIB_SHAPE::print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset,
for( unsigned ii = 0; ii < ptCount; ++ii ) for( unsigned ii = 0; ii < ptCount; ++ii )
buffer[ii] = aTransform.TransformCoordinate( (wxPoint) poly.CPoint( ii ) ) + aOffset; buffer[ii] = aTransform.TransformCoordinate( (wxPoint) poly.CPoint( ii ) ) + aOffset;
} }
else if( GetShape() == SHAPE_T::CURVE ) else if( GetShape() == SHAPE_T::BEZIER )
{ {
ptCount = m_bezierPoints.size(); ptCount = m_bezierPoints.size();
buffer = new wxPoint[ ptCount ]; buffer = new wxPoint[ ptCount ];
@ -255,8 +252,8 @@ void LIB_SHAPE::print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset,
else if( GetShape() == SHAPE_T::ARC ) else if( GetShape() == SHAPE_T::ARC )
{ {
c = aTransform.TransformCoordinate( getCenter() ) + aOffset; c = aTransform.TransformCoordinate( getCenter() ) + aOffset;
t1 = GetArcAngleStart();
t2 = GetArcAngleEnd(); CalcArcAngles( t1, t2 );
aTransform.MapAngles( &t1, &t2 ); aTransform.MapAngles( &t1, &t2 );
} }
@ -278,16 +275,16 @@ void LIB_SHAPE::print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset,
GRRect( nullptr, DC, pt1.x, pt1.y, pt2.x, pt2.y, penWidth, color ); GRRect( nullptr, DC, pt1.x, pt1.y, pt2.x, pt2.y, penWidth, color );
break; break;
case SHAPE_T::POLYGON: case SHAPE_T::POLY:
GRPoly( nullptr, DC, ptCount, buffer, false, penWidth, color, color ); GRPoly( nullptr, DC, ptCount, buffer, false, penWidth, color, color );
break; break;
case SHAPE_T::CURVE: case SHAPE_T::BEZIER:
GRPoly( nullptr, DC, ptCount, buffer, false, penWidth, color, color ); GRPoly( nullptr, DC, ptCount, buffer, false, penWidth, color, color );
break; break;
default: default:
wxFAIL_MSG( "LIB_SHAPE::print not implemented for " + SHAPE_T_asString() ); UNIMPLEMENTED_FOR( SHAPE_T_asString() );
} }
} }
else else
@ -309,16 +306,16 @@ void LIB_SHAPE::print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset,
GRFilledRect( nullptr, DC, pt1.x, pt1.y, pt2.x, pt2.y, penWidth, color, color ); GRFilledRect( nullptr, DC, pt1.x, pt1.y, pt2.x, pt2.y, penWidth, color, color );
break; break;
case SHAPE_T::POLYGON: case SHAPE_T::POLY:
GRPoly( nullptr, DC, ptCount, buffer, true, penWidth, color, color ); GRPoly( nullptr, DC, ptCount, buffer, true, penWidth, color, color );
break; break;
case SHAPE_T::CURVE: case SHAPE_T::BEZIER:
GRPoly( nullptr, DC, ptCount, buffer, true, penWidth, color, color ); GRPoly( nullptr, DC, ptCount, buffer, true, penWidth, color, color );
break; break;
default: default:
wxFAIL_MSG( "LIB_SHAPE::print not implemented for " + SHAPE_T_asString() ); UNIMPLEMENTED_FOR( SHAPE_T_asString() );
} }
} }
@ -361,16 +358,16 @@ wxString LIB_SHAPE::GetSelectMenuText( EDA_UNITS aUnits ) const
MessageTextFromValue( aUnits, std::abs( m_start.x - m_end.x ) ), MessageTextFromValue( aUnits, std::abs( m_start.x - m_end.x ) ),
MessageTextFromValue( aUnits, std::abs( m_start.y - m_end.y ) ) ); MessageTextFromValue( aUnits, std::abs( m_start.y - m_end.y ) ) );
case SHAPE_T::POLYGON: case SHAPE_T::POLY:
return wxString::Format( _( "Polyline, %d points" ), return wxString::Format( _( "Polyline, %d points" ),
int( m_poly.Outline( 0 ).GetPointCount() ) ); int( m_poly.Outline( 0 ).GetPointCount() ) );
case SHAPE_T::CURVE: case SHAPE_T::BEZIER:
return wxString::Format( _( "Bezier Curve, %d points" ), return wxString::Format( _( "Bezier Curve, %d points" ),
int( m_bezierPoints.size() ) ); int( m_bezierPoints.size() ) );
default: default:
wxFAIL_MSG( "LIB_SHAPE::GetSelectMenuText unimplemented for " + SHAPE_T_asString() ); UNIMPLEMENTED_FOR( SHAPE_T_asString() );
return wxEmptyString; return wxEmptyString;
} }
} }
@ -384,10 +381,10 @@ BITMAPS LIB_SHAPE::GetMenuImage() const
case SHAPE_T::ARC: return BITMAPS::add_arc; case SHAPE_T::ARC: return BITMAPS::add_arc;
case SHAPE_T::CIRCLE: return BITMAPS::add_circle; case SHAPE_T::CIRCLE: return BITMAPS::add_circle;
case SHAPE_T::RECT: return BITMAPS::add_rectangle; case SHAPE_T::RECT: return BITMAPS::add_rectangle;
case SHAPE_T::POLYGON: return BITMAPS::add_graphical_segments; case SHAPE_T::POLY: return BITMAPS::add_graphical_segments;
default: default:
wxFAIL_MSG( "LIB_SHAPE::GetMenuImage unimplemented for " + SHAPE_T_asString() ); UNIMPLEMENTED_FOR( SHAPE_T_asString() );
return BITMAPS::question_mark; return BITMAPS::question_mark;
} }
} }
@ -405,19 +402,21 @@ void LIB_SHAPE::BeginEdit( const wxPoint& aPosition )
break; break;
case SHAPE_T::ARC: case SHAPE_T::ARC:
SetStart( aPosition ); SetArcGeometry( aPosition, aPosition, aPosition );
SetEnd( aPosition );
SetEditState( 1 ); SetEditState( 1 );
break; break;
case SHAPE_T::POLYGON: case SHAPE_T::POLY:
m_poly.NewOutline();
m_poly.Outline( 0 ).SetClosed( false );
// Start and end of the first segment (co-located for now) // Start and end of the first segment (co-located for now)
m_poly.Outline( 0 ).Append( aPosition ); m_poly.Outline( 0 ).Append( aPosition );
m_poly.Outline( 0 ).Append( aPosition, true ); m_poly.Outline( 0 ).Append( aPosition, true );
break; break;
default: default:
wxFAIL_MSG( "LIB_SHAPE::BeginEdit not implemented for " + SHAPE_T_asString() ); UNIMPLEMENTED_FOR( SHAPE_T_asString() );
} }
} }
@ -426,23 +425,24 @@ bool LIB_SHAPE::ContinueEdit( const wxPoint& aPosition )
{ {
switch( GetShape() ) switch( GetShape() )
{ {
case SHAPE_T::ARC:
case SHAPE_T::SEGMENT: case SHAPE_T::SEGMENT:
case SHAPE_T::CIRCLE: case SHAPE_T::CIRCLE:
case SHAPE_T::RECT: case SHAPE_T::RECT:
return false; return false;
case SHAPE_T::POLYGON: case SHAPE_T::POLY:
{ {
SHAPE_LINE_CHAIN& poly = m_poly.Outline( 0 ); SHAPE_LINE_CHAIN& poly = m_poly.Outline( 0 );
// do not add zero-length segments // do not add zero-length segments
if( poly.CPoint( poly.GetPointCount() - 2 ) != poly.CLastPoint() ) if( poly.CPoint( poly.GetPointCount() - 2 ) != poly.CLastPoint() )
poly.Append( aPosition ); poly.Append( aPosition, true );
} }
return true; return true;
default: default:
wxFAIL_MSG( "LIB_SHAPE::ContinueEdit not implemented for " + SHAPE_T_asString() ); UNIMPLEMENTED_FOR( SHAPE_T_asString() );
return false; return false;
} }
} }
@ -460,11 +460,10 @@ void LIB_SHAPE::CalcEdit( const wxPoint& aPosition )
SetEnd( aPosition ); SetEnd( aPosition );
break; break;
case SHAPE_T::POLYGON:
m_poly.Outline( 0 ).SetPoint( m_poly.Outline( 0 ).GetPointCount() - 1, aPosition );
break;
case SHAPE_T::ARC: case SHAPE_T::ARC:
{
int radius = GetRadius();
// Edit state 0: drawing: place start // Edit state 0: drawing: place start
// Edit state 1: drawing: place end (center calculated for 90-degree subtended angle) // 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 2: point edit: move start (center calculated for invariant subtended angle)
@ -479,46 +478,98 @@ void LIB_SHAPE::CalcEdit( const wxPoint& aPosition )
return; return;
case 1: case 1:
{ m_end = aPosition;
wxPoint start = GetStart(); radius = KiROUND( sqrt( sq( GetLineLength( m_start, m_end ) ) / 2.0 ) );
wxPoint end = aPosition; break;
wxPoint center = CalcArcCenter( start, end, 90.0 );
wxPoint mid = (wxPoint) CalcArcMid( start, end, center, true );
SetArcGeometry( start, mid, aPosition );
}
break; break;
case 2: case 2:
{
wxPoint delta = aPosition - GetStart();
SetArcGeometry( aPosition, GetArcMid() + delta/2, GetEnd() );
}
break;
case 3: case 3:
{ {
wxPoint delta = aPosition - GetEnd(); wxPoint v = m_start - m_end;
double chordBefore = sq( v.x ) + sq( v.y );
SetArcGeometry( GetStart(), GetArcMid() + delta/2, aPosition ); if( m_editState == 2 )
m_start = aPosition;
else
m_end = aPosition;
v = m_start - m_end;
double chordAfter = sq( v.x ) + sq( v.y );
double ratio = chordAfter / chordBefore;
if( ratio != 0 )
{
radius = std::max( int( sqrt( sq( radius ) * ratio ) ) + 1,
int( sqrt( chordAfter ) / 2 ) + 1 );
}
} }
break; break;
case 4: case 4:
MoveTo( aPosition ); {
double chordA = GetLineLength( m_start, aPosition );
double chordB = GetLineLength( m_end, aPosition );
radius = int( ( chordA + chordB ) / 2.0 ) + 1;
}
break; break;
case 5: case 5:
SetArcGeometry( GetStart(), aPosition, GetEnd() ); SetArcGeometry( GetStart(), aPosition, GetEnd() );
break; return;
} }
// Calculate center based on start, end, and radius
//
// Let 'l' be the length of the chord and 'm' the middle point of the chord
double l = GetLineLength( m_start, m_end );
wxPoint m = ( m_start + m_end ) / 2;
// Calculate 'd', the vector from the chord midpoint to the center
wxPoint d;
d.x = KiROUND( sqrt( sq( radius ) - sq( l/2 ) ) * ( m_start.y - m_end.y ) / l );
d.y = KiROUND( sqrt( sq( radius ) - sq( l/2 ) ) * ( m_end.x - m_start.x ) / l );
wxPoint c1 = m + d;
wxPoint c2 = m - d;
// Solution gives us 2 centers; we need to pick one:
switch( m_editState )
{
case 1:
{
// Keep center clockwise from chord while drawing
wxPoint chordVector = m_end - m_start;
double chordAngle = ArcTangente( chordVector.y, chordVector.x );
NORMALIZE_ANGLE_POS( chordAngle );
wxPoint c1Test = c1;
RotatePoint( &c1Test, m_start, -chordAngle );
m_arcCenter = c1Test.x > 0 ? c2 : c1;
}
break;
case 2:
case 3:
// Pick the one closer to the old center
m_arcCenter = GetLineLength( c1, m_arcCenter ) < GetLineLength( c2, m_arcCenter ) ? c1 : c2;
break;
case 4:
// Pick the one closer to the mouse position
m_arcCenter = GetLineLength( c1, aPosition ) < GetLineLength( c2, aPosition ) ? c1 : c2;
break;
}
}
break;
case SHAPE_T::POLY:
m_poly.Outline( 0 ).SetPoint( m_poly.Outline( 0 ).GetPointCount() - 1, aPosition );
break; break;
default: default:
wxFAIL_MSG( "LIB_SHAPE::CalcEdit not implemented for " + SHAPE_T_asString() ); UNIMPLEMENTED_FOR( SHAPE_T_asString() );
} }
} }
@ -533,16 +584,22 @@ void LIB_SHAPE::EndEdit()
case SHAPE_T::RECT: case SHAPE_T::RECT:
break; break;
case SHAPE_T::POLYGON: case SHAPE_T::POLY:
{ {
SHAPE_LINE_CHAIN& poly = m_poly.Outline( 0 ); SHAPE_LINE_CHAIN& poly = m_poly.Outline( 0 );
// do not include last point twice
if( poly.GetPointCount() > 2 ) if( poly.GetPointCount() > 2 )
{ {
if( poly.CPoint( poly.GetPointCount() - 2 ) == poly.CLastPoint() ) if( poly.CPoint( poly.GetPointCount() - 2 ) == poly.CLastPoint() )
{
poly.SetClosed( true );
poly.Remove( poly.GetPointCount() - 1 ); poly.Remove( poly.GetPointCount() - 1 );
} }
else
{
poly.SetClosed( false );
}
}
} }
break; break;
@ -554,7 +611,7 @@ void LIB_SHAPE::EndEdit()
void LIB_SHAPE::AddPoint( const wxPoint& aPosition ) void LIB_SHAPE::AddPoint( const wxPoint& aPosition )
{ {
if( GetShape() == SHAPE_T::POLYGON ) if( GetShape() == SHAPE_T::POLY )
{ {
if( m_poly.IsEmpty() ) if( m_poly.IsEmpty() )
m_poly.NewOutline(); m_poly.NewOutline();
@ -568,3 +625,65 @@ void LIB_SHAPE::AddPoint( const wxPoint& aPosition )
} }
double LIB_SHAPE::GetArcAngleStart() const
{
int startAngle, endAngle;
CalcArcAngles( startAngle, endAngle );
if( startAngle > endAngle )
TRANSFORM().MapAngles( &startAngle, &endAngle );
return startAngle;
}
double LIB_SHAPE::GetArcAngleEnd() const
{
int startAngle, endAngle;
CalcArcAngles( startAngle, endAngle );
if( startAngle > endAngle )
TRANSFORM().MapAngles( &startAngle, &endAngle );
return endAngle;
}
void LIB_SHAPE::CalcArcAngles( int& aStartAngle, int& aEndAngle ) const
{
wxPoint centerStartVector = GetStart() - GetCenter();
wxPoint centerEndVector = GetEnd() - GetCenter();
// Angles in Eeschema are still integers
aStartAngle = KiROUND( ArcTangente( centerStartVector.y, centerStartVector.x ) );
aEndAngle = KiROUND( ArcTangente( centerEndVector.y, centerEndVector.x ) );
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( ( aEndAngle - aStartAngle ) > 1800 )
aEndAngle -= 3600;
else if( ( aEndAngle - aStartAngle ) <= -1800 )
aEndAngle += 3600;
while( ( aEndAngle - aStartAngle ) >= 1800 )
{
aEndAngle--;
aStartAngle++;
}
while( ( aStartAngle - aEndAngle ) >= 1800 )
{
aEndAngle++;
aStartAngle--;
}
NORMALIZE_ANGLE_POS( aStartAngle );
if( !IsMoving() )
NORMALIZE_ANGLE_POS( aEndAngle );
}

View File

@ -54,6 +54,19 @@ public:
int GetPenWidth() const override; int GetPenWidth() const override;
int GetEffectivePenWidth( const RENDER_SETTINGS* aSettings ) const override
{
// For historical reasons, a stored value of 0 means "default width" and negative
// numbers meant "don't stroke".
if( GetPenWidth() < 0 && GetFillType() != FILL_T::NO_FILL )
return 0;
else if( GetPenWidth() == 0 )
return aSettings->GetDefaultPenWidth();
else
return std::max( GetPenWidth(), aSettings->GetMinPenWidth() );
}
const EDA_RECT GetBoundingBox() const override; const EDA_RECT GetBoundingBox() const override;
void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override; void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
@ -72,6 +85,12 @@ public:
wxPoint GetPosition() const override { return getPosition(); } wxPoint GetPosition() const override { return getPosition(); }
void SetPosition( const wxPoint& aPosition ) override { setPosition( aPosition ); } void SetPosition( const wxPoint& aPosition ) override { setPosition( aPosition ); }
wxPoint GetCenter() const { return getCenter(); }
double GetArcAngleStart() const override;
double GetArcAngleEnd() const override;
void CalcArcAngles( int& aStartAngle, int& aEndAngle ) const;
void MirrorHorizontal( const wxPoint& aCenter ) override; void MirrorHorizontal( const wxPoint& aCenter ) override;
void MirrorVertical( const wxPoint& aCenter ) override; void MirrorVertical( const wxPoint& aCenter ) override;
void Rotate( const wxPoint& aCenter, bool aRotateCCW = true ) override; void Rotate( const wxPoint& aCenter, bool aRotateCCW = true ) override;

View File

@ -32,9 +32,8 @@
#include <transform.h> #include <transform.h>
#include <symbol_library.h> #include <symbol_library.h>
#include <lib_pin.h> #include <lib_pin.h>
#include <lib_arc.h>
#include <settings/color_settings.h> #include <settings/color_settings.h>
#include <lib_shape.h>
// the separator char between the subpart id and the reference // the separator char between the subpart id and the reference
// 0 (no separator) or '.' or some other character // 0 (no separator) or '.' or some other character
@ -475,7 +474,7 @@ wxString LIB_SYMBOL::SubReference( int aUnit, bool aAddSeparator )
void LIB_SYMBOL::Print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset, void LIB_SYMBOL::Print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset,
int aMulti, int aConvert, const LIB_SYMBOL_OPTIONS& aOpts ) int aUnit, int aConvert, const LIB_SYMBOL_OPTIONS& aOpts )
{ {
/* draw background for filled items using background option /* draw background for filled items using background option
* Solid lines will be drawn after the background * Solid lines will be drawn after the background
@ -483,39 +482,37 @@ void LIB_SYMBOL::Print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset
*/ */
if( !GetGRForceBlackPenState() ) if( !GetGRForceBlackPenState() )
{ {
for( LIB_ITEM& drawItem : m_drawings ) for( LIB_ITEM& item : m_drawings )
{ {
if( drawItem.m_fill != FILL_TYPE::FILLED_WITH_BG_BODYCOLOR ) if( item.Type() == LIB_SHAPE_T )
continue; {
LIB_SHAPE& shape = static_cast<LIB_SHAPE&>( item );
// Do not draw items not attached to the current part // Do not draw items not attached to the current part
if( aMulti && drawItem.m_unit && ( drawItem.m_unit != aMulti ) ) if( aUnit && shape.m_unit && ( shape.m_unit != aUnit ) )
continue; continue;
if( aConvert && drawItem.m_convert && ( drawItem.m_convert != aConvert ) ) if( aConvert && shape.m_convert && ( shape.m_convert != aConvert ) )
continue; continue;
if( drawItem.Type() == LIB_FIELD_T ) if( shape.GetFillType() == FILL_T::FILLED_WITH_BG_BODYCOLOR )
continue; shape.Print( aSettings, aOffset, (void*) false, aOpts.transform );
}
// Now, draw only the background for items with
// m_fill == FILLED_WITH_BG_BODYCOLOR:
drawItem.Print( aSettings, aOffset, (void*) false, aOpts.transform );
} }
} }
for( LIB_ITEM& drawItem : m_drawings ) for( LIB_ITEM& item : m_drawings )
{ {
// Do not draw items not attached to the current part // Do not draw items not attached to the current part
if( aMulti && drawItem.m_unit && ( drawItem.m_unit != aMulti ) ) if( aUnit && item.m_unit && ( item.m_unit != aUnit ) )
continue; continue;
if( aConvert && drawItem.m_convert && ( drawItem.m_convert != aConvert ) ) if( aConvert && item.m_convert && ( item.m_convert != aConvert ) )
continue; continue;
if( drawItem.Type() == LIB_FIELD_T ) if( item.Type() == LIB_FIELD_T )
{ {
LIB_FIELD& field = static_cast<LIB_FIELD&>( drawItem ); LIB_FIELD& field = static_cast<LIB_FIELD&>( item );
if( field.IsVisible() && !aOpts.draw_visible_fields ) if( field.IsVisible() && !aOpts.draw_visible_fields )
continue; continue;
@ -524,18 +521,24 @@ void LIB_SYMBOL::Print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset
continue; continue;
} }
if( drawItem.Type() == LIB_PIN_T ) if( item.Type() == LIB_PIN_T )
{ {
drawItem.Print( aSettings, aOffset, (void*) &aOpts, aOpts.transform ); item.Print( aSettings, aOffset, (void*) &aOpts, aOpts.transform );
} }
else if( drawItem.Type() == LIB_FIELD_T ) else if( item.Type() == LIB_FIELD_T )
{ {
drawItem.Print( aSettings, aOffset, (void*) nullptr, aOpts.transform ); item.Print( aSettings, aOffset, (void*) NULL, aOpts.transform );
}
else if( item.Type() == LIB_SHAPE_T )
{
LIB_SHAPE& shape = static_cast<LIB_SHAPE&>( item );
bool forceNoFill = shape.GetFillType() == FILL_T::FILLED_WITH_BG_BODYCOLOR;
shape.Print( aSettings, aOffset, (void*) forceNoFill, aOpts.transform );
} }
else else
{ {
bool forceNoFill = drawItem.m_fill == FILL_TYPE::FILLED_WITH_BG_BODYCOLOR; item.Print( aSettings, aOffset, (void*) false, aOpts.transform );
drawItem.Print( aSettings, aOffset, (void*) forceNoFill, aOpts.transform );
} }
} }
} }
@ -552,6 +555,26 @@ void LIB_SYMBOL::Plot( PLOTTER* aPlotter, int aUnit, int aConvert, const wxPoint
// draw background for filled items using background option // draw background for filled items using background option
// Solid lines will be drawn after the background // Solid lines will be drawn after the background
for( const LIB_ITEM& item : m_drawings ) for( const LIB_ITEM& item : m_drawings )
{
if( item.Type() == LIB_SHAPE_T )
{
const LIB_SHAPE& shape = static_cast<const LIB_SHAPE&>( item );
// Do not draw items not attached to the current part
if( aUnit && shape.m_unit && ( shape.m_unit != aUnit ) )
continue;
if( aConvert && shape.m_convert && ( shape.m_convert != aConvert ) )
continue;
if( shape.GetFillType() == FILL_T::FILLED_WITH_BG_BODYCOLOR )
shape.Plot( aPlotter, aOffset, fill, aTransform );
}
}
// Not filled items and filled shapes are now plotted
// Items that have BG fills only get re-stroked to ensure the edges are in the foreground
for( const LIB_ITEM& item : m_drawings )
{ {
// Lib Fields are not plotted here, because this plot function // Lib Fields are not plotted here, because this plot function
// is used to plot schematic items, which have they own fields // is used to plot schematic items, which have they own fields
@ -564,25 +587,15 @@ void LIB_SYMBOL::Plot( PLOTTER* aPlotter, int aUnit, int aConvert, const wxPoint
if( aConvert && item.m_convert && ( item.m_convert != aConvert ) ) if( aConvert && item.m_convert && ( item.m_convert != aConvert ) )
continue; continue;
if( item.m_fill == FILL_TYPE::FILLED_WITH_BG_BODYCOLOR ) bool forceNoFill = false;
item.Plot( aPlotter, aOffset, fill, aTransform );
if( item.Type() == LIB_SHAPE_T )
{
const LIB_SHAPE& shape = static_cast<const LIB_SHAPE&>( item );
forceNoFill = shape.GetFillType() == FILL_T::FILLED_WITH_BG_BODYCOLOR;
} }
// Not filled items and filled shapes are now plotted item.Plot( aPlotter, aOffset, fill && !forceNoFill, aTransform );
// Items that have BG fills only get re-stroked to ensure the edges are in the foreground
for( const LIB_ITEM& item : m_drawings )
{
if( item.Type() == LIB_FIELD_T )
continue;
if( aUnit && item.m_unit && ( item.m_unit != aUnit ) )
continue;
if( aConvert && item.m_convert && ( item.m_convert != aConvert ) )
continue;
item.Plot( aPlotter, aOffset,
fill && ( item.m_fill != FILL_TYPE::FILLED_WITH_BG_BODYCOLOR ), aTransform );
} }
} }

View File

@ -44,7 +44,7 @@ class TEST_LIB_SYMBOL_FIXTURE;
typedef std::shared_ptr<LIB_SYMBOL> LIB_SYMBOL_SPTR; ///< shared pointer to LIB_SYMBOL typedef std::shared_ptr<LIB_SYMBOL> LIB_SYMBOL_SPTR; ///< shared pointer to LIB_SYMBOL
typedef std::weak_ptr<LIB_SYMBOL> LIB_SYMBOL_REF; ///< weak pointer to LIB_SYMBOL typedef std::weak_ptr<LIB_SYMBOL> LIB_SYMBOL_REF; ///< weak pointer to LIB_SYMBOL
typedef MULTIVECTOR<LIB_ITEM, LIB_ARC_T, LIB_FIELD_T> LIB_ITEMS_CONTAINER; typedef MULTIVECTOR<LIB_ITEM, LIB_SHAPE_T, LIB_FIELD_T> LIB_ITEMS_CONTAINER;
typedef LIB_ITEMS_CONTAINER::ITEM_PTR_VECTOR LIB_ITEMS; typedef LIB_ITEMS_CONTAINER::ITEM_PTR_VECTOR LIB_ITEMS;

View File

@ -99,9 +99,6 @@ public:
void Plot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, void Plot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
const TRANSFORM& aTransform ) const override; const TRANSFORM& aTransform ) const override;
int GetWidth() const override { return GetTextThickness(); }
void SetWidth( int aWidth ) override { SetTextThickness( aWidth ); }
wxString GetSelectMenuText( EDA_UNITS aUnits ) const override; wxString GetSelectMenuText( EDA_UNITS aUnits ) const override;
void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override; void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;

View File

@ -235,7 +235,7 @@ void SCH_JUNCTION::Plot( PLOTTER* aPlotter ) const
aPlotter->SetColor( color ); aPlotter->SetColor( color );
aPlotter->Circle( m_pos, GetEffectiveDiameter(), FILL_TYPE::FILLED_SHAPE ); aPlotter->Circle( m_pos, GetEffectiveDiameter(), FILL_T::FILLED_SHAPE );
} }

View File

@ -34,14 +34,10 @@
#include <geometry/geometry_utils.h> #include <geometry/geometry_utils.h>
#include <geometry/shape_line_chain.h> #include <geometry/shape_line_chain.h>
#include <gr_text.h> #include <gr_text.h>
#include <lib_arc.h> #include <lib_shape.h>
#include <lib_bezier.h>
#include <lib_circle.h>
#include <lib_field.h> #include <lib_field.h>
#include <lib_item.h> #include <lib_item.h>
#include <lib_pin.h> #include <lib_pin.h>
#include <lib_polyline.h>
#include <lib_rectangle.h>
#include <lib_text.h> #include <lib_text.h>
#include <math/util.h> #include <math/util.h>
#include <plotters/plotter.h> #include <plotters/plotter.h>
@ -142,10 +138,10 @@ static LIB_SYMBOL* dummy()
{ {
symbol = new LIB_SYMBOL( wxEmptyString ); symbol = new LIB_SYMBOL( wxEmptyString );
LIB_RECTANGLE* square = new LIB_RECTANGLE( symbol ); LIB_SHAPE* square = new LIB_SHAPE( symbol, SHAPE_T::RECT );
square->MoveTo( wxPoint( Mils2iu( -200 ), Mils2iu( 200 ) ) ); square->MoveTo( wxPoint( Mils2iu( -200 ), Mils2iu( 200 ) ) );
square->SetEndPosition( wxPoint( Mils2iu( 200 ), Mils2iu( -200 ) ) ); square->SetEnd( wxPoint( Mils2iu( 200 ), Mils2iu( -200 ) ) );
LIB_TEXT* text = new LIB_TEXT( symbol ); LIB_TEXT* text = new LIB_TEXT( symbol );
@ -215,14 +211,10 @@ bool SCH_PAINTER::Draw( const VIEW_ITEM *aItem, int aLayer )
switch( item->Type() ) switch( item->Type() )
{ {
HANDLE_ITEM( LIB_SYMBOL_T, LIB_SYMBOL ); HANDLE_ITEM( LIB_SYMBOL_T, LIB_SYMBOL );
HANDLE_ITEM( LIB_RECTANGLE_T, LIB_RECTANGLE ); HANDLE_ITEM( LIB_SHAPE_T, LIB_SHAPE );
HANDLE_ITEM( LIB_POLYLINE_T, LIB_POLYLINE );
HANDLE_ITEM( LIB_CIRCLE_T, LIB_CIRCLE );
HANDLE_ITEM( LIB_PIN_T, LIB_PIN ); HANDLE_ITEM( LIB_PIN_T, LIB_PIN );
HANDLE_ITEM( LIB_ARC_T, LIB_ARC );
HANDLE_ITEM( LIB_FIELD_T, LIB_FIELD ); HANDLE_ITEM( LIB_FIELD_T, LIB_FIELD );
HANDLE_ITEM( LIB_TEXT_T, LIB_TEXT ); HANDLE_ITEM( LIB_TEXT_T, LIB_TEXT );
HANDLE_ITEM( LIB_BEZIER_T, LIB_BEZIER );
HANDLE_ITEM( SCH_SYMBOL_T, SCH_SYMBOL ); HANDLE_ITEM( SCH_SYMBOL_T, SCH_SYMBOL );
HANDLE_ITEM( SCH_JUNCTION_T, SCH_JUNCTION ); HANDLE_ITEM( SCH_JUNCTION_T, SCH_JUNCTION );
HANDLE_ITEM( SCH_LINE_T, SCH_LINE ); HANDLE_ITEM( SCH_LINE_T, SCH_LINE );
@ -488,6 +480,8 @@ void SCH_PAINTER::draw( const LIB_SYMBOL *aSymbol, int aLayer, bool aDrawFields,
bool SCH_PAINTER::setDeviceColors( const LIB_ITEM* aItem, int aLayer ) bool SCH_PAINTER::setDeviceColors( const LIB_ITEM* aItem, int aLayer )
{ {
const EDA_SHAPE* shape = dynamic_cast<const EDA_SHAPE*>( aItem );
switch( aLayer ) switch( aLayer )
{ {
case LAYER_SELECTION_SHADOWS: case LAYER_SELECTION_SHADOWS:
@ -504,11 +498,11 @@ bool SCH_PAINTER::setDeviceColors( const LIB_ITEM* aItem, int aLayer )
return false; return false;
case LAYER_DEVICE_BACKGROUND: case LAYER_DEVICE_BACKGROUND:
if( aItem->GetFillMode() == FILL_TYPE::FILLED_WITH_BG_BODYCOLOR ) if( shape && shape->GetFillType() == FILL_T::FILLED_WITH_BG_BODYCOLOR )
{ {
COLOR4D fillColor = getRenderColor( aItem, LAYER_DEVICE_BACKGROUND, false ); COLOR4D fillColor = getRenderColor( aItem, LAYER_DEVICE_BACKGROUND, false );
m_gal->SetIsFill( aItem->GetFillMode() == FILL_TYPE::FILLED_WITH_BG_BODYCOLOR ); m_gal->SetIsFill( shape->GetFillType() == FILL_T::FILLED_WITH_BG_BODYCOLOR );
m_gal->SetFillColor( fillColor ); m_gal->SetFillColor( fillColor );
m_gal->SetIsStroke( false ); m_gal->SetIsStroke( false );
return true; return true;
@ -517,10 +511,10 @@ bool SCH_PAINTER::setDeviceColors( const LIB_ITEM* aItem, int aLayer )
return false; return false;
case LAYER_DEVICE: case LAYER_DEVICE:
m_gal->SetIsFill( aItem->GetFillMode() == FILL_TYPE::FILLED_SHAPE ); m_gal->SetIsFill( shape && shape->GetFillType() == FILL_T::FILLED_SHAPE );
m_gal->SetFillColor( getRenderColor( aItem, LAYER_DEVICE, false ) ); m_gal->SetFillColor( getRenderColor( aItem, LAYER_DEVICE, false ) );
if( aItem->GetPenWidth() >= 0 || aItem->GetFillMode() == FILL_TYPE::NO_FILL ) if( aItem->GetPenWidth() >= 0 || !shape || !shape->IsFilled() )
{ {
m_gal->SetIsStroke( true ); m_gal->SetIsStroke( true );
m_gal->SetLineWidth( getLineWidth( aItem, false ) ); m_gal->SetLineWidth( getLineWidth( aItem, false ) );
@ -546,66 +540,66 @@ void SCH_PAINTER::fillIfSelection( int aLayer )
} }
void SCH_PAINTER::draw( const LIB_RECTANGLE *aRect, int aLayer ) void SCH_PAINTER::draw( const LIB_SHAPE *aShape, int aLayer )
{ {
if( !isUnitAndConversionShown( aRect ) ) if( !isUnitAndConversionShown( aShape ) )
return; return;
if( setDeviceColors( aRect, aLayer ) ) if( setDeviceColors( aShape, aLayer ) )
{ {
fillIfSelection( aLayer ); fillIfSelection( aLayer );
m_gal->DrawRectangle( mapCoords( aRect->GetPosition() ), mapCoords( aRect->GetEnd() ) );
}
}
switch( aShape->GetShape() )
void SCH_PAINTER::draw( const LIB_CIRCLE *aCircle, int aLayer )
{ {
if( !isUnitAndConversionShown( aCircle ) ) case SHAPE_T::ARC:
return;
if( setDeviceColors( aCircle, aLayer ) )
{
fillIfSelection( aLayer );
m_gal->DrawCircle( mapCoords( aCircle->GetPosition() ), aCircle->GetRadius() );
}
}
void SCH_PAINTER::draw( const LIB_ARC *aArc, int aLayer )
{
if( !isUnitAndConversionShown( aArc ) )
return;
if( setDeviceColors( aArc, aLayer ) )
{ {
int startAngle; int startAngle;
int endAngle; int endAngle;
aArc->CalcAngles( startAngle, endAngle ); aShape->CalcArcAngles( startAngle, endAngle );
TRANSFORM().MapAngles( &startAngle, &endAngle ); TRANSFORM().MapAngles( &startAngle, &endAngle );
m_gal->DrawArc( mapCoords( aArc->GetCenter() ), aArc->GetRadius(), m_gal->DrawArc( mapCoords( aShape->GetCenter() ), aShape->GetRadius(),
DECIDEG2RAD( startAngle ), DECIDEG2RAD( endAngle ) ); DECIDEG2RAD( startAngle ), DECIDEG2RAD( endAngle ) );
} }
} break;
case SHAPE_T::CIRCLE:
m_gal->DrawCircle( mapCoords( aShape->GetPosition() ), aShape->GetRadius() );
break;
void SCH_PAINTER::draw( const LIB_POLYLINE *aLine, int aLayer ) case SHAPE_T::RECT:
m_gal->DrawRectangle( mapCoords( aShape->GetPosition() ),
mapCoords( aShape->GetEnd() ) );
break;
case SHAPE_T::POLY:
{ {
if( !isUnitAndConversionShown( aLine ) ) const SHAPE_LINE_CHAIN poly = aShape->GetPolyShape().Outline( 0 );
return; std::deque<VECTOR2D> mappedPts;
if( setDeviceColors( aLine, aLayer ) ) for( const VECTOR2I& pt : poly.CPoints() )
{ mappedPts.push_back( mapCoords( (wxPoint) pt ) );
const std::vector<wxPoint>& pts = aLine->GetPolyPoints();
std::deque<VECTOR2D> vtx;
for( auto p : pts )
vtx.push_back( mapCoords( p ) );
fillIfSelection( aLayer ); fillIfSelection( aLayer );
m_gal->DrawPolygon( vtx ); m_gal->DrawPolygon( mappedPts );
}
break;
case SHAPE_T::BEZIER:
{
std::deque<VECTOR2D> mappedPts;
for( const VECTOR2I &p : aShape->GetPolyShape().Outline( 0 ).CPoints() )
mappedPts.push_back( mapCoords( (wxPoint) p ) );
m_gal->DrawPolygon( mappedPts );
}
break;
default:
wxFAIL_MSG( "SCH_PAINTER::draw not implemented for " + aShape->SHAPE_T_asString() );
}
} }
} }
@ -1195,26 +1189,6 @@ void SCH_PAINTER::draw( LIB_PIN *aPin, int aLayer )
} }
void SCH_PAINTER::draw( const LIB_BEZIER *aCurve, int aLayer )
{
if( !isUnitAndConversionShown( aCurve ) )
return;
if( setDeviceColors( aCurve, aLayer ) )
{
BEZIER_POLY poly ( aCurve->GetPoints() );
std::vector<wxPoint> pts;
std::deque<VECTOR2D> pts_xformed;
poly.GetPoly( pts );
for( const wxPoint &p : pts )
pts_xformed.push_back( mapCoords( p ) );
m_gal->DrawPolygon( pts_xformed );
}
}
// Draw the target (an open square) for a wire or label which has no connection or is // Draw the target (an open square) for a wire or label which has no connection or is
// being moved. // being moved.
void SCH_PAINTER::drawDanglingSymbol( const wxPoint& aPos, int aWidth, bool aDrawingShadows ) void SCH_PAINTER::drawDanglingSymbol( const wxPoint& aPos, int aWidth, bool aDrawingShadows )

View File

@ -32,16 +32,12 @@
#include <painter.h> #include <painter.h>
class LIB_RECTANGLE;
class LIB_PIN; class LIB_PIN;
class LIB_CIRCLE; class LIB_SHAPE;
class LIB_ITEM; class LIB_ITEM;
class LIB_SYMBOL; class LIB_SYMBOL;
class LIB_POLYLINE;
class LIB_ARC;
class LIB_FIELD; class LIB_FIELD;
class LIB_TEXT; class LIB_TEXT;
class LIB_BEZIER;
class SCH_SYMBOL; class SCH_SYMBOL;
class SCH_FIELD; class SCH_FIELD;
class SCH_JUNCTION; class SCH_JUNCTION;
@ -153,16 +149,12 @@ public:
} }
private: private:
void draw( const LIB_RECTANGLE* aRect, int aLayer );
void draw( LIB_PIN* aPin, int aLayer ); void draw( LIB_PIN* aPin, int aLayer );
void draw( const LIB_CIRCLE* aCircle, int aLayer ); void draw( const LIB_SHAPE* aCircle, int aLayer );
void draw( const LIB_SYMBOL* aSymbol, int, bool aDrawFields = true, int aUnit = 0, void draw( const LIB_SYMBOL* aSymbol, int, bool aDrawFields = true, int aUnit = 0,
int aConvert = 0 ); int aConvert = 0 );
void draw( const LIB_ARC* aArc, int aLayer );
void draw( const LIB_POLYLINE* aLine, int aLayer );
void draw( const LIB_FIELD* aField, int aLayer ); void draw( const LIB_FIELD* aField, int aLayer );
void draw( const LIB_TEXT* aText, int aLayer ); void draw( const LIB_TEXT* aText, int aLayer );
void draw( const LIB_BEZIER* aCurve, int aLayer );
void draw( SCH_SYMBOL* aSymbol, int aLayer ); void draw( SCH_SYMBOL* aSymbol, int aLayer );
void draw( const SCH_JUNCTION* aJct, int aLayer ); void draw( const SCH_JUNCTION* aJct, int aLayer );
void draw( const SCH_FIELD* aField, int aLayer ); void draw( const SCH_FIELD* aField, int aLayer );

View File

@ -31,14 +31,10 @@
#include <schematic.h> #include <schematic.h>
#include <lib_arc.h> #include <lib_shape.h>
#include <lib_bezier.h>
#include <lib_circle.h>
#include <lib_id.h> #include <lib_id.h>
#include <lib_item.h> #include <lib_item.h>
#include <lib_pin.h> #include <lib_pin.h>
#include <lib_polyline.h>
#include <lib_rectangle.h>
#include <lib_text.h> #include <lib_text.h>
#include <sch_bitmap.h> #include <sch_bitmap.h>
@ -1050,7 +1046,7 @@ void SCH_ALTIUM_PLUGIN::ParseBezier( const std::map<wxString, wxString>& aProper
if( i + 2 == elem.points.size() ) if( i + 2 == elem.points.size() )
{ {
// special case: single line // special case: single line
LIB_POLYLINE* line = new LIB_POLYLINE( libSymbolIt->second ); LIB_SHAPE* line = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::POLY );
libSymbolIt->second->AddDrawItem( line ); libSymbolIt->second->AddDrawItem( line );
line->SetUnit( elem.ownerpartid ); line->SetUnit( elem.ownerpartid );
@ -1069,7 +1065,7 @@ void SCH_ALTIUM_PLUGIN::ParseBezier( const std::map<wxString, wxString>& aProper
// I haven't a clue what this is all about, but the sample document we have in // I haven't a clue what this is all about, but the sample document we have in
// https://gitlab.com/kicad/code/kicad/-/issues/8974 responds best by treating it // https://gitlab.com/kicad/code/kicad/-/issues/8974 responds best by treating it
// as another single line special case. // as another single line special case.
LIB_POLYLINE* line = new LIB_POLYLINE( libSymbolIt->second ); LIB_SHAPE* line = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::POLY );
libSymbolIt->second->AddDrawItem( line ); libSymbolIt->second->AddDrawItem( line );
line->SetUnit( elem.ownerpartid ); line->SetUnit( elem.ownerpartid );
@ -1084,8 +1080,8 @@ void SCH_ALTIUM_PLUGIN::ParseBezier( const std::map<wxString, wxString>& aProper
} }
else else
{ {
// Bezier must have exactly 4 control points // Bezier always has exactly 4 control points
LIB_BEZIER* bezier = new LIB_BEZIER( libSymbolIt->second ); LIB_SHAPE* bezier = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::BEZIER );
libSymbolIt->second->AddDrawItem( bezier ); libSymbolIt->second->AddDrawItem( bezier );
bezier->SetUnit( elem.ownerpartid ); bezier->SetUnit( elem.ownerpartid );
@ -1149,7 +1145,7 @@ void SCH_ALTIUM_PLUGIN::ParsePolyline( const std::map<wxString, wxString>& aProp
return; return;
SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first ); SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
LIB_POLYLINE* line = new LIB_POLYLINE( libSymbolIt->second ); LIB_SHAPE* line = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::POLY );
libSymbolIt->second->AddDrawItem( line ); libSymbolIt->second->AddDrawItem( line );
line->SetUnit( elem.ownerpartid ); line->SetUnit( elem.ownerpartid );
@ -1208,7 +1204,7 @@ void SCH_ALTIUM_PLUGIN::ParsePolygon( const std::map<wxString, wxString>& aPrope
return; return;
SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first ); SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
LIB_POLYLINE* line = new LIB_POLYLINE( libSymbolIt->second ); LIB_SHAPE* line = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::POLY );
libSymbolIt->second->AddDrawItem( line ); libSymbolIt->second->AddDrawItem( line );
line->SetUnit( elem.ownerpartid ); line->SetUnit( elem.ownerpartid );
@ -1221,11 +1217,11 @@ void SCH_ALTIUM_PLUGIN::ParsePolygon( const std::map<wxString, wxString>& aPrope
line->SetWidth( elem.lineWidth ); line->SetWidth( elem.lineWidth );
if( !elem.isSolid ) if( !elem.isSolid )
line->SetFillMode( FILL_TYPE::NO_FILL ); line->SetFillMode( FILL_T::NO_FILL );
else if( elem.color == elem.areacolor ) else if( elem.color == elem.areacolor )
line->SetFillMode( FILL_TYPE::FILLED_SHAPE ); line->SetFillMode( FILL_T::FILLED_SHAPE );
else else
line->SetFillMode( FILL_TYPE::FILLED_WITH_BG_BODYCOLOR ); line->SetFillMode( FILL_T::FILLED_WITH_BG_BODYCOLOR );
} }
} }
@ -1289,9 +1285,8 @@ void SCH_ALTIUM_PLUGIN::ParseRoundRectangle( const std::map<wxString, wxString>&
return; return;
SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first ); SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
// TODO: misses rounded edges // TODO: misses rounded edges
LIB_RECTANGLE* rect = new LIB_RECTANGLE( libSymbolIt->second ); LIB_SHAPE* rect = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::RECT );
libSymbolIt->second->AddDrawItem( rect ); libSymbolIt->second->AddDrawItem( rect );
rect->SetUnit( elem.ownerpartid ); rect->SetUnit( elem.ownerpartid );
@ -1301,11 +1296,11 @@ void SCH_ALTIUM_PLUGIN::ParseRoundRectangle( const std::map<wxString, wxString>&
rect->SetWidth( elem.lineWidth ); rect->SetWidth( elem.lineWidth );
if( !elem.isSolid ) if( !elem.isSolid )
rect->SetFillMode( FILL_TYPE::NO_FILL ); rect->SetFillMode( FILL_T::NO_FILL );
else if( elem.color == elem.areacolor ) else if( elem.color == elem.areacolor )
rect->SetFillMode( FILL_TYPE::FILLED_SHAPE ); rect->SetFillMode( FILL_T::FILLED_SHAPE );
else else
rect->SetFillMode( FILL_TYPE::FILLED_WITH_BG_BODYCOLOR ); rect->SetFillMode( FILL_T::FILLED_WITH_BG_BODYCOLOR );
} }
} }
@ -1339,18 +1334,18 @@ void SCH_ALTIUM_PLUGIN::ParseArc( const std::map<wxString, wxString>& aPropertie
if( elem.startAngle == 0 && ( elem.endAngle == 0 || elem.endAngle == 360 ) ) if( elem.startAngle == 0 && ( elem.endAngle == 0 || elem.endAngle == 360 ) )
{ {
LIB_CIRCLE* circle = new LIB_CIRCLE( libSymbolIt->second ); LIB_SHAPE* circle = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::CIRCLE );
libSymbolIt->second->AddDrawItem( circle ); libSymbolIt->second->AddDrawItem( circle );
circle->SetUnit( elem.ownerpartid ); circle->SetUnit( elem.ownerpartid );
circle->SetPosition( GetRelativePosition( elem.center + m_sheetOffset, symbol ) ); circle->SetPosition( GetRelativePosition( elem.center + m_sheetOffset, symbol ) );
circle->SetRadius( elem.radius ); circle->SetEnd( circle->GetPosition() + wxPoint( elem.radius, 0 ) );
circle->SetWidth( elem.lineWidth ); circle->SetWidth( elem.lineWidth );
} }
else else
{ {
LIB_ARC* arc = new LIB_ARC( libSymbolIt->second ); LIB_SHAPE* arc = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::ARC );
libSymbolIt->second->AddDrawItem( arc ); libSymbolIt->second->AddDrawItem( arc );
arc->SetUnit( elem.ownerpartid ); arc->SetUnit( elem.ownerpartid );
@ -1404,7 +1399,7 @@ void SCH_ALTIUM_PLUGIN::ParseLine( const std::map<wxString, wxString>& aProperti
return; return;
SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first ); SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
LIB_POLYLINE* line = new LIB_POLYLINE( libSymbolIt->second ); LIB_SHAPE* line = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::POLY );
libSymbolIt->second->AddDrawItem( line ); libSymbolIt->second->AddDrawItem( line );
line->SetUnit( elem.ownerpartid ); line->SetUnit( elem.ownerpartid );
@ -1475,7 +1470,7 @@ void SCH_ALTIUM_PLUGIN::ParseRectangle( const std::map<wxString, wxString>& aPro
return; return;
SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first ); SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
LIB_RECTANGLE* rect = new LIB_RECTANGLE( libSymbolIt->second ); LIB_SHAPE* rect = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::RECT );
libSymbolIt->second->AddDrawItem( rect ); libSymbolIt->second->AddDrawItem( rect );
rect->SetUnit( elem.ownerpartid ); rect->SetUnit( elem.ownerpartid );
@ -1485,11 +1480,11 @@ void SCH_ALTIUM_PLUGIN::ParseRectangle( const std::map<wxString, wxString>& aPro
rect->SetWidth( elem.lineWidth ); rect->SetWidth( elem.lineWidth );
if( !elem.isSolid ) if( !elem.isSolid )
rect->SetFillMode( FILL_TYPE::NO_FILL ); rect->SetFillMode( FILL_T::NO_FILL );
else if( elem.color == elem.areacolor ) else if( elem.color == elem.areacolor )
rect->SetFillMode( FILL_TYPE::FILLED_SHAPE ); rect->SetFillMode( FILL_T::FILLED_SHAPE );
else else
rect->SetFillMode( FILL_TYPE::FILLED_WITH_BG_BODYCOLOR ); rect->SetFillMode( FILL_T::FILLED_WITH_BG_BODYCOLOR );
} }
} }
@ -1599,7 +1594,7 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S
{ {
if( aStyle == ASCH_POWER_PORT_STYLE::CIRCLE || aStyle == ASCH_POWER_PORT_STYLE::ARROW ) if( aStyle == ASCH_POWER_PORT_STYLE::CIRCLE || aStyle == ASCH_POWER_PORT_STYLE::ARROW )
{ {
LIB_POLYLINE* line1 = new LIB_POLYLINE( aKsymbol ); LIB_SHAPE* line1 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
aKsymbol->AddDrawItem( line1 ); aKsymbol->AddDrawItem( line1 );
line1->SetWidth( Mils2iu( 10 ) ); line1->SetWidth( Mils2iu( 10 ) );
line1->AddPoint( { 0, 0 } ); line1->AddPoint( { 0, 0 } );
@ -1607,15 +1602,15 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S
if( aStyle == ASCH_POWER_PORT_STYLE::CIRCLE ) if( aStyle == ASCH_POWER_PORT_STYLE::CIRCLE )
{ {
LIB_CIRCLE* circle = new LIB_CIRCLE( aKsymbol ); LIB_SHAPE* circle = new LIB_SHAPE( aKsymbol, SHAPE_T::CIRCLE );
aKsymbol->AddDrawItem( circle ); aKsymbol->AddDrawItem( circle );
circle->SetWidth( Mils2iu( 5 ) ); circle->SetWidth( Mils2iu( 5 ) );
circle->SetRadius( Mils2iu( 25 ) );
circle->SetPosition( { Mils2iu( 0 ), Mils2iu( -75 ) } ); circle->SetPosition( { Mils2iu( 0 ), Mils2iu( -75 ) } );
circle->SetEnd( circle->GetPosition() + wxPoint( Mils2iu( 25 ), 0 ) );
} }
else else
{ {
LIB_POLYLINE* line2 = new LIB_POLYLINE( aKsymbol ); LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
aKsymbol->AddDrawItem( line2 ); aKsymbol->AddDrawItem( line2 );
line2->SetWidth( Mils2iu( 10 ) ); line2->SetWidth( Mils2iu( 10 ) );
line2->AddPoint( { Mils2iu( -25 ), Mils2iu( -50 ) } ); line2->AddPoint( { Mils2iu( -25 ), Mils2iu( -50 ) } );
@ -1628,13 +1623,13 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S
} }
else if( aStyle == ASCH_POWER_PORT_STYLE::WAVE ) else if( aStyle == ASCH_POWER_PORT_STYLE::WAVE )
{ {
LIB_POLYLINE* line = new LIB_POLYLINE( aKsymbol ); LIB_SHAPE* line = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
aKsymbol->AddDrawItem( line ); aKsymbol->AddDrawItem( line );
line->SetWidth( Mils2iu( 10 ) ); line->SetWidth( Mils2iu( 10 ) );
line->AddPoint( { 0, 0 } ); line->AddPoint( { 0, 0 } );
line->AddPoint( { 0, Mils2iu( -72 ) } ); line->AddPoint( { 0, Mils2iu( -72 ) } );
LIB_BEZIER* bezier = new LIB_BEZIER( aKsymbol ); LIB_SHAPE* bezier = new LIB_SHAPE( aKsymbol, SHAPE_T::BEZIER );
aKsymbol->AddDrawItem( bezier ); aKsymbol->AddDrawItem( bezier );
bezier->SetWidth( Mils2iu( 5 ) ); bezier->SetWidth( Mils2iu( 5 ) );
bezier->AddPoint( { Mils2iu( 30 ), Mils2iu( -50 ) } ); bezier->AddPoint( { Mils2iu( 30 ), Mils2iu( -50 ) } );
@ -1649,7 +1644,7 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S
|| aStyle == ASCH_POWER_PORT_STYLE::EARTH || aStyle == ASCH_POWER_PORT_STYLE::EARTH
|| aStyle == ASCH_POWER_PORT_STYLE::GOST_ARROW ) || aStyle == ASCH_POWER_PORT_STYLE::GOST_ARROW )
{ {
LIB_POLYLINE* line1 = new LIB_POLYLINE( aKsymbol ); LIB_SHAPE* line1 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
aKsymbol->AddDrawItem( line1 ); aKsymbol->AddDrawItem( line1 );
line1->SetWidth( Mils2iu( 10 ) ); line1->SetWidth( Mils2iu( 10 ) );
line1->AddPoint( { 0, 0 } ); line1->AddPoint( { 0, 0 } );
@ -1657,25 +1652,25 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S
if( aStyle == ASCH_POWER_PORT_STYLE::POWER_GROUND ) if( aStyle == ASCH_POWER_PORT_STYLE::POWER_GROUND )
{ {
LIB_POLYLINE* line2 = new LIB_POLYLINE( aKsymbol ); LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
aKsymbol->AddDrawItem( line2 ); aKsymbol->AddDrawItem( line2 );
line2->SetWidth( Mils2iu( 10 ) ); line2->SetWidth( Mils2iu( 10 ) );
line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -100 ) } ); line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -100 ) } );
line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -100 ) } ); line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -100 ) } );
LIB_POLYLINE* line3 = new LIB_POLYLINE( aKsymbol ); LIB_SHAPE* line3 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
aKsymbol->AddDrawItem( line3 ); aKsymbol->AddDrawItem( line3 );
line3->SetWidth( Mils2iu( 10 ) ); line3->SetWidth( Mils2iu( 10 ) );
line3->AddPoint( { Mils2iu( -70 ), Mils2iu( -130 ) } ); line3->AddPoint( { Mils2iu( -70 ), Mils2iu( -130 ) } );
line3->AddPoint( { Mils2iu( 70 ), Mils2iu( -130 ) } ); line3->AddPoint( { Mils2iu( 70 ), Mils2iu( -130 ) } );
LIB_POLYLINE* line4 = new LIB_POLYLINE( aKsymbol ); LIB_SHAPE* line4 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
aKsymbol->AddDrawItem( line4 ); aKsymbol->AddDrawItem( line4 );
line4->SetWidth( Mils2iu( 10 ) ); line4->SetWidth( Mils2iu( 10 ) );
line4->AddPoint( { Mils2iu( -40 ), Mils2iu( -160 ) } ); line4->AddPoint( { Mils2iu( -40 ), Mils2iu( -160 ) } );
line4->AddPoint( { Mils2iu( 40 ), Mils2iu( -160 ) } ); line4->AddPoint( { Mils2iu( 40 ), Mils2iu( -160 ) } );
LIB_POLYLINE* line5 = new LIB_POLYLINE( aKsymbol ); LIB_SHAPE* line5 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
aKsymbol->AddDrawItem( line5 ); aKsymbol->AddDrawItem( line5 );
line5->SetWidth( Mils2iu( 10 ) ); line5->SetWidth( Mils2iu( 10 ) );
line5->AddPoint( { Mils2iu( -10 ), Mils2iu( -190 ) } ); line5->AddPoint( { Mils2iu( -10 ), Mils2iu( -190 ) } );
@ -1683,7 +1678,7 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S
} }
else if( aStyle == ASCH_POWER_PORT_STYLE::SIGNAL_GROUND ) else if( aStyle == ASCH_POWER_PORT_STYLE::SIGNAL_GROUND )
{ {
LIB_POLYLINE* line2 = new LIB_POLYLINE( aKsymbol ); LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
aKsymbol->AddDrawItem( line2 ); aKsymbol->AddDrawItem( line2 );
line2->SetWidth( Mils2iu( 10 ) ); line2->SetWidth( Mils2iu( 10 ) );
line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -100 ) } ); line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -100 ) } );
@ -1693,7 +1688,7 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S
} }
else if( aStyle == ASCH_POWER_PORT_STYLE::EARTH ) else if( aStyle == ASCH_POWER_PORT_STYLE::EARTH )
{ {
LIB_POLYLINE* line2 = new LIB_POLYLINE( aKsymbol ); LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
aKsymbol->AddDrawItem( line2 ); aKsymbol->AddDrawItem( line2 );
line2->SetWidth( Mils2iu( 10 ) ); line2->SetWidth( Mils2iu( 10 ) );
line2->AddPoint( { Mils2iu( -150 ), Mils2iu( -200 ) } ); line2->AddPoint( { Mils2iu( -150 ), Mils2iu( -200 ) } );
@ -1701,7 +1696,7 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S
line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -100 ) } ); line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -100 ) } );
line2->AddPoint( { Mils2iu( 50 ), Mils2iu( -200 ) } ); line2->AddPoint( { Mils2iu( 50 ), Mils2iu( -200 ) } );
LIB_POLYLINE* line3 = new LIB_POLYLINE( aKsymbol ); LIB_SHAPE* line3 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
aKsymbol->AddDrawItem( line3 ); aKsymbol->AddDrawItem( line3 );
line3->SetWidth( Mils2iu( 10 ) ); line3->SetWidth( Mils2iu( 10 ) );
line3->AddPoint( { Mils2iu( 0 ), Mils2iu( -100 ) } ); line3->AddPoint( { Mils2iu( 0 ), Mils2iu( -100 ) } );
@ -1709,7 +1704,7 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S
} }
else // ASCH_POWER_PORT_STYLE::GOST_ARROW else // ASCH_POWER_PORT_STYLE::GOST_ARROW
{ {
LIB_POLYLINE* line2 = new LIB_POLYLINE( aKsymbol ); LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
aKsymbol->AddDrawItem( line2 ); aKsymbol->AddDrawItem( line2 );
line2->SetWidth( Mils2iu( 10 ) ); line2->SetWidth( Mils2iu( 10 ) );
line2->AddPoint( { Mils2iu( -25 ), Mils2iu( -50 ) } ); line2->AddPoint( { Mils2iu( -25 ), Mils2iu( -50 ) } );
@ -1724,25 +1719,25 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S
else if( aStyle == ASCH_POWER_PORT_STYLE::GOST_POWER_GROUND else if( aStyle == ASCH_POWER_PORT_STYLE::GOST_POWER_GROUND
|| aStyle == ASCH_POWER_PORT_STYLE::GOST_EARTH ) || aStyle == ASCH_POWER_PORT_STYLE::GOST_EARTH )
{ {
LIB_POLYLINE* line1 = new LIB_POLYLINE( aKsymbol ); LIB_SHAPE* line1 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
aKsymbol->AddDrawItem( line1 ); aKsymbol->AddDrawItem( line1 );
line1->SetWidth( Mils2iu( 10 ) ); line1->SetWidth( Mils2iu( 10 ) );
line1->AddPoint( { 0, 0 } ); line1->AddPoint( { 0, 0 } );
line1->AddPoint( { 0, Mils2iu( -160 ) } ); line1->AddPoint( { 0, Mils2iu( -160 ) } );
LIB_POLYLINE* line2 = new LIB_POLYLINE( aKsymbol ); LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
aKsymbol->AddDrawItem( line2 ); aKsymbol->AddDrawItem( line2 );
line2->SetWidth( Mils2iu( 10 ) ); line2->SetWidth( Mils2iu( 10 ) );
line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -160 ) } ); line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -160 ) } );
line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -160 ) } ); line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -160 ) } );
LIB_POLYLINE* line3 = new LIB_POLYLINE( aKsymbol ); LIB_SHAPE* line3 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
aKsymbol->AddDrawItem( line3 ); aKsymbol->AddDrawItem( line3 );
line3->SetWidth( Mils2iu( 10 ) ); line3->SetWidth( Mils2iu( 10 ) );
line3->AddPoint( { Mils2iu( -60 ), Mils2iu( -200 ) } ); line3->AddPoint( { Mils2iu( -60 ), Mils2iu( -200 ) } );
line3->AddPoint( { Mils2iu( 60 ), Mils2iu( -200 ) } ); line3->AddPoint( { Mils2iu( 60 ), Mils2iu( -200 ) } );
LIB_POLYLINE* line4 = new LIB_POLYLINE( aKsymbol ); LIB_SHAPE* line4 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
aKsymbol->AddDrawItem( line4 ); aKsymbol->AddDrawItem( line4 );
line4->SetWidth( Mils2iu( 10 ) ); line4->SetWidth( Mils2iu( 10 ) );
line4->AddPoint( { Mils2iu( -20 ), Mils2iu( -240 ) } ); line4->AddPoint( { Mils2iu( -20 ), Mils2iu( -240 ) } );
@ -1751,23 +1746,23 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S
if( aStyle == ASCH_POWER_PORT_STYLE::GOST_POWER_GROUND ) if( aStyle == ASCH_POWER_PORT_STYLE::GOST_POWER_GROUND )
return { 0, Mils2iu( 300 ) }; return { 0, Mils2iu( 300 ) };
LIB_CIRCLE* circle = new LIB_CIRCLE( aKsymbol ); LIB_SHAPE* circle = new LIB_SHAPE( aKsymbol, SHAPE_T::CIRCLE );
aKsymbol->AddDrawItem( circle ); aKsymbol->AddDrawItem( circle );
circle->SetWidth( Mils2iu( 10 ) ); circle->SetWidth( Mils2iu( 10 ) );
circle->SetRadius( Mils2iu( 120 ) );
circle->SetPosition( { Mils2iu( 0 ), Mils2iu( -160 ) } ); circle->SetPosition( { Mils2iu( 0 ), Mils2iu( -160 ) } );
circle->SetEnd( circle->GetPosition() + wxPoint( Mils2iu( 120 ), 0 ) );
return { 0, Mils2iu( 350 ) }; return { 0, Mils2iu( 350 ) };
} }
else if( aStyle == ASCH_POWER_PORT_STYLE::GOST_BAR ) else if( aStyle == ASCH_POWER_PORT_STYLE::GOST_BAR )
{ {
LIB_POLYLINE* line1 = new LIB_POLYLINE( aKsymbol ); LIB_SHAPE* line1 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
aKsymbol->AddDrawItem( line1 ); aKsymbol->AddDrawItem( line1 );
line1->SetWidth( Mils2iu( 10 ) ); line1->SetWidth( Mils2iu( 10 ) );
line1->AddPoint( { 0, 0 } ); line1->AddPoint( { 0, 0 } );
line1->AddPoint( { 0, Mils2iu( -200 ) } ); line1->AddPoint( { 0, Mils2iu( -200 ) } );
LIB_POLYLINE* line2 = new LIB_POLYLINE( aKsymbol ); LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
aKsymbol->AddDrawItem( line2 ); aKsymbol->AddDrawItem( line2 );
line2->SetWidth( Mils2iu( 10 ) ); line2->SetWidth( Mils2iu( 10 ) );
line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -200 ) } ); line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -200 ) } );
@ -1783,13 +1778,13 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S
RPT_SEVERITY_WARNING ); RPT_SEVERITY_WARNING );
} }
LIB_POLYLINE* line1 = new LIB_POLYLINE( aKsymbol ); LIB_SHAPE* line1 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
aKsymbol->AddDrawItem( line1 ); aKsymbol->AddDrawItem( line1 );
line1->SetWidth( Mils2iu( 10 ) ); line1->SetWidth( Mils2iu( 10 ) );
line1->AddPoint( { 0, 0 } ); line1->AddPoint( { 0, 0 } );
line1->AddPoint( { 0, Mils2iu( -100 ) } ); line1->AddPoint( { 0, Mils2iu( -100 ) } );
LIB_POLYLINE* line2 = new LIB_POLYLINE( aKsymbol ); LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
aKsymbol->AddDrawItem( line2 ); aKsymbol->AddDrawItem( line2 );
line2->SetWidth( Mils2iu( 10 ) ); line2->SetWidth( Mils2iu( 10 ) );
line2->AddPoint( { Mils2iu( -50 ), Mils2iu( -100 ) } ); line2->AddPoint( { Mils2iu( -50 ), Mils2iu( -100 ) } );
@ -1837,8 +1832,7 @@ void SCH_ALTIUM_PLUGIN::ParsePowerPort( const std::map<wxString, wxString>& aPro
pin->SetType( ELECTRICAL_PINTYPE::PT_POWER_IN ); pin->SetType( ELECTRICAL_PINTYPE::PT_POWER_IN );
pin->SetVisible( false ); pin->SetVisible( false );
wxPoint valueFieldPos = HelperGeneratePowerPortGraphics( libSymbol, elem.style, wxPoint valueFieldPos = HelperGeneratePowerPortGraphics( libSymbol, elem.style, m_reporter );
m_reporter );
libSymbol->GetValueField().SetPosition( valueFieldPos ); libSymbol->GetValueField().SetPosition( valueFieldPos );

View File

@ -28,8 +28,7 @@
#include <bus_alias.h> #include <bus_alias.h>
#include <core/mirror.h> #include <core/mirror.h>
#include <eda_text.h> #include <eda_text.h>
#include <lib_arc.h> #include <lib_shape.h>
#include <lib_polyline.h>
#include <lib_text.h> #include <lib_text.h>
#include <macros.h> #include <macros.h>
#include <progress_reporter.h> #include <progress_reporter.h>
@ -1605,7 +1604,7 @@ void CADSTAR_SCH_ARCHIVE_LOADER::loadLibrarySymbolShapeVertices( const std::vect
{ {
cur = &aCadstarVertices.at( i ); cur = &aCadstarVertices.at( i );
LIB_ITEM* segment = nullptr; LIB_SHAPE* shape = nullptr;
bool cw = false; bool cw = false;
wxPoint startPoint = getKiCadLibraryPoint( prev->End, aSymbolOrigin ); wxPoint startPoint = getKiCadLibraryPoint( prev->End, aSymbolOrigin );
wxPoint endPoint = getKiCadLibraryPoint( cur->End, aSymbolOrigin ); wxPoint endPoint = getKiCadLibraryPoint( cur->End, aSymbolOrigin );
@ -1625,9 +1624,9 @@ void CADSTAR_SCH_ARCHIVE_LOADER::loadLibrarySymbolShapeVertices( const std::vect
switch( cur->Type ) switch( cur->Type )
{ {
case VERTEX_TYPE::POINT: case VERTEX_TYPE::POINT:
segment = new LIB_POLYLINE( aSymbol ); shape = new LIB_SHAPE( aSymbol, SHAPE_T::POLY );
( (LIB_POLYLINE*) segment )->AddPoint( startPoint ); shape->AddPoint( startPoint );
( (LIB_POLYLINE*) segment )->AddPoint( endPoint ); shape->AddPoint( endPoint );
break; break;
case VERTEX_TYPE::CLOCKWISE_SEMICIRCLE: case VERTEX_TYPE::CLOCKWISE_SEMICIRCLE:
@ -1637,27 +1636,27 @@ void CADSTAR_SCH_ARCHIVE_LOADER::loadLibrarySymbolShapeVertices( const std::vect
case VERTEX_TYPE::ANTICLOCKWISE_SEMICIRCLE: case VERTEX_TYPE::ANTICLOCKWISE_SEMICIRCLE:
case VERTEX_TYPE::ANTICLOCKWISE_ARC: case VERTEX_TYPE::ANTICLOCKWISE_ARC:
segment = new LIB_ARC( aSymbol ); shape = new LIB_SHAPE( aSymbol, SHAPE_T::ARC );
( (LIB_ARC*) segment )->SetPosition( centerPoint ); shape->SetPosition( centerPoint );
if( cw ) if( cw )
{ {
( (LIB_ARC*) segment )->SetStart( endPoint ); shape->SetStart( endPoint );
( (LIB_ARC*) segment )->SetEnd( startPoint ); shape->SetEnd( startPoint );
} }
else else
{ {
( (LIB_ARC*) segment )->SetStart( startPoint ); shape->SetStart( startPoint );
( (LIB_ARC*) segment )->SetEnd( endPoint ); shape->SetEnd( endPoint );
} }
break; break;
} }
segment->SetUnit( aGateNumber ); shape->SetUnit( aGateNumber );
segment->SetWidth( aLineThickness ); shape->SetWidth( aLineThickness );
aSymbol->AddDrawItem( segment ); aSymbol->AddDrawItem( shape );
prev = cur; prev = cur;
} }
@ -2043,8 +2042,7 @@ void CADSTAR_SCH_ARCHIVE_LOADER::loadShapeVertices( const std::vector<VERTEX>& a
else else
arcAngleDeciDeg = NormalizeAngleNeg( arcAngleDeciDeg ); arcAngleDeciDeg = NormalizeAngleNeg( arcAngleDeciDeg );
SHAPE_ARC tempArc( VECTOR2I(centerPoint), VECTOR2I(startPoint), SHAPE_ARC tempArc( centerPoint, startPoint, arcAngleDeciDeg / 10.0 );
arcAngleDeciDeg / 10.0 );
SHAPE_LINE_CHAIN arcSegments = tempArc.ConvertToPolyline( Millimeter2iu( 0.1 ) ); SHAPE_LINE_CHAIN arcSegments = tempArc.ConvertToPolyline( Millimeter2iu( 0.1 ) );
// Load the arc as a series of piece-wise segments // Load the arc as a series of piece-wise segments
@ -2768,28 +2766,27 @@ LIB_SYMBOL* CADSTAR_SCH_ARCHIVE_LOADER::getScaledLibPart( const LIB_SYMBOL* aSym
LIB_ITEMS_CONTAINER& items = retval->GetDrawItems(); LIB_ITEMS_CONTAINER& items = retval->GetDrawItems();
for( auto& item : items ) for( LIB_ITEM& item : items )
{ {
switch( item.Type() ) switch( item.Type() )
{ {
case KICAD_T::LIB_ARC_T: case KICAD_T::LIB_SHAPE_T:
{ {
LIB_ARC& arc = static_cast<LIB_ARC&>( item ); LIB_SHAPE& shape = static_cast<LIB_SHAPE&>( item );
arc.SetPosition( scalePt( arc.GetPosition() ) );
arc.SetStart( scalePt( arc.GetStart() ) ); if( shape.GetShape() == SHAPE_T::ARC )
arc.SetEnd( scalePt( arc.GetEnd() ) ); {
shape.SetPosition( scalePt( shape.GetPosition() ) );
shape.SetStart( scalePt( shape.GetStart() ) );
shape.SetEnd( scalePt( shape.GetEnd() ) );
} }
break; else if( shape.GetShape() == SHAPE_T::POLY )
case KICAD_T::LIB_POLYLINE_T:
{ {
LIB_POLYLINE& poly = static_cast<LIB_POLYLINE&>( item ); SHAPE_LINE_CHAIN& poly = shape.GetPolyShape().Outline( 0 );
std::vector<wxPoint> originalPts = poly.GetPolyPoints(); for( size_t ii = 0; ii < poly.GetPointCount(); ++ii )
poly.ClearPoints(); poly.SetPoint( ii, scalePt( (wxPoint) poly.CPoint( ii ) ) );
}
for( wxPoint& pt : originalPts )
poly.AddPoint( scalePt( pt ) );
} }
break; break;
@ -2811,7 +2808,8 @@ LIB_SYMBOL* CADSTAR_SCH_ARCHIVE_LOADER::getScaledLibPart( const LIB_SYMBOL* aSym
} }
break; break;
default: break; default:
break;
} }
} }
@ -2824,47 +2822,48 @@ void CADSTAR_SCH_ARCHIVE_LOADER::fixUpLibraryPins( LIB_SYMBOL* aSymbolToFix, int
{ {
// Store a list of segments that are not connected to other segments and are vertical or // Store a list of segments that are not connected to other segments and are vertical or
// horizontal. // horizontal.
std::map<wxPoint, LIB_POLYLINE*> twoPointUniqueSegments; std::map<VECTOR2I, SHAPE_LINE_CHAIN> uniqueSegments;
LIB_ITEMS_CONTAINER::ITERATOR polylineiter = LIB_ITEMS_CONTAINER::ITERATOR shapeIt = aSymbolToFix->GetDrawItems().begin( LIB_SHAPE_T );
aSymbolToFix->GetDrawItems().begin( LIB_POLYLINE_T );
for( ; polylineiter != aSymbolToFix->GetDrawItems().end( LIB_POLYLINE_T ); ++polylineiter ) for( ; shapeIt != aSymbolToFix->GetDrawItems().end( LIB_SHAPE_T ); ++shapeIt )
{ {
LIB_POLYLINE& polyline = static_cast<LIB_POLYLINE&>( *polylineiter ); LIB_SHAPE& shape = static_cast<LIB_SHAPE&>( *shapeIt );
if( aGateNumber > 0 && polyline.GetUnit() != aGateNumber ) if( aGateNumber > 0 && shape.GetUnit() != aGateNumber )
continue; continue;
const std::vector<wxPoint>& pts = polyline.GetPolyPoints(); if( shape.GetShape() != SHAPE_T::POLY )
continue;
SHAPE_LINE_CHAIN& poly = shape.GetPolyShape().Outline( 0 );
bool isUnique = true; bool isUnique = true;
auto removeSegment = auto removeSegment =
[&]( LIB_POLYLINE* aLineToRemove ) [&]( SHAPE_LINE_CHAIN& aLineToRemove )
{ {
twoPointUniqueSegments.erase( aLineToRemove->GetPolyPoints().at( 0 ) ); uniqueSegments.erase( aLineToRemove.CPoint( 0 ) );
twoPointUniqueSegments.erase( aLineToRemove->GetPolyPoints().at( 1 ) ); uniqueSegments.erase( aLineToRemove.CPoint( 1 ) );
isUnique = false; isUnique = false;
}; };
if( pts.size() == 2 ) if( poly.GetPointCount() == 2 )
{ {
const wxPoint& pt0 = pts.at( 0 ); const VECTOR2I& pt0 = poly.CPoint( 0 );
const wxPoint& pt1 = pts.at( 1 ); const VECTOR2I& pt1 = poly.CPoint( 1 );
if( twoPointUniqueSegments.count( pt0 ) ) if( uniqueSegments.count( pt0 ) )
removeSegment( twoPointUniqueSegments.at( pt0 ) ); removeSegment( uniqueSegments.at( pt0 ) );
if( twoPointUniqueSegments.count( pt1 ) ) if( uniqueSegments.count( pt1 ) )
removeSegment( twoPointUniqueSegments.at( pt1 ) ); removeSegment( uniqueSegments.at( pt1 ) );
if( isUnique && pt0 != pt1 ) if( isUnique && pt0 != pt1 )
{ {
if( pt0.x == pt1.x || pt0.y == pt1.y ) if( pt0.x == pt1.x || pt0.y == pt1.y )
{ {
twoPointUniqueSegments.insert( { pts.at( 0 ), &polyline } ); uniqueSegments.insert( { poly.CPoint( 0 ), poly } );
twoPointUniqueSegments.insert( { pts.at( 1 ), &polyline } ); uniqueSegments.insert( { poly.CPoint( 1 ), poly } );
} }
} }
} }
@ -2890,14 +2889,14 @@ void CADSTAR_SCH_ARCHIVE_LOADER::fixUpLibraryPins( LIB_SYMBOL* aSymbolToFix, int
pin->SetOrientation( 'D' ); // -90 degrees pin->SetOrientation( 'D' ); // -90 degrees
}; };
if( twoPointUniqueSegments.count( pin->GetPosition() ) ) if( uniqueSegments.count( pin->GetPosition() ) )
{ {
LIB_POLYLINE* poly = twoPointUniqueSegments.at( pin->GetPosition() ); SHAPE_LINE_CHAIN& poly = uniqueSegments.at( pin->GetPosition() );
wxPoint otherPt = poly->GetPolyPoints().at( 0 ); VECTOR2I otherPt = poly.CPoint( 0 );
if( otherPt == pin->GetPosition() ) if( otherPt == pin->GetPosition() )
otherPt = poly->GetPolyPoints().at( 1 ); otherPt = poly.CPoint( 1 );
VECTOR2I vec( otherPt - pin->GetPosition() ); VECTOR2I vec( otherPt - pin->GetPosition() );

View File

@ -38,13 +38,10 @@
#include <symbol_library.h> #include <symbol_library.h>
#include <plugins/eagle/eagle_parser.h> #include <plugins/eagle/eagle_parser.h>
#include <string_utils.h> #include <string_utils.h>
#include <lib_arc.h> #include <lib_shape.h>
#include <lib_circle.h>
#include <lib_id.h> #include <lib_id.h>
#include <lib_item.h> #include <lib_item.h>
#include <lib_pin.h> #include <lib_pin.h>
#include <lib_polyline.h>
#include <lib_rectangle.h>
#include <lib_text.h> #include <lib_text.h>
#include <project.h> #include <project.h>
#include <sch_bus_entry.h> #include <sch_bus_entry.h>
@ -1730,29 +1727,28 @@ bool SCH_EAGLE_PLUGIN::loadSymbol( wxXmlNode* aSymbolNode, std::unique_ptr<LIB_S
} }
LIB_CIRCLE* SCH_EAGLE_PLUGIN::loadSymbolCircle( std::unique_ptr<LIB_SYMBOL>& aSymbol, LIB_SHAPE* SCH_EAGLE_PLUGIN::loadSymbolCircle( std::unique_ptr<LIB_SYMBOL>& aSymbol,
wxXmlNode* aCircleNode, int aGateNumber ) wxXmlNode* aCircleNode, int aGateNumber )
{ {
// Parse the circle properties // Parse the circle properties
ECIRCLE c( aCircleNode ); ECIRCLE c( aCircleNode );
LIB_SHAPE* circle = new LIB_SHAPE( aSymbol.get(), SHAPE_T::CIRCLE );
wxPoint center( c.x.ToSchUnits(), c.y.ToSchUnits() );
unique_ptr<LIB_CIRCLE> circle( new LIB_CIRCLE( aSymbol.get() ) ); circle->SetPosition( center );
circle->SetEnd( wxPoint( center.x + c.radius.ToSchUnits(), center.y ) );
circle->SetPosition( wxPoint( c.x.ToSchUnits(), c.y.ToSchUnits() ) );
circle->SetRadius( c.radius.ToSchUnits() );
circle->SetWidth( c.width.ToSchUnits() ); circle->SetWidth( c.width.ToSchUnits() );
circle->SetUnit( aGateNumber ); circle->SetUnit( aGateNumber );
return circle.release(); return circle;
} }
LIB_RECTANGLE* SCH_EAGLE_PLUGIN::loadSymbolRectangle( std::unique_ptr<LIB_SYMBOL>& aSymbol, LIB_SHAPE* SCH_EAGLE_PLUGIN::loadSymbolRectangle( std::unique_ptr<LIB_SYMBOL>& aSymbol,
wxXmlNode* aRectNode, int aGateNumber ) wxXmlNode* aRectNode, int aGateNumber )
{ {
ERECT rect( aRectNode ); ERECT rect( aRectNode );
LIB_SHAPE* rectangle = new LIB_SHAPE( aSymbol.get(), SHAPE_T::RECT );
unique_ptr<LIB_RECTANGLE> rectangle( new LIB_RECTANGLE( aSymbol.get() ) );
rectangle->SetPosition( wxPoint( rect.x1.ToSchUnits(), rect.y1.ToSchUnits() ) ); rectangle->SetPosition( wxPoint( rect.x1.ToSchUnits(), rect.y1.ToSchUnits() ) );
rectangle->SetEnd( wxPoint( rect.x2.ToSchUnits(), rect.y2.ToSchUnits() ) ); rectangle->SetEnd( wxPoint( rect.x2.ToSchUnits(), rect.y2.ToSchUnits() ) );
@ -1760,9 +1756,9 @@ LIB_RECTANGLE* SCH_EAGLE_PLUGIN::loadSymbolRectangle( std::unique_ptr<LIB_SYMBOL
rectangle->SetUnit( aGateNumber ); rectangle->SetUnit( aGateNumber );
// Eagle rectangles are filled by definition. // Eagle rectangles are filled by definition.
rectangle->SetFillMode( FILL_TYPE::FILLED_SHAPE ); rectangle->SetFillMode( FILL_T::FILLED_SHAPE );
return rectangle.release(); return rectangle;
} }
@ -1784,9 +1780,8 @@ LIB_ITEM* SCH_EAGLE_PLUGIN::loadSymbolWire( std::unique_ptr<LIB_SYMBOL>& aSymbol
// if the wire is an arc // if the wire is an arc
if( ewire.curve ) if( ewire.curve )
{ {
std::unique_ptr<LIB_ARC> arc = std::make_unique<LIB_ARC>( aSymbol.get() ); LIB_SHAPE* arc = new LIB_SHAPE( aSymbol.get(), SHAPE_T::ARC );
wxPoint center = ConvertArcCenter( begin, end, *ewire.curve * -1 ); wxPoint center = ConvertArcCenter( begin, end, *ewire.curve * -1 );
double radius = sqrt( abs( ( ( center.x - begin.x ) * ( center.x - begin.x ) ) double radius = sqrt( abs( ( ( center.x - begin.x ) * ( center.x - begin.x ) )
+ ( ( center.y - begin.y ) * ( center.y - begin.y ) ) ) ) + ( ( center.y - begin.y ) * ( center.y - begin.y ) ) ) )
* 2; * 2;
@ -1811,49 +1806,39 @@ LIB_ITEM* SCH_EAGLE_PLUGIN::loadSymbolWire( std::unique_ptr<LIB_SYMBOL>& aSymbol
* 2; * 2;
arc->SetWidth( 1 ); arc->SetWidth( 1 );
arc->SetFillMode( FILL_TYPE::FILLED_SHAPE ); arc->SetFillMode( FILL_T::FILLED_SHAPE );
} }
else else
{ {
arc->SetWidth( ewire.width.ToSchUnits() ); arc->SetWidth( ewire.width.ToSchUnits() );
} }
arc->SetPosition( center ); if( *ewire.curve <= 0 )
std::swap( begin, end );
if( *ewire.curve > 0 )
{
arc->SetStart( begin );
arc->SetEnd( end );
}
else
{
arc->SetStart( end );
arc->SetEnd( begin );
}
arc->SetArcGeometry( begin, (wxPoint) CalcArcMid( begin, end, center ), end );
arc->SetUnit( aGateNumber ); arc->SetUnit( aGateNumber );
return (LIB_ITEM*) arc.release(); return arc;
} }
else else
{ {
std::unique_ptr<LIB_POLYLINE> polyLine = std::make_unique<LIB_POLYLINE>( aSymbol.get() ); LIB_SHAPE* poly = new LIB_SHAPE( aSymbol.get(), SHAPE_T::POLY );
polyLine->AddPoint( begin ); poly->AddPoint( begin );
polyLine->AddPoint( end ); poly->AddPoint( end );
polyLine->SetUnit( aGateNumber ); poly->SetUnit( aGateNumber );
polyLine->SetWidth( ewire.width.ToSchUnits() ); poly->SetWidth( ewire.width.ToSchUnits() );
return (LIB_ITEM*) polyLine.release(); return poly;
} }
} }
LIB_POLYLINE* SCH_EAGLE_PLUGIN::loadSymbolPolyLine( std::unique_ptr<LIB_SYMBOL>& aSymbol, LIB_SHAPE* SCH_EAGLE_PLUGIN::loadSymbolPolyLine( std::unique_ptr<LIB_SYMBOL>& aSymbol,
wxXmlNode* aPolygonNode, int aGateNumber ) wxXmlNode* aPolygonNode, int aGateNumber )
{ {
std::unique_ptr<LIB_POLYLINE> polyLine = std::make_unique<LIB_POLYLINE>( aSymbol.get() ); LIB_SHAPE* poly = new LIB_SHAPE( aSymbol.get(), SHAPE_T::POLY );
EPOLYGON epoly( aPolygonNode ); EPOLYGON epoly( aPolygonNode );
wxXmlNode* vertex = aPolygonNode->GetChildren(); wxXmlNode* vertex = aPolygonNode->GetChildren();
wxPoint pt; wxPoint pt;
@ -1864,16 +1849,16 @@ LIB_POLYLINE* SCH_EAGLE_PLUGIN::loadSymbolPolyLine( std::unique_ptr<LIB_SYMBOL>&
{ {
EVERTEX evertex( vertex ); EVERTEX evertex( vertex );
pt = wxPoint( evertex.x.ToSchUnits(), evertex.y.ToSchUnits() ); pt = wxPoint( evertex.x.ToSchUnits(), evertex.y.ToSchUnits() );
polyLine->AddPoint( pt ); poly->AddPoint( pt );
} }
vertex = vertex->GetNext(); vertex = vertex->GetNext();
} }
polyLine->SetFillMode( FILL_TYPE::FILLED_SHAPE ); poly->SetFillMode( FILL_T::FILLED_SHAPE );
polyLine->SetUnit( aGateNumber ); poly->SetUnit( aGateNumber );
return polyLine.release(); return poly;
} }
@ -1994,7 +1979,7 @@ void SCH_EAGLE_PLUGIN::loadFrame( wxXmlNode* aFrameNode, std::vector<LIB_ITEM*>&
if( yMin > yMax ) if( yMin > yMax )
std::swap( yMin, yMax ); std::swap( yMin, yMax );
LIB_POLYLINE* lines = new LIB_POLYLINE( nullptr ); LIB_SHAPE* lines = new LIB_SHAPE( nullptr, SHAPE_T::POLY );
lines->AddPoint( wxPoint( xMin, yMin ) ); lines->AddPoint( wxPoint( xMin, yMin ) );
lines->AddPoint( wxPoint( xMax, yMin ) ); lines->AddPoint( wxPoint( xMax, yMin ) );
lines->AddPoint( wxPoint( xMax, yMax ) ); lines->AddPoint( wxPoint( xMax, yMax ) );
@ -2004,7 +1989,7 @@ void SCH_EAGLE_PLUGIN::loadFrame( wxXmlNode* aFrameNode, std::vector<LIB_ITEM*>&
if( !eframe.border_left ) if( !eframe.border_left )
{ {
lines = new LIB_POLYLINE( nullptr ); lines = new LIB_SHAPE( nullptr, SHAPE_T::POLY );
lines->AddPoint( wxPoint( xMin + Mils2iu( 150 ), yMin + Mils2iu( 150 ) ) ); lines->AddPoint( wxPoint( xMin + Mils2iu( 150 ), yMin + Mils2iu( 150 ) ) );
lines->AddPoint( wxPoint( xMin + Mils2iu( 150 ), yMax - Mils2iu( 150 ) ) ); lines->AddPoint( wxPoint( xMin + Mils2iu( 150 ), yMax - Mils2iu( 150 ) ) );
aItems.push_back( lines ); aItems.push_back( lines );
@ -2020,7 +2005,7 @@ void SCH_EAGLE_PLUGIN::loadFrame( wxXmlNode* aFrameNode, std::vector<LIB_ITEM*>&
for( i = 1; i < eframe.rows; i++ ) for( i = 1; i < eframe.rows; i++ )
{ {
int newY = KiROUND( yMin + ( rowSpacing * (double) i ) ); int newY = KiROUND( yMin + ( rowSpacing * (double) i ) );
lines = new LIB_POLYLINE( nullptr ); lines = new LIB_SHAPE( nullptr, SHAPE_T::POLY );
lines->AddPoint( wxPoint( x1, newY ) ); lines->AddPoint( wxPoint( x1, newY ) );
lines->AddPoint( wxPoint( x2, newY ) ); lines->AddPoint( wxPoint( x2, newY ) );
aItems.push_back( lines ); aItems.push_back( lines );
@ -2042,7 +2027,7 @@ void SCH_EAGLE_PLUGIN::loadFrame( wxXmlNode* aFrameNode, std::vector<LIB_ITEM*>&
if( !eframe.border_right ) if( !eframe.border_right )
{ {
lines = new LIB_POLYLINE( nullptr ); lines = new LIB_SHAPE( nullptr, SHAPE_T::POLY );
lines->AddPoint( wxPoint( xMax - Mils2iu( 150 ), yMin + Mils2iu( 150 ) ) ); lines->AddPoint( wxPoint( xMax - Mils2iu( 150 ), yMin + Mils2iu( 150 ) ) );
lines->AddPoint( wxPoint( xMax - Mils2iu( 150 ), yMax - Mils2iu( 150 ) ) ); lines->AddPoint( wxPoint( xMax - Mils2iu( 150 ), yMax - Mils2iu( 150 ) ) );
aItems.push_back( lines ); aItems.push_back( lines );
@ -2058,7 +2043,7 @@ void SCH_EAGLE_PLUGIN::loadFrame( wxXmlNode* aFrameNode, std::vector<LIB_ITEM*>&
for( i = 1; i < eframe.rows; i++ ) for( i = 1; i < eframe.rows; i++ )
{ {
int newY = KiROUND( yMin + ( rowSpacing * (double) i ) ); int newY = KiROUND( yMin + ( rowSpacing * (double) i ) );
lines = new LIB_POLYLINE( nullptr ); lines = new LIB_SHAPE( nullptr, SHAPE_T::POLY );
lines->AddPoint( wxPoint( x1, newY ) ); lines->AddPoint( wxPoint( x1, newY ) );
lines->AddPoint( wxPoint( x2, newY ) ); lines->AddPoint( wxPoint( x2, newY ) );
aItems.push_back( lines ); aItems.push_back( lines );
@ -2080,7 +2065,7 @@ void SCH_EAGLE_PLUGIN::loadFrame( wxXmlNode* aFrameNode, std::vector<LIB_ITEM*>&
if( !eframe.border_top ) if( !eframe.border_top )
{ {
lines = new LIB_POLYLINE( nullptr ); lines = new LIB_SHAPE( nullptr, SHAPE_T::POLY );
lines->AddPoint( wxPoint( xMax - Mils2iu( 150 ), yMax - Mils2iu( 150 ) ) ); lines->AddPoint( wxPoint( xMax - Mils2iu( 150 ), yMax - Mils2iu( 150 ) ) );
lines->AddPoint( wxPoint( xMin + Mils2iu( 150 ), yMax - Mils2iu( 150 ) ) ); lines->AddPoint( wxPoint( xMin + Mils2iu( 150 ), yMax - Mils2iu( 150 ) ) );
aItems.push_back( lines ); aItems.push_back( lines );
@ -2096,7 +2081,7 @@ void SCH_EAGLE_PLUGIN::loadFrame( wxXmlNode* aFrameNode, std::vector<LIB_ITEM*>&
for( i = 1; i < eframe.columns; i++ ) for( i = 1; i < eframe.columns; i++ )
{ {
int newX = KiROUND( xMin + ( columnSpacing * (double) i ) ); int newX = KiROUND( xMin + ( columnSpacing * (double) i ) );
lines = new LIB_POLYLINE( nullptr ); lines = new LIB_SHAPE( nullptr, SHAPE_T::POLY );
lines->AddPoint( wxPoint( newX, y1 ) ); lines->AddPoint( wxPoint( newX, y1 ) );
lines->AddPoint( wxPoint( newX, y2 ) ); lines->AddPoint( wxPoint( newX, y2 ) );
aItems.push_back( lines ); aItems.push_back( lines );
@ -2118,7 +2103,7 @@ void SCH_EAGLE_PLUGIN::loadFrame( wxXmlNode* aFrameNode, std::vector<LIB_ITEM*>&
if( !eframe.border_bottom ) if( !eframe.border_bottom )
{ {
lines = new LIB_POLYLINE( nullptr ); lines = new LIB_SHAPE( nullptr, SHAPE_T::POLY );
lines->AddPoint( wxPoint( xMax - Mils2iu( 150 ), yMin + Mils2iu( 150 ) ) ); lines->AddPoint( wxPoint( xMax - Mils2iu( 150 ), yMin + Mils2iu( 150 ) ) );
lines->AddPoint( wxPoint( xMin + Mils2iu( 150 ), yMin + Mils2iu( 150 ) ) ); lines->AddPoint( wxPoint( xMin + Mils2iu( 150 ), yMin + Mils2iu( 150 ) ) );
aItems.push_back( lines ); aItems.push_back( lines );
@ -2134,7 +2119,7 @@ void SCH_EAGLE_PLUGIN::loadFrame( wxXmlNode* aFrameNode, std::vector<LIB_ITEM*>&
for( i = 1; i < eframe.columns; i++ ) for( i = 1; i < eframe.columns; i++ )
{ {
int newX = KiROUND( xMin + ( columnSpacing * (double) i ) ); int newX = KiROUND( xMin + ( columnSpacing * (double) i ) );
lines = new LIB_POLYLINE( nullptr ); lines = new LIB_SHAPE( nullptr, SHAPE_T::POLY );
lines->AddPoint( wxPoint( newX, y1 ) ); lines->AddPoint( wxPoint( newX, y1 ) );
lines->AddPoint( wxPoint( newX, y2 ) ); lines->AddPoint( wxPoint( newX, y2 ) );
aItems.push_back( lines ); aItems.push_back( lines );

View File

@ -51,7 +51,7 @@ class PROPERTIES;
class SCH_EAGLE_PLUGIN_CACHE; class SCH_EAGLE_PLUGIN_CACHE;
class LIB_SYMBOL; class LIB_SYMBOL;
class SYMBOL_LIB; class SYMBOL_LIB;
class LIB_CIRCLE; class LIB_SHAPE;
class LIB_FIELD; class LIB_FIELD;
class LIB_RECTANGLE; class LIB_RECTANGLE;
class LIB_POLYLINE; class LIB_POLYLINE;
@ -138,11 +138,11 @@ private:
bool loadSymbol( wxXmlNode* aSymbolNode, std::unique_ptr<LIB_SYMBOL>& aSymbol, bool loadSymbol( wxXmlNode* aSymbolNode, std::unique_ptr<LIB_SYMBOL>& aSymbol,
EDEVICE* aDevice, int aGateNumber, const wxString& aGateName ); EDEVICE* aDevice, int aGateNumber, const wxString& aGateName );
LIB_CIRCLE* loadSymbolCircle( std::unique_ptr<LIB_SYMBOL>& aSymbol, wxXmlNode* aCircleNode, LIB_SHAPE* loadSymbolCircle( std::unique_ptr<LIB_SYMBOL>& aSymbol, wxXmlNode* aCircleNode,
int aGateNumber ); int aGateNumber );
LIB_RECTANGLE* loadSymbolRectangle( std::unique_ptr<LIB_SYMBOL>& aSymbol, wxXmlNode* aRectNode, LIB_SHAPE* loadSymbolRectangle( std::unique_ptr<LIB_SYMBOL>& aSymbol, wxXmlNode* aRectNode,
int aGateNumber ); int aGateNumber );
LIB_POLYLINE* loadSymbolPolyLine( std::unique_ptr<LIB_SYMBOL>& aSymbol, LIB_SHAPE* loadSymbolPolyLine( std::unique_ptr<LIB_SYMBOL>& aSymbol,
wxXmlNode* aPolygonNode, int aGateNumber ); wxXmlNode* aPolygonNode, int aGateNumber );
LIB_ITEM* loadSymbolWire( std::unique_ptr<LIB_SYMBOL>& aSymbol, wxXmlNode* aWireNode, LIB_ITEM* loadSymbolWire( std::unique_ptr<LIB_SYMBOL>& aSymbol, wxXmlNode* aWireNode,
int aGateNumber ); int aGateNumber );

View File

@ -33,12 +33,8 @@
#include <wx/tokenzr.h> #include <wx/tokenzr.h>
#include <lib_id.h> #include <lib_id.h>
#include <lib_arc.h> #include <lib_shape.h>
#include <lib_bezier.h>
#include <lib_circle.h>
#include <lib_pin.h> #include <lib_pin.h>
#include <lib_polyline.h>
#include <lib_rectangle.h>
#include <lib_text.h> #include <lib_text.h>
#include <math/util.h> // KiROUND, Clamp #include <math/util.h> // KiROUND, Clamp
#include <string_utils.h> #include <string_utils.h>
@ -543,7 +539,7 @@ void SCH_SEXPR_PARSER::parseFill( FILL_PARAMS& aFill )
wxCHECK_RET( CurTok() == T_fill, wxCHECK_RET( CurTok() == T_fill,
wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as fill." ) ); wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as fill." ) );
aFill.m_FillType = FILL_TYPE::NO_FILL; aFill.m_FillType = FILL_T::NO_FILL;
aFill.m_Color = COLOR4D::UNSPECIFIED; aFill.m_Color = COLOR4D::UNSPECIFIED;
T token; T token;
@ -563,9 +559,9 @@ void SCH_SEXPR_PARSER::parseFill( FILL_PARAMS& aFill )
switch( token ) switch( token )
{ {
case T_none: aFill.m_FillType = FILL_TYPE::NO_FILL; break; case T_none: aFill.m_FillType = FILL_T::NO_FILL; break;
case T_outline: aFill.m_FillType = FILL_TYPE::FILLED_SHAPE; break; case T_outline: aFill.m_FillType = FILL_T::FILLED_SHAPE; break;
case T_background: aFill.m_FillType = FILL_TYPE::FILLED_WITH_BG_BODYCOLOR; break; case T_background: aFill.m_FillType = FILL_T::FILLED_WITH_BG_BODYCOLOR; break;
default: Expecting( "none, outline, or background" ); default: Expecting( "none, outline, or background" );
} }
@ -906,10 +902,10 @@ LIB_FIELD* SCH_SEXPR_PARSER::parseProperty( std::unique_ptr<LIB_SYMBOL>& aSymbol
} }
LIB_ARC* SCH_SEXPR_PARSER::parseArc() LIB_SHAPE* SCH_SEXPR_PARSER::parseArc()
{ {
wxCHECK_MSG( CurTok() == T_arc, nullptr, wxCHECK_MSG( CurTok() == T_arc, nullptr,
wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as an arc token." ) ); wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as an arc." ) );
T token; T token;
wxPoint startPoint; wxPoint startPoint;
@ -920,7 +916,8 @@ LIB_ARC* SCH_SEXPR_PARSER::parseArc()
int endAngle; int endAngle;
FILL_PARAMS fill; FILL_PARAMS fill;
bool hasMidPoint = false; bool hasMidPoint = false;
std::unique_ptr<LIB_ARC> arc = std::make_unique<LIB_ARC>( nullptr ); bool hasAngles = false;
std::unique_ptr<LIB_SHAPE> arc = std::make_unique<LIB_SHAPE>( nullptr, SHAPE_T::ARC );
arc->SetUnit( m_unit ); arc->SetUnit( m_unit );
arc->SetConvert( m_convert ); arc->SetConvert( m_convert );
@ -977,6 +974,7 @@ LIB_ARC* SCH_SEXPR_PARSER::parseArc()
NORMALIZE_ANGLE_POS( startAngle ); NORMALIZE_ANGLE_POS( startAngle );
NORMALIZE_ANGLE_POS( endAngle ); NORMALIZE_ANGLE_POS( endAngle );
NeedRIGHT(); NeedRIGHT();
hasAngles = true;
break; break;
} }
@ -1005,11 +1003,10 @@ LIB_ARC* SCH_SEXPR_PARSER::parseArc()
break; break;
default: default:
Expecting( "start, end, radius, stroke, or fill" ); Expecting( "start, mid, end, radius, stroke, or fill" );
} }
} }
arc->SetPosition( pos );
arc->SetStart( startPoint ); arc->SetStart( startPoint );
arc->SetEnd( endPoint ); arc->SetEnd( endPoint );
@ -1019,8 +1016,9 @@ LIB_ARC* SCH_SEXPR_PARSER::parseArc()
arc->SetCenter( (wxPoint) center ); arc->SetCenter( (wxPoint) center );
} }
else else if( hasAngles )
{ {
arc->SetCenter( pos );
/** /**
* This accounts for an oddity in the old library format, where the symbol is overdefined. * 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 * The previous draw (based on wxwidgets) used start point and end point and always drew
@ -1035,19 +1033,21 @@ LIB_ARC* SCH_SEXPR_PARSER::parseArc()
arc->SetEnd( temp ); arc->SetEnd( temp );
} }
} }
else
wxFAIL_MSG( "Setting arc without either midpoint or angles not implemented." );
return arc.release(); return arc.release();
} }
LIB_BEZIER* SCH_SEXPR_PARSER::parseBezier() LIB_SHAPE* SCH_SEXPR_PARSER::parseBezier()
{ {
wxCHECK_MSG( CurTok() == T_bezier, nullptr, wxCHECK_MSG( CurTok() == T_bezier, nullptr,
wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a bezier." ) ); wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a bezier." ) );
T token; T token;
FILL_PARAMS fill; FILL_PARAMS fill;
std::unique_ptr<LIB_BEZIER> bezier = std::make_unique<LIB_BEZIER>( nullptr ); std::unique_ptr<LIB_SHAPE> bezier = std::make_unique<LIB_SHAPE>( nullptr, SHAPE_T::BEZIER );
bezier->SetUnit( m_unit ); bezier->SetUnit( m_unit );
bezier->SetConvert( m_convert ); bezier->SetConvert( m_convert );
@ -1105,15 +1105,16 @@ LIB_BEZIER* SCH_SEXPR_PARSER::parseBezier()
} }
LIB_CIRCLE* SCH_SEXPR_PARSER::parseCircle() LIB_SHAPE* SCH_SEXPR_PARSER::parseCircle()
{ {
wxCHECK_MSG( CurTok() == T_circle, nullptr, wxCHECK_MSG( CurTok() == T_circle, nullptr,
wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a circle." ) );
wxT( " as a circle token." ) );
T token; T token;
wxPoint center;
int radius;
FILL_PARAMS fill; FILL_PARAMS fill;
std::unique_ptr<LIB_CIRCLE> circle = std::make_unique<LIB_CIRCLE>( nullptr ); std::unique_ptr<LIB_SHAPE> circle = std::make_unique<LIB_SHAPE>( nullptr, SHAPE_T::CIRCLE );
circle->SetUnit( m_unit ); circle->SetUnit( m_unit );
circle->SetConvert( m_convert ); circle->SetConvert( m_convert );
@ -1128,12 +1129,12 @@ LIB_CIRCLE* SCH_SEXPR_PARSER::parseCircle()
switch( token ) switch( token )
{ {
case T_center: case T_center:
circle->SetPosition( parseXY() ); center = parseXY();
NeedRIGHT(); NeedRIGHT();
break; break;
case T_radius: case T_radius:
circle->SetRadius( parseInternalUnits( "radius length" ) ); radius = parseInternalUnits( "radius length" );
NeedRIGHT(); NeedRIGHT();
break; break;
@ -1155,10 +1156,13 @@ LIB_CIRCLE* SCH_SEXPR_PARSER::parseCircle()
break; break;
default: default:
Expecting( "start, end, radius, stroke, or fill" ); Expecting( "center, radius, stroke, or fill" );
} }
} }
circle->SetCenter( center );
circle->SetEnd( wxPoint( center.x + radius, center.y ) );
return circle.release(); return circle.release();
} }
@ -1386,17 +1390,17 @@ LIB_PIN* SCH_SEXPR_PARSER::parsePin()
} }
LIB_POLYLINE* SCH_SEXPR_PARSER::parsePolyLine() LIB_SHAPE* SCH_SEXPR_PARSER::parsePolyLine()
{ {
wxCHECK_MSG( CurTok() == T_polyline, nullptr, wxCHECK_MSG( CurTok() == T_polyline, nullptr,
wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a polyline." ) ); wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a poly." ) );
T token; T token;
FILL_PARAMS fill; FILL_PARAMS fill;
std::unique_ptr<LIB_POLYLINE> polyLine = std::make_unique<LIB_POLYLINE>( nullptr ); std::unique_ptr<LIB_SHAPE> poly = std::make_unique<LIB_SHAPE>( nullptr, SHAPE_T::POLY );
polyLine->SetUnit( m_unit ); poly->SetUnit( m_unit );
polyLine->SetConvert( m_convert ); poly->SetConvert( m_convert );
for( token = NextTok(); token != T_RIGHT; token = NextTok() ) for( token = NextTok(); token != T_RIGHT; token = NextTok() )
{ {
@ -1418,7 +1422,7 @@ LIB_POLYLINE* SCH_SEXPR_PARSER::parsePolyLine()
if( token != T_xy ) if( token != T_xy )
Expecting( "xy" ); Expecting( "xy" );
polyLine->AddPoint( parseXY() ); poly->AddPoint( parseXY() );
NeedRIGHT(); NeedRIGHT();
} }
@ -1432,14 +1436,14 @@ LIB_POLYLINE* SCH_SEXPR_PARSER::parsePolyLine()
if( token != T_width ) if( token != T_width )
Expecting( "width" ); Expecting( "width" );
polyLine->SetWidth( parseInternalUnits( "stroke width" ) ); poly->SetWidth( parseInternalUnits( "stroke width" ) );
NeedRIGHT(); // Closes width token; NeedRIGHT(); // Closes width token;
NeedRIGHT(); // Closes stroke token; NeedRIGHT(); // Closes stroke token;
break; break;
case T_fill: case T_fill:
parseFill( fill ); parseFill( fill );
polyLine->SetFillMode( fill.m_FillType ); poly->SetFillMode( fill.m_FillType );
break; break;
default: default:
@ -1447,19 +1451,18 @@ LIB_POLYLINE* SCH_SEXPR_PARSER::parsePolyLine()
} }
} }
return polyLine.release(); return poly.release();
} }
LIB_RECTANGLE* SCH_SEXPR_PARSER::parseRectangle() LIB_SHAPE* SCH_SEXPR_PARSER::parseRectangle()
{ {
wxCHECK_MSG( CurTok() == T_rectangle, nullptr, wxCHECK_MSG( CurTok() == T_rectangle, nullptr,
wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a rectangle." ) );
wxT( " as a rectangle token." ) );
T token; T token;
FILL_PARAMS fill; FILL_PARAMS fill;
std::unique_ptr<LIB_RECTANGLE> rectangle = std::make_unique<LIB_RECTANGLE>( nullptr ); std::unique_ptr<LIB_SHAPE> rectangle = std::make_unique<LIB_SHAPE>( nullptr, SHAPE_T::RECT );
rectangle->SetUnit( m_unit ); rectangle->SetUnit( m_unit );
rectangle->SetConvert( m_convert ); rectangle->SetConvert( m_convert );

View File

@ -40,12 +40,9 @@
#include <default_values.h> // For some default values #include <default_values.h> // For some default values
class LIB_ARC; class LIB_SHAPE;
class LIB_BEZIER;
class LIB_CIRCLE;
class LIB_ITEM; class LIB_ITEM;
class LIB_PIN; class LIB_PIN;
class LIB_POLYLINE;
class LIB_TEXT; class LIB_TEXT;
class PAGE_INFO; class PAGE_INFO;
class SCH_BITMAP; class SCH_BITMAP;
@ -68,7 +65,7 @@ class TITLE_BLOCK;
class FILL_PARAMS class FILL_PARAMS
{ {
public: public:
FILL_TYPE m_FillType; FILL_T m_FillType;
COLOR4D m_Color; COLOR4D m_Color;
}; };
@ -165,12 +162,12 @@ class SCH_SEXPR_PARSER : public SCHEMATIC_LEXER
LIB_FIELD* parseProperty( std::unique_ptr<LIB_SYMBOL>& aSymbol ); LIB_FIELD* parseProperty( std::unique_ptr<LIB_SYMBOL>& aSymbol );
LIB_ARC* parseArc(); LIB_SHAPE* parseArc();
LIB_BEZIER* parseBezier(); LIB_SHAPE* parseBezier();
LIB_CIRCLE* parseCircle(); LIB_SHAPE* parseCircle();
LIB_PIN* parsePin(); LIB_PIN* parsePin();
LIB_POLYLINE* parsePolyLine(); LIB_SHAPE* parsePolyLine();
LIB_RECTANGLE* parseRectangle(); LIB_SHAPE* parseRectangle();
LIB_TEXT* parseText(); LIB_TEXT* parseText();
void parsePAGE_INFO( PAGE_INFO& aPageInfo ); void parsePAGE_INFO( PAGE_INFO& aPageInfo );

View File

@ -45,13 +45,9 @@
#include <sch_plugins/kicad/sch_sexpr_plugin.h> #include <sch_plugins/kicad/sch_sexpr_plugin.h>
#include <sch_screen.h> #include <sch_screen.h>
#include <symbol_library.h> #include <symbol_library.h>
#include <lib_arc.h> #include <lib_shape.h>
#include <lib_bezier.h>
#include <lib_circle.h>
#include <lib_field.h> #include <lib_field.h>
#include <lib_pin.h> #include <lib_pin.h>
#include <lib_polyline.h>
#include <lib_rectangle.h>
#include <lib_text.h> #include <lib_text.h>
#include <eeschema_id.h> // for MAX_UNIT_COUNT_PER_PACKAGE definition #include <eeschema_id.h> // for MAX_UNIT_COUNT_PER_PACKAGE definition
#include <sch_file_versions.h> #include <sch_file_versions.h>
@ -77,18 +73,16 @@ static const char* emptyString = "";
/** /**
* Fill token formatting helper. * Fill token formatting helper.
*/ */
static void formatFill( const LIB_ITEM* aItem, OUTPUTFORMATTER& aFormatter, int aNestLevel ) static void formatFill( const LIB_SHAPE* aItem, OUTPUTFORMATTER& aFormatter, int aNestLevel )
{ {
wxCHECK_RET( aItem && aItem->IsFillable(), "Invalid fill item." );
const char* fillType; const char* fillType;
switch( aItem->GetFillMode() ) switch( aItem->GetFillType() )
{ {
case FILL_TYPE::FILLED_SHAPE: fillType = "outline"; break; default:
case FILL_TYPE::FILLED_WITH_BG_BODYCOLOR: fillType = "background"; break; case FILL_T::NO_FILL: fillType = "none"; break;
case FILL_TYPE::NO_FILL: KI_FALLTHROUGH; case FILL_T::FILLED_SHAPE: fillType = "outline"; break;
default: fillType = "none"; case FILL_T::FILLED_WITH_BG_BODYCOLOR: fillType = "background"; break;
} }
aFormatter.Print( aNestLevel, "(fill (type %s))", fillType ); aFormatter.Print( aNestLevel, "(fill (type %s))", fillType );
@ -306,18 +300,14 @@ class SCH_SEXPR_PLUGIN_CACHE
static void saveSymbolDrawItem( LIB_ITEM* aItem, OUTPUTFORMATTER& aFormatter, static void saveSymbolDrawItem( LIB_ITEM* aItem, OUTPUTFORMATTER& aFormatter,
int aNestLevel ); int aNestLevel );
static void saveArc( LIB_ARC* aArc, OUTPUTFORMATTER& aFormatter, int aNestLevel = 0 ); static void saveArc( LIB_SHAPE* aArc, OUTPUTFORMATTER& aFormatter, int aNestLevel = 0 );
static void saveBezier( LIB_BEZIER* aBezier, OUTPUTFORMATTER& aFormatter, static void saveBezier( LIB_SHAPE* aBezier, OUTPUTFORMATTER& aFormatter, int aNestLevel = 0 );
int aNestLevel = 0 ); static void saveCircle( LIB_SHAPE* aCircle, OUTPUTFORMATTER& aFormatter, int aNestLevel = 0 );
static void saveCircle( LIB_CIRCLE* aCircle, OUTPUTFORMATTER& aFormatter, static void saveField( LIB_FIELD* aField, OUTPUTFORMATTER& aFormatter, int& aNextFreeFieldId,
int aNestLevel = 0 ); int aNestLevel );
static void saveField( LIB_FIELD* aField, OUTPUTFORMATTER& aFormatter,
int& aNextFreeFieldId, int aNestLevel );
static void savePin( LIB_PIN* aPin, OUTPUTFORMATTER& aFormatter, int aNestLevel = 0 ); static void savePin( LIB_PIN* aPin, OUTPUTFORMATTER& aFormatter, int aNestLevel = 0 );
static void savePolyLine( LIB_POLYLINE* aPolyLine, OUTPUTFORMATTER& aFormatter, static void savePolyLine( LIB_SHAPE* aPolyLine, OUTPUTFORMATTER& aFormatter, int aNestLevel = 0 );
int aNestLevel = 0 ); static void saveRectangle( LIB_SHAPE* aRect, OUTPUTFORMATTER& aFormatter, int aNestLevel = 0 );
static void saveRectangle( LIB_RECTANGLE* aRectangle, OUTPUTFORMATTER& aFormatter,
int aNestLevel = 0 );
static void saveText( LIB_TEXT* aText, OUTPUTFORMATTER& aFormatter, int aNestLevel = 0 ); static void saveText( LIB_TEXT* aText, OUTPUTFORMATTER& aFormatter, int aNestLevel = 0 );
static void saveDcmInfoAsFields( LIB_SYMBOL* aSymbol, OUTPUTFORMATTER& aFormatter, static void saveDcmInfoAsFields( LIB_SYMBOL* aSymbol, OUTPUTFORMATTER& aFormatter,
@ -1771,49 +1761,44 @@ void SCH_SEXPR_PLUGIN_CACHE::saveSymbolDrawItem( LIB_ITEM* aItem, OUTPUTFORMATTE
switch( aItem->Type() ) switch( aItem->Type() )
{ {
case LIB_ARC_T: case LIB_SHAPE_T:
saveArc( (LIB_ARC*) aItem, aFormatter, aNestLevel ); {
break; LIB_SHAPE* shape = static_cast<LIB_SHAPE*>( aItem );
case LIB_BEZIER_T: switch( shape->GetShape() )
saveBezier( (LIB_BEZIER*) aItem, aFormatter, aNestLevel ); {
break; case SHAPE_T::ARC: saveArc( shape, aFormatter, aNestLevel ); break;
case SHAPE_T::CIRCLE: saveCircle( shape, aFormatter, aNestLevel ); break;
case SHAPE_T::RECT: saveRectangle( shape, aFormatter, aNestLevel ); break;
case SHAPE_T::BEZIER: saveBezier( shape, aFormatter, aNestLevel ); break;
case SHAPE_T::POLY: savePolyLine( shape, aFormatter, aNestLevel ); break;
default:
UNIMPLEMENTED_FOR( shape->SHAPE_T_asString() );
}
case LIB_CIRCLE_T:
saveCircle( ( LIB_CIRCLE* ) aItem, aFormatter, aNestLevel );
break; break;
}
case LIB_PIN_T: case LIB_PIN_T:
savePin( (LIB_PIN* ) aItem, aFormatter, aNestLevel ); savePin( (LIB_PIN* ) aItem, aFormatter, aNestLevel );
break; break;
case LIB_POLYLINE_T:
savePolyLine( ( LIB_POLYLINE* ) aItem, aFormatter, aNestLevel );
break;
case LIB_RECTANGLE_T:
saveRectangle( ( LIB_RECTANGLE* ) aItem, aFormatter, aNestLevel );
break;
case LIB_TEXT_T: case LIB_TEXT_T:
saveText( ( LIB_TEXT* ) aItem, aFormatter, aNestLevel ); saveText( ( LIB_TEXT* ) aItem, aFormatter, aNestLevel );
break; break;
default: default:
; UNIMPLEMENTED_FOR( aItem->GetClass() );
} }
} }
void SCH_SEXPR_PLUGIN_CACHE::saveArc( LIB_ARC* aArc, OUTPUTFORMATTER& aFormatter, void SCH_SEXPR_PLUGIN_CACHE::saveArc( LIB_SHAPE* aArc, OUTPUTFORMATTER& aFormatter, int aNestLevel )
int aNestLevel )
{ {
wxCHECK_RET( aArc && aArc->Type() == LIB_ARC_T, "Invalid LIB_ARC object." );
int x1; int x1;
int x2; int x2;
aArc->CalcAngles( x1, x2 ); aArc->CalcArcAngles( x1, x2 );
if( x1 > 1800 ) if( x1 > 1800 )
x1 -= 3600; x1 -= 3600;
@ -1828,8 +1813,8 @@ void SCH_SEXPR_PLUGIN_CACHE::saveArc( LIB_ARC* aArc, OUTPUTFORMATTER& aFormatter
FormatInternalUnits( aArc->GetStart().y ).c_str(), FormatInternalUnits( aArc->GetStart().y ).c_str(),
FormatInternalUnits( aArc->GetEnd().x ).c_str(), FormatInternalUnits( aArc->GetEnd().x ).c_str(),
FormatInternalUnits( aArc->GetEnd().y ).c_str(), FormatInternalUnits( aArc->GetEnd().y ).c_str(),
FormatInternalUnits( aArc->GetPosition().x ).c_str(), FormatInternalUnits( aArc->GetCenter().x ).c_str(),
FormatInternalUnits( aArc->GetPosition().y ).c_str(), FormatInternalUnits( aArc->GetCenter().y ).c_str(),
FormatInternalUnits( aArc->GetRadius() ).c_str(), FormatInternalUnits( aArc->GetRadius() ).c_str(),
static_cast<double>( x1 ) / 10.0, static_cast<double>( x1 ) / 10.0,
static_cast<double>( x2 ) / 10.0 ); static_cast<double>( x2 ) / 10.0 );
@ -1838,76 +1823,47 @@ void SCH_SEXPR_PLUGIN_CACHE::saveArc( LIB_ARC* aArc, OUTPUTFORMATTER& aFormatter
aFormatter.Print( aNestLevel + 1, "(stroke (width %s)) ", aFormatter.Print( aNestLevel + 1, "(stroke (width %s)) ",
FormatInternalUnits( aArc->GetWidth() ).c_str() ); FormatInternalUnits( aArc->GetWidth() ).c_str() );
formatFill( static_cast< LIB_ITEM* >( aArc ), aFormatter, 0 ); formatFill( aArc, aFormatter, 0 );
aFormatter.Print( 0, "\n" ); aFormatter.Print( 0, "\n" );
aFormatter.Print( aNestLevel, ")\n" ); aFormatter.Print( aNestLevel, ")\n" );
} }
void SCH_SEXPR_PLUGIN_CACHE::saveBezier( LIB_BEZIER* aBezier, void SCH_SEXPR_PLUGIN_CACHE::saveBezier( LIB_SHAPE* aBezier, OUTPUTFORMATTER& aFormatter,
OUTPUTFORMATTER& aFormatter,
int aNestLevel ) int aNestLevel )
{ {
wxCHECK_RET( aBezier && aBezier->Type() == LIB_BEZIER_T, "Invalid LIB_BEZIER object." );
int newLine = 0;
int lineCount = 1;
aFormatter.Print( aNestLevel, "(bezier\n" ); aFormatter.Print( aNestLevel, "(bezier\n" );
aFormatter.Print( aNestLevel + 1, "(pts " ); aFormatter.Print( aNestLevel + 1, "(pts " );
for( const auto& pt : aBezier->GetPoints() ) for( const wxPoint& pt : { aBezier->GetStart(), aBezier->GetBezierC1(),
{ aBezier->GetBezierC2(), aBezier->GetEnd() } )
if( newLine == 4 )
{
aFormatter.Print( 0, "\n" );
aFormatter.Print( aNestLevel + 3, " (xy %s %s)",
FormatInternalUnits( pt.x ).c_str(),
FormatInternalUnits( pt.y ).c_str() );
newLine = 0;
lineCount += 1;
}
else
{ {
aFormatter.Print( 0, " (xy %s %s)", aFormatter.Print( 0, " (xy %s %s)",
FormatInternalUnits( pt.x ).c_str(), FormatInternalUnits( pt.x ).c_str(),
FormatInternalUnits( pt.y ).c_str() ); FormatInternalUnits( pt.y ).c_str() );
} }
newLine += 1;
}
if( lineCount == 1 )
{
aFormatter.Print( 0, ")\n" ); // Closes pts token on same line. aFormatter.Print( 0, ")\n" ); // Closes pts token on same line.
}
else
{
aFormatter.Print( 0, "\n" );
aFormatter.Print( aNestLevel + 1, ")\n" ); // Closes pts token with multiple lines.
}
aFormatter.Print( aNestLevel + 1, "(stroke (width %s)) ", aFormatter.Print( aNestLevel + 1, "(stroke (width %s)) ",
FormatInternalUnits( aBezier->GetWidth() ).c_str() ); FormatInternalUnits( aBezier->GetWidth() ).c_str() );
formatFill( static_cast< LIB_ITEM* >( aBezier ), aFormatter, 0 ); formatFill( aBezier, aFormatter, 0 );
aFormatter.Print( 0, "\n" ); aFormatter.Print( 0, "\n" );
aFormatter.Print( aNestLevel, ")\n" ); aFormatter.Print( aNestLevel, ")\n" );
} }
void SCH_SEXPR_PLUGIN_CACHE::saveCircle( LIB_CIRCLE* aCircle, void SCH_SEXPR_PLUGIN_CACHE::saveCircle( LIB_SHAPE* aCircle, OUTPUTFORMATTER& aFormatter,
OUTPUTFORMATTER& aFormatter,
int aNestLevel ) int aNestLevel )
{ {
wxCHECK_RET( aCircle && aCircle->Type() == LIB_CIRCLE_T, "Invalid LIB_CIRCLE object." );
aFormatter.Print( aNestLevel, "(circle (center %s %s) (radius %s) (stroke (width %s)) ", aFormatter.Print( aNestLevel, "(circle (center %s %s) (radius %s) (stroke (width %s)) ",
FormatInternalUnits( aCircle->GetPosition().x ).c_str(), FormatInternalUnits( aCircle->GetPosition().x ).c_str(),
FormatInternalUnits( aCircle->GetPosition().y ).c_str(), FormatInternalUnits( aCircle->GetPosition().y ).c_str(),
FormatInternalUnits( aCircle->GetRadius() ).c_str(), FormatInternalUnits( aCircle->GetRadius() ).c_str(),
FormatInternalUnits( aCircle->GetWidth() ).c_str() ); FormatInternalUnits( aCircle->GetWidth() ).c_str() );
formatFill( static_cast< LIB_ITEM* >( aCircle ), aFormatter, 0 ); formatFill( aCircle, aFormatter, 0 );
aFormatter.Print( 0, ")\n" ); aFormatter.Print( 0, ")\n" );
} }
@ -1988,17 +1944,15 @@ void SCH_SEXPR_PLUGIN_CACHE::savePin( LIB_PIN* aPin, OUTPUTFORMATTER& aFormatter
} }
void SCH_SEXPR_PLUGIN_CACHE::savePolyLine( LIB_POLYLINE* aPolyLine, OUTPUTFORMATTER& aFormatter, void SCH_SEXPR_PLUGIN_CACHE::savePolyLine( LIB_SHAPE* aPolyLine, OUTPUTFORMATTER& aFormatter,
int aNestLevel ) int aNestLevel )
{ {
wxCHECK_RET( aPolyLine && aPolyLine->Type() == LIB_POLYLINE_T, "Invalid LIB_POLYLINE object." );
int newLine = 0; int newLine = 0;
int lineCount = 1; int lineCount = 1;
aFormatter.Print( aNestLevel, "(polyline\n" ); aFormatter.Print( aNestLevel, "(polyline\n" );
aFormatter.Print( aNestLevel + 1, "(pts" ); aFormatter.Print( aNestLevel + 1, "(pts" );
for( const auto& pt : aPolyLine->GetPolyPoints() ) for( const VECTOR2I& pt : aPolyLine->GetPolyShape().Outline( 0 ).CPoints() )
{ {
if( newLine == 4 || !ADVANCED_CFG::GetCfg().m_CompactSave ) if( newLine == 4 || !ADVANCED_CFG::GetCfg().m_CompactSave )
{ {
@ -2031,26 +1985,23 @@ void SCH_SEXPR_PLUGIN_CACHE::savePolyLine( LIB_POLYLINE* aPolyLine, OUTPUTFORMAT
aFormatter.Print( aNestLevel + 1, "(stroke (width %s)) ", aFormatter.Print( aNestLevel + 1, "(stroke (width %s)) ",
FormatInternalUnits( aPolyLine->GetWidth() ).c_str() ); FormatInternalUnits( aPolyLine->GetWidth() ).c_str() );
formatFill( static_cast< LIB_ITEM* >( aPolyLine ), aFormatter, 0 ); formatFill( aPolyLine, aFormatter, 0 );
aFormatter.Print( 0, "\n" ); aFormatter.Print( 0, "\n" );
aFormatter.Print( aNestLevel, ")\n" ); aFormatter.Print( aNestLevel, ")\n" );
} }
void SCH_SEXPR_PLUGIN_CACHE::saveRectangle( LIB_RECTANGLE* aRectangle, OUTPUTFORMATTER& aFormatter, void SCH_SEXPR_PLUGIN_CACHE::saveRectangle( LIB_SHAPE* aRect, OUTPUTFORMATTER& aFormatter,
int aNestLevel ) int aNestLevel )
{ {
wxCHECK_RET( aRectangle && aRectangle->Type() == LIB_RECTANGLE_T,
"Invalid LIB_RECTANGLE object." );
aFormatter.Print( aNestLevel, "(rectangle (start %s %s) (end %s %s)\n", aFormatter.Print( aNestLevel, "(rectangle (start %s %s) (end %s %s)\n",
FormatInternalUnits( aRectangle->GetPosition().x ).c_str(), FormatInternalUnits( aRect->GetPosition().x ).c_str(),
FormatInternalUnits( aRectangle->GetPosition().y ).c_str(), FormatInternalUnits( aRect->GetPosition().y ).c_str(),
FormatInternalUnits( aRectangle->GetEnd().x ).c_str(), FormatInternalUnits( aRect->GetEnd().x ).c_str(),
FormatInternalUnits( aRectangle->GetEnd().y ).c_str() ); FormatInternalUnits( aRect->GetEnd().y ).c_str() );
aFormatter.Print( aNestLevel + 1, "(stroke (width %s)) ", aFormatter.Print( aNestLevel + 1, "(stroke (width %s)) ",
FormatInternalUnits( aRectangle->GetWidth() ).c_str() ); FormatInternalUnits( aRect->GetWidth() ).c_str() );
formatFill( static_cast< LIB_ITEM* >( aRectangle ), aFormatter, 0 ); formatFill( aRect, aFormatter, 0 );
aFormatter.Print( 0, "\n" ); aFormatter.Print( 0, "\n" );
aFormatter.Print( aNestLevel, ")\n" ); aFormatter.Print( aNestLevel, ")\n" );
} }

View File

@ -56,13 +56,9 @@
#include <sch_screen.h> #include <sch_screen.h>
#include <schematic.h> #include <schematic.h>
#include <symbol_library.h> #include <symbol_library.h>
#include <lib_arc.h> #include <lib_shape.h>
#include <lib_bezier.h>
#include <lib_circle.h>
#include <lib_field.h> #include <lib_field.h>
#include <lib_pin.h> #include <lib_pin.h>
#include <lib_polyline.h>
#include <lib_rectangle.h>
#include <lib_text.h> #include <lib_text.h>
#include <eeschema_id.h> // for MAX_UNIT_COUNT_PER_PACKAGE definition #include <eeschema_id.h> // for MAX_UNIT_COUNT_PER_PACKAGE definition
#include <tool/selection.h> #include <tool/selection.h>
@ -486,36 +482,24 @@ class SCH_LEGACY_PLUGIN_CACHE
static void loadAliases( std::unique_ptr<LIB_SYMBOL>& aSymbol, LINE_READER& aReader, static void loadAliases( std::unique_ptr<LIB_SYMBOL>& aSymbol, LINE_READER& aReader,
LIB_SYMBOL_MAP* aMap = nullptr ); LIB_SYMBOL_MAP* aMap = nullptr );
static void loadField( std::unique_ptr<LIB_SYMBOL>& aSymbol, LINE_READER& aReader ); static void loadField( std::unique_ptr<LIB_SYMBOL>& aSymbol, LINE_READER& aReader );
static void loadDrawEntries( std::unique_ptr<LIB_SYMBOL>& aSymbol, static void loadDrawEntries( std::unique_ptr<LIB_SYMBOL>& aSymbol, LINE_READER& aReader,
LINE_READER& aReader,
int aMajorVersion, int aMinorVersion ); int aMajorVersion, int aMinorVersion );
static void loadFootprintFilters( std::unique_ptr<LIB_SYMBOL>& aSymbol, static void loadFootprintFilters( std::unique_ptr<LIB_SYMBOL>& aSymbol,
LINE_READER& aReader ); LINE_READER& aReader );
void loadDocs(); void loadDocs();
static LIB_ARC* loadArc( std::unique_ptr<LIB_SYMBOL>& aSymbol, LINE_READER& aReader ); static LIB_SHAPE* loadArc( std::unique_ptr<LIB_SYMBOL>& aSymbol, LINE_READER& aReader );
static LIB_CIRCLE* loadCircle( std::unique_ptr<LIB_SYMBOL>& aSymbol, LINE_READER& aReader ); static LIB_SHAPE* loadCircle( std::unique_ptr<LIB_SYMBOL>& aSymbol, LINE_READER& aReader );
static LIB_TEXT* loadText( std::unique_ptr<LIB_SYMBOL>& aSymbol, LINE_READER& aReader, static LIB_TEXT* loadText( std::unique_ptr<LIB_SYMBOL>& aSymbol, LINE_READER& aReader,
int aMajorVersion, int aMinorVersion ); int aMajorVersion, int aMinorVersion );
static LIB_RECTANGLE* loadRectangle( std::unique_ptr<LIB_SYMBOL>& aSymbol, static LIB_SHAPE* loadRect( std::unique_ptr<LIB_SYMBOL>& aSymbol, LINE_READER& aReader );
LINE_READER& aReader );
static LIB_PIN* loadPin( std::unique_ptr<LIB_SYMBOL>& aSymbol, LINE_READER& aReader ); static LIB_PIN* loadPin( std::unique_ptr<LIB_SYMBOL>& aSymbol, LINE_READER& aReader );
static LIB_POLYLINE* loadPolyLine( std::unique_ptr<LIB_SYMBOL>& aSymbol, static LIB_SHAPE* loadPolyLine( std::unique_ptr<LIB_SYMBOL>& aSymbol, LINE_READER& aReader );
LINE_READER& aReader ); static LIB_SHAPE* loadBezier( std::unique_ptr<LIB_SYMBOL>& aSymbol, LINE_READER& aReader );
static LIB_BEZIER* loadBezier( std::unique_ptr<LIB_SYMBOL>& aSymbol, LINE_READER& aReader );
static FILL_TYPE parseFillMode( LINE_READER& aReader, const char* aLine, static FILL_T parseFillMode( LINE_READER& aReader, const char* aLine, const char** aOutput );
const char** aOutput );
LIB_SYMBOL* removeSymbol( LIB_SYMBOL* aAlias ); LIB_SYMBOL* removeSymbol( LIB_SYMBOL* aAlias );
void saveDocFile(); void saveDocFile();
static void saveArc( LIB_ARC* aArc, OUTPUTFORMATTER& aFormatter );
static void saveBezier( LIB_BEZIER* aBezier, OUTPUTFORMATTER& aFormatter );
static void saveCircle( LIB_CIRCLE* aCircle, OUTPUTFORMATTER& aFormatter );
static void saveField( const LIB_FIELD* aField, OUTPUTFORMATTER& aFormatter );
static void savePin( const LIB_PIN* aPin, OUTPUTFORMATTER& aFormatter );
static void savePolyLine( LIB_POLYLINE* aPolyLine, OUTPUTFORMATTER& aFormatter );
static void saveRectangle( LIB_RECTANGLE* aRectangle, OUTPUTFORMATTER& aFormatter );
static void saveText( const LIB_TEXT* aText, OUTPUTFORMATTER& aFormatter );
friend SCH_LEGACY_PLUGIN; friend SCH_LEGACY_PLUGIN;
@ -3217,7 +3201,7 @@ void SCH_LEGACY_PLUGIN_CACHE::loadDrawEntries( std::unique_ptr<LIB_SYMBOL>& aSym
break; break;
case 'S': // Square case 'S': // Square
aSymbol->AddDrawItem( loadRectangle( aSymbol, aReader ), false ); aSymbol->AddDrawItem( loadRect( aSymbol, aReader ), false );
break; break;
case 'X': // Pin Description case 'X': // Pin Description
@ -3249,30 +3233,30 @@ void SCH_LEGACY_PLUGIN_CACHE::loadDrawEntries( std::unique_ptr<LIB_SYMBOL>& aSym
} }
FILL_TYPE SCH_LEGACY_PLUGIN_CACHE::parseFillMode( LINE_READER& aReader, const char* aLine, FILL_T SCH_LEGACY_PLUGIN_CACHE::parseFillMode( LINE_READER& aReader, const char* aLine,
const char** aOutput ) const char** aOutput )
{ {
switch ( parseChar( aReader, aLine, aOutput ) ) switch ( parseChar( aReader, aLine, aOutput ) )
{ {
case 'F': return FILL_TYPE::FILLED_SHAPE; case 'F': return FILL_T::FILLED_SHAPE;
case 'f': return FILL_TYPE::FILLED_WITH_BG_BODYCOLOR; case 'f': return FILL_T::FILLED_WITH_BG_BODYCOLOR;
case 'N': return FILL_TYPE::NO_FILL; case 'N': return FILL_T::NO_FILL;
default: SCH_PARSE_ERROR( "invalid fill type, expected f, F, or N", aReader, aLine ); default: SCH_PARSE_ERROR( "invalid fill type, expected f, F, or N", aReader, aLine );
} }
// This will never be reached but quiets the compiler warnings // This will never be reached but quiets the compiler warnings
return FILL_TYPE::NO_FILL; return FILL_T::NO_FILL;
} }
LIB_ARC* SCH_LEGACY_PLUGIN_CACHE::loadArc( std::unique_ptr<LIB_SYMBOL>& aSymbol, LIB_SHAPE* SCH_LEGACY_PLUGIN_CACHE::loadArc( std::unique_ptr<LIB_SYMBOL>& aSymbol,
LINE_READER& aReader ) LINE_READER& aReader )
{ {
const char* line = aReader.Line(); const char* line = aReader.Line();
wxCHECK_MSG( strCompare( "A", line, &line ), nullptr, "Invalid LIB_ARC definition" ); wxCHECK_MSG( strCompare( "A", line, &line ), nullptr, "Invalid arc definition" );
LIB_ARC* arc = new LIB_ARC( aSymbol.get() ); LIB_SHAPE* arc = new LIB_SHAPE( aSymbol.get(), SHAPE_T::ARC );
wxPoint center; wxPoint center;
@ -3343,22 +3327,24 @@ LIB_ARC* SCH_LEGACY_PLUGIN_CACHE::loadArc( std::unique_ptr<LIB_SYMBOL>& aSymbol,
} }
LIB_CIRCLE* SCH_LEGACY_PLUGIN_CACHE::loadCircle( std::unique_ptr<LIB_SYMBOL>& aSymbol, LIB_SHAPE* SCH_LEGACY_PLUGIN_CACHE::loadCircle( std::unique_ptr<LIB_SYMBOL>& aSymbol,
LINE_READER& aReader ) LINE_READER& aReader )
{ {
const char* line = aReader.Line(); const char* line = aReader.Line();
wxCHECK_MSG( strCompare( "C", line, &line ), nullptr, "Invalid LIB_CIRCLE definition" ); wxCHECK_MSG( strCompare( "C", line, &line ), nullptr, "Invalid circle definition" );
LIB_CIRCLE* circle = new LIB_CIRCLE( aSymbol.get() ); LIB_SHAPE* circle = new LIB_SHAPE( aSymbol.get(), SHAPE_T::CIRCLE );
wxPoint center; wxPoint center;
center.x = Mils2Iu( parseInt( aReader, line, &line ) ); center.x = Mils2Iu( parseInt( aReader, line, &line ) );
center.y = Mils2Iu( parseInt( aReader, line, &line ) ); center.y = Mils2Iu( parseInt( aReader, line, &line ) );
circle->SetPosition( center ); int radius = Mils2Iu( parseInt( aReader, line, &line ) );
circle->SetRadius( Mils2Iu( parseInt( aReader, line, &line ) ) );
circle->SetStart( center );
circle->SetEnd( wxPoint( center.x + radius, center.y ) );
circle->SetUnit( parseInt( aReader, line, &line ) ); circle->SetUnit( parseInt( aReader, line, &line ) );
circle->SetConvert( parseInt( aReader, line, &line ) ); circle->SetConvert( parseInt( aReader, line, &line ) );
circle->SetWidth( Mils2Iu( parseInt( aReader, line, &line ) ) ); circle->SetWidth( Mils2Iu( parseInt( aReader, line, &line ) ) );
@ -3467,14 +3453,14 @@ LIB_TEXT* SCH_LEGACY_PLUGIN_CACHE::loadText( std::unique_ptr<LIB_SYMBOL>& aSymbo
} }
LIB_RECTANGLE* SCH_LEGACY_PLUGIN_CACHE::loadRectangle( std::unique_ptr<LIB_SYMBOL>& aSymbol, LIB_SHAPE* SCH_LEGACY_PLUGIN_CACHE::loadRect( std::unique_ptr<LIB_SYMBOL>& aSymbol,
LINE_READER& aReader ) LINE_READER& aReader )
{ {
const char* line = aReader.Line(); const char* line = aReader.Line();
wxCHECK_MSG( strCompare( "S", line, &line ), nullptr, "Invalid LIB_RECTANGLE definition" ); wxCHECK_MSG( strCompare( "S", line, &line ), nullptr, "Invalid rectangle definition" );
LIB_RECTANGLE* rectangle = new LIB_RECTANGLE( aSymbol.get() ); LIB_SHAPE* rectangle = new LIB_SHAPE( aSymbol.get(), SHAPE_T::RECT );
wxPoint pos; wxPoint pos;
@ -3698,20 +3684,19 @@ LIB_PIN* SCH_LEGACY_PLUGIN_CACHE::loadPin( std::unique_ptr<LIB_SYMBOL>& aSymbol,
} }
LIB_POLYLINE* SCH_LEGACY_PLUGIN_CACHE::loadPolyLine( std::unique_ptr<LIB_SYMBOL>& aSymbol, LIB_SHAPE* SCH_LEGACY_PLUGIN_CACHE::loadPolyLine( std::unique_ptr<LIB_SYMBOL>& aSymbol,
LINE_READER& aReader ) LINE_READER& aReader )
{ {
const char* line = aReader.Line(); const char* line = aReader.Line();
wxCHECK_MSG( strCompare( "P", line, &line ), nullptr, "Invalid LIB_POLYLINE definition" ); wxCHECK_MSG( strCompare( "P", line, &line ), nullptr, "Invalid poly definition" );
LIB_POLYLINE* polyLine = new LIB_POLYLINE( aSymbol.get() ); LIB_SHAPE* polyLine = new LIB_SHAPE( aSymbol.get(), SHAPE_T::POLY );
int points = parseInt( aReader, line, &line ); int points = parseInt( aReader, line, &line );
polyLine->SetUnit( parseInt( aReader, line, &line ) ); polyLine->SetUnit( parseInt( aReader, line, &line ) );
polyLine->SetConvert( parseInt( aReader, line, &line ) ); polyLine->SetConvert( parseInt( aReader, line, &line ) );
polyLine->SetWidth( Mils2Iu( parseInt( aReader, line, &line ) ) ); polyLine->SetWidth( Mils2Iu( parseInt( aReader, line, &line ) ) );
polyLine->Reserve( points );
wxPoint pt; wxPoint pt;
@ -3729,29 +3714,36 @@ LIB_POLYLINE* SCH_LEGACY_PLUGIN_CACHE::loadPolyLine( std::unique_ptr<LIB_SYMBOL>
} }
LIB_BEZIER* SCH_LEGACY_PLUGIN_CACHE::loadBezier( std::unique_ptr<LIB_SYMBOL>& aSymbol, LIB_SHAPE* SCH_LEGACY_PLUGIN_CACHE::loadBezier( std::unique_ptr<LIB_SYMBOL>& aSymbol,
LINE_READER& aReader ) LINE_READER& aReader )
{ {
const char* line = aReader.Line(); const char* line = aReader.Line();
wxCHECK_MSG( strCompare( "B", line, &line ), nullptr, "Invalid LIB_BEZIER definition" ); wxCHECK_MSG( strCompare( "B", line, &line ), nullptr, "Invalid Bezier definition" );
LIB_BEZIER* bezier = new LIB_BEZIER( aSymbol.get() );
int points = parseInt( aReader, line, &line ); int points = parseInt( aReader, line, &line );
wxCHECK_MSG( points == 4, NULL, "Invalid Bezier curve definition" );
LIB_SHAPE* bezier = new LIB_SHAPE( aSymbol.get(), SHAPE_T::BEZIER );
bezier->SetUnit( parseInt( aReader, line, &line ) ); bezier->SetUnit( parseInt( aReader, line, &line ) );
bezier->SetConvert( parseInt( aReader, line, &line ) ); bezier->SetConvert( parseInt( aReader, line, &line ) );
bezier->SetWidth( Mils2Iu( parseInt( aReader, line, &line ) ) ); bezier->SetWidth( Mils2Iu( parseInt( aReader, line, &line ) ) );
wxPoint pt; bezier->SetStart( wxPoint( Mils2Iu( parseInt( aReader, line, &line ) ),
bezier->Reserve( points ); Mils2Iu( parseInt( aReader, line, &line ) ) ) );
for( int i = 0; i < points; i++ ) bezier->SetBezierC1( wxPoint( Mils2Iu( parseInt( aReader, line, &line ) ),
{ Mils2Iu( parseInt( aReader, line, &line ) ) ) );
pt.x = Mils2Iu( parseInt( aReader, line, &line ) );
pt.y = Mils2Iu( parseInt( aReader, line, &line ) ); bezier->SetBezierC2( wxPoint( Mils2Iu( parseInt( aReader, line, &line ) ),
bezier->AddPoint( pt ); Mils2Iu( parseInt( aReader, line, &line ) ) ) );
}
bezier->SetEnd( wxPoint( Mils2Iu( parseInt( aReader, line, &line ) ),
Mils2Iu( parseInt( aReader, line, &line ) ) ) );
bezier->RebuildBezierToSegmentsPointsList( bezier->GetWidth() );
if( *line != 0 ) if( *line != 0 )
bezier->SetFillMode( parseFillMode( aReader, line, &line ) ); bezier->SetFillMode( parseFillMode( aReader, line, &line ) );
@ -3824,408 +3816,13 @@ void SCH_LEGACY_PLUGIN_CACHE::Save( bool aSaveDocFile )
void SCH_LEGACY_PLUGIN_CACHE::SaveSymbol( LIB_SYMBOL* aSymbol, OUTPUTFORMATTER& aFormatter, void SCH_LEGACY_PLUGIN_CACHE::SaveSymbol( LIB_SYMBOL* aSymbol, OUTPUTFORMATTER& aFormatter,
LIB_SYMBOL_MAP* aMap ) LIB_SYMBOL_MAP* aMap )
{ {
wxCHECK_RET( aSymbol && aSymbol->IsRoot(), "Invalid LIB_SYMBOL pointer." ); wxFAIL_MSG( "Writing of legacy format no longer supported." );
// LIB_ALIAS objects are deprecated but we still need to gather up the derived symbols
// and save their names for the old file format.
wxArrayString aliasNames;
if( aMap )
{
for( auto entry : *aMap )
{
LIB_SYMBOL* symbol = entry.second;
if( symbol->IsAlias() && symbol->GetParent().lock() == aSymbol->SharedPtr() )
aliasNames.Add( symbol->GetName() );
}
}
LIB_FIELD& value = aSymbol->GetValueField();
// First line: it s a comment (symbol name for readers)
aFormatter.Print( 0, "#\n# %s\n#\n", TO_UTF8( value.GetText() ) );
// Save data
aFormatter.Print( 0, "DEF" );
aFormatter.Print( 0, " %s", TO_UTF8( value.GetText() ) );
LIB_FIELD& reference = aSymbol->GetReferenceField();
if( !reference.GetText().IsEmpty() )
{
aFormatter.Print( 0, " %s", TO_UTF8( reference.GetText() ) );
}
else
{
aFormatter.Print( 0, " ~" );
}
aFormatter.Print( 0, " %d %d %c %c %d %c %c\n",
0, Iu2Mils( aSymbol->GetPinNameOffset() ),
aSymbol->ShowPinNumbers() ? 'Y' : 'N',
aSymbol->ShowPinNames() ? 'Y' : 'N',
aSymbol->GetUnitCount(), aSymbol->UnitsLocked() ? 'L' : 'F',
aSymbol->IsPower() ? 'P' : 'N' );
timestamp_t dateModified = aSymbol->GetLastModDate();
if( dateModified != 0 )
{
int sec = dateModified & 63;
int min = ( dateModified >> 6 ) & 63;
int hour = ( dateModified >> 12 ) & 31;
int day = ( dateModified >> 17 ) & 31;
int mon = ( dateModified >> 22 ) & 15;
int year = ( dateModified >> 26 ) + 1990;
aFormatter.Print( 0, "Ti %d/%d/%d %d:%d:%d\n", year, mon, day, hour, min, sec );
}
std::vector<LIB_FIELD*> fields;
aSymbol->GetFields( fields );
// Mandatory fields:
// may have their own save policy so there is a separate loop for them.
// Empty fields are saved, because the user may have set visibility,
// size and orientation
for( int i = 0; i < MANDATORY_FIELDS; ++i )
saveField( fields[i], aFormatter );
// User defined fields:
// may have their own save policy so there is a separate loop for them.
int fieldId = MANDATORY_FIELDS; // really wish this would go away.
for( unsigned i = MANDATORY_FIELDS; i < fields.size(); ++i )
{
// There is no need to save empty fields, i.e. no reason to preserve field
// names now that fields names come in dynamically through the template
// fieldnames.
if( !fields[i]->GetText().IsEmpty() )
{
fields[i]->SetId( fieldId++ );
saveField( fields[i], aFormatter );
}
}
// Save the alias list: a line starting by "ALIAS".
if( !aliasNames.IsEmpty() )
{
aFormatter.Print( 0, "ALIAS" );
for( unsigned i = 0; i < aliasNames.GetCount(); i++ )
aFormatter.Print( 0, " %s", TO_UTF8( aliasNames[i] ) );
aFormatter.Print( 0, "\n" );
}
wxArrayString footprints = aSymbol->GetFPFilters();
// Write the footprint filter list
if( footprints.GetCount() != 0 )
{
aFormatter.Print( 0, "$FPLIST\n" );
for( unsigned i = 0; i < footprints.GetCount(); i++ )
aFormatter.Print( 0, " %s\n", TO_UTF8( footprints[i] ) );
aFormatter.Print( 0, "$ENDFPLIST\n" );
}
// Save graphics items (including pins)
if( !aSymbol->GetDrawItems().empty() )
{
// Sort the draw items in order to editing a file editing by hand.
aSymbol->GetDrawItems().sort();
aFormatter.Print( 0, "DRAW\n" );
for( LIB_ITEM& item : aSymbol->GetDrawItems() )
{
switch( item.Type() )
{
default:
case LIB_FIELD_T: /* Fields have already been saved above. */ break;
case LIB_ARC_T: saveArc( (LIB_ARC*) &item, aFormatter ); break;
case LIB_BEZIER_T: saveBezier( (LIB_BEZIER*) &item, aFormatter ); break;
case LIB_CIRCLE_T: saveCircle( ( LIB_CIRCLE* ) &item, aFormatter ); break;
case LIB_PIN_T: savePin( (LIB_PIN* ) &item, aFormatter ); break;
case LIB_POLYLINE_T: savePolyLine( ( LIB_POLYLINE* ) &item, aFormatter ); break;
case LIB_RECTANGLE_T: saveRectangle( ( LIB_RECTANGLE* ) &item, aFormatter ); break;
case LIB_TEXT_T: saveText( ( LIB_TEXT* ) &item, aFormatter ); break;
}
}
aFormatter.Print( 0, "ENDDRAW\n" );
}
aFormatter.Print( 0, "ENDDEF\n" );
}
void SCH_LEGACY_PLUGIN_CACHE::saveArc( LIB_ARC* aArc, OUTPUTFORMATTER& aFormatter )
{
wxCHECK_RET( aArc && aArc->Type() == LIB_ARC_T, "Invalid LIB_ARC object." );
int x1;
int x2;
aArc->CalcAngles( x1, x2 );
if( x1 > 1800 )
x1 -= 3600;
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[ (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 )
{
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 wxPoint& pt : aBezier->GetPoints() )
aFormatter.Print( 0, " %d %d", Iu2Mils( pt.x ), Iu2Mils( pt.y ) );
aFormatter.Print( 0, " %c\n", fill_tab[static_cast<int>( aBezier->GetFillMode() )] );
}
void SCH_LEGACY_PLUGIN_CACHE::saveCircle( LIB_CIRCLE* aCircle, OUTPUTFORMATTER& aFormatter )
{
wxCHECK_RET( aCircle && aCircle->Type() == LIB_CIRCLE_T, "Invalid LIB_CIRCLE object." );
aFormatter.Print( 0, "C %d %d %d %d %d %d %c\n",
Iu2Mils( aCircle->GetPosition().x ), Iu2Mils( aCircle->GetPosition().y ),
Iu2Mils( aCircle->GetRadius() ), aCircle->GetUnit(), aCircle->GetConvert(),
Iu2Mils( aCircle->GetWidth() ),
fill_tab[static_cast<int>( aCircle->GetFillMode() )] );
}
void SCH_LEGACY_PLUGIN_CACHE::saveField( const LIB_FIELD* aField, OUTPUTFORMATTER& aFormatter )
{
wxCHECK_RET( aField && aField->Type() == LIB_FIELD_T, "Invalid LIB_FIELD object." );
int hjustify, vjustify;
int id = aField->GetId();
wxString text = aField->GetText();
hjustify = 'C';
if( aField->GetHorizJustify() == GR_TEXT_HJUSTIFY_LEFT )
hjustify = 'L';
else if( aField->GetHorizJustify() == GR_TEXT_HJUSTIFY_RIGHT )
hjustify = 'R';
vjustify = 'C';
if( aField->GetVertJustify() == GR_TEXT_VJUSTIFY_BOTTOM )
vjustify = 'B';
else if( aField->GetVertJustify() == GR_TEXT_VJUSTIFY_TOP )
vjustify = 'T';
aFormatter.Print( 0, "F%d %s %d %d %d %c %c %c %c%c%c",
id,
EscapedUTF8( text ).c_str(), // wraps in quotes
Iu2Mils( aField->GetTextPos().x ), Iu2Mils( aField->GetTextPos().y ),
Iu2Mils( aField->GetTextWidth() ),
aField->GetTextAngle() == 0 ? 'H' : 'V',
aField->IsVisible() ? 'V' : 'I',
hjustify, vjustify,
aField->IsItalic() ? 'I' : 'N',
aField->IsBold() ? 'B' : 'N' );
/* Save field name, if necessary
* Field name is saved only if it is not the default name.
* Just because default name depends on the language and can change from
* a country to another
*/
wxString defName = TEMPLATE_FIELDNAME::GetDefaultFieldName( id );
if( id >= MANDATORY_FIELDS && !aField->m_name.IsEmpty() && aField->m_name != defName )
aFormatter.Print( 0, " %s", EscapedUTF8( aField->m_name ).c_str() );
aFormatter.Print( 0, "\n" );
}
void SCH_LEGACY_PLUGIN_CACHE::savePin( const LIB_PIN* aPin, OUTPUTFORMATTER& aFormatter )
{
wxCHECK_RET( aPin && aPin->Type() == LIB_PIN_T, "Invalid LIB_PIN object." );
int Etype;
switch( aPin->GetType() )
{
default:
case ELECTRICAL_PINTYPE::PT_INPUT: Etype = 'I'; break;
case ELECTRICAL_PINTYPE::PT_OUTPUT: Etype = 'O'; break;
case ELECTRICAL_PINTYPE::PT_BIDI: Etype = 'B'; break;
case ELECTRICAL_PINTYPE::PT_TRISTATE: Etype = 'T'; break;
case ELECTRICAL_PINTYPE::PT_PASSIVE: Etype = 'P'; break;
case ELECTRICAL_PINTYPE::PT_UNSPECIFIED: Etype = 'U'; break;
case ELECTRICAL_PINTYPE::PT_POWER_IN: Etype = 'W'; break;
case ELECTRICAL_PINTYPE::PT_POWER_OUT: Etype = 'w'; break;
case ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR: Etype = 'C'; break;
case ELECTRICAL_PINTYPE::PT_OPENEMITTER: Etype = 'E'; break;
case ELECTRICAL_PINTYPE::PT_NC: Etype = 'N'; break;
}
if( !aPin->GetName().IsEmpty() )
aFormatter.Print( 0, "X %s", TO_UTF8( aPin->GetName() ) );
else
aFormatter.Print( 0, "X ~" );
aFormatter.Print( 0, " %s %d %d %d %c %d %d %d %d %c",
aPin->GetNumber().IsEmpty() ? "~" : TO_UTF8( aPin->GetNumber() ),
Iu2Mils( aPin->GetPosition().x ), Iu2Mils( aPin->GetPosition().y ),
Iu2Mils( (int) aPin->GetLength() ), (int) aPin->GetOrientation(),
Iu2Mils( aPin->GetNumberTextSize() ), Iu2Mils( aPin->GetNameTextSize() ),
aPin->GetUnit(), aPin->GetConvert(), Etype );
if( aPin->GetShape() != GRAPHIC_PINSHAPE::LINE || !aPin->IsVisible() )
aFormatter.Print( 0, " " );
if( !aPin->IsVisible() )
aFormatter.Print( 0, "N" );
switch( aPin->GetShape() )
{
case GRAPHIC_PINSHAPE::LINE: break;
case GRAPHIC_PINSHAPE::INVERTED: aFormatter.Print( 0, "I" ); break;
case GRAPHIC_PINSHAPE::CLOCK: aFormatter.Print( 0, "C" ); break;
case GRAPHIC_PINSHAPE::INVERTED_CLOCK: aFormatter.Print( 0, "IC" ); break;
case GRAPHIC_PINSHAPE::INPUT_LOW: aFormatter.Print( 0, "L" ); break;
case GRAPHIC_PINSHAPE::CLOCK_LOW: aFormatter.Print( 0, "CL" ); break;
case GRAPHIC_PINSHAPE::OUTPUT_LOW: aFormatter.Print( 0, "V" ); break;
case GRAPHIC_PINSHAPE::FALLING_EDGE_CLOCK: aFormatter.Print( 0, "F" ); break;
case GRAPHIC_PINSHAPE::NONLOGIC: aFormatter.Print( 0, "X" ); break;
default: wxFAIL_MSG( "Invalid pin shape" );
}
aFormatter.Print( 0, "\n" );
const_cast<LIB_PIN*>( aPin )->ClearFlags( IS_CHANGED );
}
void SCH_LEGACY_PLUGIN_CACHE::savePolyLine( LIB_POLYLINE* aPolyLine,
OUTPUTFORMATTER& aFormatter )
{
wxCHECK_RET( aPolyLine && aPolyLine->Type() == LIB_POLYLINE_T, "Invalid LIB_POLYLINE object." );
int ccount = aPolyLine->GetCornerCount();
aFormatter.Print( 0, "P %d %d %d %d", ccount, aPolyLine->GetUnit(), aPolyLine->GetConvert(),
Iu2Mils( aPolyLine->GetWidth() ) );
for( const auto& pt : aPolyLine->GetPolyPoints() )
{
aFormatter.Print( 0, " %d %d", Iu2Mils( pt.x ), Iu2Mils( pt.y ) );
}
aFormatter.Print( 0, " %c\n", fill_tab[static_cast<int>( aPolyLine->GetFillMode() )] );
}
void SCH_LEGACY_PLUGIN_CACHE::saveRectangle( LIB_RECTANGLE* aRectangle,
OUTPUTFORMATTER& aFormatter )
{
wxCHECK_RET( aRectangle && aRectangle->Type() == LIB_RECTANGLE_T,
"Invalid LIB_RECTANGLE object." );
aFormatter.Print( 0, "S %d %d %d %d %d %d %d %c\n",
Iu2Mils( aRectangle->GetPosition().x ),
Iu2Mils( aRectangle->GetPosition().y ),
Iu2Mils( aRectangle->GetEnd().x ), Iu2Mils( aRectangle->GetEnd().y ),
aRectangle->GetUnit(), aRectangle->GetConvert(),
Iu2Mils( aRectangle->GetWidth() ),
fill_tab[static_cast<int>( aRectangle->GetFillMode() )] );
}
void SCH_LEGACY_PLUGIN_CACHE::saveText( const LIB_TEXT* aText, OUTPUTFORMATTER& aFormatter )
{
wxCHECK_RET( aText && aText->Type() == LIB_TEXT_T, "Invalid LIB_TEXT object." );
wxString text = aText->GetText();
if( text.Contains( wxT( " " ) ) || text.Contains( wxT( "~" ) ) || text.Contains( wxT( "\"" ) ) )
{
// convert double quote to similar-looking two apostrophes
text.Replace( wxT( "\"" ), wxT( "''" ) );
text = wxT( "\"" ) + text + wxT( "\"" );
}
aFormatter.Print( 0, "T %g %d %d %d %d %d %d %s", aText->GetTextAngle(),
Iu2Mils( aText->GetTextPos().x ), Iu2Mils( aText->GetTextPos().y ),
Iu2Mils( aText->GetTextWidth() ), !aText->IsVisible(),
aText->GetUnit(), aText->GetConvert(), TO_UTF8( text ) );
aFormatter.Print( 0, " %s %d", aText->IsItalic() ? "Italic" : "Normal", aText->IsBold() );
char hjustify = 'C';
if( aText->GetHorizJustify() == GR_TEXT_HJUSTIFY_LEFT )
hjustify = 'L';
else if( aText->GetHorizJustify() == GR_TEXT_HJUSTIFY_RIGHT )
hjustify = 'R';
char vjustify = 'C';
if( aText->GetVertJustify() == GR_TEXT_VJUSTIFY_BOTTOM )
vjustify = 'B';
else if( aText->GetVertJustify() == GR_TEXT_VJUSTIFY_TOP )
vjustify = 'T';
aFormatter.Print( 0, " %c %c\n", hjustify, vjustify );
} }
void SCH_LEGACY_PLUGIN_CACHE::saveDocFile() void SCH_LEGACY_PLUGIN_CACHE::saveDocFile()
{ {
wxFileName fileName = m_libFileName; wxFAIL_MSG( "Writing of legacy format no longer supported." );
fileName.SetExt( DOC_EXT );
FILE_OUTPUTFORMATTER formatter( fileName.GetFullPath() );
formatter.Print( 0, "%s\n", DOCFILE_IDENT );
for( LIB_SYMBOL_MAP::iterator it = m_symbols.begin(); it != m_symbols.end(); ++it )
{
wxString description = it->second->GetDescription();
wxString keyWords = it->second->GetKeyWords();
wxString docFileName = it->second->GetDatasheetField().GetText();
if( description.IsEmpty() && keyWords.IsEmpty() && docFileName.IsEmpty() )
continue;
formatter.Print( 0, "#\n$CMP %s\n", TO_UTF8( it->second->GetName() ) );
if( !description.IsEmpty() )
formatter.Print( 0, "D %s\n", TO_UTF8( description ) );
if( !keyWords.IsEmpty() )
formatter.Print( 0, "K %s\n", TO_UTF8( keyWords ) );
if( !docFileName.IsEmpty() )
formatter.Print( 0, "F %s\n", TO_UTF8( docFileName ) );
formatter.Print( 0, "$ENDCMP\n" );
}
formatter.Print( 0, "#\n#End Doc Library\n" );
} }

View File

@ -985,13 +985,13 @@ void SCH_SHEET::Plot( PLOTTER* aPlotter ) const
if( fill ) if( fill )
{ {
aPlotter->SetColor( backgroundColor ); aPlotter->SetColor( backgroundColor );
aPlotter->Rect( m_pos, m_pos + m_size, FILL_TYPE::FILLED_SHAPE, 1 ); aPlotter->Rect( m_pos, m_pos + m_size, FILL_T::FILLED_SHAPE, 1 );
} }
aPlotter->SetColor( borderColor ); aPlotter->SetColor( borderColor );
int penWidth = std::max( GetPenWidth(), aPlotter->RenderSettings()->GetMinPenWidth() ); int penWidth = std::max( GetPenWidth(), aPlotter->RenderSettings()->GetMinPenWidth() );
aPlotter->Rect( m_pos, m_pos + m_size, FILL_TYPE::NO_FILL, penWidth ); aPlotter->Rect( m_pos, m_pos + m_size, FILL_T::NO_FILL, penWidth );
// Plot sheet pins // Plot sheet pins
for( SCH_SHEET_PIN* sheetPin : m_pins ) for( SCH_SHEET_PIN* sheetPin : m_pins )

View File

@ -26,9 +26,9 @@
#include <widgets/msgpanel.h> #include <widgets/msgpanel.h>
#include <bitmaps.h> #include <bitmaps.h>
#include <core/mirror.h> #include <core/mirror.h>
#include <lib_rectangle.h>
#include <lib_pin.h> #include <lib_pin.h>
#include <lib_text.h> #include <lib_text.h>
#include <lib_shape.h>
#include <sch_symbol.h> #include <sch_symbol.h>
#include <sch_sheet_path.h> #include <sch_sheet_path.h>
#include <schematic.h> #include <schematic.h>
@ -77,10 +77,10 @@ static LIB_SYMBOL* dummy()
{ {
symbol = new LIB_SYMBOL( wxEmptyString ); symbol = new LIB_SYMBOL( wxEmptyString );
LIB_RECTANGLE* square = new LIB_RECTANGLE( symbol ); LIB_SHAPE* square = new LIB_SHAPE( symbol, SHAPE_T::RECT );
square->MoveTo( wxPoint( Mils2iu( -200 ), Mils2iu( 200 ) ) ); square->MoveTo( wxPoint( Mils2iu( -200 ), Mils2iu( 200 ) ) );
square->SetEndPosition( wxPoint( Mils2iu( 200 ), Mils2iu( -200 ) ) ); square->SetEnd( wxPoint( Mils2iu( 200 ), Mils2iu( -200 ) ) );
LIB_TEXT* text = new LIB_TEXT( symbol ); LIB_TEXT* text = new LIB_TEXT( symbol );

View File

@ -732,7 +732,7 @@ void SCH_TEXT::Plot( PLOTTER* aPlotter ) const
CreateGraphicShape( aPlotter->RenderSettings(), s_poly, GetTextPos() ); CreateGraphicShape( aPlotter->RenderSettings(), s_poly, GetTextPos() );
if( s_poly.size() ) if( s_poly.size() )
aPlotter->PlotPoly( s_poly, FILL_TYPE::NO_FILL, penWidth ); aPlotter->PlotPoly( s_poly, FILL_T::NO_FILL, penWidth );
} }

View File

@ -228,22 +228,22 @@ TOOL_ACTION EE_ACTIONS::placeSymbolText( "eeschema.SymbolDrawing.placeSymbolText
TOOL_ACTION EE_ACTIONS::drawSymbolRectangle( "eeschema.SymbolDrawing.drawSymbolRectangle", TOOL_ACTION EE_ACTIONS::drawSymbolRectangle( "eeschema.SymbolDrawing.drawSymbolRectangle",
AS_GLOBAL, 0, "", AS_GLOBAL, 0, "",
_( "Add Rectangle" ), _( "Add a rectangle" ), _( "Add Rectangle" ), _( "Add a rectangle" ),
BITMAPS::add_rectangle, AF_ACTIVATE, (void*) LIB_RECTANGLE_T ); BITMAPS::add_rectangle, AF_ACTIVATE, (void*) SHAPE_T::RECT );
TOOL_ACTION EE_ACTIONS::drawSymbolCircle( "eeschema.SymbolDrawing.drawSymbolCircle", TOOL_ACTION EE_ACTIONS::drawSymbolCircle( "eeschema.SymbolDrawing.drawSymbolCircle",
AS_GLOBAL, 0, "", AS_GLOBAL, 0, "",
_( "Add Circle" ), _( "Add a circle" ), _( "Add Circle" ), _( "Add a circle" ),
BITMAPS::add_circle, AF_ACTIVATE, (void*) LIB_CIRCLE_T ); BITMAPS::add_circle, AF_ACTIVATE, (void*) SHAPE_T::CIRCLE );
TOOL_ACTION EE_ACTIONS::drawSymbolArc( "eeschema.SymbolDrawing.drawSymbolArc", TOOL_ACTION EE_ACTIONS::drawSymbolArc( "eeschema.SymbolDrawing.drawSymbolArc",
AS_GLOBAL, 0, "", AS_GLOBAL, 0, "",
_( "Add Arc" ), _( "Add an arc" ), _( "Add Arc" ), _( "Add an arc" ),
BITMAPS::add_arc, AF_ACTIVATE, (void*) LIB_ARC_T ); BITMAPS::add_arc, AF_ACTIVATE, (void*) SHAPE_T::ARC );
TOOL_ACTION EE_ACTIONS::drawSymbolLines( "eeschema.SymbolDrawing.drawSymbolLines", TOOL_ACTION EE_ACTIONS::drawSymbolLines( "eeschema.SymbolDrawing.drawSymbolLines",
AS_GLOBAL, 0, "", AS_GLOBAL, 0, "",
_( "Add Lines" ), _( "Add connected graphic lines" ), _( "Add Lines" ), _( "Add connected graphic lines" ),
BITMAPS::add_graphical_segments, AF_ACTIVATE, (void*) LIB_POLYLINE_T ); BITMAPS::add_graphical_segments, AF_ACTIVATE, (void*) SHAPE_T::POLY );
TOOL_ACTION EE_ACTIONS::placeSymbolAnchor( "eeschema.SymbolDrawing.placeSymbolAnchor", TOOL_ACTION EE_ACTIONS::placeSymbolAnchor( "eeschema.SymbolDrawing.placeSymbolAnchor",
AS_GLOBAL, 0, "", AS_GLOBAL, 0, "",

View File

@ -38,10 +38,7 @@ using namespace std::placeholders;
#include <sch_sheet.h> #include <sch_sheet.h>
#include <sch_sheet_pin.h> #include <sch_sheet_pin.h>
#include <symbol_edit_frame.h> #include <symbol_edit_frame.h>
#include <lib_arc.h> #include <lib_shape.h>
#include <lib_circle.h>
#include <lib_rectangle.h>
#include <lib_polyline.h>
// Few constants to avoid using bare numbers for point indices // Few constants to avoid using bare numbers for point indices
@ -78,42 +75,31 @@ public:
// Generate list of edit points based on the item type // Generate list of edit points based on the item type
switch( aItem->Type() ) switch( aItem->Type() )
{ {
case LIB_ARC_T: case LIB_SHAPE_T:
{ {
LIB_ARC* arc = (LIB_ARC*) aItem; LIB_SHAPE* shape = static_cast<LIB_SHAPE*>( aItem );
points->AddPoint( mapCoords( arc->GetPosition() ) ); switch( shape->GetShape() )
points->AddPoint( mapCoords( arc->GetStart() ) ); {
points->AddPoint( mapCoords( arc->GetEnd() ) ); case SHAPE_T::ARC:
points->AddPoint( mapCoords( shape->GetPosition() ) );
points->AddPoint( mapCoords( shape->GetStart() ) );
points->AddPoint( mapCoords( shape->GetEnd() ) );
break; break;
}
case LIB_CIRCLE_T:
{
LIB_CIRCLE* circle = (LIB_CIRCLE*) aItem;
points->AddPoint( mapCoords( circle->GetPosition() ) ); case SHAPE_T::CIRCLE:
points->AddPoint( mapCoords( circle->GetEnd() ) ); points->AddPoint( mapCoords( shape->GetPosition() ) );
points->AddPoint( mapCoords( shape->GetEnd() ) );
break; break;
}
case LIB_POLYLINE_T:
{
LIB_POLYLINE* lines = (LIB_POLYLINE*) aItem;
const std::vector<wxPoint>& pts = lines->GetPolyPoints();
for( wxPoint pt : pts ) case SHAPE_T::RECT:
points->AddPoint( mapCoords( pt ) );
break;
}
case LIB_RECTANGLE_T:
{ {
LIB_RECTANGLE* rect = (LIB_RECTANGLE*) aItem;
// point editor works only with rectangles having width and height > 0 // point editor works only with rectangles having width and height > 0
// Some symbols can have rectangles with width or height < 0 // Some symbols can have rectangles with width or height < 0
// So normalize the size: // So normalize the size:
BOX2I dummy; BOX2I dummy;
dummy.SetOrigin( mapCoords( rect->GetPosition() ) ); dummy.SetOrigin( mapCoords( shape->GetPosition() ) );
dummy.SetEnd( mapCoords( rect->GetEnd() ) ); dummy.SetEnd( mapCoords( shape->GetEnd() ) );
dummy.Normalize(); dummy.Normalize();
VECTOR2I topLeft = dummy.GetPosition(); VECTOR2I topLeft = dummy.GetPosition();
VECTOR2I botRight = dummy.GetEnd(); VECTOR2I botRight = dummy.GetEnd();
@ -122,8 +108,26 @@ public:
points->AddPoint( VECTOR2I( botRight.x, topLeft.y ) ); points->AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
points->AddPoint( VECTOR2I( topLeft.x, botRight.y ) ); points->AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
points->AddPoint( botRight ); points->AddPoint( botRight );
break;
} }
break;
case SHAPE_T::POLY:
for( const VECTOR2I& pt : shape->GetPolyShape().Outline( 0 ).CPoints() )
points->AddPoint( mapCoords( pt ) );
break;
case SHAPE_T::BEZIER:
// TODO
break;
default:
wxFAIL_MSG( "EDIT_POINTS_FACTORY::Make not implemented for "
+ shape->SHAPE_T_asString() );
}
}
break;
case SCH_SHEET_T: case SCH_SHEET_T:
{ {
SCH_SHEET* sheet = (SCH_SHEET*) aItem; SCH_SHEET* sheet = (SCH_SHEET*) aItem;
@ -134,8 +138,9 @@ public:
points->AddPoint( wxPoint( botRight.x, topLeft.y ) ); points->AddPoint( wxPoint( botRight.x, topLeft.y ) );
points->AddPoint( wxPoint( topLeft.x, botRight.y ) ); points->AddPoint( wxPoint( topLeft.x, botRight.y ) );
points->AddPoint( (wxPoint) botRight ); points->AddPoint( (wxPoint) botRight );
break;
} }
break;
case SCH_BITMAP_T: case SCH_BITMAP_T:
{ {
SCH_BITMAP* bitmap = (SCH_BITMAP*) aItem; SCH_BITMAP* bitmap = (SCH_BITMAP*) aItem;
@ -146,8 +151,9 @@ public:
points->AddPoint( wxPoint( botRight.x, topLeft.y ) ); points->AddPoint( wxPoint( botRight.x, topLeft.y ) );
points->AddPoint( wxPoint( topLeft.x, botRight.y ) ); points->AddPoint( wxPoint( topLeft.x, botRight.y ) );
points->AddPoint( (wxPoint) botRight ); points->AddPoint( (wxPoint) botRight );
break;
} }
break;
case SCH_LINE_T: case SCH_LINE_T:
{ {
SCH_LINE* line = (SCH_LINE*) aItem; SCH_LINE* line = (SCH_LINE*) aItem;
@ -182,11 +188,11 @@ public:
} }
} }
points->AddPoint( line->GetStartPoint(), connectedStart ); points->AddPoint( line->GetStartPoint(), connectedStart );
points->AddPoint( line->GetEndPoint(), connectedEnd ); points->AddPoint( line->GetEndPoint(), connectedEnd );
break;
} }
break;
default: default:
points.reset(); points.reset();
break; break;
@ -267,10 +273,7 @@ void EE_POINT_EDITOR::updateEditedPoint( const TOOL_EVENT& aEvent )
int EE_POINT_EDITOR::Main( const TOOL_EVENT& aEvent ) int EE_POINT_EDITOR::Main( const TOOL_EVENT& aEvent )
{ {
static KICAD_T supportedTypes[] = { static KICAD_T supportedTypes[] = {
LIB_ARC_T, LIB_SHAPE_T,
LIB_CIRCLE_T,
LIB_POLYLINE_T,
LIB_RECTANGLE_T,
SCH_SHEET_T, SCH_SHEET_T,
SCH_LINE_LOCATE_GRAPHIC_LINE_T, SCH_LINE_LOCATE_GRAPHIC_LINE_T,
SCH_BITMAP_T, SCH_BITMAP_T,
@ -325,8 +328,12 @@ int EE_POINT_EDITOR::Main( const TOOL_EVENT& aEvent )
bool snap = !evt->DisableGridSnapping(); bool snap = !evt->DisableGridSnapping();
if( item->Type() == LIB_ARC_T && getEditedPointIndex() == ARC_CENTER ) if( item->Type() == LIB_SHAPE_T
&& static_cast<LIB_SHAPE*>( item )->GetShape() == SHAPE_T::ARC
&& getEditedPointIndex() == ARC_CENTER )
{
snap = false; snap = false;
}
m_editedPoint->SetPosition( controls->GetCursorPosition( snap ) ); m_editedPoint->SetPosition( controls->GetCursorPosition( snap ) );
@ -481,52 +488,45 @@ void EE_POINT_EDITOR::updateParentItem() const
switch( item->Type() ) switch( item->Type() )
{ {
case LIB_ARC_T: case LIB_SHAPE_T:
{ {
LIB_ARC* arc = (LIB_ARC*) item; LIB_SHAPE* shape = static_cast<LIB_SHAPE*>( item );
int i = getEditedPointIndex();
if( i == ARC_CENTER ) switch( shape->GetShape() )
{ {
arc->SetEditState( 4 ); case SHAPE_T::ARC:
arc->CalcEdit( mapCoords( m_editPoints->Point( ARC_CENTER ).GetPosition() ) ); if( getEditedPointIndex() == ARC_CENTER )
}
else if( i == ARC_START )
{ {
arc->SetEditState( 2 ); shape->SetEditState( 4 );
arc->CalcEdit( mapCoords( m_editPoints->Point( ARC_START ).GetPosition() ) ); shape->CalcEdit( mapCoords( m_editPoints->Point( ARC_CENTER ).GetPosition() ) );
} }
else if( i == ARC_END ) else if( getEditedPointIndex() == ARC_START )
{ {
arc->SetEditState( 3 ); shape->SetEditState( 2 );
arc->CalcEdit( mapCoords( m_editPoints->Point( ARC_END ).GetPosition() ) ); shape->CalcEdit( mapCoords( m_editPoints->Point( ARC_START ).GetPosition() ) );
}
else if( getEditedPointIndex() == ARC_END )
{
shape->SetEditState( 3 );
shape->CalcEdit( mapCoords( m_editPoints->Point( ARC_END ).GetPosition() ) );
} }
break; break;
}
case LIB_CIRCLE_T: case SHAPE_T::CIRCLE:
{ shape->SetPosition( mapCoords( m_editPoints->Point( CIRC_CENTER ).GetPosition() ) );
LIB_CIRCLE* circle = (LIB_CIRCLE*) item; shape->SetEnd( mapCoords( m_editPoints->Point( CIRC_END ).GetPosition() ) );
circle->SetPosition( mapCoords( m_editPoints->Point( CIRC_CENTER ).GetPosition() ) );
circle->SetEnd( mapCoords( m_editPoints->Point( CIRC_END ).GetPosition() ) );
break; break;
}
case LIB_POLYLINE_T: case SHAPE_T::POLY:
{ shape->GetPolyShape().RemoveAllContours();
LIB_POLYLINE* lines = (LIB_POLYLINE*) item; shape->GetPolyShape().NewOutline();
lines->ClearPoints();
for( unsigned i = 0; i < m_editPoints->PointsSize(); ++i ) for( unsigned i = 0; i < m_editPoints->PointsSize(); ++i )
lines->AddPoint( mapCoords( m_editPoints->Point( i ).GetPosition() ) ); shape->GetPolyShape().Append( mapCoords( m_editPoints->Point( i ).GetPosition() ) );
break; break;
}
case LIB_RECTANGLE_T: case SHAPE_T::RECT:
{ {
VECTOR2I topLeft = m_editPoints->Point( RECT_TOPLEFT ).GetPosition(); VECTOR2I topLeft = m_editPoints->Point( RECT_TOPLEFT ).GetPosition();
VECTOR2I topRight = m_editPoints->Point( RECT_TOPRIGHT ).GetPosition(); VECTOR2I topRight = m_editPoints->Point( RECT_TOPRIGHT ).GetPosition();
@ -536,11 +536,21 @@ void EE_POINT_EDITOR::updateParentItem() const
pinEditedCorner( getEditedPointIndex(), Mils2iu( 1 ), Mils2iu( 1 ), pinEditedCorner( getEditedPointIndex(), Mils2iu( 1 ), Mils2iu( 1 ),
topLeft, topRight, botLeft, botRight ); topLeft, topRight, botLeft, botRight );
LIB_RECTANGLE* rect = (LIB_RECTANGLE*) item; shape->SetPosition( mapCoords( topLeft ) );
rect->SetPosition( mapCoords( topLeft ) ); shape->SetEnd( mapCoords( botRight ) );
rect->SetEnd( mapCoords( botRight ) );
break;
} }
break;
case SHAPE_T::BEZIER:
// TODO
break;
default:
wxFAIL_MSG( "EE_POINT_EDITOR::updateParentItem not implemented for "
+ shape->SHAPE_T_asString() );
}
}
break;
case SCH_BITMAP_T: case SCH_BITMAP_T:
{ {
@ -562,8 +572,8 @@ void EE_POINT_EDITOR::updateParentItem() const
double heightRatio = newHeight / oldHeight; double heightRatio = newHeight / oldHeight;
bitmap->SetImageScale( bitmap->GetImageScale() * std::min( widthRatio, heightRatio ) ); bitmap->SetImageScale( bitmap->GetImageScale() * std::min( widthRatio, heightRatio ) );
break;
} }
break;
case SCH_SHEET_T: case SCH_SHEET_T:
{ {
@ -613,9 +623,8 @@ void EE_POINT_EDITOR::updateParentItem() const
pin->SetPosition( pos ); pin->SetPosition( pos );
} }
break;
} }
break;
case SCH_LINE_T: case SCH_LINE_T:
{ {
@ -647,9 +656,8 @@ void EE_POINT_EDITOR::updateParentItem() const
getView()->Update( connected.first, KIGFX::GEOMETRY ); getView()->Update( connected.first, KIGFX::GEOMETRY );
} }
break;
} }
break;
default: default:
break; break;
@ -672,31 +680,26 @@ void EE_POINT_EDITOR::updatePoints()
switch( item->Type() ) switch( item->Type() )
{ {
case LIB_ARC_T: case LIB_SHAPE_T:
{ {
LIB_ARC* arc = (LIB_ARC*) item; LIB_SHAPE* shape = static_cast<LIB_SHAPE*>( item );
m_editPoints->Point( ARC_CENTER ).SetPosition( mapCoords( arc->GetPosition() ) ); switch( shape->GetShape() )
m_editPoints->Point( ARC_START ).SetPosition( mapCoords( arc->GetStart() ) ); {
m_editPoints->Point( ARC_END ).SetPosition( mapCoords( arc->GetEnd() ) ); case SHAPE_T::ARC:
m_editPoints->Point( ARC_CENTER ).SetPosition( mapCoords( shape->GetPosition() ) );
m_editPoints->Point( ARC_START ).SetPosition( mapCoords( shape->GetStart() ) );
m_editPoints->Point( ARC_END ).SetPosition( mapCoords( shape->GetEnd() ) );
break; break;
}
case LIB_CIRCLE_T: case SHAPE_T::CIRCLE:
{ m_editPoints->Point( CIRC_CENTER ).SetPosition( mapCoords( shape->GetPosition() ) );
LIB_CIRCLE* circle = (LIB_CIRCLE*) item; m_editPoints->Point( CIRC_END ).SetPosition( mapCoords( shape->GetEnd() ) );
m_editPoints->Point( CIRC_CENTER ).SetPosition( mapCoords( circle->GetPosition() ) );
m_editPoints->Point( CIRC_END ).SetPosition( mapCoords( circle->GetEnd() ) );
break; break;
}
case LIB_POLYLINE_T: case SHAPE_T::POLY:
{ {
LIB_POLYLINE* lines = (LIB_POLYLINE*) item; if( (int) m_editPoints->PointsSize() != shape->GetPointCount() )
const std::vector<wxPoint>& pts = lines->GetPolyPoints();
if( m_editPoints->PointsSize() != (unsigned) pts.size() )
{ {
getView()->Remove( m_editPoints.get() ); getView()->Remove( m_editPoints.get() );
m_editedPoint = nullptr; m_editedPoint = nullptr;
@ -705,22 +708,23 @@ void EE_POINT_EDITOR::updatePoints()
} }
else else
{ {
for( unsigned i = 0; i < pts.size(); i++ ) int ii = 0;
m_editPoints->Point( i ).SetPosition( mapCoords( pts[i] ) );
for( const VECTOR2I& pt : shape->GetPolyShape().Outline( 0 ).CPoints() )
m_editPoints->Point( ii++ ).SetPosition( mapCoords( pt ) );
} }
break; break;
} }
case LIB_RECTANGLE_T: case SHAPE_T::RECT:
{ {
LIB_RECTANGLE* rect = (LIB_RECTANGLE*) item;
// point editor works only with rectangles having width and height > 0 // point editor works only with rectangles having width and height > 0
// Some symbols can have rectangles with width or height < 0 // Some symbols can have rectangles with width or height < 0
// So normalize the size: // So normalize the size:
BOX2I dummy; BOX2I dummy;
dummy.SetOrigin( mapCoords( rect->GetPosition() ) ); dummy.SetOrigin( mapCoords( shape->GetPosition() ) );
dummy.SetEnd( mapCoords( rect->GetEnd() ) ); dummy.SetEnd( mapCoords( shape->GetEnd() ) );
dummy.Normalize(); dummy.Normalize();
VECTOR2I topLeft = dummy.GetPosition(); VECTOR2I topLeft = dummy.GetPosition();
VECTOR2I botRight = dummy.GetEnd(); VECTOR2I botRight = dummy.GetEnd();
@ -729,8 +733,19 @@ void EE_POINT_EDITOR::updatePoints()
m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( VECTOR2I( botRight.x, topLeft.y ) ); m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( VECTOR2I( botRight.x, topLeft.y ) );
m_editPoints->Point( RECT_BOTLEFT ).SetPosition( VECTOR2I( topLeft.x, botRight.y ) ); m_editPoints->Point( RECT_BOTLEFT ).SetPosition( VECTOR2I( topLeft.x, botRight.y ) );
m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight ); m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight );
break;
} }
break;
case SHAPE_T::BEZIER:
// TODO
break;
default:
wxFAIL_MSG( "EE_POINT_EDITOR::updatePoints not implemented for "
+ shape->SHAPE_T_asString() );
}
}
break;
case SCH_BITMAP_T: case SCH_BITMAP_T:
{ {
@ -742,8 +757,8 @@ void EE_POINT_EDITOR::updatePoints()
m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( botRight.x, topLeft.y ); m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( botRight.x, topLeft.y );
m_editPoints->Point( RECT_BOTLEFT ).SetPosition( topLeft.x, botRight.y ); m_editPoints->Point( RECT_BOTLEFT ).SetPosition( topLeft.x, botRight.y );
m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight ); m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight );
break;
} }
break;
case SCH_SHEET_T: case SCH_SHEET_T:
{ {
@ -755,8 +770,8 @@ void EE_POINT_EDITOR::updatePoints()
m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( botRight.x, topLeft.y ); m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( botRight.x, topLeft.y );
m_editPoints->Point( RECT_BOTLEFT ).SetPosition( topLeft.x, botRight.y ); m_editPoints->Point( RECT_BOTLEFT ).SetPosition( topLeft.x, botRight.y );
m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight ); m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight );
break;
} }
break;
case SCH_LINE_T: case SCH_LINE_T:
{ {
@ -764,8 +779,8 @@ void EE_POINT_EDITOR::updatePoints()
m_editPoints->Point( LINE_START ).SetPosition( line->GetStartPoint() ); m_editPoints->Point( LINE_START ).SetPosition( line->GetStartPoint() );
m_editPoints->Point( LINE_END ).SetPosition( line->GetEndPoint() ); m_editPoints->Point( LINE_END ).SetPosition( line->GetEndPoint() );
break;
} }
break;
default: default:
break; break;
@ -799,19 +814,18 @@ void EE_POINT_EDITOR::setEditedPoint( EDIT_POINT* aPoint )
bool EE_POINT_EDITOR::removeCornerCondition( const SELECTION& ) bool EE_POINT_EDITOR::removeCornerCondition( const SELECTION& )
{ {
if( !m_editPoints || !m_editedPoint ) if( !m_editPoints || !m_editedPoint || m_editPoints->GetParent()->Type() != LIB_SHAPE_T )
return false; return false;
LIB_POLYLINE* polyLine = dynamic_cast<LIB_POLYLINE*>( m_editPoints->GetParent() ); LIB_SHAPE* shape = static_cast<LIB_SHAPE*>( m_editPoints->GetParent() );
SHAPE_LINE_CHAIN& poly = shape->GetPolyShape().Outline( 0 );
if( !polyLine || polyLine->GetCornerCount() < 3 ) if( poly.GetPointCount() < 3 )
return false; return false;
const std::vector<wxPoint>& pts = polyLine->GetPolyPoints(); for( const VECTOR2I& pt : poly.CPoints() )
for( unsigned i = 0; i < polyLine->GetCornerCount(); ++i )
{ {
if( pts[i] == mapCoords( m_editedPoint->GetPosition() ) ) if( pt == mapCoords( m_editedPoint->GetPosition() ) )
return true; return true;
} }
@ -821,35 +835,49 @@ bool EE_POINT_EDITOR::removeCornerCondition( const SELECTION& )
bool EE_POINT_EDITOR::addCornerCondition( const SELECTION& ) bool EE_POINT_EDITOR::addCornerCondition( const SELECTION& )
{ {
if( !m_editPoints || !m_editedPoint ) if( !m_editPoints || m_editPoints->GetParent()->Type() != LIB_SHAPE_T )
return false; return false;
LIB_POLYLINE* polyLine = dynamic_cast<LIB_POLYLINE*>( m_editPoints->GetParent() ); LIB_SHAPE* shape = static_cast<LIB_SHAPE*>( m_editPoints->GetParent() );
if( !polyLine ) if( shape->GetShape() != SHAPE_T::POLY )
return false; return false;
VECTOR2I cursorPos = getViewControls()->GetCursorPosition(); VECTOR2I cursorPos = getViewControls()->GetCursorPosition();
double threshold = getView()->ToWorld( EDIT_POINT::POINT_SIZE ); double threshold = getView()->ToWorld( EDIT_POINT::POINT_SIZE );
return polyLine->HitTest( mapCoords( cursorPos ), (int) threshold ); return shape->HitTest( mapCoords( cursorPos ), (int) threshold );
} }
int EE_POINT_EDITOR::addCorner( const TOOL_EVENT& aEvent ) int EE_POINT_EDITOR::addCorner( const TOOL_EVENT& aEvent )
{ {
if( !m_editPoints ) if( !m_editPoints || m_editPoints->GetParent()->Type() != LIB_SHAPE_T )
return 0; return 0;
LIB_POLYLINE* polyLine = dynamic_cast<LIB_POLYLINE*>( m_editPoints->GetParent() ); LIB_SHAPE* shape = static_cast<LIB_SHAPE*>( m_editPoints->GetParent() );
SHAPE_LINE_CHAIN& poly = shape->GetPolyShape().Outline( 0 );
if( !polyLine ) VECTOR2I cursor = getViewControls()->GetCursorPosition( !aEvent.DisableGridSnapping() );
return false; wxPoint pos = mapCoords( cursor );
int currentMinDistance = INT_MAX;
int closestLineStart = 0;
VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !aEvent.DisableGridSnapping() ); for( unsigned i = 0; i < poly.GetPointCount() - 1; ++i )
polyLine->AddCorner( mapCoords( cursorPos ) ); {
int distance = (int) DistanceLinePoint( (wxPoint) poly.CPoint( i ),
(wxPoint) poly.CPoint( i + 1 ), pos );
updateItem( polyLine, true ); if( distance < currentMinDistance )
{
currentMinDistance = distance;
closestLineStart = i;
}
}
poly.Insert( closestLineStart, pos );
updateItem( shape, true );
updatePoints(); updatePoints();
return 0; return 0;
@ -858,17 +886,18 @@ int EE_POINT_EDITOR::addCorner( const TOOL_EVENT& aEvent )
int EE_POINT_EDITOR::removeCorner( const TOOL_EVENT& aEvent ) int EE_POINT_EDITOR::removeCorner( const TOOL_EVENT& aEvent )
{ {
if( !m_editPoints || !m_editedPoint ) if( !m_editPoints || !m_editedPoint || m_editPoints->GetParent()->Type() != LIB_SHAPE_T )
return 0; return 0;
LIB_POLYLINE* polyLine = dynamic_cast<LIB_POLYLINE*>( m_editPoints->GetParent() ); LIB_SHAPE* shape = static_cast<LIB_SHAPE*>( m_editPoints->GetParent() );
SHAPE_LINE_CHAIN& poly = shape->GetPolyShape().Outline( 0 );
if( !polyLine || polyLine->GetCornerCount() < 3 ) if( poly.GetPointCount() < 3 )
return 0; return 0;
polyLine->RemoveCorner( getEditedPointIndex() ); poly.Remove( getEditedPointIndex() );
updateItem( polyLine, true ); updateItem( shape, true );
updatePoints(); updatePoints();
return 0; return 0;

View File

@ -304,12 +304,8 @@ const KICAD_T movableSchematicItems[] =
const KICAD_T movableSymbolItems[] = const KICAD_T movableSymbolItems[] =
{ {
LIB_ARC_T, LIB_SHAPE_T,
LIB_CIRCLE_T,
LIB_TEXT_T, LIB_TEXT_T,
LIB_RECTANGLE_T,
LIB_POLYLINE_T,
LIB_BEZIER_T,
LIB_PIN_T, LIB_PIN_T,
LIB_FIELD_T, LIB_FIELD_T,
EOT EOT
@ -1722,12 +1718,8 @@ bool EE_SELECTION_TOOL::Selectable( const EDA_ITEM* aItem, const VECTOR2I* aPos,
case LIB_FIELD_T: // LIB_FIELD object can always be edited. case LIB_FIELD_T: // LIB_FIELD object can always be edited.
break; break;
case LIB_ARC_T: case LIB_SHAPE_T:
case LIB_CIRCLE_T:
case LIB_TEXT_T: case LIB_TEXT_T:
case LIB_RECTANGLE_T:
case LIB_POLYLINE_T:
case LIB_BEZIER_T:
case LIB_PIN_T: case LIB_PIN_T:
if( symEditFrame ) if( symEditFrame )
{ {

View File

@ -155,7 +155,7 @@ bool SCH_EDIT_TOOL::Init()
}; };
auto sheetHasUndefinedPins = auto sheetHasUndefinedPins =
[ this ] ( const SELECTION& aSel ) []( const SELECTION& aSel )
{ {
if( aSel.Size() != 1 ) if( aSel.Size() != 1 )
return false; return false;

View File

@ -29,10 +29,7 @@
#include <bitmaps.h> #include <bitmaps.h>
#include <lib_text.h> #include <lib_text.h>
#include <dialogs/dialog_lib_text_properties.h> #include <dialogs/dialog_lib_text_properties.h>
#include <lib_arc.h> #include <lib_shape.h>
#include <lib_circle.h>
#include <lib_polyline.h>
#include <lib_rectangle.h>
#include <pgm_base.h> #include <pgm_base.h>
#include <symbol_editor/symbol_editor_settings.h> #include <symbol_editor/symbol_editor_settings.h>
#include <settings/settings_manager.h> #include <settings/settings_manager.h>
@ -44,7 +41,7 @@ static void* g_lastPinWeakPtr;
SYMBOL_EDITOR_DRAWING_TOOLS::SYMBOL_EDITOR_DRAWING_TOOLS() : SYMBOL_EDITOR_DRAWING_TOOLS::SYMBOL_EDITOR_DRAWING_TOOLS() :
EE_TOOL_BASE<SYMBOL_EDIT_FRAME>( "eeschema.SymbolDrawing" ), EE_TOOL_BASE<SYMBOL_EDIT_FRAME>( "eeschema.SymbolDrawing" ),
m_lastTextAngle( 0.0 ), m_lastTextAngle( 0.0 ),
m_lastFillStyle( FILL_TYPE::NO_FILL ), m_lastFillStyle( FILL_T::NO_FILL ),
m_drawSpecificConvert( true ), m_drawSpecificConvert( true ),
m_drawSpecificUnit( false ) m_drawSpecificUnit( false )
{ {
@ -265,7 +262,7 @@ int SYMBOL_EDITOR_DRAWING_TOOLS::DrawShape( const TOOL_EVENT& aEvent )
{ {
SETTINGS_MANAGER& settingsMgr = Pgm().GetSettingsManager(); SETTINGS_MANAGER& settingsMgr = Pgm().GetSettingsManager();
SYMBOL_EDITOR_SETTINGS* settings = settingsMgr.GetAppSettings<SYMBOL_EDITOR_SETTINGS>(); SYMBOL_EDITOR_SETTINGS* settings = settingsMgr.GetAppSettings<SYMBOL_EDITOR_SETTINGS>();
KICAD_T type = aEvent.Parameter<KICAD_T>(); SHAPE_T type = aEvent.Parameter<SHAPE_T>();
LIB_SYMBOL* symbol = m_frame->GetCurSymbol(); LIB_SYMBOL* symbol = m_frame->GetCurSymbol();
LIB_ITEM* item = nullptr; LIB_ITEM* item = nullptr;
@ -347,19 +344,9 @@ int SYMBOL_EDITOR_DRAWING_TOOLS::DrawShape( const TOOL_EVENT& aEvent )
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true ); m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
switch( type ) int lineWidth = Mils2iu( settings->m_Defaults.line_width );
{
case LIB_ARC_T: item = new LIB_ARC( symbol ); break;
case LIB_CIRCLE_T: item = new LIB_CIRCLE( symbol ); break;
case LIB_POLYLINE_T: item = new LIB_POLYLINE( symbol ); break;
case LIB_RECTANGLE_T: item = new LIB_RECTANGLE( symbol ); break;
default: break; // keep compiler quiet
}
wxCHECK( item, 0 ); item = new LIB_SHAPE( symbol, type, lineWidth, m_lastFillStyle );
item->SetWidth( Mils2iu( settings->m_Defaults.line_width ) );
item->SetFillMode( m_lastFillStyle );
item->SetFlags( IS_NEW ); item->SetFlags( IS_NEW );
item->BeginEdit( wxPoint( cursorPos.x, -cursorPos.y ) ); item->BeginEdit( wxPoint( cursorPos.x, -cursorPos.y ) );

View File

@ -66,7 +66,7 @@ private:
private: private:
double m_lastTextAngle; double m_lastTextAngle;
FILL_TYPE m_lastFillStyle; FILL_T m_lastFillStyle;
bool m_drawSpecificConvert; bool m_drawSpecificConvert;
bool m_drawSpecificUnit; bool m_drawSpecificUnit;
}; };

View File

@ -240,12 +240,8 @@ int SYMBOL_EDITOR_EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent )
static KICAD_T nonFields[] = static KICAD_T nonFields[] =
{ {
LIB_SYMBOL_T, LIB_SYMBOL_T,
LIB_ARC_T, LIB_SHAPE_T,
LIB_CIRCLE_T,
LIB_TEXT_T, LIB_TEXT_T,
LIB_RECTANGLE_T,
LIB_POLYLINE_T,
LIB_BEZIER_T,
LIB_PIN_T, LIB_PIN_T,
EOT EOT
}; };
@ -433,14 +429,11 @@ int SYMBOL_EDITOR_EDIT_TOOL::Properties( const TOOL_EVENT& aEvent )
if( pinTool ) if( pinTool )
pinTool->EditPinProperties( (LIB_PIN*) item ); pinTool->EditPinProperties( (LIB_PIN*) item );
break;
} }
case LIB_ARC_T: break;
case LIB_CIRCLE_T:
case LIB_RECTANGLE_T: case LIB_SHAPE_T:
case LIB_POLYLINE_T: editShapeProperties( item );
editGraphicProperties( item );
break; break;
case LIB_TEXT_T: case LIB_TEXT_T:
@ -466,7 +459,7 @@ int SYMBOL_EDITOR_EDIT_TOOL::Properties( const TOOL_EVENT& aEvent )
} }
void SYMBOL_EDITOR_EDIT_TOOL::editGraphicProperties( LIB_ITEM* aItem ) void SYMBOL_EDITOR_EDIT_TOOL::editShapeProperties( LIB_ITEM* aItem )
{ {
DIALOG_LIB_SHAPE_PROPERTIES dlg( m_frame, aItem ); DIALOG_LIB_SHAPE_PROPERTIES dlg( m_frame, aItem );

View File

@ -64,7 +64,7 @@ public:
int DeleteItemCursor( const TOOL_EVENT& aEvent ); int DeleteItemCursor( const TOOL_EVENT& aEvent );
private: private:
void editGraphicProperties( LIB_ITEM* aItem ); void editShapeProperties( LIB_ITEM* aItem );
void editTextProperties( LIB_ITEM* aItem ); void editTextProperties( LIB_ITEM* aItem );
void editFieldProperties( LIB_FIELD* aField ); void editFieldProperties( LIB_FIELD* aField );
void editSymbolProperties(); void editSymbolProperties();

View File

@ -175,12 +175,8 @@ enum KICAD_T
*/ */
LIB_SYMBOL_T, LIB_SYMBOL_T,
LIB_ALIAS_T, LIB_ALIAS_T,
LIB_ARC_T, LIB_SHAPE_T,
LIB_CIRCLE_T,
LIB_TEXT_T, LIB_TEXT_T,
LIB_RECTANGLE_T,
LIB_POLYLINE_T,
LIB_BEZIER_T,
LIB_PIN_T, LIB_PIN_T,
/* /*

View File

@ -27,7 +27,6 @@
#include <eda_units.h> #include <eda_units.h>
#include <convert_to_biu.h> #include <convert_to_biu.h>
#include <math_for_graphics.h>
#include <trigo.h> #include <trigo.h>
#include <geometry/shape_poly_set.h> #include <geometry/shape_poly_set.h>
#include <geometry/geometry_utils.h> #include <geometry/geometry_utils.h>
@ -50,10 +49,19 @@ enum class SHAPE_T : int
}; };
enum class FILL_T : int
{
NO_FILL = 1,
FILLED_SHAPE, // Fill with object color
FILLED_WITH_BG_BODYCOLOR, // Fill with background body color
FILLED_WITH_COLOR // Fill with a separate color
};
class EDA_SHAPE class EDA_SHAPE
{ {
public: public:
EDA_SHAPE( SHAPE_T aType, int aDefaultLineWidth ); EDA_SHAPE( SHAPE_T aType, int aLineWidth, FILL_T aFill );
// Do not create a copy constructor & operator=. // Do not create a copy constructor & operator=.
// The ones generated by the compiler are adequate. // The ones generated by the compiler are adequate.
@ -66,27 +74,14 @@ public:
wxString SHAPE_T_asString() const; wxString SHAPE_T_asString() const;
void SetFilled( bool aFlag ) { m_filled = aFlag; } void SetFillMode( FILL_T aFill ) { m_fill = aFill; }
FILL_T GetFillType() const { return m_fill; }
bool IsFilled() const bool IsFilled() const { return GetFillType() != FILL_T::NO_FILL; }
void SetFilled( bool aFlag )
{ {
switch( m_shape ) m_fill = aFlag ? FILL_T::FILLED_SHAPE : FILL_T::NO_FILL;
{
case SHAPE_T::RECT:
case SHAPE_T::CIRCLE:
case SHAPE_T::POLY:
return m_filled;
case SHAPE_T::SEGMENT:
case SHAPE_T::ARC:
case SHAPE_T::BEZIER:
return false;
case SHAPE_T::LAST: // Make CLang compiler happy
return false;
}
return false; // Make GCC compiler happy
} }
void SetWidth( int aWidth ) { m_width = aWidth; } void SetWidth( int aWidth ) { m_width = aWidth; }
@ -115,15 +110,6 @@ public:
void SetEndY( int y ) { m_end.y = y; } void SetEndY( int y ) { m_end.y = y; }
void SetEndX( int x ) { m_end.x = x; } void SetEndX( int x ) { m_end.x = x; }
/**
* 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.
*/
virtual void SetArcAngle( double aAngle );
virtual void SetArcAngleAndEnd( double aAngle );
double GetArcAngle() const { return m_arcAngle; }
void SetBezierC1( const wxPoint& aPt ) { m_bezierC1 = aPt; } void SetBezierC1( const wxPoint& aPt ) { m_bezierC1 = aPt; }
const wxPoint& GetBezierC1() const { return m_bezierC1; } const wxPoint& GetBezierC1() const { return m_bezierC1; }
@ -133,6 +119,15 @@ public:
wxPoint getCenter() const; wxPoint getCenter() const;
void SetCenter( const wxPoint& aCenter ); void SetCenter( const wxPoint& aCenter );
/**
* 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.
*/
void SetArcAngle( double aAngle );
void SetArcAngleAndEnd( double aAngle );
double GetArcAngle() const { return m_arcAngle; }
// Some attributes are read only, since they are derived from m_Start, m_End, and m_Angle. // Some attributes are read only, since they are derived from m_Start, m_End, and m_Angle.
// No Set...() function for these attributes. // No Set...() function for these attributes.
@ -142,12 +137,12 @@ public:
/** /**
* @return the angle of the starting point of this arc, between 0 and 3600 in 0.1 deg. * @return the angle of the starting point of this arc, between 0 and 3600 in 0.1 deg.
*/ */
double GetArcAngleStart() const; virtual double GetArcAngleStart() const;
/** /**
* @return the angle of the ending point of this arc, between 0 and 3600 in 0.1 deg. * @return the angle of the ending point of this arc, between 0 and 3600 in 0.1 deg.
*/ */
double GetArcAngleEnd() const; virtual double GetArcAngleEnd() const;
int GetRadius() const; int GetRadius() const;
@ -260,7 +255,7 @@ protected:
protected: protected:
SHAPE_T m_shape; // Shape: line, Circle, Arc SHAPE_T m_shape; // Shape: line, Circle, Arc
int m_width; // thickness of lines ... int m_width; // thickness of lines ...
bool m_filled; // Pretty much what it says on the tin... FILL_T m_fill;
wxPoint m_start; // Line start point or Circle center wxPoint m_start; // Line start point or Circle center
wxPoint m_end; // Line end point or Circle 3 o'clock point wxPoint m_end; // Line end point or Circle 3 o'clock point

View File

@ -1,37 +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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef FILL_TYPE_H
#define FILL_TYPE_H
/**
* The set of fill types used in plotting or drawing enclosed areas.
*
* @warning Do not renumber this enum, the legacy schematic plugin demands on these values.
*/
enum class FILL_TYPE : int
{
NO_FILL = 0,
FILLED_SHAPE = 1, // Fill with object color ("Solid shape")
FILLED_WITH_BG_BODYCOLOR = 2, // Fill with background body color
// (not filled in B&W mode when plotting or printing)
FILLED_WITH_COLOR =3 // Fill with a user-defined color (currently sheets only)
};
#endif

View File

@ -31,7 +31,7 @@
#ifndef PLOT_COMMON_H_ #ifndef PLOT_COMMON_H_
#define PLOT_COMMON_H_ #define PLOT_COMMON_H_
#include <fill_type.h> #include <eda_shape.h>
#include <vector> #include <vector>
#include <math/box2.h> #include <math/box2.h>
#include <gr_text.h> #include <gr_text.h>
@ -228,16 +228,16 @@ public:
int GetPlotterArcHighDef() const { return m_IUsPerDecimil * 2; } int GetPlotterArcHighDef() const { return m_IUsPerDecimil * 2; }
// Low level primitives // Low level primitives
virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH ) = 0; int width = USE_DEFAULT_LINE_WIDTH ) = 0;
virtual void Circle( const wxPoint& pos, int diametre, FILL_TYPE fill, virtual void Circle( const wxPoint& pos, int diametre, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH ) = 0; int width = USE_DEFAULT_LINE_WIDTH ) = 0;
/** /**
* Generic fallback: arc rendered as a polyline. * Generic fallback: arc rendered as a polyline.
*/ */
virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle, virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle, int rayon,
int rayon, FILL_TYPE fill, int width = USE_DEFAULT_LINE_WIDTH ); FILL_T fill, int width = USE_DEFAULT_LINE_WIDTH );
virtual void Arc( const SHAPE_ARC& aArc ); virtual void Arc( const SHAPE_ARC& aArc );
/** /**
@ -290,7 +290,7 @@ public:
* @param aWidth is the line width. * @param aWidth is the line width.
* @param aData is an auxiliary info (mainly for gerber format). * @param aData is an auxiliary info (mainly for gerber format).
*/ */
virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, FILL_TYPE aFill, virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, FILL_T aFill,
int aWidth = USE_DEFAULT_LINE_WIDTH, void* aData = nullptr ) = 0; int aWidth = USE_DEFAULT_LINE_WIDTH, void* aData = nullptr ) = 0;
/** /**
@ -301,7 +301,7 @@ public:
* @param aWidth is the line width. * @param aWidth is the line width.
* @param aData is an auxiliary info (mainly for gerber format). * @param aData is an auxiliary info (mainly for gerber format).
*/ */
virtual void PlotPoly( const SHAPE_LINE_CHAIN& aCornerList, FILL_TYPE aFill, virtual void PlotPoly( const SHAPE_LINE_CHAIN& aCornerList, FILL_T aFill,
int aWidth = USE_DEFAULT_LINE_WIDTH, void* aData = nullptr ); int aWidth = USE_DEFAULT_LINE_WIDTH, void* aData = nullptr );
/** /**

View File

@ -89,7 +89,7 @@ public:
/** /**
* DXF rectangle: fill not supported. * DXF rectangle: fill not supported.
*/ */
virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH ) override; int width = USE_DEFAULT_LINE_WIDTH ) override;
/** /**
@ -98,7 +98,7 @@ public:
* *
* I could use this trick to do other filled primitives. * I could use this trick to do other filled primitives.
*/ */
virtual void Circle( const wxPoint& pos, int diametre, FILL_TYPE fill, virtual void Circle( const wxPoint& pos, int diametre, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH ) override; int width = USE_DEFAULT_LINE_WIDTH ) override;
/** /**
@ -108,12 +108,12 @@ public:
* It does not know thick segments, therefore filled polygons with thick outline * It does not know thick segments, therefore filled polygons with thick outline
* are converted to inflated polygon by aWidth/2. * are converted to inflated polygon by aWidth/2.
*/ */
virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, FILL_TYPE aFill, virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, FILL_T aFill,
int aWidth = USE_DEFAULT_LINE_WIDTH, void* aData = nullptr ) override; int aWidth = USE_DEFAULT_LINE_WIDTH, void* aData = nullptr ) override;
virtual void ThickSegment( const wxPoint& start, const wxPoint& end, int width, virtual void ThickSegment( const wxPoint& start, const wxPoint& end, int width,
OUTLINE_MODE tracemode, void* aData ) override; OUTLINE_MODE tracemode, void* aData ) override;
virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle, virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle,
int rayon, FILL_TYPE fill, int width = USE_DEFAULT_LINE_WIDTH ) override; int rayon, FILL_T fill, int width = USE_DEFAULT_LINE_WIDTH ) override;
virtual void PenTo( const wxPoint& pos, char plume ) override; virtual void PenTo( const wxPoint& pos, char plume ) override;
/** /**

View File

@ -65,12 +65,12 @@ public:
double aScale, bool aMirror ) override; double aScale, bool aMirror ) override;
// Basic plot primitives // Basic plot primitives
virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH ) override; int width = USE_DEFAULT_LINE_WIDTH ) override;
virtual void Circle( const wxPoint& pos, int diametre, FILL_TYPE fill, virtual void Circle( const wxPoint& pos, int diametre, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH ) override; int width = USE_DEFAULT_LINE_WIDTH ) override;
virtual void Arc( const wxPoint& aCenter, double aStAngle, double aEndAngle, virtual void Arc( const wxPoint& aCenter, double aStAngle, double aEndAngle, int aRadius,
int aRadius, FILL_TYPE aFill, int aWidth = USE_DEFAULT_LINE_WIDTH ) override; FILL_T aFill, int aWidth = USE_DEFAULT_LINE_WIDTH ) override;
virtual void Arc( const SHAPE_ARC& aArc ) override; virtual void Arc( const SHAPE_ARC& aArc ) override;
@ -91,10 +91,10 @@ public:
* Gerber polygon: they can (and *should*) be filled with the * Gerber polygon: they can (and *should*) be filled with the
* appropriate G36/G37 sequence * appropriate G36/G37 sequence
*/ */
virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, FILL_TYPE aFill, virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, FILL_T aFill,
int aWidth = USE_DEFAULT_LINE_WIDTH, void* aData = nullptr ) override; int aWidth = USE_DEFAULT_LINE_WIDTH, void* aData = nullptr ) override;
virtual void PlotPoly( const SHAPE_LINE_CHAIN& aCornerList, FILL_TYPE aFill, virtual void PlotPoly( const SHAPE_LINE_CHAIN& aCornerList, FILL_T aFill,
int aWidth = USE_DEFAULT_LINE_WIDTH, void* aData = nullptr ) override; int aWidth = USE_DEFAULT_LINE_WIDTH, void* aData = nullptr ) override;
virtual void PenTo( const wxPoint& pos, char plume ) override; virtual void PenTo( const wxPoint& pos, char plume ) override;

View File

@ -96,13 +96,12 @@ public:
virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil, virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
double aScale, bool aMirror ) override; double aScale, bool aMirror ) override;
virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH ) override; int width = USE_DEFAULT_LINE_WIDTH ) override;
virtual void Circle( const wxPoint& pos, int diametre, FILL_TYPE fill, virtual void Circle( const wxPoint& pos, int diametre, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH ) override; int width = USE_DEFAULT_LINE_WIDTH ) override;
virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, FILL_T aFill,
FILL_TYPE aFill, int aWidth = USE_DEFAULT_LINE_WIDTH, int aWidth = USE_DEFAULT_LINE_WIDTH, void* aData = nullptr ) override;
void* aData = nullptr ) override;
virtual void ThickSegment( const wxPoint& start, const wxPoint& end, int width, virtual void ThickSegment( const wxPoint& start, const wxPoint& end, int width,
OUTLINE_MODE tracemode, void* aData ) override; OUTLINE_MODE tracemode, void* aData ) override;
@ -119,8 +118,8 @@ public:
* EndAngle is end angle the arc. * EndAngle is end angle the arc.
* Radius is the radius of the arc. * Radius is the radius of the arc.
*/ */
virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle, virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle, int rayon,
int rayon, FILL_TYPE fill, int width = USE_DEFAULT_LINE_WIDTH ) override; FILL_T fill, int width = USE_DEFAULT_LINE_WIDTH ) override;
virtual void PenTo( const wxPoint& pos, char plume ) override; virtual void PenTo( const wxPoint& pos, char plume ) override;
virtual void FlashPadCircle( const wxPoint& aPadPos, int aDiameter, virtual void FlashPadCircle( const wxPoint& aPadPos, int aDiameter,
OUTLINE_MODE aTraceMode, void* aData ) override; OUTLINE_MODE aTraceMode, void* aData ) override;

View File

@ -197,14 +197,14 @@ public:
virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil, virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
double aScale, bool aMirror ) override; double aScale, bool aMirror ) override;
virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH ) override; int width = USE_DEFAULT_LINE_WIDTH ) override;
virtual void Circle( const wxPoint& pos, int diametre, FILL_TYPE fill, virtual void Circle( const wxPoint& pos, int diametre, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH ) override; int width = USE_DEFAULT_LINE_WIDTH ) override;
virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle, virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle, int rayon,
int rayon, FILL_TYPE fill, int width = USE_DEFAULT_LINE_WIDTH ) override; FILL_T fill, int width = USE_DEFAULT_LINE_WIDTH ) override;
virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, FILL_TYPE aFill, virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, FILL_T aFill,
int aWidth = USE_DEFAULT_LINE_WIDTH, void* aData = nullptr ) override; int aWidth = USE_DEFAULT_LINE_WIDTH, void* aData = nullptr ) override;
/** /**
@ -306,26 +306,26 @@ public:
/** /**
* Rectangles in PDF. Supported by the native operator. * Rectangles in PDF. Supported by the native operator.
*/ */
virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH ) override; int width = USE_DEFAULT_LINE_WIDTH ) override;
/** /**
* Circle drawing for PDF. They're approximated by curves, but fill is supported * Circle drawing for PDF. They're approximated by curves, but fill is supported
*/ */
virtual void Circle( const wxPoint& pos, int diametre, FILL_TYPE fill, virtual void Circle( const wxPoint& pos, int diametre, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH ) override; int width = USE_DEFAULT_LINE_WIDTH ) override;
/** /**
* The PDF engine can't directly plot arcs, it uses the base emulation. * The PDF engine can't directly plot arcs, it uses the base emulation.
* So no filled arcs (not a great loss... ) * So no filled arcs (not a great loss... )
*/ */
virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle, virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle, int rayon,
int rayon, FILL_TYPE fill, int width = USE_DEFAULT_LINE_WIDTH ) override; FILL_T fill, int width = USE_DEFAULT_LINE_WIDTH ) override;
/** /**
* Polygon plotting for PDF. Everything is supported * Polygon plotting for PDF. Everything is supported
*/ */
virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, FILL_TYPE aFill, virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, FILL_T aFill,
int aWidth = USE_DEFAULT_LINE_WIDTH, void* aData = nullptr ) override; int aWidth = USE_DEFAULT_LINE_WIDTH, void* aData = nullptr ) override;
virtual void PenTo( const wxPoint& pos, char plume ) override; virtual void PenTo( const wxPoint& pos, char plume ) override;
@ -442,21 +442,20 @@ public:
virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil, virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
double aScale, bool aMirror ) override; double aScale, bool aMirror ) override;
virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH ) override; int width = USE_DEFAULT_LINE_WIDTH ) override;
virtual void Circle( const wxPoint& pos, int diametre, FILL_TYPE fill, virtual void Circle( const wxPoint& pos, int diametre, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH ) override; int width = USE_DEFAULT_LINE_WIDTH ) override;
virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle, virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle, int rayon,
int rayon, FILL_TYPE fill, int width = USE_DEFAULT_LINE_WIDTH ) override; FILL_T fill, int width = USE_DEFAULT_LINE_WIDTH ) override;
virtual void BezierCurve( const wxPoint& aStart, const wxPoint& aControl1, virtual void BezierCurve( const wxPoint& aStart, const wxPoint& aControl1,
const wxPoint& aControl2, const wxPoint& aEnd, const wxPoint& aControl2, const wxPoint& aEnd,
int aTolerance, int aTolerance,
int aLineThickness = USE_DEFAULT_LINE_WIDTH ) override; int aLineThickness = USE_DEFAULT_LINE_WIDTH ) override;
virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, FILL_T aFill,
FILL_TYPE aFill, int aWidth = USE_DEFAULT_LINE_WIDTH, int aWidth = USE_DEFAULT_LINE_WIDTH, void * aData = nullptr ) override;
void * aData = nullptr ) override;
/** /**
* PostScript-likes at the moment are the only plot engines supporting bitmaps. * PostScript-likes at the moment are the only plot engines supporting bitmaps.
@ -524,9 +523,9 @@ protected:
/** /**
* Prepare parameters for setSVGPlotStyle() * Prepare parameters for setSVGPlotStyle()
*/ */
void setFillMode( FILL_TYPE fill ); void setFillMode( FILL_T fill );
FILL_TYPE m_fillMode; // true if the current contour FILL_T m_fillMode; // true if the current contour
// rect, arc, circle, polygon must be filled // rect, arc, circle, polygon must be filled
long m_pen_rgb_color; // current rgb color value: each color has long m_pen_rgb_color; // current rgb color value: each color has
// a value 0 ... 255, and the 3 colors are // a value 0 ... 255, and the 3 colors are

View File

@ -22,6 +22,7 @@
*/ */
#include <common.h> #include <common.h>
#include <math_for_graphics.h>
#include <board_design_settings.h> #include <board_design_settings.h>
#include <footprint.h> #include <footprint.h>
#include <pcb_shape.h> #include <pcb_shape.h>

View File

@ -195,8 +195,7 @@ int PLACEFILE_GERBER_WRITER::CreatePlaceFile( wxString& aFullFilename, PCB_LAYER
continue; continue;
useFpPadsBbox = false; useFpPadsBbox = false;
plotter.PLOTTER::PlotPoly( poly, FILL_TYPE::NO_FILL, line_thickness, plotter.PLOTTER::PlotPoly( poly, FILL_T::NO_FILL, line_thickness, &gbr_metadata );
&gbr_metadata );
} }
} }
@ -221,7 +220,7 @@ int PLACEFILE_GERBER_WRITER::CreatePlaceFile( wxString& aFullFilename, PCB_LAYER
poly.Rotate( -footprint->GetOrientationRadians(), VECTOR2I( 0, 0 ) ); poly.Rotate( -footprint->GetOrientationRadians(), VECTOR2I( 0, 0 ) );
poly.Move( footprint->GetPosition() ); poly.Move( footprint->GetPosition() );
plotter.PLOTTER::PlotPoly( poly, FILL_TYPE::NO_FILL, line_thickness, &gbr_metadata ); plotter.PLOTTER::PlotPoly( poly, FILL_T::NO_FILL, line_thickness, &gbr_metadata );
} }
std::vector<PAD*>pad_key_list; std::vector<PAD*>pad_key_list;

View File

@ -172,12 +172,6 @@ void FP_SHAPE::SetCenter0( const wxPoint& aCenter )
} }
void FP_SHAPE::SetArcAngle( double aAngle )
{
PCB_SHAPE::SetArcAngle( aAngle );
}
void FP_SHAPE::SetArcAngleAndEnd0( double aAngle ) void FP_SHAPE::SetArcAngleAndEnd0( double aAngle )
{ {
PCB_SHAPE::SetArcAngle( aAngle ); PCB_SHAPE::SetArcAngle( aAngle );
@ -195,13 +189,9 @@ void FP_SHAPE::Flip( const wxPoint& aCentre, bool aFlipLeftRight )
switch( GetShape() ) switch( GetShape() )
{ {
case SHAPE_T::ARC: case SHAPE_T::ARC:
// 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.
SetArcAngle( -GetArcAngle() );
KI_FALLTHROUGH;
default:
case SHAPE_T::SEGMENT: case SHAPE_T::SEGMENT:
case SHAPE_T::RECT:
case SHAPE_T::CIRCLE:
case SHAPE_T::BEZIER: case SHAPE_T::BEZIER:
// If Start0 and Start are equal (ie: Footprint Editor), then flip both sets around the // If Start0 and Start are equal (ie: Footprint Editor), then flip both sets around the
// centre point. // centre point.
@ -235,13 +225,18 @@ void FP_SHAPE::Flip( const wxPoint& aCentre, bool aFlipLeftRight )
MIRROR( m_bezierC2_0.y, pt.y ); MIRROR( m_bezierC2_0.y, pt.y );
} }
if( GetShape() == SHAPE_T::BEZIER )
RebuildBezierToSegmentsPointsList( m_width ); RebuildBezierToSegmentsPointsList( m_width );
break; break;
case SHAPE_T::POLY: case SHAPE_T::POLY:
// polygon corners coordinates are relative to the footprint position, orientation 0 // polygon corners coordinates are relative to the footprint position, orientation 0
m_poly.Mirror( aFlipLeftRight, !aFlipLeftRight ); m_poly.Mirror( aFlipLeftRight, !aFlipLeftRight );
break; break;
default:
UNIMPLEMENTED_FOR( SHAPE_T_asString() );
} }
SetLayer( FlipLayer( GetLayer(), GetBoard()->GetCopperLayerCount() ) ); SetLayer( FlipLayer( GetLayer(), GetBoard()->GetCopperLayerCount() ) );
@ -262,14 +257,10 @@ void FP_SHAPE::Mirror( const wxPoint& aCentre, bool aMirrorAroundXAxis )
switch( GetShape() ) switch( GetShape() )
{ {
case SHAPE_T::ARC: case SHAPE_T::ARC:
// 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.
SetArcAngle( -GetArcAngle() );
KI_FALLTHROUGH;
default:
case SHAPE_T::BEZIER:
case SHAPE_T::SEGMENT: case SHAPE_T::SEGMENT:
case SHAPE_T::RECT:
case SHAPE_T::CIRCLE:
case SHAPE_T::BEZIER:
if( aMirrorAroundXAxis ) if( aMirrorAroundXAxis )
{ {
MIRROR( m_start0.y, aCentre.y ); MIRROR( m_start0.y, aCentre.y );
@ -287,13 +278,8 @@ void FP_SHAPE::Mirror( const wxPoint& aCentre, bool aMirrorAroundXAxis )
MIRROR( m_bezierC2_0.x, aCentre.x ); MIRROR( m_bezierC2_0.x, aCentre.x );
} }
for( unsigned ii = 0; ii < m_bezierPoints.size(); ii++ ) if( GetShape() == SHAPE_T::BEZIER )
{ RebuildBezierToSegmentsPointsList( m_width );
if( aMirrorAroundXAxis )
MIRROR( m_bezierPoints[ii].y, aCentre.y );
else
MIRROR( m_bezierPoints[ii].x, aCentre.x );
}
break; break;
@ -302,6 +288,9 @@ void FP_SHAPE::Mirror( const wxPoint& aCentre, bool aMirrorAroundXAxis )
// footprint position, orientation 0 // footprint position, orientation 0
m_poly.Mirror( !aMirrorAroundXAxis, aMirrorAroundXAxis ); m_poly.Mirror( !aMirrorAroundXAxis, aMirrorAroundXAxis );
break; break;
default:
UNIMPLEMENTED_FOR( SHAPE_T_asString() );
} }
SetDrawCoord(); SetDrawCoord();
@ -323,15 +312,19 @@ void FP_SHAPE::Move( const wxPoint& aMoveVector )
{ {
// Move an edge of the footprint. // Move an edge of the footprint.
// This is a footprint shape modification. // This is a footprint shape modification.
switch( GetShape() )
{
case SHAPE_T::ARC:
case SHAPE_T::SEGMENT:
case SHAPE_T::RECT:
case SHAPE_T::CIRCLE:
case SHAPE_T::BEZIER:
m_start0 += aMoveVector; m_start0 += aMoveVector;
m_end0 += aMoveVector; m_end0 += aMoveVector;
m_arcCenter0 += aMoveVector; m_arcCenter0 += aMoveVector;
m_bezierC1_0 += aMoveVector; m_bezierC1_0 += aMoveVector;
m_bezierC2_0 += aMoveVector; m_bezierC2_0 += aMoveVector;
switch( GetShape() )
{
default:
break; break;
case SHAPE_T::POLY: case SHAPE_T::POLY:
@ -340,6 +333,9 @@ void FP_SHAPE::Move( const wxPoint& aMoveVector )
m_poly.Move( VECTOR2I( aMoveVector ) ); m_poly.Move( VECTOR2I( aMoveVector ) );
break; break;
default:
UNIMPLEMENTED_FOR( SHAPE_T_asString() );
} }
SetDrawCoord(); SetDrawCoord();

View File

@ -71,7 +71,6 @@ public:
* Sets the angle for arcs, and normalizes it within the range 0 - 360 degrees. * 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 aAngle is tenths of degrees, but will soon be degrees.
*/ */
void SetArcAngle( double aAngle ) override;
void SetArcAngleAndEnd0( double aAngle ); void SetArcAngleAndEnd0( double aAngle );
/** /**

View File

@ -35,14 +35,14 @@
PCB_SHAPE::PCB_SHAPE( BOARD_ITEM* aParent, KICAD_T idtype, SHAPE_T shapetype ) : PCB_SHAPE::PCB_SHAPE( BOARD_ITEM* aParent, KICAD_T idtype, SHAPE_T shapetype ) :
BOARD_ITEM( aParent, idtype ), BOARD_ITEM( aParent, idtype ),
EDA_SHAPE( shapetype, Millimeter2iu( DEFAULT_LINE_WIDTH ) ) EDA_SHAPE( shapetype, Millimeter2iu( DEFAULT_LINE_WIDTH ), FILL_T::NO_FILL )
{ {
} }
PCB_SHAPE::PCB_SHAPE( BOARD_ITEM* aParent, SHAPE_T shapetype ) : PCB_SHAPE::PCB_SHAPE( BOARD_ITEM* aParent, SHAPE_T shapetype ) :
BOARD_ITEM( aParent, PCB_SHAPE_T ), BOARD_ITEM( aParent, PCB_SHAPE_T ),
EDA_SHAPE( shapetype, Millimeter2iu( DEFAULT_LINE_WIDTH ) ) EDA_SHAPE( shapetype, Millimeter2iu( DEFAULT_LINE_WIDTH ), FILL_T::NO_FILL )
{ {
} }

View File

@ -729,7 +729,7 @@ void PlotLayerOutlines( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
const SHAPE_LINE_CHAIN& path = const SHAPE_LINE_CHAIN& path =
( kk == 0 ) ? outlines.COutline( ii ) : outlines.CHole( ii, kk - 1 ); ( kk == 0 ) ? outlines.COutline( ii ) : outlines.CHole( ii, kk - 1 );
aPlotter->PlotPoly( path, FILL_TYPE::NO_FILL ); aPlotter->PlotPoly( path, FILL_T::NO_FILL );
} }
} }
@ -751,7 +751,7 @@ void PlotLayerOutlines( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
if( hole.x == hole.y ) if( hole.x == hole.y )
{ {
hole.x = std::min( smallDrill, hole.x ); hole.x = std::min( smallDrill, hole.x );
aPlotter->Circle( pad->GetPosition(), hole.x, FILL_TYPE::NO_FILL ); aPlotter->Circle( pad->GetPosition(), hole.x, FILL_T::NO_FILL );
} }
else else
{ {
@ -771,9 +771,7 @@ void PlotLayerOutlines( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
const PCB_VIA* via = dyn_cast<const PCB_VIA*>( track ); const PCB_VIA* via = dyn_cast<const PCB_VIA*>( track );
if( via && via->IsOnLayer( layer ) ) // via holes can be not through holes if( via && via->IsOnLayer( layer ) ) // via holes can be not through holes
{ aPlotter->Circle( via->GetPosition(), via->GetDrillValue(), FILL_T::NO_FILL );
aPlotter->Circle( via->GetPosition(), via->GetDrillValue(), FILL_TYPE::NO_FILL );
}
} }
} }
} }
@ -990,7 +988,7 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
if( curr_area < poly_min_area_mm2 ) if( curr_area < poly_min_area_mm2 )
continue; continue;
aPlotter->PlotPoly( path, FILL_TYPE::FILLED_SHAPE ); aPlotter->PlotPoly( path, FILL_T::FILLED_SHAPE );
} }
#endif #endif
} }
@ -1096,7 +1094,7 @@ static void FillNegativeKnockout( PLOTTER *aPlotter, const EDA_RECT &aBbbox )
aPlotter->SetColor( WHITE ); // Which will be plotted as black aPlotter->SetColor( WHITE ); // Which will be plotted as black
EDA_RECT area = aBbbox; EDA_RECT area = aBbbox;
area.Inflate( margin ); area.Inflate( margin );
aPlotter->Rect( area.GetOrigin(), area.GetEnd(), FILL_TYPE::FILLED_SHAPE ); aPlotter->Rect( area.GetOrigin(), area.GetEnd(), FILL_T::FILLED_SHAPE );
aPlotter->SetColor( BLACK ); aPlotter->SetColor( BLACK );
} }

View File

@ -589,7 +589,7 @@ void BRDITEMS_PLOTTER::PlotFootprintGraphicItem( const FP_SHAPE* aShape )
for( const wxPoint& pt : pts ) for( const wxPoint& pt : pts )
poly.Append( pt ); poly.Append( pt );
m_plotter->PlotPoly( poly, FILL_TYPE::FILLED_SHAPE, -1, &gbr_metadata ); m_plotter->PlotPoly( poly, FILL_T::FILLED_SHAPE, -1, &gbr_metadata );
} }
} }
break; break;
@ -679,7 +679,7 @@ void BRDITEMS_PLOTTER::PlotFootprintGraphicItem( const FP_SHAPE* aShape )
for( int jj = 0; jj < tmpPoly.OutlineCount(); ++jj ) for( int jj = 0; jj < tmpPoly.OutlineCount(); ++jj )
{ {
SHAPE_LINE_CHAIN &poly = tmpPoly.Outline( jj ); SHAPE_LINE_CHAIN &poly = tmpPoly.Outline( jj );
m_plotter->PlotPoly( poly, FILL_TYPE::FILLED_SHAPE, thickness, &gbr_metadata ); m_plotter->PlotPoly( poly, FILL_T::FILLED_SHAPE, thickness, &gbr_metadata );
} }
} }
} }
@ -811,8 +811,8 @@ void BRDITEMS_PLOTTER::PlotFilledAreas( const ZONE* aZone, const SHAPE_POLY_SET&
{ {
if( outline_thickness > 0 ) if( outline_thickness > 0 )
{ {
m_plotter->PlotPoly( outline, FILL_TYPE::NO_FILL, m_plotter->PlotPoly( outline, FILL_T::NO_FILL, outline_thickness,
outline_thickness, &gbr_metadata ); &gbr_metadata );
// Ensure the outline is closed: // Ensure the outline is closed:
int last_idx = outline.PointCount() - 1; int last_idx = outline.PointCount() - 1;
@ -821,8 +821,7 @@ void BRDITEMS_PLOTTER::PlotFilledAreas( const ZONE* aZone, const SHAPE_POLY_SET&
{ {
m_plotter->ThickSegment( wxPoint( outline.CPoint( 0 ) ), m_plotter->ThickSegment( wxPoint( outline.CPoint( 0 ) ),
wxPoint( outline.CPoint( last_idx ) ), wxPoint( outline.CPoint( last_idx ) ),
outline_thickness, outline_thickness, GetPlotMode(), &gbr_metadata );
GetPlotMode(), &gbr_metadata );
} }
} }
@ -831,8 +830,8 @@ void BRDITEMS_PLOTTER::PlotFilledAreas( const ZONE* aZone, const SHAPE_POLY_SET&
} }
else else
{ {
m_plotter->PlotPoly( outline, FILL_TYPE::FILLED_SHAPE, m_plotter->PlotPoly( outline, FILL_T::FILLED_SHAPE, outline_thickness,
outline_thickness, &gbr_metadata ); &gbr_metadata );
} }
} }
else else
@ -962,7 +961,7 @@ void BRDITEMS_PLOTTER::PlotPcbShape( const PCB_SHAPE* aShape )
for( int jj = 0; jj < tmpPoly.OutlineCount(); ++jj ) for( int jj = 0; jj < tmpPoly.OutlineCount(); ++jj )
{ {
SHAPE_LINE_CHAIN& poly = tmpPoly.Outline( jj ); SHAPE_LINE_CHAIN& poly = tmpPoly.Outline( jj );
m_plotter->PlotPoly( poly, FILL_TYPE::FILLED_SHAPE, thickness, &gbr_metadata ); m_plotter->PlotPoly( poly, FILL_T::FILLED_SHAPE, thickness, &gbr_metadata );
} }
} }
} }
@ -987,7 +986,7 @@ void BRDITEMS_PLOTTER::PlotPcbShape( const PCB_SHAPE* aShape )
for( const wxPoint& pt : pts ) for( const wxPoint& pt : pts )
poly.Append( pt ); poly.Append( pt );
m_plotter->PlotPoly( poly, FILL_TYPE::FILLED_SHAPE, -1, &gbr_metadata ); m_plotter->PlotPoly( poly, FILL_T::FILLED_SHAPE, -1, &gbr_metadata );
} }
break; break;

View File

@ -29,8 +29,7 @@
#include <qa_utils/wx_utils/unit_test_utils.h> #include <qa_utils/wx_utils/unit_test_utils.h>
// Code under test // Code under test
#include <lib_rectangle.h> #include <lib_shape.h>
#include <lib_arc.h>
#include <lib_pin.h> #include <lib_pin.h>
#include "lib_field_test_utils.h" #include "lib_field_test_utils.h"
@ -266,25 +265,25 @@ BOOST_AUTO_TEST_CASE( Compare )
m_part_no_data.SetNormal(); m_part_no_data.SetNormal();
// Draw item list size comparison tests. // Draw item list size comparison tests.
testPart.AddDrawItem( new LIB_RECTANGLE( &testPart ) ); testPart.AddDrawItem( new LIB_SHAPE( &testPart, SHAPE_T::RECT ) );
m_part_no_data.AddDrawItem( new LIB_RECTANGLE( &m_part_no_data ) ); m_part_no_data.AddDrawItem( new LIB_SHAPE( &m_part_no_data, SHAPE_T::RECT ) );
BOOST_CHECK_EQUAL( m_part_no_data.Compare( testPart ), 0 ); BOOST_CHECK_EQUAL( m_part_no_data.Compare( testPart ), 0 );
m_part_no_data.RemoveDrawItem( m_part_no_data.GetNextDrawItem( nullptr, LIB_RECTANGLE_T ) ); m_part_no_data.RemoveDrawItem( m_part_no_data.GetNextDrawItem( nullptr, LIB_SHAPE_T ) );
BOOST_CHECK( m_part_no_data.Compare( testPart ) < 0 ); BOOST_CHECK( m_part_no_data.Compare( testPart ) < 0 );
testPart.RemoveDrawItem( testPart.GetNextDrawItem( nullptr, LIB_RECTANGLE_T ) ); testPart.RemoveDrawItem( testPart.GetNextDrawItem( nullptr, LIB_SHAPE_T ) );
m_part_no_data.AddDrawItem( new LIB_RECTANGLE( &m_part_no_data ) ); m_part_no_data.AddDrawItem( new LIB_SHAPE( &m_part_no_data, SHAPE_T::RECT ) );
BOOST_CHECK( m_part_no_data.Compare( testPart ) > 0 ); BOOST_CHECK( m_part_no_data.Compare( testPart ) > 0 );
m_part_no_data.RemoveDrawItem( m_part_no_data.GetNextDrawItem( nullptr, LIB_RECTANGLE_T ) ); m_part_no_data.RemoveDrawItem( m_part_no_data.GetNextDrawItem( nullptr, LIB_SHAPE_T ) );
// Draw item list contents comparison tests. // Draw item list contents comparison tests.
testPart.AddDrawItem( new LIB_RECTANGLE( &testPart ) ); testPart.AddDrawItem( new LIB_SHAPE( &testPart, SHAPE_T::RECT ) );
m_part_no_data.AddDrawItem( new LIB_ARC( &m_part_no_data ) ); m_part_no_data.AddDrawItem( new LIB_SHAPE( &m_part_no_data, SHAPE_T::ARC ) );
BOOST_CHECK( m_part_no_data.Compare( testPart ) < 0 ); BOOST_CHECK( m_part_no_data.Compare( testPart ) < 0 );
m_part_no_data.RemoveDrawItem( m_part_no_data.GetNextDrawItem( nullptr, LIB_ARC_T ) ); m_part_no_data.RemoveDrawItem( m_part_no_data.GetNextDrawItem( nullptr, LIB_SHAPE_T ) );
m_part_no_data.AddDrawItem( new LIB_PIN( &m_part_no_data ) ); m_part_no_data.AddDrawItem( new LIB_PIN( &m_part_no_data ) );
BOOST_CHECK( m_part_no_data.Compare( testPart ) > 0 ); BOOST_CHECK( m_part_no_data.Compare( testPart ) > 0 );
m_part_no_data.RemoveDrawItem( m_part_no_data.GetNextDrawItem( nullptr, LIB_PIN_T ) ); m_part_no_data.RemoveDrawItem( m_part_no_data.GetNextDrawItem( nullptr, LIB_PIN_T ) );
testPart.RemoveDrawItem( testPart.GetNextDrawItem( nullptr, LIB_RECTANGLE_T ) ); testPart.RemoveDrawItem( testPart.GetNextDrawItem( nullptr, LIB_SHAPE_T ) );
// Footprint filter array comparison tests. // Footprint filter array comparison tests.
wxArrayString footPrintFilters; wxArrayString footPrintFilters;