diff --git a/common/plotters/DXF_plotter.cpp b/common/plotters/DXF_plotter.cpp index 45270e2b70..fd046886a1 100644 --- a/common/plotters/DXF_plotter.cpp +++ b/common/plotters/DXF_plotter.cpp @@ -5,7 +5,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2017-2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2017-2022 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 diff --git a/common/plotters/GERBER_plotter.cpp b/common/plotters/GERBER_plotter.cpp index 2779dc9a76..b64cd004b2 100644 --- a/common/plotters/GERBER_plotter.cpp +++ b/common/plotters/GERBER_plotter.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr - * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2022 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 @@ -1124,9 +1124,9 @@ void GERBER_PLOTTER::ThickSegment( const VECTOR2I& start, const VECTOR2I& end, i } } -void GERBER_PLOTTER::ThickArc( const VECTOR2I& centre, const EDA_ANGLE& aStartAngle, +void GERBER_PLOTTER::ThickArc( const VECTOR2I& aCentre, const EDA_ANGLE& aStartAngle, const EDA_ANGLE& aEndAngle, int aRadius, int aWidth, - OUTLINE_MODE tracemode, void* aData ) + OUTLINE_MODE aTraceMode, void* aData ) { GBR_METADATA *gbr_metadata = static_cast( aData ); SetCurrentLineWidth( aWidth, gbr_metadata ); @@ -1134,21 +1134,59 @@ void GERBER_PLOTTER::ThickArc( const VECTOR2I& centre, const EDA_ANGLE& aStartAn if( gbr_metadata ) formatNetAttribute( &gbr_metadata->m_NetlistMetadata ); - if( tracemode == FILLED ) + if( aTraceMode == FILLED ) { - Arc( centre, aStartAngle, aEndAngle, aRadius, FILL_T::NO_FILL, DO_NOT_SET_LINE_WIDTH ); + Arc( aCentre, aStartAngle, aEndAngle, aRadius, FILL_T::NO_FILL, DO_NOT_SET_LINE_WIDTH ); } else { SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); - Arc( centre, aStartAngle, aEndAngle, aRadius - ( aWidth - m_currentPenWidth ) / 2, + Arc( aCentre, aStartAngle, aEndAngle, aRadius - ( aWidth - m_currentPenWidth ) / 2, FILL_T::NO_FILL, DO_NOT_SET_LINE_WIDTH ); - Arc( centre, aStartAngle, aEndAngle, aRadius + ( aWidth - m_currentPenWidth ) / 2, + Arc( aCentre, aStartAngle, aEndAngle, aRadius + ( aWidth - m_currentPenWidth ) / 2, FILL_T::NO_FILL, DO_NOT_SET_LINE_WIDTH ); } } +void GERBER_PLOTTER::ThickArc( const VECTOR2I& aCentre, const VECTOR2I& aStart, + const VECTOR2I& aEnd, int aWidth, + OUTLINE_MODE aTraceMode, void* aData ) +{ + EDA_ANGLE start_angle( aStart - aCentre ); + EDA_ANGLE end_angle( aEnd - aCentre ); + + if( start_angle > end_angle ) + { + if( end_angle < ANGLE_0 ) + end_angle.Normalize(); + else + start_angle = start_angle.Normalize() - ANGLE_360; + } + + int radius = (aStart - aCentre).EuclideanNorm(); + + if( !m_yaxisReversed ) // should be always the case + { + std::swap( end_angle, start_angle ); + end_angle = -end_angle; + start_angle = -start_angle; + } + + ThickArc( aCentre, start_angle, end_angle, radius, aWidth, aTraceMode, aData ); +} + + +void GERBER_PLOTTER::ThickArc( const EDA_SHAPE& aArcShape, + OUTLINE_MODE aTraceMode, void* aData ) +{ + wxASSERT( aArcShape.GetShape() == SHAPE_T::ARC ); + + ThickArc( aArcShape.getCenter(), aArcShape.GetStart(), aArcShape.GetEnd(), + aArcShape.GetWidth(), aTraceMode, aData ); +} + + void GERBER_PLOTTER::ThickRect( const VECTOR2I& p1, const VECTOR2I& p2, int width, OUTLINE_MODE tracemode, void* aData ) { diff --git a/common/plotters/HPGL_plotter.cpp b/common/plotters/HPGL_plotter.cpp index 63f8b7d28e..d75480106f 100644 --- a/common/plotters/HPGL_plotter.cpp +++ b/common/plotters/HPGL_plotter.cpp @@ -2,7 +2,7 @@ * 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) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2020-2022 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 @@ -570,8 +570,6 @@ void HPGL_PLOTTER::ThickSegment( const VECTOR2I& start, const VECTOR2I& end, void HPGL_PLOTTER::Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle, const EDA_ANGLE& aEndAngle, int aRadius, FILL_T aFill, int aWidth ) { - wxASSERT( m_outputFile ); - if( aRadius <= 0 ) return; @@ -611,6 +609,18 @@ void HPGL_PLOTTER::Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle, } +void HPGL_PLOTTER::Arc( const VECTOR2I& aCenter, const VECTOR2I& aStart, + const VECTOR2I& aEnd, + FILL_T aFill, int aWidth, int aMaxError ) +{ + EDA_ANGLE startAngle( aStart - aCenter ); + EDA_ANGLE endAngle( aEnd - aCenter ); + int radius = ( aStart - aCenter ).EuclideanNorm(); + + Arc( aCenter, -endAngle, -startAngle, radius, aFill, aWidth ); +} + + void HPGL_PLOTTER::FlashPadOval( const VECTOR2I& aPos, const VECTOR2I& aSize, const EDA_ANGLE& aOrient, OUTLINE_MODE aTraceMode, void* aData ) { diff --git a/common/plotters/plotter.cpp b/common/plotters/plotter.cpp index 15ae6e6325..4872ceacfc 100644 --- a/common/plotters/plotter.cpp +++ b/common/plotters/plotter.cpp @@ -2,7 +2,7 @@ * 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) 2017-2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2017-2022 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 @@ -159,6 +159,9 @@ void PLOTTER::Arc( const VECTOR2I& aCenter, const VECTOR2I& aStart, const VECTOR EDA_ANGLE startAngle( aStart - aCenter ); EDA_ANGLE endAngle( aEnd - aCenter ); int radius = ( aStart - aCenter ).EuclideanNorm(); + + #if 0 + // Approximate arc by segments: int numSegs = GetArcToSegmentCount( radius, aMaxError, FULL_CIRCLE ); EDA_ANGLE delta = ANGLE_360 / std::max( 8, numSegs ); VECTOR2I start( aStart ); @@ -193,6 +196,25 @@ void PLOTTER::Arc( const VECTOR2I& aCenter, const VECTOR2I& aStart, const VECTOR LineTo( end ); FinishTo( aCenter ); } + + #else + if( startAngle > endAngle ) + { + if( endAngle < ANGLE_0 ) + endAngle.Normalize(); + else + startAngle = startAngle.Normalize() - ANGLE_360; + } + + if( m_yaxisReversed ) + { + std::swap( startAngle, endAngle ); + startAngle = -startAngle; + endAngle = -endAngle; + } + + Arc( aCenter, startAngle, endAngle, radius, aFill, aWidth ); + #endif } @@ -607,6 +629,42 @@ void PLOTTER::ThickArc( const VECTOR2I& centre, const EDA_ANGLE& aStartAngle, } +void PLOTTER::ThickArc( const VECTOR2I& aCentre, const VECTOR2I& aStart, + const VECTOR2I& aEnd, int aWidth, + OUTLINE_MODE aTraceMode, void* aData ) +{ + if( aTraceMode == FILLED ) + { + Arc( aCentre, aStart, aEnd, FILL_T::NO_FILL, aWidth, GetPlotterArcHighDef() ); + } + else + { + SetCurrentLineWidth( -1 ); + int radius = ( aStart - aCentre ).EuclideanNorm(); + + int new_radius = radius - ( aWidth - m_currentPenWidth ) / 2; + VECTOR2I start = ( aStart - aCentre ).Resize( new_radius ) + aCentre; + VECTOR2I end = ( aEnd - aCentre ).Resize( new_radius ) + aCentre; + + Arc( aCentre, start, end, FILL_T::NO_FILL, -1, GetPlotterArcHighDef() ); + + new_radius = radius + ( aWidth - m_currentPenWidth ) / 2; + start = ( aStart - aCentre ).Resize( new_radius ) + aCentre; + end = ( aEnd - aCentre ).Resize( new_radius ) + aCentre; + + Arc( aCentre, start, end, FILL_T::NO_FILL, -1, GetPlotterArcHighDef() ); + } +} + + +void PLOTTER::ThickArc( const EDA_SHAPE& aArcShape, + OUTLINE_MODE aTraceMode, void* aData ) +{ + ThickArc( aArcShape.getCenter(),aArcShape.GetStart(), aArcShape.GetEnd(), + aArcShape.GetWidth(), aTraceMode, aData ); +} + + void PLOTTER::ThickRect( const VECTOR2I& p1, const VECTOR2I& p2, int width, OUTLINE_MODE tracemode, void* aData ) { diff --git a/include/plotters/plotter.h b/include/plotters/plotter.h index 63b873d5d0..786ecef11d 100644 --- a/include/plotters/plotter.h +++ b/include/plotters/plotter.h @@ -309,13 +309,24 @@ public: // Higher level primitives -- can be drawn as line, sketch or 'filled' virtual void ThickSegment( const VECTOR2I& start, const VECTOR2I& end, int width, OUTLINE_MODE tracemode, void* aData ); - virtual void ThickArc( const VECTOR2I& centre, const EDA_ANGLE& StAngle, - const EDA_ANGLE& EndAngle, int rayon, int width, - OUTLINE_MODE tracemode, void* aData ); + + virtual void ThickArc( const VECTOR2I& aCentre, const EDA_ANGLE& StAngle, + const EDA_ANGLE& EndAngle, int aRadius, int aWidth, + OUTLINE_MODE aTraceMode, void* aData ); + + virtual void ThickArc( const VECTOR2I& aCentre, const VECTOR2I& aStart, + const VECTOR2I& aEnd, int aWidth, + OUTLINE_MODE aTraceMode, void* aData ); + + virtual void ThickArc( const EDA_SHAPE& aArcShape, + OUTLINE_MODE aTraceMode, void* aData ); + virtual void ThickRect( const VECTOR2I& p1, const VECTOR2I& p2, int width, OUTLINE_MODE tracemode, void* aData ); + virtual void ThickCircle( const VECTOR2I& pos, int diametre, int width, OUTLINE_MODE tracemode, void* aData ); + virtual void FilledCircle( const VECTOR2I& pos, int diametre, OUTLINE_MODE tracemode, void* aData ); diff --git a/include/plotters/plotter_gerber.h b/include/plotters/plotter_gerber.h index ec01394d5a..0388edc661 100644 --- a/include/plotters/plotter_gerber.h +++ b/include/plotters/plotter_gerber.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2020 Jean-Pierre Charras, jp.charras at wanadoo.fr - * Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2022 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 @@ -77,13 +77,23 @@ public: virtual void ThickSegment( const VECTOR2I& start, const VECTOR2I& end, int width, OUTLINE_MODE tracemode, void* aData ) override; - virtual void ThickArc( const VECTOR2I& centre, const EDA_ANGLE& aStartAngle, + virtual void ThickArc( const VECTOR2I& aCentre, const EDA_ANGLE& aStartAngle, const EDA_ANGLE& aEndAngle, int aRadius, int aWidth, - OUTLINE_MODE tracemode, void* aData ) override; + OUTLINE_MODE aTraceMode, void* aData ) override; + + virtual void ThickArc( const VECTOR2I& aCentre, const VECTOR2I& aStart, + const VECTOR2I& aEnd, int aWidth, + OUTLINE_MODE aTraceMode, void* aData ) override; + + virtual void ThickArc( const EDA_SHAPE& aArcShape, + OUTLINE_MODE aTraceMode, void* aData ) override; + virtual void ThickRect( const VECTOR2I& p1, const VECTOR2I& p2, int width, OUTLINE_MODE tracemode, void* aData ) override; + virtual void ThickCircle( const VECTOR2I& pos, int diametre, int width, OUTLINE_MODE tracemode, void* aData ) override; + virtual void FilledCircle( const VECTOR2I& pos, int diametre, OUTLINE_MODE tracemode, void* aData ) override; diff --git a/include/plotters/plotter_hpgl.h b/include/plotters/plotter_hpgl.h index 8926dbe3cd..d3720bf503 100644 --- a/include/plotters/plotter_hpgl.h +++ b/include/plotters/plotter_hpgl.h @@ -1,7 +1,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2022 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 @@ -121,7 +121,12 @@ public: virtual void Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle, const EDA_ANGLE& aEndAngle, int aRadius, FILL_T aFill, int aWidth = USE_DEFAULT_LINE_WIDTH ) override; + + virtual void Arc( const VECTOR2I& aCenter, const VECTOR2I& aStart, const VECTOR2I& aEnd, + FILL_T aFill, int aWidth, int aMaxError ) override; + virtual void PenTo( const VECTOR2I& pos, char plume ) override; + virtual void FlashPadCircle( const VECTOR2I& aPadPos, int aDiameter, OUTLINE_MODE aTraceMode, void* aData ) override; virtual void FlashPadOval( const VECTOR2I& aPadPos, const VECTOR2I& aSize, diff --git a/pcbnew/plot_board_layers.cpp b/pcbnew/plot_board_layers.cpp index 868890f74c..68cfcd4298 100644 --- a/pcbnew/plot_board_layers.cpp +++ b/pcbnew/plot_board_layers.cpp @@ -579,13 +579,14 @@ void PlotStandardLayer( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask, if( track->Type() == PCB_ARC_T ) { const PCB_ARC* arc = static_cast( track ); - VECTOR2D center( arc->GetCenter() ); - int radius = arc->GetRadius(); - EDA_ANGLE start_angle = arc->GetArcAngleStart(); - EDA_ANGLE end_angle = start_angle + arc->GetAngle(); + PCB_SHAPE arc_shape( nullptr, SHAPE_T::ARC ); + arc_shape.SetWidth( width ); + arc_shape.SetStart( arc->GetStart() ); + arc_shape.SetEnd( arc->GetEnd() ); + arc_shape.SetCenter( arc->GetCenter() ); - aPlotter->ThickArc( center, -end_angle, -start_angle, radius, width, plotMode, - &gbr_metadata ); + aPlotter->ThickArc( arc->GetCenter(), arc->GetStart(), arc->GetEnd(), + width, plotMode, &gbr_metadata ); } else { diff --git a/pcbnew/plot_brditems_plotter.cpp b/pcbnew/plot_brditems_plotter.cpp index cda1f1d0c9..db612b3004 100644 --- a/pcbnew/plot_brditems_plotter.cpp +++ b/pcbnew/plot_brditems_plotter.cpp @@ -673,10 +673,9 @@ void BRDITEMS_PLOTTER::PlotFootprintShape( const FP_SHAPE* aShape ) case SHAPE_T::ARC: { radius = KiROUND( GetLineLength( aShape->GetCenter(), aShape->GetStart() ) ); - EDA_ANGLE startAngle( aShape->GetStart() - aShape->GetCenter() ); - EDA_ANGLE endAngle = startAngle - aShape->GetArcAngle(); // when startAngle == endAngle ThickArc() doesn't know whether it's 0 deg and 360 deg + // but it is a circle if( std::abs( aShape->GetArcAngle().AsDegrees() ) == 360.0 ) { m_plotter->ThickCircle( aShape->GetCenter(), radius * 2, thickness, GetPlotMode(), @@ -684,8 +683,7 @@ void BRDITEMS_PLOTTER::PlotFootprintShape( const FP_SHAPE* aShape ) } else { - m_plotter->ThickArc( aShape->GetCenter(), -startAngle, -endAngle, radius, - thickness, GetPlotMode(), &gbr_metadata ); + m_plotter->ThickArc( *aShape, GetPlotMode(), &gbr_metadata ); } } break; @@ -945,10 +943,8 @@ void BRDITEMS_PLOTTER::PlotPcbShape( const PCB_SHAPE* aShape ) case SHAPE_T::ARC: { - EDA_ANGLE startAngle( aShape->GetStart() - aShape->GetCenter() ); - EDA_ANGLE endAngle = startAngle - aShape->GetArcAngle(); - // when startAngle == endAngle ThickArc() doesn't know whether it's 0 deg and 360 deg + // but it is a circle if( std::abs( aShape->GetArcAngle().AsDegrees() ) == 360.0 ) { m_plotter->ThickCircle( aShape->GetCenter(), aShape->GetRadius() * 2, thickness, @@ -956,8 +952,7 @@ void BRDITEMS_PLOTTER::PlotPcbShape( const PCB_SHAPE* aShape ) } else { - m_plotter->ThickArc( aShape->GetCenter(), -startAngle, -endAngle, - aShape->GetRadius(), thickness, GetPlotMode(), &gbr_metadata ); + m_plotter->ThickArc( *aShape, GetPlotMode(), &gbr_metadata ); } break;