From 1703729269ce0903c25ba815d5af978ec6667b1a Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Tue, 13 Oct 2020 11:55:24 +0100 Subject: [PATCH] Require explicit decl of maxError and errorLocations. This should reduce both performance issues and clearance issues. --- .../3d_canvas/create_3Dgraphic_brd_items.cpp | 8 +- 3d-viewer/3d_canvas/create_layer_items.cpp | 117 +++++++------- 3d-viewer/3d_canvas/create_layer_poly.cpp | 10 +- .../c3d_render_createscene_ogl_legacy.cpp | 7 +- common/plotters/DXF_plotter.cpp | 7 +- common/plotters/GERBER_plotter.cpp | 15 +- common/plotters/HPGL_plotter.cpp | 4 +- common/plotters/PS_plotter.cpp | 4 +- gerbview/am_primitive.cpp | 7 +- gerbview/dcode.cpp | 6 +- include/class_board_item.h | 8 +- .../include/convert_basic_shapes_to_polygon.h | 42 ++--- libs/kimath/include/geometry/geometry_utils.h | 7 + .../src/convert_basic_shapes_to_polygon.cpp | 64 ++++---- ...board_items_to_polygon_shape_transform.cpp | 146 +++++++++++------- pcbnew/class_board.h | 9 +- pcbnew/class_board_item.cpp | 4 +- pcbnew/class_module.h | 34 ++-- pcbnew/class_pad.cpp | 12 +- pcbnew/class_pad.h | 11 +- pcbnew/class_track.h | 5 +- pcbnew/class_zone.h | 5 +- .../convert_drawsegment_list_to_polygon.cpp | 3 +- pcbnew/exporters/export_vrml.cpp | 4 +- pcbnew/pad_custom_shape_functions.cpp | 18 +-- pcbnew/pcb_expr_evaluator.cpp | 6 +- pcbnew/pcb_painter.cpp | 11 +- pcbnew/pcb_shape.h | 5 +- pcbnew/pcb_text.h | 6 +- pcbnew/plot_board_layers.cpp | 23 ++- pcbnew/plugins/altium/altium_pcb.cpp | 4 +- .../specctra_export.cpp | 3 +- pcbnew/tools/pad_tool.cpp | 46 +++--- pcbnew/tracks_cleaner.cpp | 13 +- pcbnew/zone_filler.cpp | 28 ++-- .../polygon_generator/polygon_generator.cpp | 3 +- 36 files changed, 387 insertions(+), 318 deletions(-) diff --git a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp index c0c8246763..b6397c5bd2 100644 --- a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp +++ b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp @@ -349,7 +349,7 @@ void BOARD_ADAPTER::createNewPadWithClearance( const D_PAD* aPad, { D_PAD dummy( *aPad ); dummy.SetSize( aPad->GetSize() + aClearanceValue + aClearanceValue ); - dummy.TransformShapeWithClearanceToPolygon( poly, aLayer, 0 ); + dummy.TransformShapeWithClearanceToPolygon( poly, aLayer, 0, ARC_HIGH_DEF, ERROR_INSIDE ); aClearanceValue = { 0, 0 }; } else @@ -683,7 +683,8 @@ void BOARD_ADAPTER::AddShapeWithClearanceToContainer( const PCB_SHAPE* aDrawSegm SHAPE_POLY_SET polyList; aDrawSegment->TransformShapeWithClearanceToPolygon( polyList, aLayerId, - aClearanceValue ); + aClearanceValue, + ARC_HIGH_DEF, ERROR_INSIDE ); polyList.Simplify( SHAPE_POLY_SET::PM_FAST ); @@ -736,7 +737,8 @@ void BOARD_ADAPTER::AddShapeWithClearanceToContainer( const PCB_SHAPE* aDrawSegm { SHAPE_POLY_SET polyList; - aDrawSegment->TransformShapeWithClearanceToPolygon( polyList, aLayerId, aClearanceValue ); + aDrawSegment->TransformShapeWithClearanceToPolygon( polyList, aLayerId, aClearanceValue, + ARC_HIGH_DEF, ERROR_INSIDE ); polyList.Simplify( SHAPE_POLY_SET::PM_FAST ); diff --git a/3d-viewer/3d_canvas/create_layer_items.cpp b/3d-viewer/3d_canvas/create_layer_items.cpp index d4fca9415d..2ea78a5a01 100644 --- a/3d-viewer/3d_canvas/create_layer_items.cpp +++ b/3d-viewer/3d_canvas/create_layer_items.cpp @@ -392,10 +392,10 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) const int hole_outer_radius = (holediameter / 2) + GetHolePlatingThicknessBIU(); TransformCircleToPolygon( *layerOuterHolesPoly, via->GetStart(), - hole_outer_radius, ARC_HIGH_DEF ); + hole_outer_radius, ARC_HIGH_DEF, ERROR_INSIDE ); TransformCircleToPolygon( *layerInnerHolesPoly, via->GetStart(), - holediameter / 2, ARC_HIGH_DEF ); + holediameter / 2, ARC_HIGH_DEF, ERROR_INSIDE ); } else if( curr_layer_id == layer_id[0] ) // it only adds once the THT holes { @@ -406,17 +406,18 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) // Add through hole contourns // ///////////////////////////////////////////////////////// TransformCircleToPolygon( m_through_outer_holes_poly, via->GetStart(), - hole_outer_radius, ARC_HIGH_DEF ); + hole_outer_radius, ARC_HIGH_DEF, ERROR_INSIDE ); // Add same thing for vias only - TransformCircleToPolygon( m_through_outer_holes_vias_poly, - via->GetStart(), hole_outer_radius, ARC_HIGH_DEF ); + TransformCircleToPolygon( m_through_outer_holes_vias_poly, via->GetStart(), + hole_outer_radius, ARC_HIGH_DEF, ERROR_INSIDE ); if( GetFlag( FL_CLIP_SILK_ON_VIA_ANNULUS ) ) { TransformCircleToPolygon( m_through_outer_ring_holes_poly, - via->GetStart(), hole_outer_ring_radius, ARC_HIGH_DEF ); + via->GetStart(), hole_outer_ring_radius, + ARC_HIGH_DEF, ERROR_INSIDE ); } } } @@ -451,7 +452,8 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) continue; // Add the track/via contour - track->TransformShapeWithClearanceToPolygon( *layerPoly, curr_layer_id, 0 ); + track->TransformShapeWithClearanceToPolygon( *layerPoly, curr_layer_id, 0, + ARC_HIGH_DEF, ERROR_INSIDE ); } } } @@ -506,17 +508,26 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) if( pad->GetAttribute () != PAD_ATTRIB_NPTH ) { if( GetFlag( FL_CLIP_SILK_ON_VIA_ANNULUS ) ) - pad->TransformHoleWithClearanceToPolygon( m_through_outer_ring_holes_poly, inflate ); + { + pad->TransformHoleWithClearanceToPolygon( m_through_outer_ring_holes_poly, + inflate, + ARC_HIGH_DEF, ERROR_INSIDE ); + } - pad->TransformHoleWithClearanceToPolygon( m_through_outer_holes_poly, inflate ); + pad->TransformHoleWithClearanceToPolygon( m_through_outer_holes_poly, inflate, + ARC_HIGH_DEF, ERROR_INSIDE ); } else { // If not plated, no copper. if( GetFlag( FL_CLIP_SILK_ON_VIA_ANNULUS ) ) - pad->TransformHoleWithClearanceToPolygon( m_through_outer_ring_holes_poly, 0 ); + { + pad->TransformHoleWithClearanceToPolygon( m_through_outer_ring_holes_poly, 0, + ARC_HIGH_DEF, ERROR_INSIDE ); + } - pad->TransformHoleWithClearanceToPolygon( m_through_outer_holes_poly_NPTH, 0 ); + pad->TransformHoleWithClearanceToPolygon( m_through_outer_holes_poly_NPTH, 0, + ARC_HIGH_DEF, ERROR_INSIDE ); } } } @@ -535,19 +546,11 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) { // Note: NPTH pads are not drawn on copper layers when the pad // has same shape as its hole - AddPadsShapesWithClearanceToContainer( module, - layerContainer, - curr_layer_id, - 0, - true, - renderPlatedPadsAsPlated, - false ); + AddPadsShapesWithClearanceToContainer( module, layerContainer, curr_layer_id, 0, + true, renderPlatedPadsAsPlated, false ); // Micro-wave modules may have items on copper layers - AddGraphicsShapesWithClearanceToContainer( module, - layerContainer, - curr_layer_id, - 0 ); + AddGraphicsShapesWithClearanceToContainer( module, layerContainer, curr_layer_id, 0 ); } } @@ -556,21 +559,11 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) // ADD PLATED PADS for( MODULE* module : m_board->Modules() ) { - AddPadsShapesWithClearanceToContainer( module, - m_platedpads_container2D_F_Cu, - F_Cu, - 0, - true, - false, - true ); + AddPadsShapesWithClearanceToContainer( module, m_platedpads_container2D_F_Cu, F_Cu, 0, + true, false, true ); - AddPadsShapesWithClearanceToContainer( module, - m_platedpads_container2D_B_Cu, - B_Cu, - 0, - true, - false, - true ); + AddPadsShapesWithClearanceToContainer( module, m_platedpads_container2D_B_Cu, B_Cu, 0, + true, false, true ); } } @@ -589,9 +582,9 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) { // Note: NPTH pads are not drawn on copper layers when the pad // has same shape as its hole - module->TransformPadsShapesWithClearanceToPolygon( curr_layer_id, *layerPoly, - 0, ARC_HIGH_DEF, true, - renderPlatedPadsAsPlated, + module->TransformPadsShapesWithClearanceToPolygon( *layerPoly, curr_layer_id, + 0, ARC_HIGH_DEF, ERROR_INSIDE, + true, renderPlatedPadsAsPlated, false ); transformGraphicModuleEdgeToPolygonSet( module, curr_layer_id, *layerPoly ); @@ -603,15 +596,15 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) // ADD PLATED PADS contourns for( auto module : m_board->Modules() ) { - module->TransformPadsShapesWithClearanceToPolygon( F_Cu, *m_F_Cu_PlatedPads_poly, - 0, ARC_HIGH_DEF, true, - false, true ); + module->TransformPadsShapesWithClearanceToPolygon( *m_F_Cu_PlatedPads_poly, F_Cu, + 0, ARC_HIGH_DEF, ERROR_INSIDE, + true, false, true ); //transformGraphicModuleEdgeToPolygonSet( module, F_Cu, *m_F_Cu_PlatedPads_poly ); - module->TransformPadsShapesWithClearanceToPolygon( B_Cu, *m_B_Cu_PlatedPads_poly, - 0, ARC_HIGH_DEF, true, - false, true ); + module->TransformPadsShapesWithClearanceToPolygon( *m_B_Cu_PlatedPads_poly, B_Cu, + 0, ARC_HIGH_DEF, ERROR_INSIDE, + true, false, true ); //transformGraphicModuleEdgeToPolygonSet( module, B_Cu, *m_B_Cu_PlatedPads_poly ); } @@ -636,17 +629,13 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) { case PCB_SHAPE_T: { - AddShapeWithClearanceToContainer( (PCB_SHAPE*)item, - layerContainer, - curr_layer_id, + AddShapeWithClearanceToContainer( (PCB_SHAPE*)item, layerContainer, curr_layer_id, 0 ); } break; case PCB_TEXT_T: - AddShapeWithClearanceToContainer( (PCB_TEXT*) item, - layerContainer, - curr_layer_id, + AddShapeWithClearanceToContainer( (PCB_TEXT*) item, layerContainer, curr_layer_id, 0 ); break; @@ -654,9 +643,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) case PCB_DIM_CENTER_T: case PCB_DIM_ORTHOGONAL_T: case PCB_DIM_LEADER_T: - AddShapeWithClearanceToContainer( (DIMENSION*) item, - layerContainer, - curr_layer_id, + AddShapeWithClearanceToContainer( (DIMENSION*) item, layerContainer, curr_layer_id, 0 ); break; @@ -689,11 +676,15 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) { case PCB_SHAPE_T: ( (PCB_SHAPE*) item )->TransformShapeWithClearanceToPolygon( *layerPoly, - cur_layer_id, 0 ); + cur_layer_id, 0, + ARC_HIGH_DEF, + ERROR_INSIDE ); break; case PCB_TEXT_T: - ( (PCB_TEXT*) item )->TransformShapeWithClearanceToPolygonSet( *layerPoly, 0 ); + ( (PCB_TEXT*) item )->TransformShapeWithClearanceToPolygonSet( *layerPoly, 0, + ARC_HIGH_DEF, + ERROR_INSIDE ); break; default: @@ -972,11 +963,15 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) { case PCB_SHAPE_T: ( (PCB_SHAPE*) item )->TransformShapeWithClearanceToPolygon( *layerPoly, - curr_layer_id, 0 ); + curr_layer_id, 0, + ARC_HIGH_DEF, + ERROR_INSIDE ); break; case PCB_TEXT_T: - ( (PCB_TEXT*) item )->TransformShapeWithClearanceToPolygonSet( *layerPoly, 0 ); + ( (PCB_TEXT*) item )->TransformShapeWithClearanceToPolygonSet( *layerPoly, 0, + ARC_HIGH_DEF, + ERROR_INSIDE ); break; default: @@ -1030,11 +1025,13 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) } else { - module->TransformPadsShapesWithClearanceToPolygon( curr_layer_id, *layerPoly, 0 ); + module->TransformPadsShapesWithClearanceToPolygon( *layerPoly, curr_layer_id, 0, + ARC_HIGH_DEF, ERROR_INSIDE ); } // On tech layers, use a poor circle approximation, only for texts (stroke font) - module->TransformGraphicTextWithClearanceToPolygonSet( curr_layer_id, *layerPoly, 0 ); + module->TransformGraphicTextWithClearanceToPolygonSet( *layerPoly, curr_layer_id, 0, + ARC_HIGH_DEF, ERROR_INSIDE ); // Add the remaining things with dynamic seg count for circles transformGraphicModuleEdgeToPolygonSet( module, curr_layer_id, *layerPoly ); diff --git a/3d-viewer/3d_canvas/create_layer_poly.cpp b/3d-viewer/3d_canvas/create_layer_poly.cpp index 2f38bd2590..15de111e72 100644 --- a/3d-viewer/3d_canvas/create_layer_poly.cpp +++ b/3d-viewer/3d_canvas/create_layer_poly.cpp @@ -41,7 +41,7 @@ void BOARD_ADAPTER::buildPadShapeThickOutlineAsPolygon( const D_PAD* aPad, if( aPad->GetShape() == PAD_SHAPE_CIRCLE ) // Draw a ring { TransformRingToPolygon( aCornerBuffer, aPad->ShapePos(), aPad->GetSize().x / 2, - ARC_HIGH_DEF, aWidth ); + aWidth, ARC_HIGH_DEF, ERROR_INSIDE ); return; } @@ -54,7 +54,8 @@ void BOARD_ADAPTER::buildPadShapeThickOutlineAsPolygon( const D_PAD* aPad, const VECTOR2I& a = path.CPoint( ii ); const VECTOR2I& b = path.CPoint( ii + 1 ); - TransformOvalToPolygon( aCornerBuffer, (wxPoint) a, (wxPoint) b, aWidth, ARC_HIGH_DEF ); + TransformOvalToPolygon( aCornerBuffer, (wxPoint) a, (wxPoint) b, aWidth, ARC_HIGH_DEF, + ERROR_INSIDE ); } } @@ -70,7 +71,10 @@ void BOARD_ADAPTER::transformGraphicModuleEdgeToPolygonSet( const MODULE *aModul FP_SHAPE* outline = (FP_SHAPE*) item; if( outline->GetLayer() == aLayer ) - outline->TransformShapeWithClearanceToPolygon( aCornerBuffer, aLayer, 0 ); + { + outline->TransformShapeWithClearanceToPolygon( aCornerBuffer, aLayer, 0, + ARC_HIGH_DEF, ERROR_INSIDE ); + } } } } diff --git a/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_createscene_ogl_legacy.cpp b/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_createscene_ogl_legacy.cpp index d0223575ce..d943688ab8 100644 --- a/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_createscene_ogl_legacy.cpp +++ b/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_createscene_ogl_legacy.cpp @@ -825,9 +825,10 @@ void C3D_RENDER_OGL_LEGACY::generate_3D_Vias_and_Pads() const int copperThickness = m_boardAdapter.GetHolePlatingThicknessBIU(); pad->TransformHoleWithClearanceToPolygon( tht_outer_holes_poly, - copperThickness, ARC_LOW_DEF ); - pad->TransformHoleWithClearanceToPolygon( tht_inner_holes_poly, - 0, ARC_LOW_DEF ); + copperThickness, + ARC_LOW_DEF, ERROR_INSIDE ); + pad->TransformHoleWithClearanceToPolygon( tht_inner_holes_poly, 0, + ARC_LOW_DEF, ERROR_INSIDE ); } } } diff --git a/common/plotters/DXF_plotter.cpp b/common/plotters/DXF_plotter.cpp index d4279933f4..5f4f2a61b9 100644 --- a/common/plotters/DXF_plotter.cpp +++ b/common/plotters/DXF_plotter.cpp @@ -533,7 +533,7 @@ void DXF_PLOTTER::PlotPoly( const std::vector& aCornerList, for( unsigned ii = 1; ii < aCornerList.size(); ii++ ) { TransformOvalToPolygon( bufferOutline, aCornerList[ ii - 1 ], aCornerList[ ii ], - aWidth, GetPlotterArcHighDef() ); + aWidth, GetPlotterArcHighDef(), ERROR_INSIDE ); } // enter the initial polygon: @@ -620,7 +620,8 @@ void DXF_PLOTTER::ThickSegment( const wxPoint& aStart, const wxPoint& aEnd, int { std::vector cornerList; SHAPE_POLY_SET outlineBuffer; - TransformOvalToPolygon( outlineBuffer, aStart, aEnd, aWidth, GetPlotterArcHighDef() ); + TransformOvalToPolygon( outlineBuffer, aStart, aEnd, aWidth, GetPlotterArcHighDef(), + ERROR_INSIDE ); const SHAPE_LINE_CHAIN& path = outlineBuffer.COutline( 0 ); cornerList.reserve( path.PointCount() ); @@ -777,7 +778,7 @@ void DXF_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize { SHAPE_POLY_SET outline; TransformRoundChamferedRectToPolygon( outline, aPadPos, aSize, aOrient, - aCornerRadius, 0.0, 0, GetPlotterArcHighDef() ); + aCornerRadius, 0.0, 0, GetPlotterArcHighDef(), ERROR_INSIDE ); // 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 eb2c85f135..53884d8c14 100644 --- a/common/plotters/GERBER_plotter.cpp +++ b/common/plotters/GERBER_plotter.cpp @@ -1227,7 +1227,7 @@ void GERBER_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aS { SHAPE_POLY_SET outline; TransformRoundChamferedRectToPolygon( outline, aPadPos, aSize, aOrient, - aCornerRadius, 0.0, 0, GetPlotterArcHighDef() ); + aCornerRadius, 0.0, 0, GetPlotterArcHighDef(), ERROR_INSIDE ); SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH, &gbr_metadata ); outline.Inflate( -GetCurrentLineWidth()/2, 16 ); @@ -1489,10 +1489,9 @@ void GERBER_PLOTTER::FlashPadChamferRoundRect( const wxPoint& aShapePos, const w if( aPlotMode != FILLED || hasRoundedCorner || m_gerberDisableApertMacros ) #endif { - TransformRoundChamferedRectToPolygon( outline, aShapePos, aPadSize, - aPadOrient, aCornerRadius, - aChamferRatio, - aChamferPositions, m_IUsPerDecimil * 2 ); + TransformRoundChamferedRectToPolygon( outline, aShapePos, aPadSize, aPadOrient, + aCornerRadius, aChamferRatio, aChamferPositions, + GetPlotterArcHighDef(), ERROR_INSIDE ); // Build the corner list const SHAPE_LINE_CHAIN& corners = outline.Outline(0); @@ -1535,9 +1534,9 @@ void GERBER_PLOTTER::FlashPadChamferRoundRect( const wxPoint& aShapePos, const w } // Build the chamfered polygon (4 to 8 corners ) - TransformRoundChamferedRectToPolygon( outline, wxPoint( 0, 0 ), aPadSize, - 0.0, 0, aChamferRatio, - aChamferPositions, 0 ); + TransformRoundChamferedRectToPolygon( outline, wxPoint( 0, 0 ), aPadSize, 0.0, 0, + aChamferRatio, aChamferPositions, + GetPlotterArcHighDef(), ERROR_INSIDE ); // Build the corner list const SHAPE_LINE_CHAIN& corners = outline.Outline(0); diff --git a/common/plotters/HPGL_plotter.cpp b/common/plotters/HPGL_plotter.cpp index 96597adeeb..07f2ffecab 100644 --- a/common/plotters/HPGL_plotter.cpp +++ b/common/plotters/HPGL_plotter.cpp @@ -640,8 +640,8 @@ void HPGL_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSiz aCornerRadius = std::min( aCornerRadius, std::min( size.x, size.y ) /2 ); } - TransformRoundChamferedRectToPolygon( outline, aPadPos, size, aOrient, - aCornerRadius, 0.0, 0, GetPlotterArcHighDef() ); + TransformRoundChamferedRectToPolygon( outline, aPadPos, size, aOrient, aCornerRadius, + 0.0, 0, GetPlotterArcHighDef(), ERROR_INSIDE ); // TransformRoundRectToPolygon creates only one convex polygon std::vector cornerList; diff --git a/common/plotters/PS_plotter.cpp b/common/plotters/PS_plotter.cpp index 3d8ab4554b..bc9fcd450e 100644 --- a/common/plotters/PS_plotter.cpp +++ b/common/plotters/PS_plotter.cpp @@ -192,8 +192,8 @@ void PSLIKE_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aS SHAPE_POLY_SET outline; - TransformRoundChamferedRectToPolygon( outline, aPadPos, size, aOrient, - aCornerRadius, 0.0, 0, GetPlotterArcHighDef() ); + TransformRoundChamferedRectToPolygon( outline, aPadPos, size, aOrient, aCornerRadius, + 0.0, 0, GetPlotterArcHighDef(), ERROR_INSIDE ); std::vector< wxPoint > cornerList; // TransformRoundRectToPolygon creates only one convex polygon diff --git a/gerbview/am_primitive.cpp b/gerbview/am_primitive.cpp index 37145c49e9..9f541b3ead 100644 --- a/gerbview/am_primitive.cpp +++ b/gerbview/am_primitive.cpp @@ -311,11 +311,14 @@ 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, ARC_HIGH_DEF ); + TransformCircleToPolygon( aShapeBuffer, center, outerDiam / 2, ARC_HIGH_DEF, + ERROR_INSIDE ); } else + { TransformRingToPolygon( aShapeBuffer, center, ( outerDiam - penThickness ) / 2, - ARC_HIGH_DEF, penThickness ); + penThickness, ARC_HIGH_DEF, ERROR_INSIDE ); + } } // Draw the cross: diff --git a/gerbview/dcode.cpp b/gerbview/dcode.cpp index 2b55dfe5f9..2617a3cc58 100644 --- a/gerbview/dcode.cpp +++ b/gerbview/dcode.cpp @@ -306,7 +306,8 @@ 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, ARC_HIGH_DEF ); + TransformCircleToPolygon( m_Polygon, initialpos, m_Size.x >> 1, ARC_HIGH_DEF, + ERROR_INSIDE ); addHoleToPolygon( &m_Polygon, m_DrillShape, m_Drill, initialpos ); break; @@ -428,7 +429,8 @@ static void addHoleToPolygon( SHAPE_POLY_SET* aPolygon, if( aHoleShape == APT_DEF_ROUND_HOLE ) { - TransformCircleToPolygon( holeBuffer, wxPoint( 0, 0 ), aSize.x / 2, ARC_HIGH_DEF ); + TransformCircleToPolygon( holeBuffer, wxPoint( 0, 0 ), aSize.x / 2, ARC_HIGH_DEF, + ERROR_INSIDE ); } else if( aHoleShape == APT_DEF_RECT_HOLE ) { diff --git a/include/class_board_item.h b/include/class_board_item.h index 6d0be2d11e..afbd40f15c 100644 --- a/include/class_board_item.h +++ b/include/class_board_item.h @@ -36,7 +36,7 @@ #include #include #include - +#include class BOARD; class BOARD_ITEM_CONTAINER; @@ -360,13 +360,13 @@ public: * @param aCornerBuffer = a buffer to store the polygon * @param aClearanceValue = the clearance around the pad * @param aError = the maximum deviation from true circle + * @param aErrorLoc = should the approximation error be placed outside or inside the polygon? * @param ignoreLineWidth = used for edge cut items where the line width is only * for visualization */ virtual void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, - PCB_LAYER_ID aLayer, - int aClearanceValue, - int aError = ARC_LOW_DEF, + PCB_LAYER_ID aLayer, int aClearanceValue, + int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth = false ) const; struct ptr_cmp diff --git a/libs/kimath/include/convert_basic_shapes_to_polygon.h b/libs/kimath/include/convert_basic_shapes_to_polygon.h index 5500edfb3e..212a02029b 100644 --- a/libs/kimath/include/convert_basic_shapes_to_polygon.h +++ b/libs/kimath/include/convert_basic_shapes_to_polygon.h @@ -25,26 +25,26 @@ #ifndef CONVERT_BASIC_SHAPES_TO_POLYGON_H #define CONVERT_BASIC_SHAPES_TO_POLYGON_H -/** - * @file convert_basic_shapes_to_polygon.h - */ - #include +#include #include // for wxPoint + // The chamfer positions of chamfered rect shape. // the position is relative to a pad with orientation = 0 // we can have 1 to 4 chamfered corners (0 corner = roundrect) // The position list is the OR of corner to chamfer enum RECT_CHAMFER_POSITIONS : int { - RECT_NO_CHAMFER = 0, - RECT_CHAMFER_TOP_LEFT = 1, - RECT_CHAMFER_TOP_RIGHT = 2, - RECT_CHAMFER_BOTTOM_LEFT = 4, + RECT_NO_CHAMFER = 0, + RECT_CHAMFER_TOP_LEFT = 1, + RECT_CHAMFER_TOP_RIGHT = 2, + RECT_CHAMFER_BOTTOM_LEFT = 4, RECT_CHAMFER_BOTTOM_RIGHT = 8, - RECT_CHAMFER_ALL = RECT_CHAMFER_BOTTOM_RIGHT | RECT_CHAMFER_BOTTOM_LEFT - | RECT_CHAMFER_TOP_RIGHT | RECT_CHAMFER_TOP_LEFT + RECT_CHAMFER_ALL = RECT_CHAMFER_BOTTOM_RIGHT + | RECT_CHAMFER_BOTTOM_LEFT + | RECT_CHAMFER_TOP_RIGHT + | RECT_CHAMFER_TOP_LEFT }; @@ -55,11 +55,10 @@ enum RECT_CHAMFER_POSITIONS : int * @param aCenter = the center of the circle * @param aRadius = the radius of the 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 + * @param aErrorLoc = should the approximation error be placed outside or inside the polygon? */ void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCenter, int aRadius, - int aError ); + int aError, ERROR_LOC aErrorLoc ); /** @@ -75,9 +74,10 @@ void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCenter, i * @param aEnd = the second point of the segment * @param aWidth = the width of the segment * @param aError = the IU allowed for error in approximation + * @param aErrorLoc = should the approximation error be placed outside or inside the polygon? */ void TransformOvalToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aStart, wxPoint aEnd, - int aWidth, int aError ); + int aWidth, int aError, ERROR_LOC aErrorLoc ); /** @@ -112,11 +112,13 @@ void GetRoundRectCornerCenters( wxPoint aCenters[4], int aRadius, const wxPoint& * 8 = BOTTOM_RIGHT * One can have more than one chamfered corner by ORing the corner identifers * @param aError = the IU allowed for error in approximation + * @param aErrorLoc = should the approximation error be placed outside or inside the polygon? */ void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer, const wxPoint& aPosition, const wxSize& aSize, double aRotation, int aCornerRadius, - double aChamferRatio, int aChamferCorners, int aError ); + double aChamferRatio, int aChamferCorners, + int aError, ERROR_LOC aErrorLoc ); /** * Function TransformArcToPolygon @@ -126,11 +128,12 @@ void TransformRoundChamferedRectToPolygon( 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 aError = the IU allowed for error in approximation * @param aWidth = width (thickness) of the line + * @param aError = the IU allowed for error in approximation + * @param aErrorLoc = should the approximation error be placed outside or inside the polygon? */ void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCentre, wxPoint aStart, - double aArcAngle, int aError, int aWidth ); + double aArcAngle, int aWidth, int aError, ERROR_LOC aErrorLoc ); /** * Function TransformRingToPolygon @@ -139,10 +142,11 @@ void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCentre, wxPo * @param aCornerBuffer = a buffer to store the polygon * @param aCentre = centre of the arc or circle * @param aRadius = radius of the circle - * @param aError = the IU allowed for error in approximation * @param aWidth = width (thickness) of the ring + * @param aError = the IU allowed for error in approximation + * @param aErrorLoc = should the approximation error be placed outside or inside the polygon? */ void TransformRingToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCentre, int aRadius, - int aError, int aWidth ); + int aWidth, int aError, ERROR_LOC aErrorLoc ); #endif // CONVERT_BASIC_SHAPES_TO_POLYGON_H diff --git a/libs/kimath/include/geometry/geometry_utils.h b/libs/kimath/include/geometry/geometry_utils.h index 2a507f751a..bf5cc6a33f 100644 --- a/libs/kimath/include/geometry/geometry_utils.h +++ b/libs/kimath/include/geometry/geometry_utils.h @@ -37,6 +37,13 @@ class EDA_RECT; +/** + * When approximating an arc or circle, should the error be placed on the outside + * or inside of the curve? (Generally speaking filled shape errors go on the inside + * and knockout errors go on the outside. This preserves minimum clearances.) + */ +enum ERROR_LOC { ERROR_OUTSIDE, ERROR_INSIDE }; + /** * @return the number of segments to approximate a arc by segments * with a given max error (this number is >= 1) diff --git a/libs/kimath/src/convert_basic_shapes_to_polygon.cpp b/libs/kimath/src/convert_basic_shapes_to_polygon.cpp index a3c0008f02..e3f387c361 100644 --- a/libs/kimath/src/convert_basic_shapes_to_polygon.cpp +++ b/libs/kimath/src/convert_basic_shapes_to_polygon.cpp @@ -39,14 +39,15 @@ void TransformCircleToPolygon( SHAPE_LINE_CHAIN& aCornerBuffer, wxPoint aCenter, int aRadius, - int aError ) + int aError, ERROR_LOC aErrorLoc ) { wxPoint corner_position; int numSegs = GetArcToSegmentCount( aRadius, aError, 360.0 ); int delta = 3600 / numSegs; // rotate angle in 0.1 degree - int correction = GetCircleToPolyCorrection( aError ); - int radius = aRadius + correction; // make segments outside the circles - double halfstep = delta / 2.0; // the starting value for rot angles + int radius = aRadius; + + if( aErrorLoc == ERROR_OUTSIDE ) + radius += GetCircleToPolyCorrection( aError ); for( int angle = 0; angle < 3600; angle += delta ) { @@ -62,13 +63,15 @@ void TransformCircleToPolygon( SHAPE_LINE_CHAIN& aCornerBuffer, wxPoint aCenter, void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCenter, int aRadius, - int aError ) + int aError, ERROR_LOC aErrorLoc ) { wxPoint corner_position; int numSegs = GetArcToSegmentCount( aRadius, aError, 360.0 ); int delta = 3600 / numSegs; // rotate angle in 0.1 degree - int correction = GetCircleToPolyCorrection( aError ); - int radius = aRadius + correction; // make segments outside the circles + int radius = aRadius; + + if( aErrorLoc == ERROR_OUTSIDE ) + radius += GetCircleToPolyCorrection( aError ); aCornerBuffer.NewOutline(); @@ -90,7 +93,7 @@ void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCenter, i void TransformOvalToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aStart, wxPoint aEnd, - int aWidth, int aError ) + int aWidth, int aError, ERROR_LOC aErrorLoc ) { // To build the polygonal shape outside the actual shape, we use a bigger // radius to build rounded ends. @@ -102,7 +105,8 @@ void TransformOvalToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aStart, wxPo int delta = 3600 / numSegs; // rotate angle in 0.1 degree int correction = GetCircleToPolyCorrection( aError ); - radius += correction; // make segments outside the circles + if( aErrorLoc == ERROR_OUTSIDE ) + radius += correction; // end point is the coordinate relative to aStart wxPoint endp = aEnd - aStart; @@ -218,7 +222,7 @@ void GetRoundRectCornerCenters( wxPoint aCenters[4], int aRadius, const wxPoint& void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer, const wxPoint& aPosition, const wxSize& aSize, double aRotation, int aCornerRadius, double aChamferRatio, - int aChamferCorners, int aError ) + int aChamferCorners, int aError, ERROR_LOC aErrorLoc ) { // Build the basic shape in orientation 0.0, position 0,0 for chamfered corners // or in actual position/orientation for round rect only @@ -244,28 +248,13 @@ void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer, const // radius to build rounded corners. int correction = GetCircleToPolyCorrection( aError ); - int radius = aCornerRadius + correction; // make segments outside the circles + int radius = aCornerRadius; + + if( aErrorLoc == ERROR_OUTSIDE ) + radius += correction; + outline.Inflate( radius, numSegs ); - if( correction > 1.0 ) - { - // Refinement: clamp the inflated polygonal shape by the rectangular shape - // containing the rounded polygon - SHAPE_POLY_SET bbox; // the rectangular shape - bbox.NewOutline(); - - for( const wxPoint& corner : corners ) - bbox.Append( corner ); - - // Just build the rectangular bbox - bbox.Inflate( aCornerRadius, 1, SHAPE_POLY_SET::CORNER_STRATEGY::ALLOW_ACUTE_CORNERS ); - - // Now, clamp the shape - outline.BooleanIntersection( bbox, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE ); - // Note the final polygon is a simple, convex polygon with no hole - // due to the shape of initial polygons - } - if( aChamferCorners == RECT_NO_CHAMFER ) // no chamfer { // Add the outline: @@ -334,7 +323,7 @@ void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer, const void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCentre, wxPoint aStart, - double aArcAngle, int aError, int aWidth ) + double aArcAngle, int aWidth, int aError, ERROR_LOC aErrorLoc ) { wxPoint arc_start, arc_end; int dist = EuclideanNorm( aCentre - aStart ); @@ -360,34 +349,35 @@ void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCentre, wxPo { curr_end = arc_start; RotatePoint( &curr_end, aCentre, -ii ); - TransformOvalToPolygon( aCornerBuffer, curr_start, curr_end, aWidth, aError ); + TransformOvalToPolygon( aCornerBuffer, curr_start, curr_end, aWidth, aError, aErrorLoc ); curr_start = curr_end; } if( curr_end != arc_end ) - TransformOvalToPolygon( aCornerBuffer, curr_end, arc_end, aWidth, aError ); + TransformOvalToPolygon( aCornerBuffer, curr_end, arc_end, aWidth, aError, aErrorLoc ); } void TransformRingToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCentre, int aRadius, - int aError, int aWidth ) + int aWidth, int aError, ERROR_LOC aErrorLoc ) { int inner_radius = aRadius - ( aWidth / 2 ); int outer_radius = inner_radius + aWidth; if( inner_radius <= 0 ) { //In this case, the ring is just a circle (no hole inside) - TransformCircleToPolygon( aCornerBuffer, aCentre, aRadius + ( aWidth / 2 ), aError ); + TransformCircleToPolygon( aCornerBuffer, aCentre, aRadius + ( aWidth / 2 ), aError, + aErrorLoc ); return; } SHAPE_POLY_SET buffer; - TransformCircleToPolygon( buffer, aCentre, outer_radius, aError ); + TransformCircleToPolygon( buffer, aCentre, outer_radius, aError, aErrorLoc ); // Build the hole: buffer.NewHole(); - TransformCircleToPolygon( buffer.Hole( 0, 0 ), aCentre, inner_radius, aError ); + TransformCircleToPolygon( buffer.Hole( 0, 0 ), aCentre, inner_radius, aError, aErrorLoc ); buffer.Fracture( SHAPE_POLY_SET::PM_FAST ); aCornerBuffer.Append( buffer ); diff --git a/pcbnew/board_items_to_polygon_shape_transform.cpp b/pcbnew/board_items_to_polygon_shape_transform.cpp index d265132ab4..efcb58d98f 100644 --- a/pcbnew/board_items_to_polygon_shape_transform.cpp +++ b/pcbnew/board_items_to_polygon_shape_transform.cpp @@ -46,40 +46,48 @@ // These variables are parameters used in addTextSegmToPoly. // But addTextSegmToPoly is a call-back function, // so we cannot send them as arguments. -struct TSEGM_2_POLY_PRMS { +struct TSEGM_2_POLY_PRMS +{ int m_textWidth; int m_error; SHAPE_POLY_SET* m_cornerBuffer; }; + TSEGM_2_POLY_PRMS prms; + // This is a call back function, used by GRText to draw the 3D text shape: static void addTextSegmToPoly( int x0, int y0, int xf, int yf, void* aData ) { TSEGM_2_POLY_PRMS* prm = static_cast( aData ); TransformOvalToPolygon( *prm->m_cornerBuffer, wxPoint( x0, y0 ), wxPoint( xf, yf ), - prm->m_textWidth, prm->m_error ); + prm->m_textWidth, prm->m_error, ERROR_INSIDE ); } void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, SHAPE_POLY_SET& aOutlines ) { + int maxError = GetDesignSettings().m_MaxError; + // convert tracks and vias: for( auto track : m_tracks ) { if( !track->IsOnLayer( aLayer ) ) continue; - track->TransformShapeWithClearanceToPolygon( aOutlines, aLayer, 0 ); + track->TransformShapeWithClearanceToPolygon( aOutlines, aLayer, 0, maxError, + ERROR_INSIDE ); } // convert pads - for( auto module : m_modules ) + for( MODULE* module : m_modules ) { - module->TransformPadsShapesWithClearanceToPolygon( aLayer, aOutlines, 0 ); + module->TransformPadsShapesWithClearanceToPolygon( aOutlines, aLayer, 0, maxError, + ERROR_INSIDE ); // Micro-wave modules may have items on copper layers - module->TransformGraphicShapesWithClearanceToPolygonSet( aLayer, aOutlines, 0 ); + module->TransformGraphicShapesWithClearanceToPolygonSet( aOutlines, aLayer, 0, maxError, + ERROR_INSIDE ); } // convert copper zones @@ -90,7 +98,7 @@ void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, SHAPE_POLY_ } // convert graphic items on copper layers (texts) - for( auto item : m_drawings ) + for( BOARD_ITEM* item : m_drawings ) { if( !item->IsOnLayer( aLayer ) ) continue; @@ -98,11 +106,18 @@ void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, SHAPE_POLY_ switch( item->Type() ) { case PCB_SHAPE_T: - ( (PCB_SHAPE*) item )->TransformShapeWithClearanceToPolygon( aOutlines, aLayer, 0 ); + { + PCB_SHAPE* shape = static_cast( item ); + shape->TransformShapeWithClearanceToPolygon( aOutlines, aLayer, 0, maxError, + ERROR_INSIDE ); + } break; case PCB_TEXT_T: - ( (PCB_TEXT*) item )->TransformShapeWithClearanceToPolygonSet( aOutlines, 0 ); + { + PCB_TEXT* text = static_cast( item ); + text->TransformShapeWithClearanceToPolygonSet( aOutlines, 0, maxError, ERROR_INSIDE ); + } break; default: @@ -112,9 +127,9 @@ void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, SHAPE_POLY_ } -void MODULE::TransformPadsShapesWithClearanceToPolygon( PCB_LAYER_ID aLayer, - SHAPE_POLY_SET& aCornerBuffer, - int aInflateValue, int aMaxError, +void MODULE::TransformPadsShapesWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, + PCB_LAYER_ID aLayer, int aClearance, + int aMaxError, ERROR_LOC aErrorLoc, bool aSkipNPTHPadsWihNoCopper, bool aSkipPlatedPads, bool aSkipNonPlatedPads ) const @@ -160,7 +175,7 @@ void MODULE::TransformPadsShapesWithClearanceToPolygon( PCB_LAYER_ID aLayer, if( aSkipNonPlatedPads && !isPlated ) continue; - wxSize clearance( aInflateValue, aInflateValue ); + wxSize clearance( aClearance, aClearance ); switch( aLayer ) { @@ -191,12 +206,13 @@ void MODULE::TransformPadsShapesWithClearanceToPolygon( PCB_LAYER_ID aLayer, { D_PAD dummy( *pad ); dummy.SetSize( pad->GetSize() + clearance + clearance ); - dummy.TransformShapeWithClearanceToPolygon( aCornerBuffer, aLayer, 0, aMaxError ); + dummy.TransformShapeWithClearanceToPolygon( aCornerBuffer, aLayer, 0, + aMaxError, aErrorLoc ); } else { pad->TransformShapeWithClearanceToPolygon( aCornerBuffer, aLayer, clearance.x, - aMaxError ); + aMaxError, aErrorLoc ); } } } @@ -209,10 +225,9 @@ void MODULE::TransformPadsShapesWithClearanceToPolygon( PCB_LAYER_ID aLayer, * @aIncludeText = indicates footprint text items (reference, value, etc.) should be included * in the outline */ -void MODULE::TransformGraphicShapesWithClearanceToPolygonSet( PCB_LAYER_ID aLayer, - SHAPE_POLY_SET& aCornerBuffer, - int aInflateValue, - int aError, +void MODULE::TransformGraphicShapesWithClearanceToPolygonSet( SHAPE_POLY_SET& aCornerBuffer, + PCB_LAYER_ID aLayer, int aClearance, + int aError, ERROR_LOC aErrorLoc, bool aIncludeText, bool aIncludeEdges ) const { @@ -233,7 +248,10 @@ void MODULE::TransformGraphicShapesWithClearanceToPolygonSet( PCB_LAYER_ID aLaye FP_SHAPE* outline = static_cast( item ); if( aLayer != UNDEFINED_LAYER && outline->GetLayer() == aLayer ) - outline->TransformShapeWithClearanceToPolygon( aCornerBuffer, aLayer, 0, aError ); + { + outline->TransformShapeWithClearanceToPolygon( aCornerBuffer, aLayer, 0, + aError, aErrorLoc ); + } } } @@ -253,7 +271,7 @@ void MODULE::TransformGraphicShapesWithClearanceToPolygonSet( PCB_LAYER_ID aLaye bool forceBold = true; int penWidth = 0; // force max width for bold text - prms.m_textWidth = textmod->GetEffectiveTextPenWidth() + ( 2 * aInflateValue ); + prms.m_textWidth = textmod->GetEffectiveTextPenWidth() + ( 2 * aClearance ); prms.m_error = aError; wxSize size = textmod->GetTextSize(); @@ -339,7 +357,8 @@ void EDA_TEXT::TransformBoundingBoxWithClearanceToPolygon( SHAPE_POLY_SET* aCorn * @aError = the maximum error to allow when approximating curves */ void PCB_TEXT::TransformShapeWithClearanceToPolygonSet( SHAPE_POLY_SET& aCornerBuffer, - int aClearanceValue, int aError ) const + int aClearanceValue, + int aError, ERROR_LOC aErrorLoc ) const { wxSize size = GetTextSize(); @@ -378,8 +397,8 @@ void PCB_TEXT::TransformShapeWithClearanceToPolygonSet( SHAPE_POLY_SET& aCornerB void PCB_SHAPE::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, - PCB_LAYER_ID aLayer, - int aClearanceValue, int aError, + PCB_LAYER_ID aLayer, int aClearanceValue, + int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth ) const { int width = ignoreLineWidth ? 0 : m_Width; @@ -397,9 +416,15 @@ void PCB_SHAPE::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuf { case S_CIRCLE: if( width == 0 ) - TransformCircleToPolygon( aCornerBuffer, GetCenter(), GetRadius(), aError ); + { + TransformCircleToPolygon( aCornerBuffer, GetCenter(), GetRadius(), aError, + aErrorLoc ); + } else - TransformRingToPolygon( aCornerBuffer, GetCenter(), GetRadius(), aError, width ); + { + TransformRingToPolygon( aCornerBuffer, GetCenter(), GetRadius(), width, aError, + aErrorLoc ); + } break; case S_RECT: @@ -417,20 +442,21 @@ void PCB_SHAPE::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuf if( width > 0 ) { // Add in segments - TransformOvalToPolygon( aCornerBuffer, pts[0], pts[1], width, aError ); - TransformOvalToPolygon( aCornerBuffer, pts[1], pts[2], width, aError ); - TransformOvalToPolygon( aCornerBuffer, pts[2], pts[3], width, aError ); - TransformOvalToPolygon( aCornerBuffer, pts[3], pts[0], width, aError ); + TransformOvalToPolygon( aCornerBuffer, pts[0], pts[1], width, aError, aErrorLoc ); + TransformOvalToPolygon( aCornerBuffer, pts[1], pts[2], width, aError, aErrorLoc ); + TransformOvalToPolygon( aCornerBuffer, pts[2], pts[3], width, aError, aErrorLoc ); + TransformOvalToPolygon( aCornerBuffer, pts[3], pts[0], width, aError, aErrorLoc ); } } break; case S_ARC: - TransformArcToPolygon( aCornerBuffer, GetCenter(), GetArcStart(), m_Angle, aError, width ); + TransformArcToPolygon( aCornerBuffer, GetCenter(), GetArcStart(), m_Angle, width, + aError, aErrorLoc ); break; case S_SEGMENT: - TransformOvalToPolygon( aCornerBuffer, m_Start, m_End, width, aError ); + TransformOvalToPolygon( aCornerBuffer, m_Start, m_End, width, aError, aErrorLoc ); break; case S_POLYGON: @@ -470,7 +496,10 @@ void PCB_SHAPE::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuf for( wxPoint pt2 : poly ) { if( pt2 != pt1 ) - TransformOvalToPolygon( aCornerBuffer, pt1, pt2, width, aError ); + { + TransformOvalToPolygon( aCornerBuffer, pt1, pt2, width, + aError, aErrorLoc ); + } pt1 = pt2; } @@ -488,7 +517,10 @@ void PCB_SHAPE::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuf if( width != 0 ) { for( unsigned ii = 1; ii < poly.size(); ii++ ) - TransformOvalToPolygon( aCornerBuffer, poly[ii-1], poly[ii], width, aError ); + { + TransformOvalToPolygon( aCornerBuffer, poly[ii-1], poly[ii], width, + aError, aErrorLoc ); + } } } break; @@ -502,8 +534,8 @@ void PCB_SHAPE::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuf void TRACK::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, - PCB_LAYER_ID aLayer, - int aClearanceValue, int aError, + PCB_LAYER_ID aLayer, int aClearanceValue, + int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth ) const { wxASSERT_MSG( !ignoreLineWidth, "IgnoreLineWidth has no meaning for tracks." ); @@ -514,7 +546,7 @@ void TRACK::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, case PCB_VIA_T: { int radius = ( m_Width / 2 ) + aClearanceValue; - TransformCircleToPolygon( aCornerBuffer, m_Start, radius, aError ); + TransformCircleToPolygon( aCornerBuffer, m_Start, radius, aError, aErrorLoc ); } break; @@ -525,7 +557,8 @@ void TRACK::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, VECTOR2D center( arc->GetCenter() ); double angle = arc->GetAngle(); - TransformArcToPolygon( aCornerBuffer, (wxPoint) center, GetStart(), angle, aError, width ); + TransformArcToPolygon( aCornerBuffer, (wxPoint) center, GetStart(), angle, width, + aError, aErrorLoc ); } break; @@ -533,7 +566,7 @@ void TRACK::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, { int width = m_Width + ( 2 * aClearanceValue ); - TransformOvalToPolygon( aCornerBuffer, m_Start, m_End, width, aError ); + TransformOvalToPolygon( aCornerBuffer, m_Start, m_End, width, aError, aErrorLoc ); } break; } @@ -541,8 +574,8 @@ void TRACK::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, void D_PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, - PCB_LAYER_ID aLayer, - int aClearanceValue, int aError, + PCB_LAYER_ID aLayer, int aClearanceValue, + int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth ) const { wxASSERT_MSG( !ignoreLineWidth, "IgnoreLineWidth has no meaning for pads." ); @@ -564,7 +597,8 @@ void D_PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, case PAD_SHAPE_OVAL: if( dx == dy ) { - TransformCircleToPolygon( aCornerBuffer, padShapePos, dx + aClearanceValue, aError ); + TransformCircleToPolygon( aCornerBuffer, padShapePos, dx + aClearanceValue, aError, + aErrorLoc ); } else { @@ -574,7 +608,7 @@ void D_PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, RotatePoint( &delta, angle ); TransformOvalToPolygon( aCornerBuffer, padShapePos - delta, padShapePos + delta, - ( half_width + aClearanceValue ) * 2, aError ); + ( half_width + aClearanceValue ) * 2, aError, aErrorLoc ); } break; @@ -619,19 +653,19 @@ void D_PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, case PAD_SHAPE_CHAMFERED_RECT: case PAD_SHAPE_ROUNDRECT: { - int radius = GetRoundRectCornerRadius() + aClearanceValue; - int clearance = aClearanceValue + GetCircleToPolyCorrection( aError ); + int radius = GetRoundRectCornerRadius(); wxSize shapesize( m_size ); + bool doChamfer = GetShape() == PAD_SHAPE_CHAMFERED_RECT; - radius = radius + GetCircleToPolyCorrection( aError ); - shapesize.x += clearance * 2; - shapesize.y += clearance * 2; - bool doChamfer = GetShape() == PAD_SHAPE_CHAMFERED_RECT; + radius += aClearanceValue; + shapesize.x += aClearanceValue * 2; + shapesize.y += aClearanceValue * 2; SHAPE_POLY_SET outline; TransformRoundChamferedRectToPolygon( outline, padShapePos, shapesize, angle, radius, doChamfer ? GetChamferRectRatio() : 0.0, - doChamfer ? GetChamferPositions() : 0, aError ); + doChamfer ? GetChamferPositions() : 0, + aError, aErrorLoc ); aCornerBuffer.Append( outline ); } @@ -648,7 +682,10 @@ void D_PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, { int numSegs = std::max( GetArcToSegmentCount( aClearanceValue, aError, 360.0 ), pad_min_seg_per_circle_count ); - int clearance = aClearanceValue + GetCircleToPolyCorrection( aError ); + int clearance = aClearanceValue; + + if( aErrorLoc == ERROR_OUTSIDE ) + clearance += GetCircleToPolyCorrection( aError ); outline.Inflate( clearance, numSegs ); outline.Simplify( SHAPE_POLY_SET::PM_FAST ); @@ -669,7 +706,7 @@ void D_PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, bool D_PAD::TransformHoleWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, int aInflateValue, - int aError ) const + int aError, ERROR_LOC aErrorLoc ) const { wxSize drillsize = GetDrillSize(); @@ -679,7 +716,7 @@ bool D_PAD::TransformHoleWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, const SHAPE_SEGMENT* seg = GetEffectiveHoleShape(); TransformOvalToPolygon( aCornerBuffer, (wxPoint) seg->GetSeg().A, (wxPoint) seg->GetSeg().B, - seg->GetWidth() + aInflateValue * 2, aError ); + seg->GetWidth() + aInflateValue * 2, aError, aErrorLoc ); return true; } @@ -687,7 +724,8 @@ bool D_PAD::TransformHoleWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, void ZONE_CONTAINER::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, PCB_LAYER_ID aLayer, int aClearance, - int aError, bool ignoreLineWidth ) const + int aError, ERROR_LOC aErrorLoc, + bool ignoreLineWidth ) const { wxASSERT_MSG( !ignoreLineWidth, "IgnoreLineWidth has no meaning for zones." ); diff --git a/pcbnew/class_board.h b/pcbnew/class_board.h index f7100a5caf..f86c25b887 100644 --- a/pcbnew/class_board.h +++ b/pcbnew/class_board.h @@ -598,12 +598,9 @@ public: wxPoint* aErrorLocation = nullptr ); /** - * Build a set of polygons which are the outlines of copper items - * (pads, tracks, vias, texts, zones) - * Holes in vias or pads are ignored - * Useful to export the shape of copper layers to dxf polygons - * or 3D viewer - * the polygons are not merged. + * Build a set of polygons which are the outlines of copper items (pads, tracks, vias, texts, + * zones). Holes in vias or pads are ignored. The polygons are not merged. + * Useful to export the shape of copper layers to dxf polygons or 3D viewer * @param aLayer = A copper layer, like B_Cu, etc. * @param aOutlines The SHAPE_POLY_SET to fill in with items outline. */ diff --git a/pcbnew/class_board_item.cpp b/pcbnew/class_board_item.cpp index b44068908f..c18db4588c 100644 --- a/pcbnew/class_board_item.cpp +++ b/pcbnew/class_board_item.cpp @@ -128,8 +128,8 @@ void BOARD_ITEM::SwapData( BOARD_ITEM* aImage ) void BOARD_ITEM::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, - PCB_LAYER_ID aLayer, - int aClearanceValue, int aError, + PCB_LAYER_ID aLayer, int aClearanceValue, + int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth ) const { wxASSERT_MSG( false, "Called TransformShapeWithClearanceToPolygon() on unsupported BOARD_ITEM." ); diff --git a/pcbnew/class_module.h b/pcbnew/class_module.h index 1129c83419..aaeaa3103a 100644 --- a/pcbnew/class_module.h +++ b/pcbnew/class_module.h @@ -349,8 +349,7 @@ public: * when a full polygonal approach is needed * @param aLayer = the layer to consider, or UNDEFINED_LAYER to consider all * @param aCornerBuffer = the buffer to store polygons - * @param aInflateValue = an additionnal size to add to pad shapes - * aInflateValue = 0 to have the exact pad size + * @param aClearance = an additionnal size to add to pad shapes * @param aMaxError = Maximum deviation from true for arcs * @param aSkipNPTHPadsWihNoCopper = if true, do not add a NPTH pad shape, if the shape has * same size and position as the hole. Usually, these pads are not drawn on copper @@ -361,11 +360,12 @@ public: * @param aSkipPlatedPads = used on 3D-Viewer to extract plated and nontplated pads. * @param aSkipNonPlatedPads = used on 3D-Viewer to extract plated and plated pads. */ - void TransformPadsShapesWithClearanceToPolygon(PCB_LAYER_ID aLayer, - SHAPE_POLY_SET& aCornerBuffer, int aInflateValue, int aMaxError = ARC_HIGH_DEF, - bool aSkipNPTHPadsWihNoCopper = false, - bool aSkipPlatedPads = false, - bool aSkipNonPlatedPads = false ) const; + void TransformPadsShapesWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, + PCB_LAYER_ID aLayer,int aClearance, + int aMaxError, ERROR_LOC aErrorLoc, + bool aSkipNPTHPadsWihNoCopper = false, + bool aSkipPlatedPads = false, + bool aSkipNonPlatedPads = false ) const; /** * function TransformGraphicShapesWithClearanceToPolygonSet @@ -375,26 +375,28 @@ public: * when a full polygonal approach is needed * @param aLayer = the layer to consider, or UNDEFINED_LAYER to consider all * @param aCornerBuffer = the buffer to store polygons - * @param aInflateValue = a value to inflate shapes - * aInflateValue = 0 to have the exact shape size + * @param aClearance = a value to inflate shapes * @param aError = Maximum error between true arc and polygon approx * @param aIncludeText = True to transform text shapes * @param aIncludeEdges = True to transform module shapes */ - void TransformGraphicShapesWithClearanceToPolygonSet( PCB_LAYER_ID aLayer, - SHAPE_POLY_SET& aCornerBuffer, int aInflateValue, int aError = ARC_HIGH_DEF, - bool aIncludeText = true, bool aIncludeEdges = true ) const; + void TransformGraphicShapesWithClearanceToPolygonSet( SHAPE_POLY_SET& aCornerBuffer, + PCB_LAYER_ID aLayer, int aClearance, + int aError, ERROR_LOC aErrorLoc, + bool aIncludeText = true, + bool aIncludeEdges = true ) const; /** * @brief TransformGraphicTextWithClearanceToPolygonSet * This function is the same as TransformGraphicShapesWithClearanceToPolygonSet * but only generate text */ - void TransformGraphicTextWithClearanceToPolygonSet( PCB_LAYER_ID aLayer, - SHAPE_POLY_SET& aCornerBuffer, int aInflateValue, int aError = ARC_HIGH_DEF ) const + void TransformGraphicTextWithClearanceToPolygonSet( SHAPE_POLY_SET& aCornerBuffer, + PCB_LAYER_ID aLayer, int aClearance, + int aError, ERROR_LOC aErrorLoc ) const { - TransformGraphicShapesWithClearanceToPolygonSet( aLayer, aCornerBuffer, aInflateValue, - aError, true, false ); + TransformGraphicShapesWithClearanceToPolygonSet( aCornerBuffer, aLayer, aClearance, + aError, aErrorLoc, true, false ); } /** diff --git a/pcbnew/class_pad.cpp b/pcbnew/class_pad.cpp index 11c6b54787..df657ec38f 100644 --- a/pcbnew/class_pad.cpp +++ b/pcbnew/class_pad.cpp @@ -287,6 +287,9 @@ int D_PAD::GetBoundingRadius() const void D_PAD::BuildEffectiveShapes( PCB_LAYER_ID aLayer ) const { + BOARD* board = GetBoard(); + int maxError = board ? board->GetDesignSettings().m_MaxError : ARC_HIGH_DEF; + m_effectiveShape = std::make_shared(); m_effectiveHoleShape = nullptr; @@ -385,15 +388,10 @@ void D_PAD::BuildEffectiveShapes( PCB_LAYER_ID aLayer ) const case PAD_SHAPE_CHAMFERED_RECT: { SHAPE_POLY_SET outline; - auto board = GetBoard(); - int maxError = ARC_HIGH_DEF; - - if( board ) - maxError = board->GetDesignSettings().m_MaxError; TransformRoundChamferedRectToPolygon( outline, shapePos, GetSize(), m_orient, GetRoundRectCornerRadius(), GetChamferRectRatio(), - GetChamferPositions(), maxError ); + GetChamferPositions(), maxError, ERROR_INSIDE ); add( new SHAPE_SIMPLE( outline.COutline( 0 ) ) ); } @@ -421,7 +419,7 @@ void D_PAD::BuildEffectiveShapes( PCB_LAYER_ID aLayer ) const // Polygon // m_effectivePolygon = std::make_shared(); - TransformShapeWithClearanceToPolygon( *m_effectivePolygon, aLayer, 0 ); + TransformShapeWithClearanceToPolygon( *m_effectivePolygon, aLayer, 0, maxError, ERROR_INSIDE ); // Bounding box and radius // diff --git a/pcbnew/class_pad.h b/pcbnew/class_pad.h index 195e73f1e8..67e2df1261 100644 --- a/pcbnew/class_pad.h +++ b/pcbnew/class_pad.h @@ -372,10 +372,12 @@ public: * @param aCornerBuffer = a buffer to store the polygon * @param aClearanceValue = the clearance around the pad * @param aMaxError = maximum error from true when converting arcs + * @param aErrorLoc = should the approximation error be placed outside or inside the polygon? * @param ignoreLineWidth = used for edge cuts where the line width is only for visualization */ - void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, PCB_LAYER_ID aLayer, - int aClearanceValue, int aMaxError = ARC_HIGH_DEF, + void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, + PCB_LAYER_ID aLayer, int aClearanceValue, + int aMaxError, ERROR_LOC aErrorLoc, bool ignoreLineWidth = false ) const override; /** @@ -384,10 +386,11 @@ public: * @param aCornerBuffer = a buffer to fill. * @param aInflateValue = the clearance or margin value. * @param aError = maximum deviation of an arc from the polygon approximation + * @param aErrorLoc = should the approximation error be placed outside or inside the polygon? * @return false if the pad has no hole, true otherwise */ bool TransformHoleWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, int aInflateValue, - int aError = ARC_HIGH_DEF ) const; + int aError, ERROR_LOC aErrorLoc ) const; // @copydoc BOARD_ITEM::GetEffectiveShape virtual std::shared_ptr GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const override; @@ -634,7 +637,7 @@ public: private: void addPadPrimitivesToPolygon( SHAPE_POLY_SET* aMergedPolygon, PCB_LAYER_ID aLayer, - int aError ) const; + int aError, ERROR_LOC aErrorLoc ) const; private: wxString m_name; // Pad name (pin number in schematic) diff --git a/pcbnew/class_track.h b/pcbnew/class_track.h index dd7c4b48dc..2fdc7caba9 100644 --- a/pcbnew/class_track.h +++ b/pcbnew/class_track.h @@ -164,8 +164,9 @@ public: * @param ignoreLineWidth = used for edge cut items where the line width is only * for visualization */ - void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, PCB_LAYER_ID aLayer, - int aClearanceValue, int aError = ARC_HIGH_DEF, + void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, + PCB_LAYER_ID aLayer, int aClearanceValue, + int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth = false ) const override; // @copydoc BOARD_ITEM::GetEffectiveShape diff --git a/pcbnew/class_zone.h b/pcbnew/class_zone.h index e0843b2a1b..4893503cb7 100644 --- a/pcbnew/class_zone.h +++ b/pcbnew/class_zone.h @@ -386,8 +386,9 @@ public: * @param ignoreLineWidth = used for edge cut items where the line width is only * for visualization */ - void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, PCB_LAYER_ID aLayer, - int aClearanceValue, int aError = ARC_HIGH_DEF, + void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, + PCB_LAYER_ID aLayer, int aClearanceValue, + int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth = false ) const override; /** diff --git a/pcbnew/convert_drawsegment_list_to_polygon.cpp b/pcbnew/convert_drawsegment_list_to_polygon.cpp index ce32ce8fa5..414d35c553 100644 --- a/pcbnew/convert_drawsegment_list_to_polygon.cpp +++ b/pcbnew/convert_drawsegment_list_to_polygon.cpp @@ -338,7 +338,8 @@ bool ConvertOutlineToPolygon( std::vector& aSegList, SHAPE_POLY_SET& // Output the outline perimeter as polygon. if( graphic->GetShape() == S_CIRCLE ) { - TransformCircleToPolygon( aPolygons, graphic->GetCenter(), graphic->GetRadius(), aTolerance ); + TransformCircleToPolygon( aPolygons, graphic->GetCenter(), graphic->GetRadius(), + ARC_LOW_DEF, ERROR_INSIDE ); } else if( graphic->GetShape() == S_RECT ) { diff --git a/pcbnew/exporters/export_vrml.cpp b/pcbnew/exporters/export_vrml.cpp index 8eaf84b6d0..9428c1f4ec 100644 --- a/pcbnew/exporters/export_vrml.cpp +++ b/pcbnew/exporters/export_vrml.cpp @@ -1146,8 +1146,8 @@ static void export_vrml_padshape( MODEL_VRML& aModel, VRML_LAYER* aTinLayer, D_P { SHAPE_POLY_SET polySet; const int corner_radius = aPad->GetRoundRectCornerRadius(); - TransformRoundChamferedRectToPolygon( polySet, wxPoint( 0, 0 ), aPad->GetSize(), - 0.0, corner_radius, 0.0, 0, ARC_HIGH_DEF ); + TransformRoundChamferedRectToPolygon( polySet, wxPoint( 0, 0 ), aPad->GetSize(), 0.0, + corner_radius, 0.0, 0, ARC_HIGH_DEF, ERROR_INSIDE ); 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 7f115dc7aa..000ee212dd 100644 --- a/pcbnew/pad_custom_shape_functions.cpp +++ b/pcbnew/pad_custom_shape_functions.cpp @@ -173,12 +173,12 @@ void D_PAD::DeletePrimitivesList() void D_PAD::addPadPrimitivesToPolygon( SHAPE_POLY_SET* aMergedPolygon, PCB_LAYER_ID aLayer, - int aError ) const + int aError, ERROR_LOC aErrorLoc ) const { SHAPE_POLY_SET polyset; for( const std::shared_ptr& primitive : m_editPrimitives ) - primitive->TransformShapeWithClearanceToPolygon( polyset, aLayer, 0, aError ); + primitive->TransformShapeWithClearanceToPolygon( polyset, aLayer, 0, aError, aErrorLoc ); polyset.Simplify( SHAPE_POLY_SET::PM_FAST ); @@ -192,11 +192,8 @@ void D_PAD::addPadPrimitivesToPolygon( SHAPE_POLY_SET* aMergedPolygon, PCB_LAYER void D_PAD::MergePrimitivesAsPolygon( SHAPE_POLY_SET* aMergedPolygon, PCB_LAYER_ID aLayer ) const { - auto board = GetBoard(); - int maxError = ARC_HIGH_DEF; - - if( board ) - maxError = board->GetDesignSettings().m_MaxError; + BOARD* board = GetBoard(); + int maxError = board ? board->GetDesignSettings().m_MaxError: ARC_HIGH_DEF; aMergedPolygon->RemoveAllContours(); @@ -213,18 +210,19 @@ void D_PAD::MergePrimitivesAsPolygon( SHAPE_POLY_SET* aMergedPolygon, PCB_LAYER_ default: case PAD_SHAPE_CIRCLE: - TransformCircleToPolygon( *aMergedPolygon, wxPoint( 0, 0 ), GetSize().x / 2, maxError ); + TransformCircleToPolygon( *aMergedPolygon, wxPoint( 0, 0 ), GetSize().x / 2, maxError, + ERROR_INSIDE ); break; } - addPadPrimitivesToPolygon( aMergedPolygon, aLayer, maxError ); + addPadPrimitivesToPolygon( aMergedPolygon, aLayer, maxError, ERROR_INSIDE ); } bool D_PAD::GetBestAnchorPosition( VECTOR2I& aPos ) { SHAPE_POLY_SET poly; - addPadPrimitivesToPolygon( &poly, UNDEFINED_LAYER, ARC_LOW_DEF ); + addPadPrimitivesToPolygon( &poly, UNDEFINED_LAYER, ARC_LOW_DEF, ERROR_INSIDE ); if( poly.OutlineCount() > 1 ) return false; diff --git a/pcbnew/pcb_expr_evaluator.cpp b/pcbnew/pcb_expr_evaluator.cpp index f06214effc..d1369b6ded 100644 --- a/pcbnew/pcb_expr_evaluator.cpp +++ b/pcbnew/pcb_expr_evaluator.cpp @@ -186,7 +186,8 @@ static void insideCourtyard( LIBEVAL::CONTEXT* aCtx, void* self ) SHAPE_POLY_SET testPoly; - item->TransformShapeWithClearanceToPolygon( testPoly, context->GetLayer(), 0 ); + item->TransformShapeWithClearanceToPolygon( testPoly, context->GetLayer(), 0, + ARC_LOW_DEF, ERROR_INSIDE ); testPoly.BooleanIntersection( footprintCourtyard, SHAPE_POLY_SET::PM_FAST ); if( testPoly.OutlineCount() ) @@ -242,7 +243,8 @@ static void insideArea( LIBEVAL::CONTEXT* aCtx, void* self ) { SHAPE_POLY_SET testPoly; - item->TransformShapeWithClearanceToPolygon( testPoly, context->GetLayer(), 0 ); + item->TransformShapeWithClearanceToPolygon( testPoly, context->GetLayer(), 0, + ARC_LOW_DEF, ERROR_INSIDE ); testPoly.BooleanIntersection( *zone->Outline(), SHAPE_POLY_SET::PM_FAST ); if( testPoly.OutlineCount() ) diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp index aa28ffda61..e88ee01411 100644 --- a/pcbnew/pcb_painter.cpp +++ b/pcbnew/pcb_painter.cpp @@ -858,7 +858,8 @@ void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer ) } // Pad drawing - COLOR4D color; + BOARD_DESIGN_SETTINGS& bds = aPad->GetBoard()->GetDesignSettings(); + COLOR4D color; // Pad hole color is pad-type-specific: the background color for plated holes and the // pad color for NPTHs. Note the extra check for "should be" NPTHs to keep mis-marked @@ -947,7 +948,8 @@ void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer ) else { SHAPE_POLY_SET polySet; - aPad->TransformShapeWithClearanceToPolygon( polySet, ToLAYER_ID( aLayer ), margin.x ); + aPad->TransformShapeWithClearanceToPolygon( polySet, ToLAYER_ID( aLayer ), margin.x, + bds.m_MaxError, ERROR_INSIDE ); m_gal->DrawPolygon( polySet ); } @@ -991,13 +993,14 @@ void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer ) { SHAPE_POLY_SET polySet; aPad->TransformShapeWithClearanceToPolygon( polySet, ToLAYER_ID( aLayer ), - clearance ); + clearance, + bds.m_MaxError, ERROR_OUTSIDE ); m_gal->DrawPolygon( polySet ); } } else if( aPad->GetEffectiveHoleShape() ) { - clearance += aPad->GetBoard()->GetDesignSettings().GetHolePlatingThickness(); + clearance += bds.GetHolePlatingThickness(); const SHAPE_SEGMENT* seg = aPad->GetEffectiveHoleShape(); m_gal->DrawSegment( seg->GetSeg().A, seg->GetSeg().B, diff --git a/pcbnew/pcb_shape.h b/pcbnew/pcb_shape.h index 37658dfeac..cfbb456f73 100644 --- a/pcbnew/pcb_shape.h +++ b/pcbnew/pcb_shape.h @@ -311,8 +311,9 @@ public: * @param ignoreLineWidth = used for edge cut items where the line width is only * for visualization */ - void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, PCB_LAYER_ID aLayer, - int aClearanceValue, int aError = ARC_HIGH_DEF, + void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, + PCB_LAYER_ID aLayer, int aClearanceValue, + int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth = false ) const override; virtual wxString GetSelectMenuText( EDA_UNITS aUnits ) const override; diff --git a/pcbnew/pcb_text.h b/pcbnew/pcb_text.h index fcbb3dd534..149a16a4fe 100644 --- a/pcbnew/pcb_text.h +++ b/pcbnew/pcb_text.h @@ -116,11 +116,11 @@ public: * Used in 3D viewer * Circles and arcs are approximated by segments * @param aCornerBuffer = a buffer to store the polygon - * @param aClearanceValue = the clearance around the text + * @param aClearance = the clearance around the text * @param aError = deviation from true arc position to segment approx */ - void TransformShapeWithClearanceToPolygonSet( - SHAPE_POLY_SET& aCornerBuffer, int aClearanceValue, int aError = ARC_HIGH_DEF ) const; + void TransformShapeWithClearanceToPolygonSet( SHAPE_POLY_SET& aCornerBuffer, int aClearance, + int aError, ERROR_LOC aErrorLoc ) const; // @copydoc BOARD_ITEM::GetEffectiveShape virtual std::shared_ptr GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const override; diff --git a/pcbnew/plot_board_layers.cpp b/pcbnew/plot_board_layers.cpp index 797a0cdd02..84a4f905aa 100644 --- a/pcbnew/plot_board_layers.cpp +++ b/pcbnew/plot_board_layers.cpp @@ -756,6 +756,7 @@ void PlotLayerOutlines( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask, void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask, const PCB_PLOT_PARAMS& aPlotOpt, int aMinThickness ) { + int maxError = aBoard->GetDesignSettings().m_MaxError; PCB_LAYER_ID layer = aLayerMask[B_Mask] ? B_Mask : F_Mask; SHAPE_POLY_SET buffer; SHAPE_POLY_SET* boardOutline = nullptr; @@ -763,14 +764,10 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask, if( aBoard->GetBoardPolygonOutlines( buffer ) ) boardOutline = &buffer; - // Set the current arc to segment max approx error - int currMaxError = aBoard->GetDesignSettings().m_MaxError; - aBoard->GetDesignSettings().m_MaxError = Millimeter2iu( 0.005 ); - // We remove 1nm as we expand both sides of the shapes, so allowing for // a strictly greater than or equal comparison in the shape separation (boolean add) // means that we will end up with separate shapes that then are shrunk - int inflate = aMinThickness/2 - 1; + int inflate = aMinThickness/2 - 1; BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt ); itemplotter.SetLayerSet( aLayerMask ); @@ -814,9 +811,11 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask, for( MODULE* module : aBoard->Modules() ) { // add shapes with their exact mask layer size in initialPolys - module->TransformPadsShapesWithClearanceToPolygon( layer, initialPolys, 0 ); + module->TransformPadsShapesWithClearanceToPolygon( initialPolys, layer, 0, maxError, + ERROR_OUTSIDE ); // add shapes inflated by aMinThickness/2 in areas - module->TransformPadsShapesWithClearanceToPolygon( layer, areas, inflate ); + module->TransformPadsShapesWithClearanceToPolygon( areas, layer, inflate, maxError, + ERROR_OUTSIDE ); } // Plot vias on solder masks, if aPlotOpt.GetPlotViaOnMaskLayer() is true, @@ -846,9 +845,11 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask, continue; // add shapes with their exact mask layer size in initialPolys - via->TransformShapeWithClearanceToPolygon( initialPolys, layer, via_clearance ); + via->TransformShapeWithClearanceToPolygon( initialPolys, layer, via_clearance, + maxError, ERROR_OUTSIDE ); // add shapes inflated by aMinThickness/2 in areas - via->TransformShapeWithClearanceToPolygon( areas, layer, via_margin ); + via->TransformShapeWithClearanceToPolygon( areas, layer, via_margin, maxError, + ERROR_OUTSIDE ); } } @@ -870,16 +871,12 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask, zone->TransformSmoothedOutlineToPolygon( initialPolys, zone_margin, boardOutline ); } - int maxError = aBoard->GetDesignSettings().m_MaxError; int numSegs = GetArcToSegmentCount( inflate, maxError, 360.0 ); // Merge all polygons: After deflating, not merged (not overlapping) polygons // will have the initial shape (with perhaps small changes due to deflating transform) areas.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE ); areas.Deflate( inflate, numSegs ); - - // Restore initial settings: - aBoard->GetDesignSettings().m_MaxError = currMaxError; } #if !NEW_ALGO diff --git a/pcbnew/plugins/altium/altium_pcb.cpp b/pcbnew/plugins/altium/altium_pcb.cpp index 93c881c4d4..a36597104e 100644 --- a/pcbnew/plugins/altium/altium_pcb.cpp +++ b/pcbnew/plugins/altium/altium_pcb.cpp @@ -1541,7 +1541,7 @@ void ALTIUM_PCB::ParseArcs6Data( const CFB::CompoundFileReader& aReader, zone->SetDoNotAllowCopperPour( true ); shape.TransformShapeWithClearanceToPolygon( *zone->Outline(), klayer, 0, ARC_HIGH_DEF, - false ); + ERROR_INSIDE ); zone->Outline()->Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE ); // the outline is not a single polygon! zone->SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE, @@ -2094,7 +2094,7 @@ void ALTIUM_PCB::ParseTracks6Data( const CFB::CompoundFileReader& aReader, zone->SetDoNotAllowCopperPour( true ); shape.TransformShapeWithClearanceToPolygon( *zone->Outline(), klayer, 0, ARC_HIGH_DEF, - false ); + ERROR_INSIDE ); zone->SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE, ZONE_CONTAINER::GetDefaultHatchPitch(), true ); diff --git a/pcbnew/specctra_import_export/specctra_export.cpp b/pcbnew/specctra_import_export/specctra_export.cpp index f97d6c41d9..4ee3e1c321 100644 --- a/pcbnew/specctra_import_export/specctra_export.cpp +++ b/pcbnew/specctra_import_export/specctra_export.cpp @@ -487,7 +487,8 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad ) 0, rradius, aPad->GetChamferRectRatio(), doChamfer ? aPad->GetChamferPositions() : 0, - aBoard->GetDesignSettings().m_MaxError ); + aBoard->GetDesignSettings().m_MaxError, + ERROR_INSIDE ); SHAPE_LINE_CHAIN& polygonal_shape = cornerBuffer.Outline( 0 ); for( int ndx=0; ndx < reportedLayers; ++ndx ) diff --git a/pcbnew/tools/pad_tool.cpp b/pcbnew/tools/pad_tool.cpp index 9b6d8b9920..b28bb459aa 100644 --- a/pcbnew/tools/pad_tool.cpp +++ b/pcbnew/tools/pad_tool.cpp @@ -613,31 +613,36 @@ PCB_LAYER_ID PAD_TOOL::explodePad( D_PAD* aPad ) void PAD_TOOL::recombinePad( D_PAD* aPad ) { - auto findNext = [&]( PCB_LAYER_ID aLayer ) -> FP_SHAPE* - { - SHAPE_POLY_SET padPoly; - aPad->TransformShapeWithClearanceToPolygon( padPoly, aLayer, 0 ); + int maxError = board()->GetDesignSettings().m_MaxError; - for( BOARD_ITEM* item : board()->GetFirstModule()->GraphicalItems() ) - { - PCB_SHAPE* draw = dynamic_cast( item ); + auto findNext = + [&]( PCB_LAYER_ID aLayer ) -> FP_SHAPE* + { + SHAPE_POLY_SET padPoly; + aPad->TransformShapeWithClearanceToPolygon( padPoly, aLayer, 0, maxError, + ERROR_INSIDE ); - if( !draw || ( draw->GetEditFlags() & STRUCT_DELETED ) ) - continue; + for( BOARD_ITEM* item : board()->GetFirstModule()->GraphicalItems() ) + { + PCB_SHAPE* draw = dynamic_cast( item ); - if( draw->GetLayer() != aLayer ) - continue; + if( !draw || ( draw->GetEditFlags() & STRUCT_DELETED ) ) + continue; - SHAPE_POLY_SET drawPoly; - draw->TransformShapeWithClearanceToPolygon( drawPoly, aLayer, 0 ); - drawPoly.BooleanIntersection( padPoly, SHAPE_POLY_SET::PM_FAST ); + if( draw->GetLayer() != aLayer ) + continue; - if( !drawPoly.IsEmpty() ) - return (FP_SHAPE*) item; - } + SHAPE_POLY_SET drawPoly; + draw->TransformShapeWithClearanceToPolygon( drawPoly, aLayer, 0, maxError, + ERROR_INSIDE ); + drawPoly.BooleanIntersection( padPoly, SHAPE_POLY_SET::PM_FAST ); - return nullptr; - }; + if( !drawPoly.IsEmpty() ) + return (FP_SHAPE*) item; + } + + return nullptr; + }; BOARD_COMMIT commit( frame() ); PCB_LAYER_ID layer; @@ -666,7 +671,8 @@ void PAD_TOOL::recombinePad( D_PAD* aPad ) // to a polygon primitive SHAPE_POLY_SET existingOutline; int maxError = board()->GetDesignSettings().m_MaxError; - aPad->TransformShapeWithClearanceToPolygon( existingOutline, layer, 0, maxError ); + aPad->TransformShapeWithClearanceToPolygon( existingOutline, layer, 0, maxError, + ERROR_INSIDE ); aPad->SetAnchorPadShape( PAD_SHAPE_CIRCLE ); wxSize minAnnulus( Millimeter2iu( 0.2 ), Millimeter2iu( 0.2 ) ); diff --git a/pcbnew/tracks_cleaner.cpp b/pcbnew/tracks_cleaner.cpp index 6133be2ad4..19cd213e0d 100644 --- a/pcbnew/tracks_cleaner.cpp +++ b/pcbnew/tracks_cleaner.cpp @@ -342,17 +342,18 @@ void TRACKS_CLEANER::deleteTracksInPads() if( pad->HitTest( track->GetStart() ) && pad->HitTest( track->GetEnd() ) ) { SHAPE_POLY_SET poly; - track->TransformShapeWithClearanceToPolygon( poly, track->GetLayer(), 0 ); + track->TransformShapeWithClearanceToPolygon( poly, track->GetLayer(), 0, + ARC_HIGH_DEF, ERROR_INSIDE ); poly.BooleanSubtract( *pad->GetEffectivePolygon(), SHAPE_POLY_SET::PM_FAST ); if( poly.IsEmpty() ) - { - std::shared_ptr item( new CLEANUP_ITEM( CLEANUP_TRACK_IN_PAD ) ); - item->SetItems( track ); - m_itemsList->push_back( item ); + { + std::shared_ptr item( new CLEANUP_ITEM( CLEANUP_TRACK_IN_PAD ) ); + item->SetItems( track ); + m_itemsList->push_back( item ); - toRemove.insert( track ); + toRemove.insert( track ); } } } diff --git a/pcbnew/zone_filler.cpp b/pcbnew/zone_filler.cpp index 1b8bcb5744..2b8eaaeacb 100644 --- a/pcbnew/zone_filler.cpp +++ b/pcbnew/zone_filler.cpp @@ -577,7 +577,8 @@ void ZONE_FILLER::addKnockout( D_PAD* aPad, PCB_LAYER_ID aLayer, int aGap, SHAPE if( aPad->GetShape() == PAD_SHAPE_CUSTOM ) { SHAPE_POLY_SET poly; - aPad->TransformShapeWithClearanceToPolygon( poly, aLayer, aGap, m_maxError ); + aPad->TransformShapeWithClearanceToPolygon( poly, aLayer, aGap, m_maxError, + ERROR_OUTSIDE ); // the pad shape in zone can be its convex hull or the shape itself if( aPad->GetCustomShapeInZoneOpt() == CUST_PAD_SHAPE_IN_ZONE_CONVEXHULL ) @@ -595,7 +596,8 @@ void ZONE_FILLER::addKnockout( D_PAD* aPad, PCB_LAYER_ID aLayer, int aGap, SHAPE } else { - aPad->TransformShapeWithClearanceToPolygon( aHoles, aLayer, aGap, m_maxError ); + aPad->TransformShapeWithClearanceToPolygon( aHoles, aLayer, aGap, m_maxError, + ERROR_OUTSIDE ); } } @@ -613,7 +615,7 @@ void ZONE_FILLER::addKnockout( BOARD_ITEM* aItem, PCB_LAYER_ID aLayer, int aGap, { PCB_SHAPE* shape = (PCB_SHAPE*) aItem; shape->TransformShapeWithClearanceToPolygon( aHoles, aLayer, aGap, m_maxError, - aIgnoreLineWidth ); + ERROR_OUTSIDE, aIgnoreLineWidth ); break; } case PCB_TEXT_T: @@ -626,7 +628,7 @@ void ZONE_FILLER::addKnockout( BOARD_ITEM* aItem, PCB_LAYER_ID aLayer, int aGap, { FP_SHAPE* shape = (FP_SHAPE*) aItem; shape->TransformShapeWithClearanceToPolygon( aHoles, aLayer, aGap, m_maxError, - aIgnoreLineWidth ); + ERROR_OUTSIDE, aIgnoreLineWidth ); break; } case PCB_FP_TEXT_T: @@ -790,16 +792,19 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE_CONTAINER* aZone, PCB_LA if( !via->FlashLayer( aLayer ) ) { int radius = via->GetDrillValue() / 2 + bds.GetHolePlatingThickness() + gap; - TransformCircleToPolygon( aHoles, via->GetPosition(), radius, m_maxError ); + TransformCircleToPolygon( aHoles, via->GetPosition(), radius, m_maxError, + ERROR_OUTSIDE ); } else { - via->TransformShapeWithClearanceToPolygon( aHoles, aLayer, gap, m_maxError ); + via->TransformShapeWithClearanceToPolygon( aHoles, aLayer, gap, m_maxError, + ERROR_OUTSIDE ); } } else { - track->TransformShapeWithClearanceToPolygon( aHoles, aLayer, gap, m_maxError ); + track->TransformShapeWithClearanceToPolygon( aHoles, aLayer, gap, m_maxError, + ERROR_OUTSIDE ); } } } @@ -872,7 +877,9 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE_CONTAINER* aZone, PCB_LA { // 6.0 uses filled areas with clearance SHAPE_POLY_SET poly; - aKnockout->TransformShapeWithClearanceToPolygon( poly, aLayer, gap ); + aKnockout->TransformShapeWithClearanceToPolygon( poly, aLayer, gap, + m_maxError, + ERROR_OUTSIDE ); aHoles.Append( poly ); } } @@ -1448,7 +1455,8 @@ void ZONE_FILLER::addHatchFillTypeOnZone( const ZONE_CONTAINER* aZone, PCB_LAYER int r = std::max( min_apron_radius, via->GetDrillValue() / 2 + outline_margin ); - TransformCircleToPolygon( aprons, via->GetPosition(), r, ARC_HIGH_DEF ); + TransformCircleToPolygon( aprons, via->GetPosition(), r, ARC_HIGH_DEF, + ERROR_OUTSIDE ); } } } @@ -1474,7 +1482,7 @@ void ZONE_FILLER::addHatchFillTypeOnZone( const ZONE_CONTAINER* aZone, PCB_LAYER clearance = std::max( 0, clearance - linethickness / 2 ); pad->TransformShapeWithClearanceToPolygon( aprons, aLayer, clearance, - ARC_HIGH_DEF ); + ARC_HIGH_DEF, ERROR_OUTSIDE ); } } } diff --git a/qa/pcbnew_tools/tools/polygon_generator/polygon_generator.cpp b/qa/pcbnew_tools/tools/polygon_generator/polygon_generator.cpp index a8a0149b25..a700466a3e 100644 --- a/qa/pcbnew_tools/tools/polygon_generator/polygon_generator.cpp +++ b/qa/pcbnew_tools/tools/polygon_generator/polygon_generator.cpp @@ -45,7 +45,8 @@ void process( const BOARD_CONNECTED_ITEM* item, int net ) SHAPE_POLY_SET pset; - item->TransformShapeWithClearanceToPolygon( pset, UNDEFINED_LAYER, 1, ARC_HIGH_DEF ); + item->TransformShapeWithClearanceToPolygon( pset, UNDEFINED_LAYER, 1, ARC_HIGH_DEF, + ERROR_OUTSIDE ); SHAPE_FILE_IO shapeIo; // default = stdout shapeIo.Write( &pset );