From ac435ecd68afb648a0d5d11f431b91106cf0b36a Mon Sep 17 00:00:00 2001 From: Seth Hillbrand Date: Wed, 22 May 2019 06:33:48 -0700 Subject: [PATCH] Moving further arc approximations down This corrects an issue with fill segments-per-circle and moves the error to segmetns calculation down in a number of functions to expose the single value for approximation --- .../3d_canvas/create_3Dgraphic_brd_items.cpp | 2 +- 3d-viewer/3d_canvas/create_layer_items.cpp | 30 ++-- 3d-viewer/3d_canvas/create_layer_poly.cpp | 16 +- common/convert_basic_shapes_to_polygon.cpp | 167 +++++++----------- common/plotters/DXF_plotter.cpp | 7 +- common/plotters/GERBER_plotter.cpp | 3 +- common/plotters/HPGL_plotter.cpp | 4 +- common/plotters/PS_plotter.cpp | 4 +- gerbview/am_primitive.cpp | 12 +- gerbview/dcode.cpp | 6 +- include/convert_basic_shapes_to_polygon.h | 29 ++- include/plotter.h | 3 + ...board_items_to_polygon_shape_transform.cpp | 69 +++----- pcbnew/class_module.h | 2 +- pcbnew/class_pad.cpp | 4 +- .../convert_drawsegment_list_to_polygon.cpp | 3 +- pcbnew/drc_clearance_test_functions.cpp | 6 +- pcbnew/exporters/export_vrml.cpp | 3 +- pcbnew/pad_custom_shape_functions.cpp | 25 +-- pcbnew/pad_draw_functions.cpp | 4 +- pcbnew/pcb_painter.cpp | 3 +- pcbnew/plot_brditems_plotter.cpp | 3 +- .../specctra_export.cpp | 2 +- 23 files changed, 150 insertions(+), 257 deletions(-) diff --git a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp index e4c719c169..03571ef94c 100644 --- a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp +++ b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp @@ -502,7 +502,7 @@ void CINFO3D_VISU::createNewPadWithClearance( const D_PAD* aPad, int corner_radius = aPad->GetRoundRectCornerRadius( shapesize ); TransformRoundChamferedRectToPolygon( polyList, PadShapePos, shapesize, aPad->GetOrientation(), corner_radius, aPad->GetChamferRectRatio(), - aPad->GetChamferPositions(), 32 ); + aPad->GetChamferPositions(), ARC_HIGH_DEF ); // Add the PAD polygon Convert_shape_line_polygon_to_triangles( polyList, *aDstContainer, m_biuTo3Dunits, *aPad ); diff --git a/3d-viewer/3d_canvas/create_layer_items.cpp b/3d-viewer/3d_canvas/create_layer_items.cpp index 2e75007696..ac29b8273d 100644 --- a/3d-viewer/3d_canvas/create_layer_items.cpp +++ b/3d-viewer/3d_canvas/create_layer_items.cpp @@ -414,15 +414,11 @@ void CINFO3D_VISU::createLayers( REPORTER *aStatusTextReporter ) const int holediameter = via->GetDrillValue(); const int hole_outer_radius = (holediameter / 2) + GetCopperThicknessBIU(); - TransformCircleToPolygon( *layerOuterHolesPoly, - via->GetStart(), - hole_outer_radius, - GetNrSegmentsCircle( hole_outer_radius * 2 ) ); + TransformCircleToPolygon( *layerOuterHolesPoly, via->GetStart(), + hole_outer_radius, ARC_HIGH_DEF ); - TransformCircleToPolygon( *layerInnerHolesPoly, - via->GetStart(), - holediameter / 2, - GetNrSegmentsCircle( holediameter ) ); + TransformCircleToPolygon( *layerInnerHolesPoly, via->GetStart(), + holediameter / 2, ARC_HIGH_DEF ); } else if( lIdx == 0 ) // it only adds once the THT holes { @@ -431,22 +427,16 @@ void CINFO3D_VISU::createLayers( REPORTER *aStatusTextReporter ) // Add through hole contourns // ///////////////////////////////////////////////////////// - TransformCircleToPolygon( m_through_outer_holes_poly, - via->GetStart(), - hole_outer_radius, - GetNrSegmentsCircle( hole_outer_radius * 2 ) ); + TransformCircleToPolygon( m_through_outer_holes_poly, via->GetStart(), + hole_outer_radius, ARC_HIGH_DEF ); - TransformCircleToPolygon( m_through_inner_holes_poly, - via->GetStart(), - holediameter / 2, - GetNrSegmentsCircle( holediameter ) ); + TransformCircleToPolygon( m_through_inner_holes_poly, via->GetStart(), + holediameter / 2, ARC_HIGH_DEF ); // Add samething for vias only - TransformCircleToPolygon( m_through_outer_holes_vias_poly, - via->GetStart(), - hole_outer_radius, - GetNrSegmentsCircle( hole_outer_radius * 2 ) ); + TransformCircleToPolygon( m_through_outer_holes_vias_poly, via->GetStart(), + hole_outer_radius, ARC_HIGH_DEF ); //TransformCircleToPolygon( m_through_inner_holes_vias_poly, // via->GetStart(), diff --git a/3d-viewer/3d_canvas/create_layer_poly.cpp b/3d-viewer/3d_canvas/create_layer_poly.cpp index f9d3e9124e..b66f6090f8 100644 --- a/3d-viewer/3d_canvas/create_layer_poly.cpp +++ b/3d-viewer/3d_canvas/create_layer_poly.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2015-2016 Mario Luzeiro - * Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2019 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 @@ -111,11 +111,8 @@ void CINFO3D_VISU::buildPadShapeThickOutlineAsPolygon( const D_PAD* aPad, { if( aPad->GetShape() == PAD_SHAPE_CIRCLE ) // Draw a ring { - unsigned int nr_sides_per_circle = GetNrSegmentsCircle( ( aPad->GetSize().x / 2 + - aWidth / 2 ) * 2 ); - TransformRingToPolygon( aCornerBuffer, aPad->ShapePos(), - aPad->GetSize().x / 2, nr_sides_per_circle, aWidth ); + aPad->GetSize().x / 2, ARC_HIGH_DEF, aWidth ); return; } @@ -123,8 +120,6 @@ void CINFO3D_VISU::buildPadShapeThickOutlineAsPolygon( const D_PAD* aPad, // For other shapes, draw polygon outlines SHAPE_POLY_SET corners; - auto nr_sides_per_circle = - GetNrSegmentsCircle( std::min( aPad->GetSize().x, aPad->GetSize().y ) ); buildPadShapePolygon( aPad, corners, wxSize( 0, 0 ) ); // Add outlines as thick segments in polygon buffer @@ -136,11 +131,8 @@ void CINFO3D_VISU::buildPadShapeThickOutlineAsPolygon( const D_PAD* aPad, const VECTOR2I& a = path.CPoint( ii ); const VECTOR2I& b = path.CPoint( ii + 1 ); - TransformRoundedEndsSegmentToPolygon( aCornerBuffer, - wxPoint( a.x, a.y ), - wxPoint( b.x, b.y ), - nr_sides_per_circle, - aWidth ); + TransformRoundedEndsSegmentToPolygon( aCornerBuffer, wxPoint( a.x, a.y ), + wxPoint( b.x, b.y ), ARC_HIGH_DEF, aWidth ); } } diff --git a/common/convert_basic_shapes_to_polygon.cpp b/common/convert_basic_shapes_to_polygon.cpp index 8976c79259..6ff1f3ff54 100644 --- a/common/convert_basic_shapes_to_polygon.cpp +++ b/common/convert_basic_shapes_to_polygon.cpp @@ -5,7 +5,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr - * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2019 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 @@ -31,28 +31,23 @@ #include #include #include +#include + -/** - * Function TransformCircleToPolygon - * convert a circle to a polygon, using multiple straight lines - * @param aBuffer = a SHAPE_LINE_CHAIN to store the polygon corners - * @param aCenter = the center of the circle - * @param aRadius = the radius of the circle - * @param aCircleToSegmentsCount = the number of segments to approximate a circle - * Note: the polygon is inside the circle, so if you want to have the polygon - * outside the circle, you should give aRadius calculated with a correction factor - */ void TransformCircleToPolygon( SHAPE_LINE_CHAIN& aBuffer, wxPoint aCenter, int aRadius, - int aCircleToSegmentsCount ) + int aError ) { wxPoint corner_position; - double delta = 3600.0 / aCircleToSegmentsCount; // rot angle in 0.1 degree - double halfstep = delta/2; // the starting value for rot angles + int numSegs = std::max( GetArcToSegmentCount( aRadius, aError, 360.0 ), 6 ); + int delta = 3600 / numSegs; // rotate angle in 0.1 degree + double correction = GetCircletoPolyCorrectionFactor( numSegs ); + int radius = aRadius * correction; // make segments outside the circles + double halfstep = delta/2; // the starting value for rot angles - for( int ii = 0; ii < aCircleToSegmentsCount; ii++ ) + for( int ii = 0; ii < numSegs; ii++ ) { - corner_position.x = aRadius; + corner_position.x = radius; corner_position.y = 0; double angle = (ii * delta) + halfstep; RotatePoint( &corner_position, angle ); @@ -64,29 +59,22 @@ void TransformCircleToPolygon( SHAPE_LINE_CHAIN& aBuffer, } -/** - * Function TransformCircleToPolygon - * convert a circle to a polygon, using multiple straight lines - * @param aCornerBuffer = a SHAPE_POLY_SET to store the polygon - * @param aCenter = the center of the circle - * @param aRadius = the radius of the circle - * @param aCircleToSegmentsCount = the number of segments to approximate a circle - * Note: the polygon is inside the circle, so if you want to have the polygon - * outside the circle, you should give aRadius calculated with a correction factor - */ void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCenter, int aRadius, - int aCircleToSegmentsCount ) + int aError ) { wxPoint corner_position; - double delta = 3600.0 / aCircleToSegmentsCount; // rot angle in 0.1 degree - double halfstep = delta/2; // the starting value for rot angles + int numSegs = std::max( GetArcToSegmentCount( aRadius, aError, 360.0 ), 6 ); + int delta = 3600 / numSegs; // rotate angle in 0.1 degree + double correction = GetCircletoPolyCorrectionFactor( numSegs ); + int radius = aRadius * correction; // make segments outside the circles + double halfstep = delta/2; // the starting value for rot angles aCornerBuffer.NewOutline(); - for( int ii = 0; ii < aCircleToSegmentsCount; ii++ ) + for( int ii = 0; ii < numSegs; ii++ ) { - corner_position.x = aRadius; + corner_position.x = radius; corner_position.y = 0; double angle = (ii * delta) + halfstep; RotatePoint( &corner_position, angle ); @@ -95,9 +83,10 @@ void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, } } + void TransformOvalClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, - wxPoint aStart, wxPoint aEnd, int aWidth, - int aCircleToSegmentsCount, double aCorrectionFactor ) + wxPoint aStart, wxPoint aEnd, int aWidth, + int aError ) { // To build the polygonal shape outside the actual shape, we use a bigger // radius to build rounded ends. @@ -105,13 +94,11 @@ void TransformOvalClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, // so, later, we will clamp the polygonal shape with the bounding box // of the segment. int radius = aWidth / 2; + int numSegs = std::max( GetArcToSegmentCount( radius, aError, 360.0 ), 6 ); + int delta = 3600 / numSegs; // rotate angle in 0.1 degree + double correction = GetCircletoPolyCorrectionFactor( numSegs ); - // Note if we want to compensate the radius reduction of a circle due to - // the segment approx, aCorrectionFactor must be calculated like this: - // For a circle the min radius is radius * cos( 2PI / s_CircleToSegmentsCount / 2) - // aCorrectionFactor is 1 /cos( PI/s_CircleToSegmentsCount ) - - radius = radius * aCorrectionFactor; // make segments outside the circles + radius = radius * correction; // make segments outside the circles // end point is the coordinate relative to aStart wxPoint endp = aEnd - aStart; @@ -133,17 +120,16 @@ void TransformOvalClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, double delta_angle = atan2( (double)endp.y, (double)endp.x ); int seg_len = KiROUND( EuclideanNorm( endp ) ); - double delta = 3600.0 / aCircleToSegmentsCount; // rot angle in 0.1 degree // Compute the outlines of the segment, and creates a polygon // Note: the polygonal shape is built from the equivalent horizontal // segment starting ar 0,0, and ending at seg_len,0 // add right rounded end: - for( int ii = 0; ii < aCircleToSegmentsCount/2; ii++ ) + for( int ii = 0; ii < numSegs / 2; ii++ ) { corner = wxPoint( 0, radius ); - RotatePoint( &corner, delta*ii ); + RotatePoint( &corner, delta * ii ); corner.x += seg_len; polyshape.Append( corner.x, corner.y ); } @@ -153,10 +139,10 @@ void TransformOvalClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, polyshape.Append( corner.x, corner.y ); // add left rounded end: - for( int ii = 0; ii < aCircleToSegmentsCount/2; ii++ ) + for( int ii = 0; ii < numSegs / 2; ii++ ) { corner = wxPoint( 0, -radius ); - RotatePoint( &corner, delta*ii ); + RotatePoint( &corner, delta * ii ); polyshape.Append( corner.x, corner.y ); } @@ -167,7 +153,7 @@ void TransformOvalClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, // Now, clamp the polygonal shape (too big) with the segment bounding box // the polygonal shape bbox equivalent to the segment has a too big height, // and the right width - if( aCorrectionFactor > 1.0 ) + if( correction > 1.0 ) { SHAPE_POLY_SET bbox; bbox.NewOutline(); @@ -197,8 +183,7 @@ void TransformOvalClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, aCornerBuffer.Append( polyshape); } -/* Returns the centers of the rounded corners of a rect. - */ + void GetRoundRectCornerCenters( wxPoint aCenters[4], int aRadius, const wxPoint& aPosition, const wxSize& aSize, double aRotation ) { @@ -243,7 +228,7 @@ void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer, const wxPoint& aPosition, const wxSize& aSize, double aRotation, int aCornerRadius, double aChamferRatio, int aChamferCorners, - int aCircleToSegmentsCount ) + int aError ) { // Build the basic shape in orientation 0.0, position 0,0 for chamfered corners // or in actual position/orientation for round rect only @@ -258,7 +243,8 @@ void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer, for( int ii = 0; ii < 4; ++ii ) outline.Append( corners[ii].x, corners[ii].y ); - outline.Inflate( aCornerRadius, aCircleToSegmentsCount ); + int numSegs = std::max( GetArcToSegmentCount( aCornerRadius, aError, 360.0 ), 6 ); + outline.Inflate( aCornerRadius, numSegs ); if( aChamferCorners == RECT_NO_CHAMFER ) // no chamfer { @@ -299,9 +285,9 @@ void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer, chamfered_corner.RemoveAllContours(); chamfered_corner.NewOutline(); chamfered_corner.Append( 0, 0 ); - chamfered_corner.Append( 0, signY[ii]*aSize.y/2 ); - chamfered_corner.Append( signX[ii]*aSize.x/2, signY[ii]*aSize.y/2 ); - chamfered_corner.Append( signX[ii]*aSize.x/2, 0 ); + chamfered_corner.Append( 0, signY[ii] * aSize.y / 2 ); + chamfered_corner.Append( signX[ii] * aSize.x / 2, signY[ii] * aSize.y / 2 ); + chamfered_corner.Append( signX[ii] * aSize.x / 2, 0 ); chamfered_corner.Move( corner_pos ); outline.BooleanAdd( chamfered_corner, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE ); } @@ -310,8 +296,8 @@ void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer, chamfered_corner.RemoveAllContours(); chamfered_corner.NewOutline(); chamfered_corner.Append( 0, 0 ); - chamfered_corner.Append( 0, signY[ii]*chamfer_value ); - chamfered_corner.Append( signX[ii]*chamfer_value, 0 ); + chamfered_corner.Append( 0, signY[ii] * chamfer_value ); + chamfered_corner.Append( signX[ii] * chamfer_value, 0 ); chamfered_corner.Move( corner_pos ); outline.BooleanSubtract( chamfered_corner, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE ); } @@ -327,29 +313,20 @@ void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer, } -/** - * Function TransformRoundedEndsSegmentToPolygon - * convert a segment with rounded ends to a polygon - * Convert arcs to multiple straight lines - * @param aCornerBuffer = a buffer to store the polygon - * @param aStart = the segment start point coordinate - * @param aEnd = the segment end point coordinate - * @param aCircleToSegmentsCount = the number of segments to approximate a circle - * @param aWidth = the segment width - * Note: the polygon is inside the arc ends, so if you want to have the polygon - * outside the circle, you should give aStart and aEnd calculated with a correction factor - */ void TransformRoundedEndsSegmentToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aStart, wxPoint aEnd, - int aCircleToSegmentsCount, - int aWidth ) + int aError, int aWidth ) { - int radius = aWidth / 2; - wxPoint endp = aEnd - aStart; // end point coordinate for the same segment starting at (0,0) - wxPoint startp = aStart; - wxPoint corner; + int radius = aWidth / 2; + wxPoint endp = aEnd - aStart; // end point coordinate for the same segment starting at (0,0) + wxPoint startp = aStart; + wxPoint corner; VECTOR2I polypoint; + int numSegs = std::max( GetArcToSegmentCount( radius, aError, 360.0 ), 6 ); + double correction = GetCircletoPolyCorrectionFactor( numSegs ); + int delta = 3600 / numSegs; // rotate angle in 0.1 degree + radius = KiROUND( radius * correction ); aCornerBuffer.NewOutline(); // normalize the position in order to have endp.x >= 0; @@ -362,8 +339,6 @@ void TransformRoundedEndsSegmentToPolygon( SHAPE_POLY_SET& aCornerBuffer, double delta_angle = ArcTangente( endp.y, endp.x ); // delta_angle is in 0.1 degrees int seg_len = KiROUND( EuclideanNorm( endp ) ); - int delta = 3600 / aCircleToSegmentsCount; // rot angle in 0.1 degree - // Compute the outlines of the segment, and creates a polygon // add right rounded end: for( int ii = 0; ii < 1800; ii += delta ) @@ -408,23 +383,14 @@ void TransformRoundedEndsSegmentToPolygon( SHAPE_POLY_SET& aCornerBuffer, } -/** - * Function TransformArcToPolygon - * Creates a polygon from an Arc - * Convert arcs to multiple straight segments - * @param aCornerBuffer = a buffer to store the polygon - * @param aCentre = centre of the arc or circle - * @param aStart = start point of the arc, or a point on the circle - * @param aArcAngle = arc angle in 0.1 degrees. For a circle, aArcAngle = 3600 - * @param aCircleToSegmentsCount = the number of segments to approximate a circle - * @param aWidth = width (thickness) of the line - */ void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCentre, wxPoint aStart, double aArcAngle, - int aCircleToSegmentsCount, int aWidth ) + int aError, int aWidth ) { wxPoint arc_start, arc_end; - int delta = 3600 / aCircleToSegmentsCount; // rotate angle in 0.1 degree + int dist = EuclideanNorm( aCentre - aStart ); + int numSegs = std::max( GetArcToSegmentCount( dist, aError, 360.0 ), 6 ); + int delta = 3600 / numSegs; // rotate angle in 0.1 degree arc_end = arc_start = aStart; @@ -447,31 +413,19 @@ void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, { curr_end = arc_start; RotatePoint( &curr_end, aCentre, -ii ); - TransformRoundedEndsSegmentToPolygon( aCornerBuffer, curr_start, curr_end, - aCircleToSegmentsCount, aWidth ); + TransformRoundedEndsSegmentToPolygon( aCornerBuffer, curr_start, curr_end, aError, + aWidth ); curr_start = curr_end; } if( curr_end != arc_end ) - TransformRoundedEndsSegmentToPolygon( aCornerBuffer, - curr_end, arc_end, - aCircleToSegmentsCount, aWidth ); + TransformRoundedEndsSegmentToPolygon( aCornerBuffer, curr_end, arc_end, aError, aWidth ); } -/** - * Function TransformRingToPolygon - * Creates a polygon from a ring - * Convert arcs to multiple straight segments - * @param aCornerBuffer = a buffer to store the polygon - * @param aCentre = centre of the arc or circle - * @param aRadius = radius of the circle - * @param aCircleToSegmentsCount = the number of segments to approximate a circle - * @param aWidth = width (thickness) of the ring - */ void TransformRingToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCentre, int aRadius, - int aCircleToSegmentsCount, int aWidth ) + int aError, int aWidth ) { // Compute the corners positions and creates the poly wxPoint curr_point; @@ -480,18 +434,17 @@ void TransformRingToPolygon( SHAPE_POLY_SET& aCornerBuffer, if( inner_radius <= 0 ) { //In this case, the ring is just a circle (no hole inside) - TransformCircleToPolygon( aCornerBuffer, aCentre, aRadius + ( aWidth / 2 ), - aCircleToSegmentsCount ); + TransformCircleToPolygon( aCornerBuffer, aCentre, aRadius + ( aWidth / 2 ), aError ); return; } SHAPE_POLY_SET buffer; - TransformCircleToPolygon( buffer, aCentre, outer_radius, aCircleToSegmentsCount ); + TransformCircleToPolygon( buffer, aCentre, outer_radius, aError ); // Build the hole: buffer.NewHole(); - TransformCircleToPolygon( buffer.Hole( 0, 0 ), aCentre, inner_radius, aCircleToSegmentsCount ); + TransformCircleToPolygon( buffer.Hole( 0, 0 ), aCentre, inner_radius, aError ); buffer.Fracture( SHAPE_POLY_SET::PM_FAST ); aCornerBuffer.Append( buffer ); diff --git a/common/plotters/DXF_plotter.cpp b/common/plotters/DXF_plotter.cpp index 22c7028b18..08c3d978c9 100644 --- a/common/plotters/DXF_plotter.cpp +++ b/common/plotters/DXF_plotter.cpp @@ -496,7 +496,6 @@ void DXF_PLOTTER::PlotPoly( const std::vector& aCornerList, // polygon and its thick outline SHAPE_POLY_SET bufferOutline; SHAPE_POLY_SET bufferPolybase; - const int circleToSegmentsCount = 16; bufferPolybase.NewOutline(); @@ -504,7 +503,7 @@ void DXF_PLOTTER::PlotPoly( const std::vector& aCornerList, for( unsigned ii = 1; ii < aCornerList.size(); ii++ ) { TransformRoundedEndsSegmentToPolygon( bufferOutline, - aCornerList[ii-1], aCornerList[ii], circleToSegmentsCount, aWidth ); + aCornerList[ii-1], aCornerList[ii], GetPlotterArcHighDef(), aWidth ); } // enter the initial polygon: @@ -591,7 +590,7 @@ void DXF_PLOTTER::ThickSegment( const wxPoint& aStart, const wxPoint& aEnd, int std::vector cornerList; SHAPE_POLY_SET outlineBuffer; TransformOvalClearanceToPolygon( outlineBuffer, - aStart, aEnd, aWidth, 32 , 1.0 ); + aStart, aEnd, aWidth, GetPlotterArcHighDef() ); const SHAPE_LINE_CHAIN& path = outlineBuffer.COutline(0 ); for( int jj = 0; jj < path.PointCount(); jj++ ) @@ -748,7 +747,7 @@ void DXF_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize SHAPE_POLY_SET outline; const int segmentToCircleCount = 64; TransformRoundChamferedRectToPolygon( outline, aPadPos, aSize, aOrient, - aCornerRadius, 0.0, 0, segmentToCircleCount ); + aCornerRadius, 0.0, 0, GetPlotterArcHighDef() ); // TransformRoundRectToPolygon creates only one convex polygon SHAPE_LINE_CHAIN& poly = outline.Outline( 0 ); diff --git a/common/plotters/GERBER_plotter.cpp b/common/plotters/GERBER_plotter.cpp index 08f0402dc8..61eb8adc5e 100644 --- a/common/plotters/GERBER_plotter.cpp +++ b/common/plotters/GERBER_plotter.cpp @@ -841,9 +841,8 @@ void GERBER_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aS // Currently, a Pad RoundRect is plotted as polygon. // TODO: use Aperture macro and flash it SHAPE_POLY_SET outline; - const int segmentToCircleCount = 64; TransformRoundChamferedRectToPolygon( outline, aPadPos, aSize, aOrient, - aCornerRadius, 0.0, 0, segmentToCircleCount ); + aCornerRadius, 0.0, 0, GetPlotterArcHighDef() ); if( aTraceMode != FILLED ) outline.Inflate( -GetCurrentLineWidth()/2, 16 ); diff --git a/common/plotters/HPGL_plotter.cpp b/common/plotters/HPGL_plotter.cpp index 0e2d194fe3..a8044a5377 100644 --- a/common/plotters/HPGL_plotter.cpp +++ b/common/plotters/HPGL_plotter.cpp @@ -625,7 +625,6 @@ void HPGL_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSiz EDA_DRAW_MODE_T aTraceMode, void* aData ) { SHAPE_POLY_SET outline; - const int segmentToCircleCount = 32; wxSize size = aSize; @@ -643,11 +642,10 @@ void HPGL_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSiz } TransformRoundChamferedRectToPolygon( outline, aPadPos, size, aOrient, - aCornerRadius, 0.0, 0, segmentToCircleCount ); + aCornerRadius, 0.0, 0, GetPlotterArcHighDef() ); // TransformRoundRectToPolygon creates only one convex polygon std::vector< wxPoint > cornerList; - cornerList.reserve( segmentToCircleCount + 5 ); SHAPE_LINE_CHAIN& poly = outline.Outline( 0 ); for( int ii = 0; ii < poly.PointCount(); ++ii ) diff --git a/common/plotters/PS_plotter.cpp b/common/plotters/PS_plotter.cpp index 5c9301125f..ac13d2826c 100644 --- a/common/plotters/PS_plotter.cpp +++ b/common/plotters/PS_plotter.cpp @@ -200,12 +200,10 @@ void PSLIKE_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aS SHAPE_POLY_SET outline; - const int segmentToCircleCount = 64; TransformRoundChamferedRectToPolygon( outline, aPadPos, size, aOrient, - aCornerRadius, 0.0, 0, segmentToCircleCount ); + aCornerRadius, 0.0, 0, GetPlotterArcHighDef() ); std::vector< wxPoint > cornerList; - cornerList.reserve( segmentToCircleCount + 5 ); // TransformRoundRectToPolygon creates only one convex polygon SHAPE_LINE_CHAIN& poly = outline.Outline( 0 ); diff --git a/gerbview/am_primitive.cpp b/gerbview/am_primitive.cpp index 29e3b56091..a31667480b 100644 --- a/gerbview/am_primitive.cpp +++ b/gerbview/am_primitive.cpp @@ -7,7 +7,7 @@ * * Copyright (C) 1992-2017 Jean-Pierre Charras * Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck - * Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2019 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 @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -92,6 +93,7 @@ bool AM_PRIMITIVE::IsAMPrimitiveExposureOn( const GERBER_DRAW_ITEM* aParent ) co } } +// TODO(snh): Remove hard coded count const int seg_per_circle = 64; // Number of segments to approximate a circle void AM_PRIMITIVE::DrawBasicShape( const GERBER_DRAW_ITEM* aParent, @@ -313,13 +315,11 @@ void AM_PRIMITIVE::DrawBasicShape( const GERBER_DRAW_ITEM* aParent, if( outerDiam <= penThickness ) { // No room to draw a ring (no room for the hole): // draw a circle instead (with no hole), with the right diameter - TransformCircleToPolygon( aShapeBuffer, center, - outerDiam / 2, seg_per_circle ); + TransformCircleToPolygon( aShapeBuffer, center, outerDiam / 2, ARC_HIGH_DEF ); } else - TransformRingToPolygon( aShapeBuffer, center, - (outerDiam - penThickness) / 2, - seg_per_circle, penThickness ); + TransformRingToPolygon( aShapeBuffer, center, ( outerDiam - penThickness ) / 2, + ARC_HIGH_DEF, penThickness ); } // Draw the cross: diff --git a/gerbview/dcode.cpp b/gerbview/dcode.cpp index dc2d589f94..5539058410 100644 --- a/gerbview/dcode.cpp +++ b/gerbview/dcode.cpp @@ -289,7 +289,7 @@ void D_CODE::DrawFlashedPolygon( GERBER_DRAW_ITEM* aParent, GRClosedPoly( aClipBox, aDC, pointCount, &points[0], aFilled, aColor, aColor ); } - +// TODO(snh): Remove the hard-coded count #define SEGS_CNT 64 // number of segments to approximate a circle @@ -310,7 +310,7 @@ void D_CODE::ConvertShapeToPolygon() switch( m_Shape ) { case APT_CIRCLE: // creates only a circle with rectangular hole - TransformCircleToPolygon( m_Polygon, initialpos, m_Size.x >> 1, SEGS_CNT ); + TransformCircleToPolygon( m_Polygon, initialpos, m_Size.x >> 1, ARC_HIGH_DEF ); addHoleToPolygon( &m_Polygon, m_DrillShape, m_Drill, initialpos ); break; @@ -435,7 +435,7 @@ static void addHoleToPolygon( SHAPE_POLY_SET* aPolygon, if( aHoleShape == APT_DEF_ROUND_HOLE ) { - TransformCircleToPolygon( holeBuffer, wxPoint( 0, 0 ), aSize.x / 2, SEGS_CNT ); + TransformCircleToPolygon( holeBuffer, wxPoint( 0, 0 ), aSize.x / 2, ARC_HIGH_DEF ); } else if( aHoleShape == APT_DEF_RECT_HOLE ) { diff --git a/include/convert_basic_shapes_to_polygon.h b/include/convert_basic_shapes_to_polygon.h index 806cec8394..14eddf3b24 100644 --- a/include/convert_basic_shapes_to_polygon.h +++ b/include/convert_basic_shapes_to_polygon.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2012 Jean-Pierre Charras, jp.charras at wanadoo.fr - * Copyright (C) 1992-2012 KiCad Developers, see change_log.txt for contributors. + * Copyright (C) 1992-2019 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 @@ -59,13 +59,13 @@ enum RECT_CHAMFER_POSITIONS : int * @param aCornerBuffer = a buffer to store the polygon * @param aCenter = the center of the circle * @param aRadius = the radius of the circle - * @param aCircleToSegmentsCount = the number of segments to approximate a circle + * @param aError = the IU allowed for error in approximation * Note: the polygon is inside the circle, so if you want to have the polygon * outside the circle, you should give aRadius calculated with a correction factor */ void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCenter, int aRadius, - int aCircleToSegmentsCount ); + int aError ); /** @@ -80,14 +80,11 @@ void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, * @param aStart = the first point of the segment * @param aEnd = the second point of the segment * @param aWidth = the width of the segment - * @param aCircleToSegmentsCount = the number of segments to approximate a circle - * @param aCorrectionFactor = the coefficient to have segments outside the circle - * if aCorrectionFactor = 1.0, the shape will be the same as - * TransformRoundedEndsSegmentToPolygon + * @param aError = the IU allowed for error in approximation */ void TransformOvalClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aStart, wxPoint aEnd, int aWidth, - int aCircleToSegmentsCount, double aCorrectionFactor ); + int aError ); /** @@ -120,13 +117,13 @@ void GetRoundRectCornerCenters( wxPoint aCenters[4], int aRadius, * 4 = BOTTOM_LEFT * 8 = BOTTOM_RIGHT * One can have more than one chamfered corner by ORing the corner identifers - * @param aCircleToSegmentsCount = the number of segments to approximate a circle + * @param aError = the IU allowed for error in approximation */ void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer, const wxPoint& aPosition, const wxSize& aSize, double aRotation, int aCornerRadius, double aChamferRatio, int aChamferCorners, - int aCircleToSegmentsCount ); + int aError ); /** * Function TransformRoundedEndsSegmentToPolygon @@ -135,14 +132,14 @@ void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer, * @param aCornerBuffer = a buffer to store the polygon * @param aStart = the segment start point coordinate * @param aEnd = the segment end point coordinate - * @param aCircleToSegmentsCount = the number of segments to approximate a circle + * @param aError = the IU allowed for error in approximation * @param aWidth = the segment width * Note: the polygon is inside the arc ends, so if you want to have the polygon * outside the circle, you should give aStart and aEnd calculated with a correction factor */ void TransformRoundedEndsSegmentToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aStart, wxPoint aEnd, - int aCircleToSegmentsCount, + int aError, int aWidth ); @@ -154,12 +151,12 @@ void TransformRoundedEndsSegmentToPolygon( SHAPE_POLY_SET& aCornerBuffer, * @param aCentre = centre of the arc or circle * @param aStart = start point of the arc, or a point on the circle * @param aArcAngle = arc angle in 0.1 degrees. For a circle, aArcAngle = 3600 - * @param aCircleToSegmentsCount = the number of segments to approximate a circle + * @param aError = the IU allowed for error in approximation * @param aWidth = width (thickness) of the line */ void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCentre, wxPoint aStart, double aArcAngle, - int aCircleToSegmentsCount, int aWidth ); + int aError, int aWidth ); /** * Function TransformRingToPolygon @@ -168,11 +165,11 @@ void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, * @param aCornerBuffer = a buffer to store the polygon * @param aCentre = centre of the arc or circle * @param aRadius = radius of the circle - * @param aCircleToSegmentsCount = the number of segments to approximate a circle + * @param aError = the IU allowed for error in approximation * @param aWidth = width (thickness) of the ring */ void TransformRingToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCentre, int aRadius, - int aCircleToSegmentsCount, int aWidth ); + int aError, int aWidth ); #endif // CONVERT_BASIC_SHAPES_TO_POLYGON_H diff --git a/include/plotter.h b/include/plotter.h index 0321a1f7da..d7b64d373c 100644 --- a/include/plotter.h +++ b/include/plotter.h @@ -216,6 +216,9 @@ public: */ double GetIUsPerDecimil() const { return m_IUsPerDecimil; } + int GetPlotterArcLowDef() const { return m_IUsPerDecimil * 8; } + int GetPlotterArcHighDef() const { return m_IUsPerDecimil * 2; } + // Low level primitives virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill, int width = USE_DEFAULT_LINE_WIDTH ) = 0; diff --git a/pcbnew/board_items_to_polygon_shape_transform.cpp b/pcbnew/board_items_to_polygon_shape_transform.cpp index 8eb7f04ebe..376ba80417 100644 --- a/pcbnew/board_items_to_polygon_shape_transform.cpp +++ b/pcbnew/board_items_to_polygon_shape_transform.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2009-2018 Jean-Pierre Charras, jp.charras at wanadoo.fr - * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2019 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 @@ -56,7 +56,7 @@ // so we cannot send them as arguments. struct TSEGM_2_POLY_PRMS { int m_textWidth; - int m_textCircle2SegmentCount; + int m_error; SHAPE_POLY_SET* m_cornerBuffer; }; TSEGM_2_POLY_PRMS prms; @@ -67,7 +67,7 @@ static void addTextSegmToPoly( int x0, int y0, int xf, int yf, void* aData ) TSEGM_2_POLY_PRMS* prm = static_cast( aData ); TransformRoundedEndsSegmentToPolygon( *prm->m_cornerBuffer, wxPoint( x0, y0), wxPoint( xf, yf ), - prm->m_textCircle2SegmentCount, prm->m_textWidth ); + prm->m_error, prm->m_textWidth ); } @@ -244,8 +244,7 @@ void MODULE::TransformGraphicShapesWithClearanceToPolygonSet( PCB_LAYER_ID aLaye { TEXTE_MODULE *textmod = texts[ii]; prms.m_textWidth = textmod->GetThickness() + ( 2 * aInflateValue ); - prms.m_textCircle2SegmentCount = - std::max( GetArcToSegmentCount( prms.m_textWidth / 2, aError, 360.0 ), 6 ); + prms.m_error = aError; wxSize size = textmod->GetTextSize(); if( textmod->IsMirrored() ) @@ -304,8 +303,7 @@ void MODULE::TransformGraphicTextWithClearanceToPolygonSet( { TEXTE_MODULE *textmod = texts[ii]; prms.m_textWidth = textmod->GetThickness() + ( 2 * aInflateValue ); - prms.m_textCircle2SegmentCount = - std::max( GetArcToSegmentCount( prms.m_textWidth / 2, aError, 360.0 ), 6 ); + prms.m_error = aError; wxSize size = textmod->GetTextSize(); if( textmod->IsMirrored() ) @@ -327,8 +325,6 @@ void ZONE_CONTAINER::TransformSolidAreasShapesToPolygonSet( if( GetFilledPolysList().IsEmpty() ) return; - int numSegs = std::max( GetArcToSegmentCount( GetMinThickness() / 2, aError, 360.0 ), 6 ); - // add filled areas polygons aCornerBuffer.Append( m_FilledPolysList ); @@ -343,7 +339,7 @@ void ZONE_CONTAINER::TransformSolidAreasShapesToPolygonSet( const VECTOR2I& b = path.CPoint( j + 1 ); TransformRoundedEndsSegmentToPolygon( aCornerBuffer, wxPoint( a.x, a.y ), - wxPoint( b.x, b.y ), numSegs, GetMinThickness() ); + wxPoint( b.x, b.y ), ARC_HIGH_DEF, GetMinThickness() ); } } } @@ -405,8 +401,7 @@ void TEXTE_PCB::TransformShapeWithClearanceToPolygonSet( prms.m_cornerBuffer = &aCornerBuffer; prms.m_textWidth = GetThickness() + ( 2 * aClearanceValue ); - prms.m_textCircle2SegmentCount = - std::max( GetArcToSegmentCount( prms.m_textWidth / 2, aError, 360.0 ), 6 ); + prms.m_error = aError; COLOR4D color = COLOR4D::BLACK; // not actually used, but needed by DrawGraphicText if( IsMultilineAllowed() ) @@ -446,9 +441,6 @@ void DRAWSEGMENT::TransformShapeWithClearanceToPolygon( linewidth += 2 * aClearanceValue; - int numSegs = std::max( GetArcToSegmentCount( linewidth / 2, aError, 360.0 ), 6 ); - double correction = GetCircletoPolyCorrectionFactor( numSegs ); - // Creating a reliable clearance shape for circles and arcs is not so easy, due to // the error created by segment approximation. // for a circle this is not so hard: create a polygon from a circle slightly bigger: @@ -460,17 +452,17 @@ void DRAWSEGMENT::TransformShapeWithClearanceToPolygon( { case S_CIRCLE: TransformRingToPolygon( - aCornerBuffer, GetCenter(), GetRadius(), numSegs, correction * linewidth ); + aCornerBuffer, GetCenter(), GetRadius(), aError, linewidth ); break; case S_ARC: TransformArcToPolygon( - aCornerBuffer, GetCenter(), GetArcStart(), m_Angle, numSegs, linewidth ); + aCornerBuffer, GetCenter(), GetArcStart(), m_Angle, aError, linewidth ); break; case S_SEGMENT: TransformOvalClearanceToPolygon( - aCornerBuffer, m_Start, m_End, linewidth, numSegs, correction ); + aCornerBuffer, m_Start, m_End, linewidth, aError ); break; case S_POLYGON: @@ -500,12 +492,12 @@ void DRAWSEGMENT::TransformShapeWithClearanceToPolygon( { for( size_t ii = 1; ii < poly.size(); ii++ ) { - TransformOvalClearanceToPolygon( - aCornerBuffer, poly[ii - 1], poly[ii], linewidth, numSegs, correction ); + TransformOvalClearanceToPolygon( aCornerBuffer, poly[ii - 1], poly[ii], + linewidth, aError ); } - TransformOvalClearanceToPolygon( - aCornerBuffer, poly.back(), poly.front(), linewidth, numSegs, correction ); + TransformOvalClearanceToPolygon( aCornerBuffer, poly.back(), poly.front(), + linewidth, aError ); break; } @@ -530,7 +522,7 @@ void DRAWSEGMENT::TransformShapeWithClearanceToPolygon( if( corner2 != corner1 ) { TransformRoundedEndsSegmentToPolygon( - aCornerBuffer, corner1, corner2, numSegs, linewidth ); + aCornerBuffer, corner1, corner2, aError, linewidth ); } corner1 = corner2; @@ -549,7 +541,7 @@ void DRAWSEGMENT::TransformShapeWithClearanceToPolygon( for( unsigned ii = 1; ii < poly.size(); ii++ ) { TransformRoundedEndsSegmentToPolygon( - aCornerBuffer, poly[ii - 1], poly[ii], numSegs, linewidth ); + aCornerBuffer, poly[ii - 1], poly[ii], aError, linewidth ); } } break; @@ -566,21 +558,18 @@ void TRACK::TransformShapeWithClearanceToPolygon( wxASSERT_MSG( !ignoreLineWidth, "IgnoreLineWidth has no meaning for tracks." ); int radius = ( m_Width / 2 ) + aClearanceValue; - int numSegs = std::max( GetArcToSegmentCount( radius, aError, 360.0 ), 6 ); - double correction = GetCircletoPolyCorrectionFactor( numSegs ); switch( Type() ) { case PCB_VIA_T: { - radius = KiROUND( radius * correction ); - TransformCircleToPolygon( aCornerBuffer, m_Start, radius, numSegs ); + TransformCircleToPolygon( aCornerBuffer, m_Start, radius, aError ); } break; default: TransformOvalClearanceToPolygon( aCornerBuffer, m_Start, m_End, - m_Width + ( 2 * aClearanceValue ), numSegs, correction ); + m_Width + ( 2 * aClearanceValue ), aError ); break; } } @@ -602,10 +591,7 @@ void D_PAD::TransformShapeWithClearanceToPolygon( { case PAD_SHAPE_CIRCLE: { - int numSegs = std::max( GetArcToSegmentCount( dx, aError, 360.0 ), 6 ); - double correction = GetCircletoPolyCorrectionFactor( numSegs ); - dx = KiROUND( dx * correction ); - TransformCircleToPolygon( aCornerBuffer, padShapePos, dx, numSegs ); + TransformCircleToPolygon( aCornerBuffer, padShapePos, dx, aError ); } break; @@ -625,13 +611,10 @@ void D_PAD::TransformShapeWithClearanceToPolygon( width = dy * 2; } - int numSegs = std::max( GetArcToSegmentCount( width / 2, aError, 360.0 ), 6 ); - double correction = GetCircletoPolyCorrectionFactor( numSegs ); - RotatePoint( &shape_offset, angle ); wxPoint start = padShapePos - shape_offset; wxPoint end = padShapePos + shape_offset; - TransformOvalClearanceToPolygon( aCornerBuffer, start, end, width, numSegs, correction ); + TransformOvalClearanceToPolygon( aCornerBuffer, start, end, width, aError ); } break; @@ -671,13 +654,13 @@ void D_PAD::TransformShapeWithClearanceToPolygon( int rounding_radius = GetRoundRectCornerRadius() + clearance; wxSize shapesize( m_Size ); - shapesize.x += clearance*2; - shapesize.y += clearance*2; + shapesize.x += clearance * 2; + shapesize.y += clearance * 2; bool doChamfer = GetShape() == PAD_SHAPE_CHAMFERED_RECT; TransformRoundChamferedRectToPolygon( outline, padShapePos, shapesize, angle, rounding_radius, doChamfer ? GetChamferRectRatio() : 0.0, - doChamfer ? GetChamferPositions() : 0, numSegs ); + doChamfer ? GetChamferPositions() : 0, aError ); aCornerBuffer.Append( outline ); } @@ -769,8 +752,7 @@ bool D_PAD::BuildPadDrillShapePolygon( if( drillsize.x == drillsize.y ) // usual round hole { int radius = ( drillsize.x / 2 ) + aInflateValue; - int numSegs = std::max( GetArcToSegmentCount( radius, aError, 360.0 ), 6 ); - TransformCircleToPolygon( aCornerBuffer, GetPosition(), radius, numSegs ); + TransformCircleToPolygon( aCornerBuffer, GetPosition(), radius, aError ); } else // Oblong hole { @@ -780,10 +762,9 @@ bool D_PAD::BuildPadDrillShapePolygon( GetOblongDrillGeometry( start, end, width ); width += aInflateValue * 2; - int numSegs = std::max( GetArcToSegmentCount( width / 2, aError, 360.0 ), 6 ); TransformRoundedEndsSegmentToPolygon( - aCornerBuffer, GetPosition() + start, GetPosition() + end, numSegs, width ); + aCornerBuffer, GetPosition() + start, GetPosition() + end, aError, width ); } return true; diff --git a/pcbnew/class_module.h b/pcbnew/class_module.h index ae59f8d87e..4f3e4fca47 100644 --- a/pcbnew/class_module.h +++ b/pcbnew/class_module.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr - * Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2019 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/pcbnew/class_pad.cpp b/pcbnew/class_pad.cpp index 57b392fd7f..d17988e119 100644 --- a/pcbnew/class_pad.cpp +++ b/pcbnew/class_pad.cpp @@ -937,15 +937,13 @@ bool D_PAD::HitTest( const wxPoint& aPosition, int aAccuracy ) const { // Check for hit in polygon SHAPE_POLY_SET outline; - int segmentToCircleCount = std::max( - GetArcToSegmentCount( GetRoundRectCornerRadius(), ARC_HIGH_DEF, 360.0 ), 3 ); bool doChamfer = GetShape() == PAD_SHAPE_CHAMFERED_RECT; TransformRoundChamferedRectToPolygon( outline, wxPoint(0,0), GetSize(), m_Orient, GetRoundRectCornerRadius(), doChamfer ? GetChamferRectRatio() : 0.0, doChamfer ? GetChamferPositions() : 0, - segmentToCircleCount ); + ARC_HIGH_DEF ); const SHAPE_LINE_CHAIN &poly = outline.COutline( 0 ); return TestPointInsidePolygon( (const wxPoint*)&poly.CPoint(0), poly.PointCount(), delta ); diff --git a/pcbnew/convert_drawsegment_list_to_polygon.cpp b/pcbnew/convert_drawsegment_list_to_polygon.cpp index 46f832057b..55083a6d92 100644 --- a/pcbnew/convert_drawsegment_list_to_polygon.cpp +++ b/pcbnew/convert_drawsegment_list_to_polygon.cpp @@ -324,8 +324,7 @@ bool ConvertOutlineToPolygon( std::vector& aSegList, SHAPE_POLY_SE // Output the outline perimeter as polygon. if( graphic->GetShape() == S_CIRCLE ) { - int steps = std::max( 4, GetArcToSegmentCount( graphic->GetRadius(), aTolerance, 360.0 ) ); - TransformCircleToPolygon( aPolygons, graphic->GetCenter(), graphic->GetRadius(), steps ); + TransformCircleToPolygon( aPolygons, graphic->GetCenter(), graphic->GetRadius(), aTolerance ); } else if( graphic->GetShape() == S_POLYGON ) { diff --git a/pcbnew/drc_clearance_test_functions.cpp b/pcbnew/drc_clearance_test_functions.cpp index 678bb844b9..4a1f88c707 100644 --- a/pcbnew/drc_clearance_test_functions.cpp +++ b/pcbnew/drc_clearance_test_functions.cpp @@ -989,7 +989,7 @@ bool DRC::checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad ) TransformRoundChamferedRectToPolygon( polysetref, wxPoint( 0, 0 ), aRefPad->GetSize(), aRefPad->GetOrientation(), padRadius, aRefPad->GetChamferRectRatio(), - aRefPad->GetChamferPositions(), 64 ); + aRefPad->GetChamferPositions(), ARC_HIGH_DEF ); } else if( aRefPad->GetShape() == PAD_SHAPE_CUSTOM ) { @@ -1031,7 +1031,7 @@ bool DRC::checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad ) TransformRoundChamferedRectToPolygon( polysetcompare, relativePadPos, aPad->GetSize(), aPad->GetOrientation(), padRadius, aPad->GetChamferRectRatio(), - aPad->GetChamferPositions(), 64 ); + aPad->GetChamferPositions(), ARC_HIGH_DEF ); } else if( aPad->GetShape() == PAD_SHAPE_CUSTOM ) { @@ -1422,7 +1422,7 @@ bool DRC::checkClearanceSegmToPad( const D_PAD* aPad, int aSegmentWidth, int aMi TransformRoundChamferedRectToPolygon( polyset, m_padToTestPos, aPad->GetSize(), aPad->GetOrientation(), padRadius, aPad->GetChamferRectRatio(), - aPad->GetChamferPositions(), 64 ); + aPad->GetChamferPositions(), ARC_HIGH_DEF ); // Rotate also coordinates by m_segmAngle, because the segment orient // is m_segmAngle. // we are using a horizontal segment for test, because we know here diff --git a/pcbnew/exporters/export_vrml.cpp b/pcbnew/exporters/export_vrml.cpp index 264c7187b9..88de2ac358 100644 --- a/pcbnew/exporters/export_vrml.cpp +++ b/pcbnew/exporters/export_vrml.cpp @@ -1119,10 +1119,9 @@ static void export_vrml_padshape( MODEL_VRML& aModel, VRML_LAYER* aTinLayer, D_P case PAD_SHAPE_CHAMFERED_RECT: { SHAPE_POLY_SET polySet; - int segmentToCircleCount = ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF; const int corner_radius = aPad->GetRoundRectCornerRadius( aPad->GetSize() ); TransformRoundChamferedRectToPolygon( polySet, wxPoint( 0, 0 ), aPad->GetSize(), - 0.0, corner_radius, 0.0, 0, segmentToCircleCount ); + 0.0, corner_radius, 0.0, 0, ARC_HIGH_DEF ); std::vector< wxRealPoint > cornerList; // TransformRoundChamferedRectToPolygon creates only one convex polygon SHAPE_LINE_CHAIN poly( polySet.Outline( 0 ) ); diff --git a/pcbnew/pad_custom_shape_functions.cpp b/pcbnew/pad_custom_shape_functions.cpp index 6be845bc6b..9f2526278b 100644 --- a/pcbnew/pad_custom_shape_functions.cpp +++ b/pcbnew/pad_custom_shape_functions.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr - * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2019 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 @@ -220,40 +220,33 @@ bool D_PAD::buildCustomPadPolygon( SHAPE_POLY_SET* aMergedPolygon, int aError ) for( unsigned ii = 1; ii < poly.size(); ii++ ) { - int numSegs = std::max( - GetArcToSegmentCount( bshape.m_Thickness / 2, aError, 360.0 ), 6 ); TransformRoundedEndsSegmentToPolygon( - aux_polyset, poly[ii - 1], poly[ii], numSegs, bshape.m_Thickness ); + aux_polyset, poly[ii - 1], poly[ii], aError, bshape.m_Thickness ); } break; } case S_SEGMENT: // usual segment : line with rounded ends { - int numSegs = - std::max( GetArcToSegmentCount( bshape.m_Thickness / 2, aError, 360.0 ), 6 ); TransformRoundedEndsSegmentToPolygon( - aux_polyset, bshape.m_Start, bshape.m_End, numSegs, bshape.m_Thickness ); + aux_polyset, bshape.m_Start, bshape.m_End, aError, bshape.m_Thickness ); break; } case S_ARC: // Arc with rounded ends { - int radius = KiROUND( EuclideanNorm( ( bshape.m_Start - bshape.m_End ) ) ); - int numSegs = std::max( GetArcToSegmentCount( radius, aError, 360.0 ), 6 ); TransformArcToPolygon( aux_polyset, bshape.m_Start, bshape.m_End, bshape.m_ArcAngle, - numSegs, bshape.m_Thickness ); + aError, bshape.m_Thickness ); break; } case S_CIRCLE: // ring or circle { - int numSegs = std::max( GetArcToSegmentCount( bshape.m_Radius, aError, 360.0 ), 6 ); if( bshape.m_Thickness ) // ring TransformRingToPolygon( - aux_polyset, bshape.m_Start, bshape.m_Radius, numSegs, bshape.m_Thickness ); + aux_polyset, bshape.m_Start, bshape.m_Radius, aError, bshape.m_Thickness ); else // Filled circle - TransformCircleToPolygon( aux_polyset, bshape.m_Start, bshape.m_Radius, numSegs ); + TransformCircleToPolygon( aux_polyset, bshape.m_Start, bshape.m_Radius, aError ); break; } @@ -325,12 +318,8 @@ bool D_PAD::MergePrimitivesAsPolygon( SHAPE_POLY_SET* aMergedPolygon ) { default: case PAD_SHAPE_CIRCLE: - { - int numSegs = std::max( GetArcToSegmentCount( GetSize().x / 2, ARC_HIGH_DEF, 360.0 ), 6 ); - TransformCircleToPolygon( *aMergedPolygon, wxPoint( 0, 0 ), GetSize().x / 2, numSegs ); - + TransformCircleToPolygon( *aMergedPolygon, wxPoint( 0, 0 ), GetSize().x / 2, ARC_HIGH_DEF ); break; - } case PAD_SHAPE_RECT: { diff --git a/pcbnew/pad_draw_functions.cpp b/pcbnew/pad_draw_functions.cpp index 819777af3b..30a713fb2e 100644 --- a/pcbnew/pad_draw_functions.cpp +++ b/pcbnew/pad_draw_functions.cpp @@ -450,7 +450,7 @@ void D_PAD::DrawShape( EDA_RECT* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo ) TransformRoundChamferedRectToPolygon( outline, shape_pos, size, GetOrientation(), corner_radius, GetChamferRectRatio(), doChamfer ? GetChamferPositions() : 0, - SEGCOUNT ); + ARC_HIGH_DEF ); // Draw the polygon: Inflate creates only one convex polygon bool filled = aDrawInfo.m_ShowPadFilled; @@ -472,7 +472,7 @@ void D_PAD::DrawShape( EDA_RECT* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo ) TransformRoundChamferedRectToPolygon( outline, shape_pos, size, GetOrientation(), corner_radius, GetChamferRectRatio(), doChamfer ? GetChamferPositions() : 0, - SEGCOUNT ); + ARC_HIGH_DEF ); // Draw the polygon: Inflate creates only one convex polygon SHAPE_LINE_CHAIN& clearance_poly = outline.Outline( 0 ); diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp index 14a3b85630..aa68704318 100644 --- a/pcbnew/pcb_painter.cpp +++ b/pcbnew/pcb_painter.cpp @@ -823,13 +823,12 @@ void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer ) { SHAPE_POLY_SET polySet; wxSize prsize( size.x * 2, size.y * 2 ); // size is the half pad area size) - const int segmentToCircleCount = 64; const int corner_radius = aPad->GetRoundRectCornerRadius( prsize ); bool doChamfer = shape == PAD_SHAPE_CHAMFERED_RECT; TransformRoundChamferedRectToPolygon( polySet, wxPoint( 0, 0 ), prsize, 0.0, corner_radius, aPad->GetChamferRectRatio(), - doChamfer ? aPad->GetChamferPositions() : 0, segmentToCircleCount ); + doChamfer ? aPad->GetChamferPositions() : 0, ARC_HIGH_DEF ); m_gal->DrawPolygon( polySet ); break; } diff --git a/pcbnew/plot_brditems_plotter.cpp b/pcbnew/plot_brditems_plotter.cpp index af853a937b..96056b2dc4 100644 --- a/pcbnew/plot_brditems_plotter.cpp +++ b/pcbnew/plot_brditems_plotter.cpp @@ -184,11 +184,10 @@ void BRDITEMS_PLOTTER::PlotPad( D_PAD* aPad, COLOR4D aColor, EDA_DRAW_MODE_T aPl case PAD_SHAPE_CHAMFERED_RECT: { SHAPE_POLY_SET polygons; - const int segmentToCircleCount = 64; const int corner_radius = aPad->GetRoundRectCornerRadius( aPad->GetSize() ); TransformRoundChamferedRectToPolygon( polygons, shape_pos, aPad->GetSize(), aPad->GetOrientation(), corner_radius, aPad->GetChamferRectRatio(), - aPad->GetChamferPositions(), segmentToCircleCount ); + aPad->GetChamferPositions(), ARC_HIGH_DEF ); if( polygons.OutlineCount() == 0 ) break; diff --git a/pcbnew/specctra_import_export/specctra_export.cpp b/pcbnew/specctra_import_export/specctra_export.cpp index 54ea174b87..4f809502a5 100644 --- a/pcbnew/specctra_import_export/specctra_export.cpp +++ b/pcbnew/specctra_import_export/specctra_export.cpp @@ -517,7 +517,7 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad ) 0, rradius, aPad->GetChamferRectRatio(), doChamfer ? aPad->GetChamferPositions() : 0, - circleToSegmentsCount ); + ARC_HIGH_DEF ); SHAPE_LINE_CHAIN& polygonal_shape = cornerBuffer.Outline( 0 ); for( int ndx=0; ndx < reportedLayers; ++ndx )