From 4d66a8ebdbdba711e34dd6530606b2e3a7bf3c10 Mon Sep 17 00:00:00 2001 From: Alex Shvartzkop Date: Sat, 9 Mar 2024 02:07:21 +0300 Subject: [PATCH] Fix rendering/plotting of arcs with tiny angle and huge radius. Fixes https://gitlab.com/kicad/code/kicad/-/issues/17343 --- common/plotters/GERBER_plotter.cpp | 10 +++++----- common/plotters/HPGL_plotter.cpp | 6 +++--- common/plotters/PDF_plotter.cpp | 12 ++++++------ include/plotters/plotter_gerber.h | 2 +- libs/kimath/include/trigo.h | 3 +-- pcbnew/pcb_track.cpp | 10 ++++++++-- 6 files changed, 24 insertions(+), 19 deletions(-) diff --git a/common/plotters/GERBER_plotter.cpp b/common/plotters/GERBER_plotter.cpp index 9efdbb1cfb..b59ad9fa44 100644 --- a/common/plotters/GERBER_plotter.cpp +++ b/common/plotters/GERBER_plotter.cpp @@ -879,19 +879,19 @@ void GERBER_PLOTTER::plotArc( const SHAPE_ARC& aArc, bool aPlotInRegion ) void GERBER_PLOTTER::plotArc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle, - const EDA_ANGLE& aEndAngle, int aRadius, bool aPlotInRegion ) + const EDA_ANGLE& aEndAngle, double aRadius, bool aPlotInRegion ) { VECTOR2I start, end; - start.x = aCenter.x + KiROUND( aRadius * aStartAngle.Cos() ); - start.y = aCenter.y + KiROUND( aRadius * aStartAngle.Sin() ); + start.x = KiROUND( aCenter.x + aRadius * aStartAngle.Cos() ); + start.y = KiROUND( aCenter.y + aRadius * aStartAngle.Sin() ); if( !aPlotInRegion ) MoveTo( start ); else LineTo( start ); - end.x = aCenter.x + KiROUND( aRadius * aEndAngle.Cos() ); - end.y = aCenter.y + KiROUND( aRadius * aEndAngle.Sin() ); + end.x = KiROUND( aCenter.x + aRadius * aEndAngle.Cos() ); + end.y = KiROUND( aCenter.y + aRadius * aEndAngle.Sin() ); VECTOR2D devEnd = userToDeviceCoordinates( end ); // devRelCenter is the position on arc center relative to the arc start, in Gerber coord. VECTOR2D devRelCenter = userToDeviceCoordinates( aCenter ) - userToDeviceCoordinates( start ); diff --git a/common/plotters/HPGL_plotter.cpp b/common/plotters/HPGL_plotter.cpp index 3975107390..5d9e07cd70 100644 --- a/common/plotters/HPGL_plotter.cpp +++ b/common/plotters/HPGL_plotter.cpp @@ -581,11 +581,11 @@ void HPGL_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle, EDA_ANGLE startAngle = -aStartAngle; // Calculate arc start point: - VECTOR2I cmap( aCenter.x + KiROUND( aRadius * startAngle.Cos() ), - aCenter.y - KiROUND( aRadius * startAngle.Sin() ) ); + VECTOR2I cmap( KiROUND( aCenter.x + aRadius * startAngle.Cos() ), + KiROUND( aCenter.y - aRadius * startAngle.Sin() ) ); VECTOR2D cmap_dev = userToDeviceCoordinates( cmap ); - startOrAppendItem( cmap_dev, wxString::Format( "AA %.0f,%.0f,%.0f,%g", + startOrAppendItem( cmap_dev, wxString::Format( "AA %.0f,%.0f,%g,%g", centre_device.x, centre_device.y, angle.AsDegrees(), diff --git a/common/plotters/PDF_plotter.cpp b/common/plotters/PDF_plotter.cpp index 06d4e563bd..d95be91778 100644 --- a/common/plotters/PDF_plotter.cpp +++ b/common/plotters/PDF_plotter.cpp @@ -354,21 +354,21 @@ void PDF_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle, SetCurrentLineWidth( aWidth ); // Usual trig arc plotting routine... - start.x = aCenter.x + KiROUND( aRadius * (-startAngle).Cos() ); - start.y = aCenter.y + KiROUND( aRadius * (-startAngle).Sin() ); + start.x = KiROUND( aCenter.x + aRadius * ( -startAngle ).Cos() ); + start.y = KiROUND( aCenter.y + aRadius * ( -startAngle ).Sin() ); VECTOR2D pos_dev = userToDeviceCoordinates( start ); fprintf( m_workFile, "%g %g m ", pos_dev.x, pos_dev.y ); for( EDA_ANGLE ii = startAngle + delta; ii < endAngle; ii += delta ) { - end.x = aCenter.x + KiROUND( aRadius * (-ii).Cos() ); - end.y = aCenter.y + KiROUND( aRadius * (-ii).Sin() ); + end.x = KiROUND( aCenter.x + aRadius * ( -ii ).Cos() ); + end.y = KiROUND( aCenter.y + aRadius * ( -ii ).Sin() ); pos_dev = userToDeviceCoordinates( end ); fprintf( m_workFile, "%g %g l ", pos_dev.x, pos_dev.y ); } - end.x = aCenter.x + KiROUND( aRadius * (-endAngle).Cos() ); - end.y = aCenter.y + KiROUND( aRadius * (-endAngle).Sin() ); + end.x = KiROUND( aCenter.x + aRadius * ( -endAngle ).Cos() ); + end.y = KiROUND( aCenter.y + aRadius * ( -endAngle ).Sin() ); pos_dev = userToDeviceCoordinates( end ); fprintf( m_workFile, "%g %g l ", pos_dev.x, pos_dev.y ); diff --git a/include/plotters/plotter_gerber.h b/include/plotters/plotter_gerber.h index 0c8d249952..29827eebc4 100644 --- a/include/plotters/plotter_gerber.h +++ b/include/plotters/plotter_gerber.h @@ -292,7 +292,7 @@ protected: * be initialized before calling it if needed. */ void plotArc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle, const EDA_ANGLE& aEndAngle, - int aRadius, bool aPlotInRegion ); + double aRadius, bool aPlotInRegion ); void plotArc( const SHAPE_ARC& aArc, bool aPlotInRegion ); /** diff --git a/libs/kimath/include/trigo.h b/libs/kimath/include/trigo.h index 0949acc6e1..7c06ec216a 100644 --- a/libs/kimath/include/trigo.h +++ b/libs/kimath/include/trigo.h @@ -193,8 +193,7 @@ bool TestSegmentHit( const VECTOR2I& aRefPoint, const VECTOR2I& aStart, const VE */ inline double GetLineLength( const VECTOR2I& aPointA, const VECTOR2I& aPointB ) { - // Implicitly casted to double - return hypot( aPointA.x - aPointB.x, aPointA.y - aPointB.y ); + return hypot( (double) aPointA.x - aPointB.x, (double) aPointA.y - aPointB.y ); } // These are the usual degrees <-> radians conversion routines diff --git a/pcbnew/pcb_track.cpp b/pcbnew/pcb_track.cpp index 5637bf0c2a..e9b74e34f0 100644 --- a/pcbnew/pcb_track.cpp +++ b/pcbnew/pcb_track.cpp @@ -1348,7 +1348,10 @@ EDA_ANGLE PCB_ARC::GetAngle() const EDA_ANGLE PCB_ARC::GetArcAngleStart() const { - EDA_ANGLE angleStart( m_Start - GetPosition() ); + VECTOR2I pos( GetPosition() ); + VECTOR2D dir( (double) m_Start.x - pos.x, (double) m_Start.y - pos.y ); + + EDA_ANGLE angleStart( dir ); return angleStart.Normalize(); } @@ -1356,7 +1359,10 @@ EDA_ANGLE PCB_ARC::GetArcAngleStart() const // Note: used in python tests. Ignore CLion's claim that it's unused.... EDA_ANGLE PCB_ARC::GetArcAngleEnd() const { - EDA_ANGLE angleEnd( m_End - GetPosition() ); + VECTOR2I pos( GetPosition() ); + VECTOR2D dir( (double) m_End.x - pos.x, (double) m_End.y - pos.y ); + + EDA_ANGLE angleEnd( dir ); return angleEnd.Normalize(); }