From ddc6079ceb931062dbe896b937cac5b26ae425de Mon Sep 17 00:00:00 2001 From: Seth Hillbrand Date: Tue, 14 May 2019 05:39:34 -0700 Subject: [PATCH] Move remaining hard-coded segment counts This removes the remaining hard-coded segments counts and replaces them with the relative error calculation where the segments per arc is determined by the maximum error we allow (smaller arcs = fewer segments) --- .../3d_canvas/create_3Dgraphic_brd_items.cpp | 25 +- 3d-viewer/3d_canvas/create_layer_items.cpp | 116 ++---- .../c3d_render_createscene_ogl_legacy.cpp | 9 +- common/CMakeLists.txt | 4 +- common/footprint_info.cpp | 1 - common/geometry/hetriang.cpp | 1 - common/preview_items/bright_box.cpp | 1 - common/tool/tool_base.cpp | 8 +- common/tool/tool_dispatcher.cpp | 7 +- common/tool/tool_manager.cpp | 2 +- common/tool/zoom_tool.cpp | 14 +- include/class_board_item.h | 11 +- include/eda_base_frame.h | 15 +- include/id.h | 2 + ...board_items_to_polygon_shape_transform.cpp | 379 +++++++----------- pcbnew/class_board_item.cpp | 7 +- pcbnew/class_drawsegment.h | 15 +- pcbnew/class_module.h | 55 +-- pcbnew/class_pad.cpp | 6 +- pcbnew/class_pad.h | 48 +-- pcbnew/class_pcb_text.h | 11 +- pcbnew/class_track.h | 17 +- pcbnew/class_zone.cpp | 32 +- pcbnew/class_zone.h | 25 +- pcbnew/drc.cpp | 12 +- pcbnew/exporters/export_vrml.cpp | 3 +- pcbnew/pad_custom_shape_functions.cpp | 69 ++-- pcbnew/pad_draw_functions.cpp | 35 +- pcbnew/pcb_painter.cpp | 10 +- pcbnew/plot_board_layers.cpp | 35 +- pcbnew/plot_brditems_plotter.cpp | 2 +- pcbnew/router/pns_kicad_iface.cpp | 8 +- pcbnew/zone_filler.cpp | 102 +++-- .../polygon_generator/polygon_generator.cpp | 9 +- 34 files changed, 404 insertions(+), 692 deletions(-) diff --git a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp index 3818043fbc..e4c719c169 100644 --- a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp +++ b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp @@ -836,12 +836,9 @@ void CINFO3D_VISU::AddShapeWithClearanceToContainer( const DRAWSEGMENT* aDrawSeg case S_CURVE: case S_POLYGON: { - const int segcountforcircle = ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF; - const double correctionFactor = GetCircleCorrectionFactor( segcountforcircle ); SHAPE_POLY_SET polyList; - aDrawSegment->TransformShapeWithClearanceToPolygon( polyList, aClearanceValue, - segcountforcircle, correctionFactor ); + aDrawSegment->TransformShapeWithClearanceToPolygon( polyList, aClearanceValue ); polyList.Simplify( SHAPE_POLY_SET::PM_FAST ); @@ -967,15 +964,7 @@ void CINFO3D_VISU::buildPadShapeThickOutlineAsSegments( const D_PAD* aPad, // For other shapes, draw polygon outlines SHAPE_POLY_SET corners; - - const int segcountforcircle = GetNrSegmentsCircle( glm::min( aPad->GetSize().x, - aPad->GetSize().y) ); - - const double correctionFactor = GetCircleCorrectionFactor( segcountforcircle ); - - aPad->BuildPadShapePolygon( corners, wxSize( 0, 0 ), - // This two factors are only expected to be used if render an oval - segcountforcircle, correctionFactor ); + aPad->BuildPadShapePolygon( corners, wxSize( 0, 0 ) ); // Add outlines as thick segments in polygon buffer @@ -992,15 +981,13 @@ void CINFO3D_VISU::buildPadShapeThickOutlineAsSegments( const D_PAD* aPad, if( Is_segment_a_circle( start3DU, end3DU ) ) { - aDstContainer->Add( new CFILLEDCIRCLE2D( start3DU, - (aWidth / 2) * m_biuTo3Dunits, - *aPad ) ); + aDstContainer->Add( + new CFILLEDCIRCLE2D( start3DU, ( aWidth / 2 ) * m_biuTo3Dunits, *aPad ) ); } else { - aDstContainer->Add( new CROUNDSEGMENT2D( start3DU, end3DU, - aWidth * m_biuTo3Dunits, - *aPad ) ); + aDstContainer->Add( + new CROUNDSEGMENT2D( start3DU, end3DU, aWidth * m_biuTo3Dunits, *aPad ) ); } } } diff --git a/3d-viewer/3d_canvas/create_layer_items.cpp b/3d-viewer/3d_canvas/create_layer_items.cpp index 313b470400..6259452d06 100644 --- a/3d-viewer/3d_canvas/create_layer_items.cpp +++ b/3d-viewer/3d_canvas/create_layer_items.cpp @@ -140,17 +140,6 @@ void CINFO3D_VISU::destroyLayers() void CINFO3D_VISU::createLayers( REPORTER *aStatusTextReporter ) { - // Number of segments to draw a circle using segments (used on countour zones - // and text copper elements ) - const int segcountforcircle = 12; - const double correctionFactor = GetCircleCorrectionFactor( segcountforcircle ); - - // segments to draw a circle to build texts. Is is used only to build - // the shape of each segment of the stroke font, therefore no need to have - // many segments per circle. - const int segcountInStrokeFont = 12; - const double correctionFactorStroke = GetCircleCorrectionFactor( segcountInStrokeFont ); - destroyLayers(); // Build Copper layers @@ -563,28 +552,16 @@ void CINFO3D_VISU::createLayers( REPORTER *aStatusTextReporter ) // The hole in the body is inflated by copper thickness. const int inflate = GetCopperThicknessBIU(); - // we use the hole diameter to calculate the seg count. - // for round holes, padHole.x == padHole.y - // for oblong holes, the diameter is the smaller of (padHole.x, padHole.y) - const int diam = std::min( padHole.x, padHole.y ); - - if( pad->GetAttribute () != PAD_ATTRIB_HOLE_NOT_PLATED ) { - pad->BuildPadDrillShapePolygon( m_through_outer_holes_poly, - inflate, - GetNrSegmentsCircle( diam ) ); + pad->BuildPadDrillShapePolygon( m_through_outer_holes_poly, inflate ); - pad->BuildPadDrillShapePolygon( m_through_inner_holes_poly, - 0, - GetNrSegmentsCircle( diam ) ); + pad->BuildPadDrillShapePolygon( m_through_inner_holes_poly, 0 ); } else { // If not plated, no copper. - pad->BuildPadDrillShapePolygon( m_through_outer_holes_poly_NPTH, - inflate, - GetNrSegmentsCircle( diam ) ); + pad->BuildPadDrillShapePolygon( m_through_outer_holes_poly_NPTH, inflate ); } } } @@ -656,11 +633,8 @@ void CINFO3D_VISU::createLayers( REPORTER *aStatusTextReporter ) true ); // Micro-wave modules may have items on copper layers - module->TransformGraphicTextWithClearanceToPolygonSet( curr_layer_id, - *layerPoly, - 0, - segcountforcircle, - correctionFactor ); + module->TransformGraphicTextWithClearanceToPolygonSet( + curr_layer_id, *layerPoly, 0 ); transformGraphicModuleEdgeToPolygonSet( module, curr_layer_id, *layerPoly ); } @@ -749,31 +723,17 @@ void CINFO3D_VISU::createLayers( REPORTER *aStatusTextReporter ) switch( item->Type() ) { case PCB_LINE_T: - { - const int nrSegments = - GetNrSegmentsCircle( item->GetBoundingBox().GetSizeMax() ); - - ( (DRAWSEGMENT*) item )->TransformShapeWithClearanceToPolygon( - *layerPoly, - 0, - nrSegments, - GetCircleCorrectionFactor( nrSegments ) ); - } - break; + ( (DRAWSEGMENT*) item )->TransformShapeWithClearanceToPolygon( *layerPoly, 0 ); + break; case PCB_TEXT_T: - ( (TEXTE_PCB*) item )->TransformShapeWithClearanceToPolygonSet( - *layerPoly, - 0, - segcountforcircle, - correctionFactor ); - break; + ( (TEXTE_PCB*) item )->TransformShapeWithClearanceToPolygonSet( *layerPoly, 0 ); + break; default: - wxLogTrace( m_logTrace, - wxT( "createLayers: item type: %d not implemented" ), - item->Type() ); - break; + wxLogTrace( m_logTrace, wxT( "createLayers: item type: %d not implemented" ), + item->Type() ); + break; } } } @@ -846,7 +806,7 @@ void CINFO3D_VISU::createLayers( REPORTER *aStatusTextReporter ) auto layerContainer = m_layers_poly.find( zone->GetLayer() ); if( layerContainer != m_layers_poly.end() ) - zone->TransformSolidAreasShapesToPolygonSet( *layerContainer->second, segcountforcircle, correctionFactor ); + zone->TransformSolidAreasShapesToPolygonSet( *layerContainer->second ); } } @@ -1034,22 +994,11 @@ void CINFO3D_VISU::createLayers( REPORTER *aStatusTextReporter ) switch( item->Type() ) { case PCB_LINE_T: - { - const unsigned int nr_segments = - GetNrSegmentsCircle( item->GetBoundingBox().GetSizeMax() ); - - ((DRAWSEGMENT*) item)->TransformShapeWithClearanceToPolygon( *layerPoly, - 0, - nr_segments, - 0.0 ); - } + ( (DRAWSEGMENT*) item )->TransformShapeWithClearanceToPolygon( *layerPoly, 0 ); break; case PCB_TEXT_T: - ((TEXTE_PCB*) item)->TransformShapeWithClearanceToPolygonSet( *layerPoly, - 0, - segcountInStrokeFont, - 1.0 ); + ( (TEXTE_PCB*) item )->TransformShapeWithClearanceToPolygonSet( *layerPoly, 0 ); break; default: @@ -1072,24 +1021,16 @@ void CINFO3D_VISU::createLayers( REPORTER *aStatusTextReporter ) if( !pad->IsOnLayer( curr_layer_id ) ) continue; - buildPadShapeThickOutlineAsSegments( pad, - layerContainer, - linewidth ); + buildPadShapeThickOutlineAsSegments( pad, layerContainer, linewidth ); } } else { - AddPadsShapesWithClearanceToContainer( module, - layerContainer, - curr_layer_id, - 0, - false ); + AddPadsShapesWithClearanceToContainer( + module, layerContainer, curr_layer_id, 0, false ); } - AddGraphicsShapesWithClearanceToContainer( module, - layerContainer, - curr_layer_id, - 0 ); + AddGraphicsShapesWithClearanceToContainer( module, layerContainer, curr_layer_id, 0 ); } @@ -1112,20 +1053,12 @@ void CINFO3D_VISU::createLayers( REPORTER *aStatusTextReporter ) } else { - transformPadsShapesWithClearanceToPolygon( module->PadsList(), - curr_layer_id, - *layerPoly, - 0, - false ); + transformPadsShapesWithClearanceToPolygon( + module->PadsList(), curr_layer_id, *layerPoly, 0, false ); } // On tech layers, use a poor circle approximation, only for texts (stroke font) - module->TransformGraphicTextWithClearanceToPolygonSet( curr_layer_id, - *layerPoly, - 0, - segcountInStrokeFont, - correctionFactorStroke, - segcountInStrokeFont ); + module->TransformGraphicTextWithClearanceToPolygonSet( curr_layer_id, *layerPoly, 0 ); // Add the remaining things with dynamic seg count for circles transformGraphicModuleEdgeToPolygonSet( module, curr_layer_id, *layerPoly ); @@ -1155,10 +1088,7 @@ void CINFO3D_VISU::createLayers( REPORTER *aStatusTextReporter ) if( !zone->IsOnLayer( curr_layer_id ) ) continue; - zone->TransformSolidAreasShapesToPolygonSet( *layerPoly, - // Use the same segcount as stroke font - segcountInStrokeFont, - correctionFactorStroke ); + zone->TransformSolidAreasShapesToPolygonSet( *layerPoly ); } } 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 c88e10acc7..239b8ae004 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 @@ -823,13 +823,10 @@ void C3D_RENDER_OGL_LEGACY::generate_3D_Vias_and_Pads() double correctionFactor = m_settings.GetCircleCorrectionFactor( nrSegments ); int correction = radius * ( correctionFactor - 1 ); - pad->BuildPadDrillShapePolygon( tht_outer_holes_poly, - copperThickness + correction, - nrSegments ); + pad->BuildPadDrillShapePolygon( + tht_outer_holes_poly, copperThickness + correction ); - pad->BuildPadDrillShapePolygon( tht_inner_holes_poly, - correction, - nrSegments ); + pad->BuildPadDrillShapePolygon( tht_inner_holes_poly, correction ); } } } diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 020124b648..74b5f67526 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -34,7 +34,6 @@ set( GAL_SRCS draw_panel_gal.cpp gl_context_mgr.cpp newstroke_font.cpp - origin_viewitem.cpp painter.cpp text_utils.cpp worksheet_viewitem.cpp @@ -322,7 +321,6 @@ set( COMMON_SRCS getrunningmicrosecs.cpp gr_basic.cpp grid_tricks.cpp - hash_eda.cpp hotkey_store.cpp hotkeys_basic.cpp html_messagebox.cpp @@ -444,7 +442,9 @@ set( PCB_COMMON_SRCS base_screen.cpp eda_text.cpp fp_lib_table.cpp + hash_eda.cpp lset.cpp + origin_viewitem.cpp page_info.cpp pcb_keywords.cpp pcb_plot_params_keywords.cpp diff --git a/common/footprint_info.cpp b/common/footprint_info.cpp index 23f2191631..daec55e03b 100644 --- a/common/footprint_info.cpp +++ b/common/footprint_info.cpp @@ -28,7 +28,6 @@ * and their documentation (comments and keywords) */ -#include #include #include #include diff --git a/common/geometry/hetriang.cpp b/common/geometry/hetriang.cpp index 99325286ec..9047a40ec3 100644 --- a/common/geometry/hetriang.cpp +++ b/common/geometry/hetriang.cpp @@ -45,7 +45,6 @@ #include #include #include -#include #include using namespace hed; diff --git a/common/preview_items/bright_box.cpp b/common/preview_items/bright_box.cpp index cc55dfa371..099fd03b4f 100644 --- a/common/preview_items/bright_box.cpp +++ b/common/preview_items/bright_box.cpp @@ -24,7 +24,6 @@ #include #include -#include using namespace KIGFX; diff --git a/common/tool/tool_base.cpp b/common/tool/tool_base.cpp index d297e45292..314760975e 100644 --- a/common/tool/tool_base.cpp +++ b/common/tool/tool_base.cpp @@ -25,7 +25,8 @@ #include #include -#include +#include +#include bool TOOL_BASE::IsToolActive() const { @@ -94,9 +95,8 @@ wxConfigBase* TOOL_SETTINGS::getConfigBase() const if( !m_tool ) return NULL; - // fixme: make independent of pcbnew (post-stable) - if( PCB_EDIT_FRAME* frame = m_tool->getEditFrame() ) - return frame->GetSettings(); + if( EDA_BASE_FRAME* frame = m_tool->getEditFrame() ) + return frame->config(); return NULL; } diff --git a/common/tool/tool_dispatcher.cpp b/common/tool/tool_dispatcher.cpp index 71bf6c08d3..1caa7e548a 100644 --- a/common/tool/tool_dispatcher.cpp +++ b/common/tool/tool_dispatcher.cpp @@ -23,7 +23,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#include +#include #include #include @@ -33,6 +33,7 @@ #include #include +#include #include #include @@ -319,10 +320,10 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent ) // Sometimes there is no window that has the focus (it happens when another PCB_BASE_FRAME // is opened and is iconized on Windows). - // In this case, gives the focus to the parent PCB_BASE_FRAME (for an obscure reason, + // In this case, gives the focus to the parent frame (for an obscure reason, // when happens, the GAL canvas itself does not accept the focus) if( wxWindow::FindFocus() == nullptr ) - static_cast( m_toolMgr->GetEditFrame() )->SetFocus(); + m_toolMgr->GetEditFrame()->SetFocus(); // Mouse handling // Note: wxEVT_LEFT_DOWN event must always be skipped. diff --git a/common/tool/tool_manager.cpp b/common/tool/tool_manager.cpp index 97ad3464f2..a8cbd57be3 100644 --- a/common/tool/tool_manager.cpp +++ b/common/tool/tool_manager.cpp @@ -41,8 +41,8 @@ #include #include -#include #include +#include /// Struct describing the current execution state of a TOOL struct TOOL_MANAGER::TOOL_STATE diff --git a/common/tool/zoom_tool.cpp b/common/tool/zoom_tool.cpp index e779b9f766..c07df2131b 100644 --- a/common/tool/zoom_tool.cpp +++ b/common/tool/zoom_tool.cpp @@ -17,15 +17,15 @@ * with this program. If not, see . */ - -#include #include -#include -#include -#include -#include -#include +#include +#include #include +#include +#include +#include +#include +#include ZOOM_TOOL::ZOOM_TOOL() : diff --git a/include/class_board_item.h b/include/class_board_item.h index 09ec22bf37..1970192444 100644 --- a/include/class_board_item.h +++ b/include/class_board_item.h @@ -32,6 +32,7 @@ #include +#include #include #include @@ -295,18 +296,12 @@ public: * Circles and arcs are approximated by segments * @param aCornerBuffer = a buffer to store the polygon * @param aClearanceValue = the clearance around the pad - * @param aCircleToSegmentsCount = the number of segments to approximate a circle - * @param aCorrectionFactor = the correction to apply to circles radius to keep - * clearance when the circle is approximated by segment bigger or equal - * to the real clearance value (usually near from 1.0) + * @param aError = the maximum deviation from true circle * @param ignoreLineWidth = used for edge cut items where the line width is only * for visualization */ virtual void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, - int aClearanceValue, - int aCircleToSegmentsCount, - double aCorrectionFactor, - bool ignoreLineWidth = false ) const; + int aClearanceValue, int aError = ARC_LOW_DEF, bool ignoreLineWidth = false ) const; }; #endif /* BOARD_ITEM_STRUCT_H */ diff --git a/include/eda_base_frame.h b/include/eda_base_frame.h index 1ea3589c60..cada104350 100644 --- a/include/eda_base_frame.h +++ b/include/eda_base_frame.h @@ -181,13 +181,6 @@ protected: */ virtual bool doAutoSave(); - /** - * Return the wxConfigBase used in SaveSettings(). - * - * This is overloaded in #KICAD_MANAGER_FRAME - */ - virtual wxConfigBase* config(); - /** * Return a SEARCH_STACK pertaining to entire program. * @@ -230,8 +223,14 @@ public: void PrintMsg( const wxString& text ); /** + * Returns the wxConfigBase used in SaveSettings(), and is overloaded in + * KICAD_MANAGER_FRAME + */ + virtual wxConfigBase* config(); + + /** + * Function InstallPreferences * Allow a frame to load its preference panels (if any) into the preferences dialog. - * * @param aParent a paged dialog into which the preference panels should be installed */ virtual void InstallPreferences( PAGED_DIALOG* aParent ) { } diff --git a/include/id.h b/include/id.h index 24da6788f1..e57d84d6d6 100644 --- a/include/id.h +++ b/include/id.h @@ -31,6 +31,8 @@ #ifndef ID_H_ #define ID_H_ +#include + /** * Common command IDs shared by more than one of the KiCad applications. * diff --git a/pcbnew/board_items_to_polygon_shape_transform.cpp b/pcbnew/board_items_to_polygon_shape_transform.cpp index 493cc83eb4..8eb7f04ebe 100644 --- a/pcbnew/board_items_to_polygon_shape_transform.cpp +++ b/pcbnew/board_items_to_polygon_shape_transform.cpp @@ -61,12 +61,6 @@ struct TSEGM_2_POLY_PRMS { }; TSEGM_2_POLY_PRMS prms; -// The max error is the distance between the middle of a segment, and the circle -// for circle/arc to segment approximation. -// Warning: too small values can create very long calculation time in zone filling -// 0.05 to 0.01 mm is a reasonable value -double s_error_max = Millimeter2iu( 0.02 ); - // This is a call back function, used by DrawGraphicText to draw the 3D text shape: static void addTextSegmToPoly( int x0, int y0, int xf, int yf, void* aData ) { @@ -79,29 +73,22 @@ static void addTextSegmToPoly( int x0, int y0, int xf, int yf, void* aData ) void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, SHAPE_POLY_SET& aOutlines ) { - // Number of segments to convert a circle to a polygon - const int segcountforcircle = ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF; - double correctionFactor = GetCircletoPolyCorrectionFactor( segcountforcircle ); - // convert tracks and vias: for( TRACK* track = m_Track; track != NULL; track = track->Next() ) { if( !track->IsOnLayer( aLayer ) ) continue; - track->TransformShapeWithClearanceToPolygon( aOutlines, - 0, segcountforcircle, correctionFactor ); + track->TransformShapeWithClearanceToPolygon( aOutlines, 0 ); } // convert pads for( MODULE* module = m_Modules; module != NULL; module = module->Next() ) { - module->TransformPadsShapesWithClearanceToPolygon( aLayer, - aOutlines, 0, segcountforcircle, correctionFactor ); + module->TransformPadsShapesWithClearanceToPolygon( aLayer, aOutlines, 0 ); // Micro-wave modules may have items on copper layers - module->TransformGraphicShapesWithClearanceToPolygonSet( aLayer, - aOutlines, 0, segcountforcircle, correctionFactor ); + module->TransformGraphicShapesWithClearanceToPolygonSet( aLayer, aOutlines, 0 ); } // convert copper zones @@ -111,8 +98,7 @@ void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, SHAPE_POLY_ PCB_LAYER_ID zonelayer = zone->GetLayer(); if( zonelayer == aLayer ) - zone->TransformSolidAreasShapesToPolygonSet( - aOutlines, segcountforcircle, correctionFactor ); + zone->TransformSolidAreasShapesToPolygonSet( aOutlines ); } // convert graphic items on copper layers (texts) @@ -124,13 +110,11 @@ void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, SHAPE_POLY_ switch( item->Type() ) { case PCB_LINE_T: - ( (DRAWSEGMENT*) item )->TransformShapeWithClearanceToPolygon( - aOutlines, 0, segcountforcircle, correctionFactor ); + ( (DRAWSEGMENT*) item )->TransformShapeWithClearanceToPolygon( aOutlines, 0 ); break; case PCB_TEXT_T: - ( (TEXTE_PCB*) item )->TransformShapeWithClearanceToPolygonSet( - aOutlines, 0, segcountforcircle, correctionFactor ); + ( (TEXTE_PCB*) item )->TransformShapeWithClearanceToPolygonSet( aOutlines, 0 ); break; default: @@ -141,11 +125,8 @@ void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, SHAPE_POLY_ void MODULE::TransformPadsShapesWithClearanceToPolygon( PCB_LAYER_ID aLayer, - SHAPE_POLY_SET& aCornerBuffer, - int aInflateValue, - int aCircleToSegmentsCount, - double aCorrectionFactor, - bool aSkipNPTHPadsWihNoCopper ) const + SHAPE_POLY_SET& aCornerBuffer, int aInflateValue, int aMaxError, + bool aSkipNPTHPadsWihNoCopper ) const { D_PAD* pad = PadsList(); @@ -198,8 +179,7 @@ void MODULE::TransformPadsShapesWithClearanceToPolygon( PCB_LAYER_ID aLayer, break; } - pad->BuildPadShapePolygon( aCornerBuffer, margin, - aCircleToSegmentsCount, aCorrectionFactor ); + pad->BuildPadShapePolygon( aCornerBuffer, margin ); } } @@ -214,14 +194,8 @@ void MODULE::TransformPadsShapesWithClearanceToPolygon( PCB_LAYER_ID aLayer, * the radius of circle approximated by segments is * initial radius * aCorrectionFactor */ -void MODULE::TransformGraphicShapesWithClearanceToPolygonSet( - PCB_LAYER_ID aLayer, - SHAPE_POLY_SET& aCornerBuffer, - int aInflateValue, - int aCircleToSegmentsCount, - double aCorrectionFactor, - int aCircleToSegmentsCountForTexts, - bool aIncludeText ) const +void MODULE::TransformGraphicShapesWithClearanceToPolygonSet( PCB_LAYER_ID aLayer, + SHAPE_POLY_SET& aCornerBuffer, int aInflateValue, int aError, bool aIncludeText ) const { std::vector texts; // List of TEXTE_MODULE to convert EDGE_MODULE* outline; @@ -231,15 +205,14 @@ void MODULE::TransformGraphicShapesWithClearanceToPolygonSet( switch( item->Type() ) { case PCB_MODULE_TEXT_T: - { - TEXTE_MODULE* text = static_cast( item ); + { + TEXTE_MODULE* text = static_cast( item ); - if( ( aLayer != UNDEFINED_LAYER && text->GetLayer() == aLayer ) - && text->IsVisible() ) - texts.push_back( text ); + if( ( aLayer != UNDEFINED_LAYER && text->GetLayer() == aLayer ) && text->IsVisible() ) + texts.push_back( text ); - break; - } + break; + } case PCB_MODULE_EDGE_T: outline = (EDGE_MODULE*) item; @@ -247,12 +220,11 @@ void MODULE::TransformGraphicShapesWithClearanceToPolygonSet( if( aLayer != UNDEFINED_LAYER && outline->GetLayer() != aLayer ) break; - outline->TransformShapeWithClearanceToPolygon( aCornerBuffer, 0, - aCircleToSegmentsCount, aCorrectionFactor ); + outline->TransformShapeWithClearanceToPolygon( aCornerBuffer, 0, aError ); break; - default: - break; + default: + break; } } @@ -268,16 +240,12 @@ void MODULE::TransformGraphicShapesWithClearanceToPolygonSet( prms.m_cornerBuffer = &aCornerBuffer; - // To allow optimization of circles approximated by segments, - // aCircleToSegmentsCountForTexts, when not 0, is used. - // if 0 (default value) the aCircleToSegmentsCount is used - prms.m_textCircle2SegmentCount = aCircleToSegmentsCountForTexts ? - aCircleToSegmentsCountForTexts : aCircleToSegmentsCount; - for( unsigned ii = 0; ii < texts.size(); ii++ ) { 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 ); wxSize size = textmod->GetTextSize(); if( textmod->IsMirrored() ) @@ -296,12 +264,7 @@ void MODULE::TransformGraphicShapesWithClearanceToPolygonSet( // Same as function TransformGraphicShapesWithClearanceToPolygonSet but // this only render text void MODULE::TransformGraphicTextWithClearanceToPolygonSet( - PCB_LAYER_ID aLayer, - SHAPE_POLY_SET& aCornerBuffer, - int aInflateValue, - int aCircleToSegmentsCount, - double aCorrectionFactor, - int aCircleToSegmentsCountForTexts ) const + PCB_LAYER_ID aLayer, SHAPE_POLY_SET& aCornerBuffer, int aInflateValue, int aError ) const { std::vector texts; // List of TEXTE_MODULE to convert @@ -337,16 +300,12 @@ void MODULE::TransformGraphicTextWithClearanceToPolygonSet( prms.m_cornerBuffer = &aCornerBuffer; - // To allow optimization of circles approximated by segments, - // aCircleToSegmentsCountForTexts, when not 0, is used. - // if 0 (default value) the aCircleToSegmentsCount is used - prms.m_textCircle2SegmentCount = aCircleToSegmentsCountForTexts ? - aCircleToSegmentsCountForTexts : aCircleToSegmentsCount; - for( unsigned ii = 0; ii < texts.size(); ii++ ) { 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 ); wxSize size = textmod->GetTextSize(); if( textmod->IsMirrored() ) @@ -361,24 +320,15 @@ void MODULE::TransformGraphicTextWithClearanceToPolygonSet( } - /* Function TransformSolidAreasShapesToPolygonSet - * Convert solid areas full shapes to polygon set - * (the full shape is the polygon area with a thick outline) - * Used in 3D view - * Arcs (ends of segments) are approximated by segments - * aCornerBuffer = a buffer to store the polygons - * aCircleToSegmentsCount = the number of segments to approximate a circle - * aCorrectionFactor = the correction to apply to arcs radius to roughly - * keep arc radius when approximated by segments - */ + void ZONE_CONTAINER::TransformSolidAreasShapesToPolygonSet( - SHAPE_POLY_SET& aCornerBuffer, - int aCircleToSegmentsCount, - double aCorrectionFactor ) const + SHAPE_POLY_SET& aCornerBuffer, int aError ) const { if( GetFilledPolysList().IsEmpty() ) return; + int numSegs = std::max( GetArcToSegmentCount( GetMinThickness() / 2, aError, 360.0 ), 6 ); + // add filled areas polygons aCornerBuffer.Append( m_FilledPolysList ); @@ -392,24 +342,15 @@ void ZONE_CONTAINER::TransformSolidAreasShapesToPolygonSet( const VECTOR2I& a = path.CPoint( j ); const VECTOR2I& b = path.CPoint( j + 1 ); - TransformRoundedEndsSegmentToPolygon( aCornerBuffer, wxPoint( a.x, a.y ), wxPoint( b.x, b.y ), - aCircleToSegmentsCount, - GetMinThickness() ); + TransformRoundedEndsSegmentToPolygon( aCornerBuffer, wxPoint( a.x, a.y ), + wxPoint( b.x, b.y ), numSegs, GetMinThickness() ); } } } -/** - * Function TransformBoundingBoxWithClearanceToPolygon - * Convert the text bounding box to a rectangular polygon - * Used in filling zones calculations - * Circles and arcs are approximated by segments - * @param aCornerBuffer = a buffer to store the polygon - * @param aClearanceValue = the clearance around the text bounding box - */ + void EDA_TEXT::TransformBoundingBoxWithClearanceToPolygon( - SHAPE_POLY_SET* aCornerBuffer, - int aClearanceValue ) const + SHAPE_POLY_SET* aCornerBuffer, int aClearanceValue ) const { // Oh dear. When in UTF-8 mode, wxString puts string iterators in a linked list, and // that linked list is not thread-safe. @@ -455,10 +396,7 @@ void EDA_TEXT::TransformBoundingBoxWithClearanceToPolygon( */ void TEXTE_PCB::TransformShapeWithClearanceToPolygonSet( - SHAPE_POLY_SET& aCornerBuffer, - int aClearanceValue, - int aCircleToSegmentsCount, - double aCorrectionFactor ) const + SHAPE_POLY_SET& aCornerBuffer, int aClearanceValue, int aError ) const { wxSize size = GetTextSize(); @@ -466,8 +404,9 @@ void TEXTE_PCB::TransformShapeWithClearanceToPolygonSet( size.x = -size.x; prms.m_cornerBuffer = &aCornerBuffer; - prms.m_textWidth = GetThickness() + ( 2 * aClearanceValue ); - prms.m_textCircle2SegmentCount = aCircleToSegmentsCount; + prms.m_textWidth = GetThickness() + ( 2 * aClearanceValue ); + prms.m_textCircle2SegmentCount = + std::max( GetArcToSegmentCount( prms.m_textWidth / 2, aError, 360.0 ), 6 ); COLOR4D color = COLOR4D::BLACK; // not actually used, but needed by DrawGraphicText if( IsMultilineAllowed() ) @@ -499,61 +438,39 @@ void TEXTE_PCB::TransformShapeWithClearanceToPolygonSet( } -/** - * Function TransformShapeWithClearanceToPolygon - * Convert the track shape to a closed polygon - * Used in filling zones calculations - * Circles and arcs are approximated by segments - * @param aCornerBuffer = a buffer to store the polygon - * @param aClearanceValue = the clearance around the pad - * @param aCircleToSegmentsCount = the number of segments to approximate a circle - * @param aCorrectionFactor = the correction to apply to circles radius to keep - * clearance when the circle is approxiamted by segment bigger or equal - * to the real clearance value (usually near from 1.0) - * @param ignoreLineWidth = used for edge cut items where the line width is only - * for visualization - */ -void DRAWSEGMENT::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, - int aClearanceValue, - int aCircleToSegmentsCount, - double aCorrectionFactor, - bool ignoreLineWidth ) const +void DRAWSEGMENT::TransformShapeWithClearanceToPolygon( + SHAPE_POLY_SET& aCornerBuffer, int aClearanceValue, int aError, bool ignoreLineWidth ) const { // The full width of the lines to create: int linewidth = ignoreLineWidth ? 0 : m_Width; 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 cicle this is not so hard: create a polygon from a circle slightly bigger: + // for a circle this is not so hard: create a polygon from a circle slightly bigger: // thickness = linewidth + s_error_max, and radius = initial radius + s_error_max/2 // giving a shape with a suitable internal radius and external radius // For an arc this is more tricky: TODO - if( m_Shape == S_CIRCLE || m_Shape == S_ARC ) - { - int segCount = GetArcToSegmentCount( GetRadius(), s_error_max, 360.0 ); - - if( segCount > aCircleToSegmentsCount ) - aCircleToSegmentsCount = segCount; - } switch( m_Shape ) { case S_CIRCLE: - TransformRingToPolygon( aCornerBuffer, GetCenter(), GetRadius() + (s_error_max/2), - aCircleToSegmentsCount, linewidth + s_error_max ) ; + TransformRingToPolygon( + aCornerBuffer, GetCenter(), GetRadius(), numSegs, correction * linewidth ); break; case S_ARC: - TransformArcToPolygon( aCornerBuffer, GetCenter(), - GetArcStart(), m_Angle, - aCircleToSegmentsCount, linewidth ); + TransformArcToPolygon( + aCornerBuffer, GetCenter(), GetArcStart(), m_Angle, numSegs, linewidth ); break; case S_SEGMENT: - TransformOvalClearanceToPolygon( aCornerBuffer, m_Start, m_End, linewidth, - aCircleToSegmentsCount, aCorrectionFactor ); + TransformOvalClearanceToPolygon( + aCornerBuffer, m_Start, m_End, linewidth, numSegs, correction ); break; case S_POLYGON: @@ -583,12 +500,12 @@ void DRAWSEGMENT::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerB { for( size_t ii = 1; ii < poly.size(); ii++ ) { - TransformOvalClearanceToPolygon( aCornerBuffer, poly[ii - 1], poly[ii], - linewidth, aCircleToSegmentsCount, aCorrectionFactor ); + TransformOvalClearanceToPolygon( + aCornerBuffer, poly[ii - 1], poly[ii], linewidth, numSegs, correction ); } - TransformOvalClearanceToPolygon( aCornerBuffer, poly.back(), poly.front(), - linewidth, aCircleToSegmentsCount, aCorrectionFactor ); + TransformOvalClearanceToPolygon( + aCornerBuffer, poly.back(), poly.front(), linewidth, numSegs, correction ); break; } @@ -612,8 +529,8 @@ void DRAWSEGMENT::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerB if( corner2 != corner1 ) { - TransformRoundedEndsSegmentToPolygon( aCornerBuffer, - corner1, corner2, aCircleToSegmentsCount, linewidth ); + TransformRoundedEndsSegmentToPolygon( + aCornerBuffer, corner1, corner2, numSegs, linewidth ); } corner1 = corner2; @@ -631,8 +548,8 @@ void DRAWSEGMENT::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerB for( unsigned ii = 1; ii < poly.size(); ii++ ) { - TransformRoundedEndsSegmentToPolygon( aCornerBuffer, - poly[ii-1], poly[ii], aCircleToSegmentsCount, linewidth ); + TransformRoundedEndsSegmentToPolygon( + aCornerBuffer, poly[ii - 1], poly[ii], numSegs, linewidth ); } } break; @@ -643,66 +560,34 @@ void DRAWSEGMENT::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerB } -/** - * Function TransformShapeWithClearanceToPolygon - * Convert the track shape to a closed polygon - * Used in filling zones calculations - * Circles (vias) and arcs (ends of tracks) are approximated by segments - * @param aCornerBuffer = a buffer to store the polygon - * @param aClearanceValue = the clearance around the pad - * @param aCircleToSegmentsCount = the number of segments to approximate a circle - * @param aCorrectionFactor = the correction to apply to circles radius to keep - * clearance when the circle is approximated by segment bigger or equal - * to the real clearance value (usually near from 1.0) - * @param ignoreLineWidth = used for edge cut items where the line width is only - * for visualization - */ -void TRACK::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, - int aClearanceValue, - int aCircleToSegmentsCount, - double aCorrectionFactor, - bool ignoreLineWidth ) const +void TRACK::TransformShapeWithClearanceToPolygon( + SHAPE_POLY_SET& aCornerBuffer, int aClearanceValue, int aError, bool ignoreLineWidth ) const { 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: { - int radius = (m_Width / 2) + aClearanceValue; - radius = KiROUND( radius * aCorrectionFactor ); - TransformCircleToPolygon( aCornerBuffer, m_Start, radius, aCircleToSegmentsCount ); + radius = KiROUND( radius * correction ); + TransformCircleToPolygon( aCornerBuffer, m_Start, radius, numSegs ); } break; default: TransformOvalClearanceToPolygon( aCornerBuffer, m_Start, m_End, - m_Width + ( 2 * aClearanceValue), - aCircleToSegmentsCount, - aCorrectionFactor ); + m_Width + ( 2 * aClearanceValue ), numSegs, correction ); break; } } -/* Function TransformShapeWithClearanceToPolygon - * Convert the pad shape to a closed polygon - * Used in filling zones calculations and 3D view generation - * Circles and arcs are approximated by segments - * aCornerBuffer = a SHAPE_POLY_SET to store the polygon corners - * aClearanceValue = the clearance around the pad - * aCircleToSegmentsCount = the number of segments to approximate a circle - * aCorrectionFactor = the correction to apply to circles radius to keep - * clearance when the circle is approximated by segment bigger or equal - * to the real clearance value (usually near from 1.0) - * @param ignoreLineWidth = used for edge cut items where the line width is only - * for visualization - */ -void D_PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, - int aClearanceValue, - int aCircleToSegmentsCount, - double aCorrectionFactor, - bool ignoreLineWidth ) const +void D_PAD::TransformShapeWithClearanceToPolygon( + SHAPE_POLY_SET& aCornerBuffer, int aClearanceValue, int aError, bool ignoreLineWidth ) const { wxASSERT_MSG( !ignoreLineWidth, "IgnoreLineWidth has no meaning for pads." ); @@ -716,9 +601,12 @@ void D_PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, switch( GetShape() ) { case PAD_SHAPE_CIRCLE: - dx = KiROUND( dx * aCorrectionFactor ); - TransformCircleToPolygon( aCornerBuffer, padShapePos, dx, - aCircleToSegmentsCount ); + { + int numSegs = std::max( GetArcToSegmentCount( dx, aError, 360.0 ), 6 ); + double correction = GetCircletoPolyCorrectionFactor( numSegs ); + dx = KiROUND( dx * correction ); + TransformCircleToPolygon( aCornerBuffer, padShapePos, dx, numSegs ); + } break; case PAD_SHAPE_OVAL: @@ -737,11 +625,13 @@ void D_PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, 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, - aCircleToSegmentsCount, aCorrectionFactor ); + TransformOvalClearanceToPolygon( aCornerBuffer, start, end, width, numSegs, correction ); } break; @@ -760,8 +650,11 @@ void D_PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, outline.Append( corners[ii].x, corners[ii].y ); } - int rounding_radius = int( aClearanceValue * aCorrectionFactor ); - outline.Inflate( rounding_radius, aCircleToSegmentsCount ); + int numSegs = std::max( GetArcToSegmentCount( aClearanceValue, aError, 360.0 ), 6 ); + double correction = GetCircletoPolyCorrectionFactor( numSegs ); + + int rounding_radius = KiROUND( aClearanceValue * correction ); + outline.Inflate( rounding_radius, numSegs ); aCornerBuffer.Append( outline ); } @@ -771,18 +664,20 @@ void D_PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, case PAD_SHAPE_ROUNDRECT: { SHAPE_POLY_SET outline; - int clearance = int( aClearanceValue * aCorrectionFactor ); - int rounding_radius = GetRoundRectCornerRadius() + clearance; - wxSize shapesize( m_Size ); + int radius = GetRoundRectCornerRadius() + aClearanceValue; + int numSegs = std::max( GetArcToSegmentCount( radius, aError, 360.0 ), 6 ); + double correction = GetCircletoPolyCorrectionFactor( numSegs ); + int clearance = KiROUND( aClearanceValue * correction ); + int rounding_radius = GetRoundRectCornerRadius() + clearance; + wxSize shapesize( m_Size ); + 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, - aCircleToSegmentsCount ); + rounding_radius, doChamfer ? GetChamferRectRatio() : 0.0, + doChamfer ? GetChamferPositions() : 0, numSegs ); aCornerBuffer.Append( outline ); } @@ -790,12 +685,14 @@ void D_PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, case PAD_SHAPE_CUSTOM: { - int clearance = KiROUND( aClearanceValue * aCorrectionFactor ); + int numSegs = std::max( GetArcToSegmentCount( aClearanceValue, aError, 360.0 ), 6 ); + double correction = GetCircletoPolyCorrectionFactor( numSegs ); + int clearance = KiROUND( aClearanceValue * correction ); SHAPE_POLY_SET outline; // Will contain the corners in board coordinates outline.Append( m_customShapeAsPolygon ); CustomShapeAsPolygonToBoardPosition( &outline, GetPosition(), GetOrientation() ); outline.Simplify( SHAPE_POLY_SET::PM_FAST ); - outline.Inflate( clearance, aCircleToSegmentsCount ); + outline.Inflate( clearance, numSegs ); outline.Fracture( SHAPE_POLY_SET::PM_FAST ); aCornerBuffer.Append( outline ); } @@ -812,9 +709,8 @@ void D_PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, * Note: for Round and oval pads this function is equivalent to * TransformShapeWithClearanceToPolygon, but not for other shapes */ -void D_PAD::BuildPadShapePolygon( SHAPE_POLY_SET& aCornerBuffer, - wxSize aInflateValue, int aSegmentsPerCircle, - double aCorrectionFactor ) const +void D_PAD::BuildPadShapePolygon( + SHAPE_POLY_SET& aCornerBuffer, wxSize aInflateValue, int aError ) const { wxPoint corners[4]; wxPoint padShapePos = ShapePos(); /* Note: for pad having a shape offset, @@ -834,8 +730,7 @@ void D_PAD::BuildPadShapePolygon( SHAPE_POLY_SET& aCornerBuffer, // a wxSize to inflate the pad size D_PAD dummy( *this ); dummy.SetSize( GetSize() + aInflateValue + aInflateValue ); - dummy.TransformShapeWithClearanceToPolygon( aCornerBuffer, 0, - aSegmentsPerCircle, aCorrectionFactor ); + dummy.TransformShapeWithClearanceToPolygon( aCornerBuffer, 0 ); } break; @@ -856,21 +751,15 @@ void D_PAD::BuildPadShapePolygon( SHAPE_POLY_SET& aCornerBuffer, // for a custom shape, that is in fact a polygon (with holes), we can use only a inflate value. // so use ( aInflateValue.x + aInflateValue.y ) / 2 as polygon inflate value. // (different values for aInflateValue.x and aInflateValue.y has no sense for a custom pad) - TransformShapeWithClearanceToPolygon( aCornerBuffer, - ( aInflateValue.x + aInflateValue.y ) / 2, - aSegmentsPerCircle, aCorrectionFactor ); + TransformShapeWithClearanceToPolygon( + aCornerBuffer, ( aInflateValue.x + aInflateValue.y ) / 2 ); break; } } -/* - * Function BuildPadDrillShapePolygon - * Build the Corner list of the polygonal drill shape, - * depending on shape pad hole and orientation - * return false if the pad has no hole, true otherwise - */ -bool D_PAD::BuildPadDrillShapePolygon( SHAPE_POLY_SET& aCornerBuffer, - int aInflateValue, int aSegmentsPerCircle ) const + +bool D_PAD::BuildPadDrillShapePolygon( + SHAPE_POLY_SET& aCornerBuffer, int aInflateValue, int aError ) const { wxSize drillsize = GetDrillSize(); @@ -879,8 +768,9 @@ bool D_PAD::BuildPadDrillShapePolygon( SHAPE_POLY_SET& aCornerBuffer, if( drillsize.x == drillsize.y ) // usual round hole { - TransformCircleToPolygon( aCornerBuffer, GetPosition(), - (drillsize.x / 2) + aInflateValue, aSegmentsPerCircle ); + int radius = ( drillsize.x / 2 ) + aInflateValue; + int numSegs = std::max( GetArcToSegmentCount( radius, aError, 360.0 ), 6 ); + TransformCircleToPolygon( aCornerBuffer, GetPosition(), radius, numSegs ); } else // Oblong hole { @@ -890,9 +780,10 @@ bool D_PAD::BuildPadDrillShapePolygon( SHAPE_POLY_SET& aCornerBuffer, GetOblongDrillGeometry( start, end, width ); width += aInflateValue * 2; + int numSegs = std::max( GetArcToSegmentCount( width / 2, aError, 360.0 ), 6 ); - TransformRoundedEndsSegmentToPolygon( aCornerBuffer, - GetPosition() + start, GetPosition() + end, aSegmentsPerCircle, width ); + TransformRoundedEndsSegmentToPolygon( + aCornerBuffer, GetPosition() + start, GetPosition() + end, numSegs, width ); } return true; @@ -907,8 +798,7 @@ bool D_PAD::BuildPadDrillShapePolygon( SHAPE_POLY_SET& aCornerBuffer, * @param aThermalGap = gap in thermal shape * @param aCopperThickness = stubs thickness in thermal shape * @param aMinThicknessValue = min copper thickness allowed - * @param aCircleToSegmentsCount = the number of segments to approximate a circle - * @param aCorrectionFactor = the correction to apply to circles radius to keep + * @param aError = maximum error allowed when approximating arcs * @param aThermalRot = for rond pads the rotation of thermal stubs (450 usually for 45 deg.) */ @@ -926,21 +816,18 @@ bool D_PAD::BuildPadDrillShapePolygon( SHAPE_POLY_SET& aCornerBuffer, * and are used in microwave applications and they *DO NOT* have a thermal relief that * change the shape by creating stubs and destroy their properties. */ -void CreateThermalReliefPadPolygon( SHAPE_POLY_SET& aCornerBuffer, - const D_PAD& aPad, - int aThermalGap, - int aCopperThickness, - int aMinThicknessValue, - int aCircleToSegmentsCount, - double aCorrectionFactor, - double aThermalRot ) +void CreateThermalReliefPadPolygon( SHAPE_POLY_SET& aCornerBuffer, + const D_PAD& aPad, + int aThermalGap, + int aCopperThickness, + int aMinThicknessValue, + int aError, + double aThermalRot ) { wxPoint corner, corner_end; + wxSize copper_thickness; wxPoint padShapePos = aPad.ShapePos(); // Note: for pad having a shape offset, // the pad position is NOT the shape position - wxSize copper_thickness; - - double delta = 3600.0 / aCircleToSegmentsCount; // rot angle in 0.1 degree /* Keep in account the polygon outline thickness * aThermalGap must be increased by aMinThicknessValue/2 because drawing external outline @@ -984,8 +871,12 @@ void CreateThermalReliefPadPolygon( SHAPE_POLY_SET& aCornerBuffer, // The pattern roughtly is a 90 deg arc pie std::vector corners_buffer; + int numSegs = std::max( GetArcToSegmentCount( dx + aThermalGap, aError, 360.0 ), 6 ); + double correction = GetCircletoPolyCorrectionFactor( numSegs ); + double delta = 3600.0 / numSegs; + // Radius of outer arcs of the shape corrected for arc approximation by lines - int outer_radius = KiROUND( (dx + aThermalGap) * aCorrectionFactor ); + int outer_radius = KiROUND( ( dx + aThermalGap ) * correction ); // Crosspoint of thermal spoke sides, the first point of polygon buffer corners_buffer.push_back( wxPoint( copper_thickness.x / 2, copper_thickness.y / 2 ) ); @@ -1006,7 +897,7 @@ void CreateThermalReliefPadPolygon( SHAPE_POLY_SET& aCornerBuffer, ( (double) corner.x * corner.x ) ) ); RotatePoint( &corner, 90 ); // 9 degrees is the spoke fillet size - // calculate the ending point of the outter arc + // calculate the ending point of the outer arc corner_end.x = corner.y; corner_end.y = corner.x; @@ -1074,6 +965,10 @@ void CreateThermalReliefPadPolygon( SHAPE_POLY_SET& aCornerBuffer, // Radius of outer arcs of the shape: int outer_radius = dy; // The radius of the outer arc is radius end + aThermalGap + + int numSegs = std::max( GetArcToSegmentCount( outer_radius, aError, 360.0 ), 6 ); + double delta = 3600.0 / numSegs; + // Some coordinate fiddling, depending on the shape offset direction shape_offset = wxPoint( deltasize, 0 ); @@ -1236,11 +1131,13 @@ void CreateThermalReliefPadPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint arc_start_point( -(aThermalGap / 4 + copper_thickness.x / 2) , -dy ); corners_buffer.push_back( arc_start_point ); - int rounding_radius = KiROUND( aThermalGap * aCorrectionFactor ); // Corner rounding radius + int numSegs = std::max( GetArcToSegmentCount( aThermalGap, aError, 360.0 ), 6 ); + double correction = GetCircletoPolyCorrectionFactor( numSegs ); + int rounding_radius = KiROUND( aThermalGap * correction ); // Corner rounding radius // Calculate arc angle parameters. // the start angle id near 900 decidegrees, the final angle is near 1800.0 decidegrees. - double arc_increment = 3600.0 / aCircleToSegmentsCount; + double arc_increment = 3600.0 / numSegs; // the arc_angle_start is 900.0 or slighly more, depending on the actual arc starting point double arc_angle_start = atan2( -arc_start_point.y -corner_origin_pos.y, arc_start_point.x - corner_origin_pos.x ) * 1800/M_PI; @@ -1319,8 +1216,7 @@ void CreateThermalReliefPadPolygon( SHAPE_POLY_SET& aCornerBuffer, EDA_RECT bbox = aPad.GetBoundingBox(); int stub_len = std::max( bbox.GetWidth(), bbox.GetHeight() ); - aPad.TransformShapeWithClearanceToPolygon( antipad, aThermalGap, - aCircleToSegmentsCount, aCorrectionFactor ); + aPad.TransformShapeWithClearanceToPolygon( antipad, aThermalGap ); SHAPE_POLY_SET stub; // A basic stub ( a rectangle) SHAPE_POLY_SET stubs; // the full stubs shape @@ -1388,11 +1284,8 @@ void CreateThermalReliefPadPolygon( SHAPE_POLY_SET& aCornerBuffer, } } -void ZONE_CONTAINER::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, - int aClearanceValue, - int aCircleToSegmentsCount, - double aCorrectionFactor, - bool ignoreLineWidth ) const +void ZONE_CONTAINER::TransformShapeWithClearanceToPolygon( + SHAPE_POLY_SET& aCornerBuffer, int aClearanceValue, int aError, bool ignoreLineWidth ) const { wxASSERT_MSG( !ignoreLineWidth, "IgnoreLineWidth has no meaning for zones." ); diff --git a/pcbnew/class_board_item.cpp b/pcbnew/class_board_item.cpp index 9af3ee7569..0ca472002c 100644 --- a/pcbnew/class_board_item.cpp +++ b/pcbnew/class_board_item.cpp @@ -140,11 +140,8 @@ void BOARD_ITEM::SwapData( BOARD_ITEM* aImage ) } -void BOARD_ITEM::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, - int aClearanceValue, - int aCircleToSegmentsCount, - double aCorrectionFactor, - bool ignoreLineWidth ) const +void BOARD_ITEM::TransformShapeWithClearanceToPolygon( + SHAPE_POLY_SET& aCornerBuffer, int aClearanceValue, int aError, bool ignoreLineWidth ) const { wxASSERT_MSG( false, "Called TransformShapeWithClearanceToPolygon() on unsupported BOARD_ITEM." ); }; diff --git a/pcbnew/class_drawsegment.h b/pcbnew/class_drawsegment.h index 5477db51e6..dbea975d65 100644 --- a/pcbnew/class_drawsegment.h +++ b/pcbnew/class_drawsegment.h @@ -31,9 +31,10 @@ #define CLASS_DRAWSEGMENT_H_ #include +#include +#include #include #include -#include #include @@ -246,18 +247,12 @@ public: * Circles and arcs are approximated by segments * @param aCornerBuffer = a buffer to store the polygon * @param aClearanceValue = the clearance around the pad - * @param aCircleToSegmentsCount = the number of segments to approximate a circle - * @param aCorrectionFactor = the correction to apply to circles radius to keep - * clearance when the circle is approximated by segment bigger or equal - * to the real clearance value (usually near from 1.0) + * @param aError = the maximum deviation from a true arc * @param ignoreLineWidth = used for edge cut items where the line width is only * for visualization */ - void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, - int aClearanceValue, - int aCircleToSegmentsCount, - double aCorrectionFactor, - bool ignoreLineWidth = false ) const override; + void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, int aClearanceValue, + int aError = ARC_HIGH_DEF, bool ignoreLineWidth = false ) const override; virtual wxString GetSelectMenuText( EDA_UNITS_T aUnits ) const override; diff --git a/pcbnew/class_module.h b/pcbnew/class_module.h index 1db84f4d35..ae59f8d87e 100644 --- a/pcbnew/class_module.h +++ b/pcbnew/class_module.h @@ -32,13 +32,14 @@ #define MODULE_H_ -#include -#include -#include // ALL_LAYERS definition. -#include #include +#include #include +#include +#include +#include // ALL_LAYERS definition. #include +#include #include #include "zones.h" @@ -351,12 +352,7 @@ public: * @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 aCircleToSegmentsCount = number of segments to generate a circle - * @param aCorrectionFactor = the correction to apply to a circle radius - * to approximate a circle by the polygon. - * if aCorrectionFactor = 1.0, the polygon is inside the circle - * the radius of circle approximated by segments is - * initial radius * aCorrectionFactor + * @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 layers, because there is actually no copper @@ -365,10 +361,7 @@ public: * default = false */ void TransformPadsShapesWithClearanceToPolygon( PCB_LAYER_ID aLayer, - SHAPE_POLY_SET& aCornerBuffer, - int aInflateValue, - int aCircleToSegmentsCount, - double aCorrectionFactor, + SHAPE_POLY_SET& aCornerBuffer, int aInflateValue, int aMaxError = ARC_HIGH_DEF, bool aSkipNPTHPadsWihNoCopper = false ) const; /** @@ -381,41 +374,25 @@ public: * @param aCornerBuffer = the buffer to store polygons * @param aInflateValue = a value to inflate shapes * aInflateValue = 0 to have the exact shape size - * @param aCircleToSegmentsCount = number of segments to generate a circle - * @param aCorrectionFactor = the correction to apply to a circle radius - * to approximate a circle by the polygon. - * if aCorrectionFactor = 1.0, the polygon is inside the circle - * the radius of circle approximated by segments is - * initial radius * aCorrectionFactor - * @param aCircleToSegmentsCountForTexts = number of segments to generate - * a circle when building the texts polygonal shapes of the stroke font - * if 0, use the aCircleToSegmentsCount value + * @param aError = Maximum error between true arc and polygon approx + * @param aIncludeText = True to transform text shapes */ void TransformGraphicShapesWithClearanceToPolygonSet( PCB_LAYER_ID aLayer, - SHAPE_POLY_SET& aCornerBuffer, - int aInflateValue, - int aCircleToSegmentsCount, - double aCorrectionFactor, - int aCircleToSegmentsCountForTexts = 0, + SHAPE_POLY_SET& aCornerBuffer, int aInflateValue, int aError = ARC_HIGH_DEF, bool aIncludeText = true ) const; /** * @brief TransformGraphicTextWithClearanceToPolygonSet * This function is the same as TransformGraphicShapesWithClearanceToPolygonSet * but only generate text - * @param aLayer - * @param aCornerBuffer - * @param aInflateValue - * @param aCircleToSegmentsCount - * @param aCorrectionFactor - * @param aCircleToSegmentsCountForTexts + * @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 aError = Maximum error between true arc and polygon approx */ void TransformGraphicTextWithClearanceToPolygonSet( PCB_LAYER_ID aLayer, - SHAPE_POLY_SET& aCornerBuffer, - int aInflateValue, - int aCircleToSegmentsCount, - double aCorrectionFactor, - int aCircleToSegmentsCountForTexts = 0 ) const; + SHAPE_POLY_SET& aCornerBuffer, int aInflateValue, int aError = ARC_HIGH_DEF ) const; /** * Function DrawEdgesOnly diff --git a/pcbnew/class_pad.cpp b/pcbnew/class_pad.cpp index 063238ec86..57b392fd7f 100644 --- a/pcbnew/class_pad.cpp +++ b/pcbnew/class_pad.cpp @@ -35,8 +35,9 @@ #include #include -#include +#include #include +#include #include #include @@ -936,7 +937,8 @@ bool D_PAD::HitTest( const wxPoint& aPosition, int aAccuracy ) const { // Check for hit in polygon SHAPE_POLY_SET outline; - const int segmentToCircleCount = ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF; + 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, diff --git a/pcbnew/class_pad.h b/pcbnew/class_pad.h index 05244e5ade..210972a4be 100644 --- a/pcbnew/class_pad.h +++ b/pcbnew/class_pad.h @@ -30,13 +30,14 @@ #ifndef PAD_H_ #define PAD_H_ -#include -#include -#include -#include -#include -#include // PARAM_CFG_ARRAY #include "zones.h" +#include +#include +#include // PARAM_CFG_ARRAY +#include +#include +#include +#include class DRAWSEGMENT; @@ -312,8 +313,7 @@ public: * (default = 32) * Note: The corners coordinates are relative to the pad position, orientation 0, */ - bool MergePrimitivesAsPolygon( SHAPE_POLY_SET * aMergedPolygon = NULL, - int aCircleToSegmentsCount = ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF ); + bool MergePrimitivesAsPolygon( SHAPE_POLY_SET* aMergedPolygon = NULL ); /** * clear the basic shapes list @@ -443,18 +443,12 @@ public: * Circles and arcs are approximated by segments * @param aCornerBuffer = a buffer to store the polygon * @param aClearanceValue = the clearance around the pad - * @param aCircleToSegmentsCount = the number of segments to approximate a circle - * @param aCorrectionFactor = the correction to apply to circles radius to keep - * clearance when the circle is approximated by segment bigger or equal - * to the real clearance value (usually near from 1.0) + * @param aMaxError = Maximum error from true when converting arcs * @param ignoreLineWidth = used for edge cut items where the line width is only * for visualization */ - void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, - int aClearanceValue, - int aCircleToSegmentsCount, - double aCorrectionFactor, - bool ignoreLineWidth = false ) const override; + void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, int aClearanceValue, + int aMaxError = ARC_HIGH_DEF, bool ignoreLineWidth = false ) const override; /** * Function GetClearance @@ -576,14 +570,10 @@ public: * value > 0: inflate, < 0 deflate, = 0 : no change * the clearance can have different values for x and y directions * (relative to the pad) - * @param aSegmentsPerCircle = number of segments to approximate a circle - * (used for round and oblong shapes only (16 to 32 is a good value) - * @param aCorrectionFactor = the correction to apply to circles radius to keep - * the pad size/clearance when the arcs are approximated by segments + * @param aError = Maximum deviation of an arc from the polygon segment */ - void BuildPadShapePolygon( SHAPE_POLY_SET& aCornerBuffer, - wxSize aInflateValue, int aSegmentsPerCircle, - double aCorrectionFactor ) const; + void BuildPadShapePolygon( + SHAPE_POLY_SET& aCornerBuffer, wxSize aInflateValue, int aError = ARC_HIGH_DEF ) const; /** * Function BuildPadDrillShapePolygon @@ -592,12 +582,11 @@ public: * @param aCornerBuffer = a buffer to fill. * @param aInflateValue = the clearance or margin value. * value > 0: inflate, < 0 deflate, = 0 : no change - * @param aSegmentsPerCircle = number of segments to approximate a circle - * (used for round and oblong shapes only(16 to 32 is a good value) + * @param aError = Maximum deviation of an arc from the polygon approximation * @return false if the pad has no hole, true otherwise */ - bool BuildPadDrillShapePolygon( SHAPE_POLY_SET& aCornerBuffer, - int aInflateValue, int aSegmentsPerCircle ) const; + bool BuildPadDrillShapePolygon( + SHAPE_POLY_SET& aCornerBuffer, int aInflateValue, int aError = ARC_HIGH_DEF ) const; /** * Function BuildSegmentFromOvalShape @@ -832,8 +821,7 @@ private: */ int boundingRadius() const; - bool buildCustomPadPolygon( SHAPE_POLY_SET* aMergedPolygon, - int aCircleToSegmentsCount ); + bool buildCustomPadPolygon( SHAPE_POLY_SET* aMergedPolygon, int aError ); private: // Private variable members: diff --git a/pcbnew/class_pcb_text.h b/pcbnew/class_pcb_text.h index 9cf441c014..423d3017bf 100644 --- a/pcbnew/class_pcb_text.h +++ b/pcbnew/class_pcb_text.h @@ -105,15 +105,10 @@ public: * Circles and arcs are approximated by segments * @param aCornerBuffer = a buffer to store the polygon * @param aClearanceValue = the clearance around the text - * @param aCircleToSegmentsCount = the number of segments to approximate a circle - * @param aCorrectionFactor = the correction to apply to circles radius to keep - * clearance when the circle is approximated by segment bigger or equal - * to the real clearance value (usually near from 1.0) + * @param aError = deviation from true arc position to segment approx */ - void TransformShapeWithClearanceToPolygonSet( SHAPE_POLY_SET& aCornerBuffer, - int aClearanceValue, - int aCircleToSegmentsCount, - double aCorrectionFactor ) const; + void TransformShapeWithClearanceToPolygonSet( + SHAPE_POLY_SET& aCornerBuffer, int aClearanceValue, int aError = ARC_HIGH_DEF ) const; wxString GetSelectMenuText( EDA_UNITS_T aUnits ) const override; diff --git a/pcbnew/class_track.h b/pcbnew/class_track.h index b4f3e9c1a3..ee43987a7c 100644 --- a/pcbnew/class_track.h +++ b/pcbnew/class_track.h @@ -31,10 +31,11 @@ #define CLASS_TRACK_H -#include -#include #include +#include +#include #include +#include #include @@ -199,18 +200,12 @@ public: * Circles (vias) and arcs (ends of tracks) are approximated by segments * @param aCornerBuffer = a buffer to store the polygon * @param aClearanceValue = the clearance around the pad - * @param aCircleToSegmentsCount = the number of segments to approximate a circle - * @param aCorrectionFactor = the correction to apply to circles radius to keep - * clearance when the circle is approximated by segment bigger or equal - * to the real clearance value (usually near from 1.0) + * @param aError = the maximum deviation from true circle * @param ignoreLineWidth = used for edge cut items where the line width is only * for visualization */ - void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, - int aClearanceValue, - int aCircleToSegmentsCount, - double aCorrectionFactor, - bool ignoreLineWidth = false ) const override; + void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, int aClearanceValue, + int aError = ARC_HIGH_DEF, bool ignoreLineWidth = false ) const override; /** * Function IsPointOnEnds * returns STARTPOINT if point if near (dist = min_dist) start point, ENDPOINT if diff --git a/pcbnew/class_zone.cpp b/pcbnew/class_zone.cpp index 51829e4d29..52a977f448 100644 --- a/pcbnew/class_zone.cpp +++ b/pcbnew/class_zone.cpp @@ -28,16 +28,17 @@ * @brief Implementation of class to handle copper zones. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -1304,12 +1305,7 @@ bool ZONE_CONTAINER::BuildSmoothedPoly( SHAPE_POLY_SET& aSmoothedPoly ) const break; case ZONE_SETTINGS::SMOOTHING_FILLET: - // Note: we're now using m_ArcToSegmentsCount only as a hint to determine accuracy - // vs. speed. - if( m_ArcToSegmentsCount > SEGMENT_COUNT_CROSSOVER ) - aSmoothedPoly = m_Poly->Fillet( m_cornerRadius, ARC_HIGH_DEF ); - else - aSmoothedPoly = m_Poly->Fillet( m_cornerRadius, ARC_LOW_DEF ); + aSmoothedPoly = m_Poly->Fillet( m_cornerRadius, ARC_HIGH_DEF ); break; default: @@ -1353,8 +1349,10 @@ void ZONE_CONTAINER::TransformOutlinesShapeWithClearanceToPolygon( // Calculate the polygon with clearance // holes are linked to the main outline, so only one polygon is created. if( clearance ) - polybuffer.Inflate( clearance, ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF ); - + { + int segCount = std::max( GetArcToSegmentCount( clearance, ARC_HIGH_DEF, 360.0 ), 3 ); + polybuffer.Inflate( clearance, segCount ); + } polybuffer.Fracture( SHAPE_POLY_SET::PM_FAST ); aCornerBuffer.Append( polybuffer ); } diff --git a/pcbnew/class_zone.h b/pcbnew/class_zone.h index 58ca4ff372..02debee344 100644 --- a/pcbnew/class_zone.h +++ b/pcbnew/class_zone.h @@ -290,22 +290,19 @@ public: */ bool HitTestFilledArea( const wxPoint& aRefPos ) const; - /** + /** * Function TransformSolidAreasShapesToPolygonSet * Convert solid areas full shapes to polygon set * (the full shape is the polygon area with a thick outline) * Used in 3D view * Arcs (ends of segments) are approximated by segments * @param aCornerBuffer = a buffer to store the polygons - * @param aCircleToSegmentsCount = the number of segments to approximate a circle - * @param aCorrectionFactor = the correction to apply to arcs radius to roughly - * keep arc radius when approximated by segments + * @param aError = Maximum error allowed between true arc and polygon approx */ - void TransformSolidAreasShapesToPolygonSet( SHAPE_POLY_SET& aCornerBuffer, - int aCircleToSegmentsCount, - double aCorrectionFactor ) const; + void TransformSolidAreasShapesToPolygonSet( + SHAPE_POLY_SET& aCornerBuffer, int aError = ARC_HIGH_DEF ) const; - /** + /** * Function TransformOutlinesShapeWithClearanceToPolygon * Convert the outlines shape to a polygon with no holes * inflated (optional) by max( aClearanceValue, the zone clearance) @@ -330,18 +327,12 @@ public: * Circles and arcs are approximated by segments * @param aCornerBuffer = a buffer to store the polygon * @param aClearanceValue = the clearance around the pad - * @param aCircleToSegmentsCount = the number of segments to approximate a circle - * @param aCorrectionFactor = the correction to apply to circles radius to keep - * clearance when the circle is approximated by segment bigger or equal - * to the real clearance value (usually near from 1.0) + * @param aError = the maximum deviation from true circle * @param ignoreLineWidth = used for edge cut items where the line width is only * for visualization */ - void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, - int aClearanceValue, - int aCircleToSegmentsCount, - double aCorrectionFactor, - bool ignoreLineWidth = false ) const override; + void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, int aClearanceValue, + int aError = ARC_HIGH_DEF, bool ignoreLineWidth = false ) const override; /** * Function HitTestForCorner diff --git a/pcbnew/drc.cpp b/pcbnew/drc.cpp index cbafcf5754..d1f3085572 100644 --- a/pcbnew/drc.cpp +++ b/pcbnew/drc.cpp @@ -1136,13 +1136,8 @@ void DRC::testCopperDrawItem( DRAWSEGMENT* aItem ) if( pad->GetParent() == aItem->GetParent() ) continue; - const int segmentCount = ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF; - double correctionFactor = GetCircletoPolyCorrectionFactor( segmentCount ); SHAPE_POLY_SET padOutline; - - // We incorporate "minDist" into the pad's outline - pad->TransformShapeWithClearanceToPolygon( padOutline, pad->GetClearance( NULL ), - segmentCount, correctionFactor ); + pad->TransformShapeWithClearanceToPolygon( padOutline, pad->GetClearance( NULL ) ); for( const auto& itemSeg : itemShape ) { @@ -1219,13 +1214,10 @@ void DRC::testCopperTextItem( BOARD_ITEM* aTextItem ) if( !rect_area.Collide( SEG( shape_pos, shape_pos ), bb_radius ) ) continue; - const int segmentCount = ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF; - double correctionFactor = GetCircletoPolyCorrectionFactor( segmentCount ); SHAPE_POLY_SET padOutline; int minDist = textWidth/2 + pad->GetClearance( NULL ); - pad->TransformShapeWithClearanceToPolygon( padOutline, 0, - segmentCount, correctionFactor ); + pad->TransformShapeWithClearanceToPolygon( padOutline, 0 ); for( unsigned jj = 0; jj < textShape.size(); jj += 2 ) { diff --git a/pcbnew/exporters/export_vrml.cpp b/pcbnew/exporters/export_vrml.cpp index 66cac34d72..264c7187b9 100644 --- a/pcbnew/exporters/export_vrml.cpp +++ b/pcbnew/exporters/export_vrml.cpp @@ -1142,9 +1142,8 @@ static void export_vrml_padshape( MODEL_VRML& aModel, VRML_LAYER* aTinLayer, D_P case PAD_SHAPE_CUSTOM: { SHAPE_POLY_SET polySet; - int segmentToCircleCount = ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF; std::vector< wxRealPoint > cornerList; - aPad->MergePrimitivesAsPolygon( &polySet, segmentToCircleCount ); + aPad->MergePrimitivesAsPolygon( &polySet ); for( int cnt = 0; cnt < polySet.OutlineCount(); ++cnt ) { diff --git a/pcbnew/pad_custom_shape_functions.cpp b/pcbnew/pad_custom_shape_functions.cpp index 0ef94a0d65..6be845bc6b 100644 --- a/pcbnew/pad_custom_shape_functions.cpp +++ b/pcbnew/pad_custom_shape_functions.cpp @@ -200,8 +200,7 @@ void D_PAD::DeletePrimitivesList() } -bool D_PAD::buildCustomPadPolygon( SHAPE_POLY_SET* aMergedPolygon, - int aCircleToSegmentsCount ) +bool D_PAD::buildCustomPadPolygon( SHAPE_POLY_SET* aMergedPolygon, int aError ) { SHAPE_POLY_SET aux_polyset; @@ -221,33 +220,42 @@ bool D_PAD::buildCustomPadPolygon( SHAPE_POLY_SET* aMergedPolygon, for( unsigned ii = 1; ii < poly.size(); ii++ ) { - TransformRoundedEndsSegmentToPolygon( aux_polyset, - poly[ii-1], poly[ii], aCircleToSegmentsCount, bshape.m_Thickness ); + 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 ); } break; } case S_SEGMENT: // usual segment : line with rounded ends - TransformRoundedEndsSegmentToPolygon( aux_polyset, - bshape.m_Start, bshape.m_End, aCircleToSegmentsCount, bshape.m_Thickness ); + { + 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 ); break; + } case S_ARC: // Arc with rounded ends - TransformArcToPolygon( aux_polyset, - bshape.m_Start, bshape.m_End, bshape.m_ArcAngle, - aCircleToSegmentsCount, bshape.m_Thickness ); + { + 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 ); 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, - aCircleToSegmentsCount, bshape.m_Thickness ) ; + TransformRingToPolygon( + aux_polyset, bshape.m_Start, bshape.m_Radius, numSegs, bshape.m_Thickness ); else // Filled circle - TransformCircleToPolygon( aux_polyset, - bshape.m_Start, bshape.m_Radius, - aCircleToSegmentsCount ) ; + TransformCircleToPolygon( aux_polyset, bshape.m_Start, bshape.m_Radius, numSegs ); break; + } case S_POLYGON: // polygon if( bshape.m_Poly.size() < 2 ) @@ -268,7 +276,9 @@ bool D_PAD::buildCustomPadPolygon( SHAPE_POLY_SET* aMergedPolygon, polyset.Append( poly[ii].x, poly[ii].y ); } - polyset.Inflate( bshape.m_Thickness/2, ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF ); + int numSegs = std::max( + GetArcToSegmentCount( bshape.m_Thickness / 2, aError, 360.0 ), 6 ); + polyset.Inflate( bshape.m_Thickness / 2, numSegs ); aux_polyset.Append( polyset ); } @@ -300,8 +310,7 @@ bool D_PAD::buildCustomPadPolygon( SHAPE_POLY_SET* aMergedPolygon, * return true if OK, false in there is more than one polygon * in aMergedPolygon */ -bool D_PAD::MergePrimitivesAsPolygon( SHAPE_POLY_SET* aMergedPolygon, - int aCircleToSegmentsCount ) +bool D_PAD::MergePrimitivesAsPolygon( SHAPE_POLY_SET* aMergedPolygon ) { // if aMergedPolygon == NULL, use m_customShapeAsPolygon as target @@ -316,19 +325,23 @@ bool D_PAD::MergePrimitivesAsPolygon( SHAPE_POLY_SET* aMergedPolygon, { default: case PAD_SHAPE_CIRCLE: - TransformCircleToPolygon( *aMergedPolygon, wxPoint( 0,0 ), GetSize().x/2, - aCircleToSegmentsCount ); - break; + { + int numSegs = std::max( GetArcToSegmentCount( GetSize().x / 2, ARC_HIGH_DEF, 360.0 ), 6 ); + TransformCircleToPolygon( *aMergedPolygon, wxPoint( 0, 0 ), GetSize().x / 2, numSegs ); - case PAD_SHAPE_RECT: - { - SHAPE_RECT rect( -GetSize().x/2, -GetSize().y/2, GetSize().x, GetSize().y ); - aMergedPolygon->AddOutline( rect.Outline() ); - } break; } - if ( !buildCustomPadPolygon( aMergedPolygon, aCircleToSegmentsCount ) ) + case PAD_SHAPE_RECT: + { + SHAPE_RECT rect( -GetSize().x / 2, -GetSize().y / 2, GetSize().x, GetSize().y ); + aMergedPolygon->AddOutline( rect.Outline() ); + + break; + } + } + + if( !buildCustomPadPolygon( aMergedPolygon, ARC_HIGH_DEF ) ) return false; m_boundingRadius = -1; // The current bouding radius is no more valid. @@ -364,7 +377,7 @@ bool D_PAD::GetBestAnchorPosition( VECTOR2I& aPos ) { SHAPE_POLY_SET poly; - if ( !buildCustomPadPolygon( &poly, ARC_APPROX_SEGMENTS_COUNT_LOW_DEF ) ) + if( !buildCustomPadPolygon( &poly, ARC_LOW_DEF ) ) return false; const int minSteps = 10; diff --git a/pcbnew/pad_draw_functions.cpp b/pcbnew/pad_draw_functions.cpp index ee8f55668a..819777af3b 100644 --- a/pcbnew/pad_draw_functions.cpp +++ b/pcbnew/pad_draw_functions.cpp @@ -28,20 +28,20 @@ * @file class_pad_draw_functions.cpp */ -#include -#include -#include -#include -#include +#include #include +#include +#include #include +#include +#include +#include #include #include -#include // ID_TRACK_BUTT +#include #include -#include -#include - +#include // ID_TRACK_BUTT +#include /* uncomment this line to show this pad with its specfic size and color @@ -420,7 +420,7 @@ void D_PAD::DrawShape( EDA_RECT* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo ) if( aDrawInfo.m_PadClearance ) { SHAPE_POLY_SET outline; - TransformShapeWithClearanceToPolygon( outline, aDrawInfo.m_PadClearance, ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF, 1.0 ); + TransformShapeWithClearanceToPolygon( outline, aDrawInfo.m_PadClearance ); // Draw the polygon: Inflate creates only one convex polygon if( outline.OutlineCount() > 0 ) @@ -527,11 +527,12 @@ void D_PAD::DrawShape( EDA_RECT* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo ) CustomShapeAsPolygonToBoardPosition( &outline, pad_pos, GetOrientation() ); SHAPE_LINE_CHAIN* poly; - const int segmentToCircleCount = ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF; - if( aDrawInfo.m_Mask_margin.x ) - outline.InflateWithLinkedHoles( aDrawInfo.m_Mask_margin.x, - segmentToCircleCount, SHAPE_POLY_SET::PM_FAST ); + { + int numSegs = GetArcToSegmentCount( aDrawInfo.m_Mask_margin.x, ARC_HIGH_DEF, 360.0 ); + outline.InflateWithLinkedHoles( + aDrawInfo.m_Mask_margin.x, numSegs, SHAPE_POLY_SET::PM_FAST ); + } // Draw the polygon: only one polygon is expected // However we provide a multi polygon shape drawing @@ -550,8 +551,9 @@ void D_PAD::DrawShape( EDA_RECT* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo ) SHAPE_POLY_SET clearance_outline; clearance_outline.Append( outline ); - clearance_outline.InflateWithLinkedHoles( aDrawInfo.m_PadClearance, - segmentToCircleCount, SHAPE_POLY_SET::PM_FAST ); + int numSegs = GetArcToSegmentCount( aDrawInfo.m_PadClearance, ARC_HIGH_DEF, 360.0 ); + clearance_outline.InflateWithLinkedHoles( + aDrawInfo.m_PadClearance, numSegs, SHAPE_POLY_SET::PM_FAST ); for( int jj = 0; jj < clearance_outline.OutlineCount(); ++jj ) { @@ -565,6 +567,7 @@ void D_PAD::DrawShape( EDA_RECT* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo ) } } } + break; } } diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp index 73c5f08d7f..14a3b85630 100644 --- a/pcbnew/pcb_painter.cpp +++ b/pcbnew/pcb_painter.cpp @@ -40,8 +40,9 @@ #include #include -#include #include +#include +#include #include using namespace KIGFX; @@ -845,11 +846,11 @@ void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer ) { SHAPE_POLY_SET outline; outline.Append( aPad->GetCustomShapeAsPolygon() ); - const int segmentToCircleCount = ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF; // outline polygon can have holes linked to the main outline. // So use InflateWithLinkedHoles(), not Inflate() that can create // bad shapes if custom_margin is < 0 - outline.InflateWithLinkedHoles( custom_margin, segmentToCircleCount, SHAPE_POLY_SET::PM_FAST ); + int numSegs = std::max( GetArcToSegmentCount( custom_margin, ARC_HIGH_DEF, 360.0 ), 6 ); + outline.InflateWithLinkedHoles( custom_margin, numSegs, SHAPE_POLY_SET::PM_FAST ); m_gal->DrawPolygon( outline ); } else @@ -900,8 +901,7 @@ void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer ) || aLayer == LAYER_PADS_TH ) ) { SHAPE_POLY_SET polySet; - constexpr int SEGCOUNT = 64; - aPad->TransformShapeWithClearanceToPolygon( polySet, aPad->GetClearance(), SEGCOUNT, 1.0 ); + aPad->TransformShapeWithClearanceToPolygon( polySet, aPad->GetClearance() ); m_gal->SetLineWidth( m_pcbSettings.m_outlineWidth ); m_gal->SetIsStroke( true ); m_gal->SetIsFill( false ); diff --git a/pcbnew/plot_board_layers.cpp b/pcbnew/plot_board_layers.cpp index 72f2740136..3f1e843389 100644 --- a/pcbnew/plot_board_layers.cpp +++ b/pcbnew/plot_board_layers.cpp @@ -450,12 +450,12 @@ void PlotStandardLayer( BOARD *aBoard, PLOTTER* aPlotter, D_PAD dummy( *pad ); SHAPE_POLY_SET shape; - pad->MergePrimitivesAsPolygon( &shape, 64 ); + pad->MergePrimitivesAsPolygon( &shape ); // shape polygon can have holes linked to the main outline. // So use InflateWithLinkedHoles(), not Inflate() that can create // bad shapes if margin.x is < 0 - shape.InflateWithLinkedHoles( margin.x, ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF, - SHAPE_POLY_SET::PM_FAST ); + int numSegs = std::max( GetArcToSegmentCount( margin.x, ARC_HIGH_DEF, 360.0 ), 6 ); + shape.InflateWithLinkedHoles( margin.x, numSegs, SHAPE_POLY_SET::PM_FAST ); dummy.DeletePrimitivesList(); dummy.AddPrimitive( shape, 0 ); dummy.MergePrimitivesAsPolygon(); @@ -801,21 +801,13 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, SHAPE_POLY_SET areas; // Contains shapes to plot SHAPE_POLY_SET initialPolys; // Contains exact shapes to plot - /* calculates the coeff to compensate radius reduction of holes clearance - * due to the segment approx ( 1 /cos( PI/circleToSegmentsCount ) - */ - int circleToSegmentsCount = ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF; - double correction = GetCircletoPolyCorrectionFactor( circleToSegmentsCount ); - // Plot pads for( MODULE* module = aBoard->m_Modules; module; module = module->Next() ) { // add shapes with exact size - module->TransformPadsShapesWithClearanceToPolygon( layer, - initialPolys, 0, circleToSegmentsCount, correction ); + module->TransformPadsShapesWithClearanceToPolygon( layer, initialPolys, 0 ); // add shapes inflated by aMinThickness/2 - module->TransformPadsShapesWithClearanceToPolygon( layer, - areas, inflate, circleToSegmentsCount, correction ); + module->TransformPadsShapesWithClearanceToPolygon( layer, areas, inflate ); } // Plot vias on solder masks, if aPlotOpt.GetPlotViaOnMaskLayer() is true, @@ -846,12 +838,8 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, if( !( via_set & aLayerMask ).any() ) continue; - via->TransformShapeWithClearanceToPolygon( areas, via_margin, - circleToSegmentsCount, - correction ); - via->TransformShapeWithClearanceToPolygon( initialPolys, via_clearance, - circleToSegmentsCount, - correction ); + via->TransformShapeWithClearanceToPolygon( areas, via_margin ); + via->TransformShapeWithClearanceToPolygon( initialPolys, via_clearance ); } } @@ -869,10 +857,8 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, if( zone->GetLayer() != layer ) continue; - zone->TransformOutlinesShapeWithClearanceToPolygon( areas, - inflate+zone_margin, false ); - zone->TransformOutlinesShapeWithClearanceToPolygon( initialPolys, - zone_margin, false ); + zone->TransformOutlinesShapeWithClearanceToPolygon( areas, inflate + zone_margin, false ); + zone->TransformOutlinesShapeWithClearanceToPolygon( initialPolys, zone_margin, false ); } // To avoid a lot of code, use a ZONE_CONTAINER @@ -885,9 +871,10 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, zone.SetArcSegmentCount( ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF ); zone.SetMinThickness( 0 ); // trace polygons only zone.SetLayer ( layer ); + int numSegs = std::max( GetArcToSegmentCount( inflate, ARC_HIGH_DEF, 360.0 ), 6 ); areas.BooleanAdd( initialPolys, SHAPE_POLY_SET::PM_FAST ); - areas.Inflate( -inflate, circleToSegmentsCount ); + areas.Inflate( -inflate, numSegs ); // Combine the current areas to initial areas. This is mandatory because // inflate/deflate transform is not perfect, and we want the initial areas perfectly kept diff --git a/pcbnew/plot_brditems_plotter.cpp b/pcbnew/plot_brditems_plotter.cpp index 03dcb871fd..af853a937b 100644 --- a/pcbnew/plot_brditems_plotter.cpp +++ b/pcbnew/plot_brditems_plotter.cpp @@ -201,7 +201,7 @@ void BRDITEMS_PLOTTER::PlotPad( D_PAD* aPad, COLOR4D aColor, EDA_DRAW_MODE_T aPl case PAD_SHAPE_CUSTOM: { SHAPE_POLY_SET polygons; - aPad->MergePrimitivesAsPolygon(&polygons, 64 ); + aPad->MergePrimitivesAsPolygon( &polygons ); if( polygons.OutlineCount() == 0 ) break; diff --git a/pcbnew/router/pns_kicad_iface.cpp b/pcbnew/router/pns_kicad_iface.cpp index 3e2332d3ef..7d9ead406b 100644 --- a/pcbnew/router/pns_kicad_iface.cpp +++ b/pcbnew/router/pns_kicad_iface.cpp @@ -616,9 +616,7 @@ std::unique_ptr PNS_KICAD_IFACE::syncPad( D_PAD* aPad ) case PAD_SHAPE_ROUNDRECT: { SHAPE_POLY_SET outline; - const int segmentToCircleCount = 64; - - aPad->BuildPadShapePolygon( outline, wxSize( 0, 0 ), segmentToCircleCount, 1.0 ); + aPad->BuildPadShapePolygon( outline, wxSize( 0, 0 ) ); // TransformRoundRectToPolygon creates only one convex polygon SHAPE_LINE_CHAIN& poly = outline.Outline( 0 ); @@ -711,9 +709,7 @@ std::unique_ptr PNS_KICAD_IFACE::syncPad( D_PAD* aPad ) case PAD_SHAPE_ROUNDRECT: { SHAPE_POLY_SET outline; - const int segmentToCircleCount = ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF; - aPad->BuildPadShapePolygon( outline, wxSize( 0, 0 ), - segmentToCircleCount, 1.0 ); + aPad->BuildPadShapePolygon( outline, wxSize( 0, 0 ) ); // TransformRoundRectToPolygon creates only one convex polygon SHAPE_LINE_CHAIN& poly = outline.Outline( 0 ); diff --git a/pcbnew/zone_filler.cpp b/pcbnew/zone_filler.cpp index 497eeaa52c..533c8ebed4 100644 --- a/pcbnew/zone_filler.cpp +++ b/pcbnew/zone_filler.cpp @@ -74,10 +74,9 @@ private: }; -extern void CreateThermalReliefPadPolygon( SHAPE_POLY_SET& aCornerBuffer, - const D_PAD& aPad, int aThermalGap, int aCopperThickness, - int aMinThicknessValue, int aCircleToSegmentsCount, - double aCorrectionFactor, double aThermalRot ); +extern void CreateThermalReliefPadPolygon( SHAPE_POLY_SET& aCornerBuffer, const D_PAD& aPad, + int aThermalGap, int aCopperThickness, int aMinThicknessValue, int aError, + double aThermalRot ); static double s_thermalRot = 450; // angle of stubs in thermal reliefs for round pads static const bool s_DumpZonesWhenFilling = false; @@ -138,7 +137,8 @@ bool ZONE_FILLER::Fill( const std::vector& aZones, bool aCheck } std::atomic nextItem( 0 ); - size_t parallelThreadCount = std::min( std::thread::hardware_concurrency(), toFill.size() ); + size_t parallelThreadCount = + std::min( std::thread::hardware_concurrency(), aZones.size() ); std::vector> returns( parallelThreadCount ); auto fill_lambda = [&] ( PROGRESS_REPORTER* aReporter ) -> size_t @@ -218,12 +218,18 @@ bool ZONE_FILLER::Fill( const std::vector& aZones, bool aCheck } } // Zones with no net can have areas outside the board cutouts. - // Please, use only this clipping for no-net zones: this is a very time consumming - // calculation (x 5 in a test case if made for all zones), mainly due to poly.Fracture + // By definition, the island has all points outside the outline, so we only + // need to check one point for each island else if( clip_to_brd_outlines ) { - poly.BooleanIntersection( boardOutline, SHAPE_POLY_SET::PM_FAST ); - poly.Fracture( SHAPE_POLY_SET::PM_FAST ); + for( auto idx : zone.m_islands ) + { + if( poly.Polygon( idx ).empty() + || !boardOutline.Contains( poly.Polygon( idx ).front().CPoint( 0 ) ) ) + { + poly.DeletePolygon( idx ); + } + } } zone.m_zone->SetFilledPolysList( poly ); @@ -326,20 +332,6 @@ bool ZONE_FILLER::Fill( const std::vector& aZones, bool aCheck void ZONE_FILLER::buildZoneFeatureHoleList( const ZONE_CONTAINER* aZone, SHAPE_POLY_SET& aFeatures ) const { - // Set the number of segments in arc approximations - // Since we can no longer edit the segment count in pcbnew, we set - // the fill to our high-def count to avoid jagged knock-outs - // However, if the user has edited their zone to increase the segment count, - // we keep this preference - int segsPerCircle = std::max( aZone->GetArcSegmentCount(), ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF ); - - /* calculates the coeff to compensate radius reduction of holes clearance - * due to the segment approx. - * For a circle the min radius is radius * cos( 2PI / segsPerCircle / 2) - * correctionFactor is 1 /cos( PI/segsPerCircle ) - */ - double correctionFactor = GetCircletoPolyCorrectionFactor( segsPerCircle ); - aFeatures.RemoveAllContours(); int zone_clearance = aZone->GetClearance(); @@ -428,9 +420,12 @@ void ZONE_FILLER::buildZoneFeatureHoleList( const ZONE_CONTAINER* aZone, // the pad shape in zone can be its convex hull or // the shape itself SHAPE_POLY_SET outline( pad->GetCustomShapeAsPolygon() ); - outline.Inflate( KiROUND( clearance * correctionFactor ), segsPerCircle ); - pad->CustomShapeAsPolygonToBoardPosition( &outline, - pad->GetPosition(), pad->GetOrientation() ); + int numSegs = std::max( + GetArcToSegmentCount( clearance, ARC_HIGH_DEF, 360.0 ), 6 ); + double correction = GetCircletoPolyCorrectionFactor( numSegs ); + outline.Inflate( KiROUND( clearance * correction ), numSegs ); + pad->CustomShapeAsPolygonToBoardPosition( + &outline, pad->GetPosition(), pad->GetOrientation() ); if( pad->GetCustomShapeInZoneOpt() == CUST_PAD_SHAPE_IN_ZONE_CONVEXHULL ) { @@ -446,10 +441,7 @@ void ZONE_FILLER::buildZoneFeatureHoleList( const ZONE_CONTAINER* aZone, aFeatures.Append( outline ); } else - pad->TransformShapeWithClearanceToPolygon( aFeatures, - clearance, - segsPerCircle, - correctionFactor ); + pad->TransformShapeWithClearanceToPolygon( aFeatures, clearance ); } continue; @@ -477,10 +469,13 @@ void ZONE_FILLER::buildZoneFeatureHoleList( const ZONE_CONTAINER* aZone, { // the pad shape in zone can be its convex hull or // the shape itself + int numSegs = + std::max( GetArcToSegmentCount( gap, ARC_HIGH_DEF, 360.0 ), 6 ); + double correction = GetCircletoPolyCorrectionFactor( numSegs ); SHAPE_POLY_SET outline( pad->GetCustomShapeAsPolygon() ); - outline.Inflate( KiROUND( gap * correctionFactor ), segsPerCircle ); - pad->CustomShapeAsPolygonToBoardPosition( &outline, - pad->GetPosition(), pad->GetOrientation() ); + outline.Inflate( KiROUND( gap * correction ), numSegs ); + pad->CustomShapeAsPolygonToBoardPosition( + &outline, pad->GetPosition(), pad->GetOrientation() ); std::vector convex_hull; BuildConvexHull( convex_hull, outline ); @@ -491,8 +486,7 @@ void ZONE_FILLER::buildZoneFeatureHoleList( const ZONE_CONTAINER* aZone, aFeatures.Append( convex_hull[ii] ); } else - pad->TransformShapeWithClearanceToPolygon( aFeatures, - gap, segsPerCircle, correctionFactor ); + pad->TransformShapeWithClearanceToPolygon( aFeatures, gap ); } } } @@ -515,8 +509,7 @@ void ZONE_FILLER::buildZoneFeatureHoleList( const ZONE_CONTAINER* aZone, if( item_boundingbox.Intersects( zone_boundingbox ) ) { int clearance = std::max( zone_clearance, item_clearance ); - track->TransformShapeWithClearanceToPolygon( aFeatures, - clearance, segsPerCircle, correctionFactor ); + track->TransformShapeWithClearanceToPolygon( aFeatures, clearance ); } } @@ -549,7 +542,7 @@ void ZONE_FILLER::buildZoneFeatureHoleList( const ZONE_CONTAINER* aZone, { case PCB_LINE_T: static_cast( aItem )->TransformShapeWithClearanceToPolygon( - aFeatures, zclearance, segsPerCircle, correctionFactor, ignoreLineWidth ); + aFeatures, zclearance, ARC_HIGH_DEF, ignoreLineWidth ); break; case PCB_TEXT_T: @@ -559,7 +552,7 @@ void ZONE_FILLER::buildZoneFeatureHoleList( const ZONE_CONTAINER* aZone, case PCB_MODULE_EDGE_T: static_cast( aItem )->TransformShapeWithClearanceToPolygon( - aFeatures, zclearance, segsPerCircle, correctionFactor, ignoreLineWidth ); + aFeatures, zclearance, ARC_HIGH_DEF, ignoreLineWidth ); break; case PCB_MODULE_TEXT_T: @@ -667,12 +660,9 @@ void ZONE_FILLER::buildZoneFeatureHoleList( const ZONE_CONTAINER* aZone, if( item_boundingbox.Intersects( zone_boundingbox ) ) { - CreateThermalReliefPadPolygon( aFeatures, - *pad, thermalGap, - aZone->GetThermalReliefCopperBridge( pad ), - aZone->GetMinThickness(), - segsPerCircle, - correctionFactor, s_thermalRot ); + CreateThermalReliefPadPolygon( aFeatures, *pad, thermalGap, + aZone->GetThermalReliefCopperBridge( pad ), aZone->GetMinThickness(), + ARC_HIGH_DEF, s_thermalRot ); } } } @@ -717,19 +707,16 @@ void ZONE_FILLER::computeRawFilledAreas( const ZONE_CONTAINER* aZone, std::unique_ptr dumper( new SHAPE_FILE_IO( s_DumpZonesWhenFilling ? "zones_dump.txt" : "", SHAPE_FILE_IO::IOM_APPEND ) ); - // Set the number of segments in arc approximations - int segsPerCircle = std::max( aZone->GetArcSegmentCount(), ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF ); - - /* calculates the coeff to compensate radius reduction of holes clearance - */ - double correctionFactor = GetCircletoPolyCorrectionFactor( segsPerCircle ); - if( s_DumpZonesWhenFilling ) dumper->BeginGroup( "clipper-zone" ); SHAPE_POLY_SET solidAreas = aSmoothedOutline; - solidAreas.Inflate( -outline_half_thickness, segsPerCircle ); + int numSegs = + std::max( GetArcToSegmentCount( outline_half_thickness, ARC_HIGH_DEF, 360.0 ), 6 ); + double correction = GetCircletoPolyCorrectionFactor( numSegs ); + + solidAreas.Inflate( -outline_half_thickness, numSegs ); solidAreas.Simplify( SHAPE_POLY_SET::PM_FAST ); SHAPE_POLY_SET holes; @@ -788,9 +775,8 @@ void ZONE_FILLER::computeRawFilledAreas( const ZONE_CONTAINER* aZone, if( aZone->GetNetCode() > 0 ) { - buildUnconnectedThermalStubsPolygonList( thermalHoles, aZone, solidAreas, - correctionFactor, s_thermalRot ); - + buildUnconnectedThermalStubsPolygonList( + thermalHoles, aZone, solidAreas, correction, s_thermalRot ); } // remove copper areas corresponding to not connected stubs @@ -853,7 +839,9 @@ bool ZONE_FILLER::fillSingleZone( ZONE_CONTAINER* aZone, SHAPE_POLY_SET& aRawPol } else { - aFinalPolys.Inflate( -aZone->GetMinThickness() / 2, ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF ); + int numSegs = std::max( + GetArcToSegmentCount( aZone->GetMinThickness() / 2, ARC_HIGH_DEF, 360.0 ), 6 ); + aFinalPolys.Inflate( -aZone->GetMinThickness() / 2, numSegs ); // Remove the non filled areas due to the hatch pattern if( aZone->GetFillMode() == ZFM_HATCH_PATTERN ) diff --git a/qa/pcbnew_tools/tools/polygon_generator/polygon_generator.cpp b/qa/pcbnew_tools/tools/polygon_generator/polygon_generator.cpp index 8aba10b90a..1def32e1bf 100644 --- a/qa/pcbnew_tools/tools/polygon_generator/polygon_generator.cpp +++ b/qa/pcbnew_tools/tools/polygon_generator/polygon_generator.cpp @@ -46,12 +46,7 @@ void process( const BOARD_CONNECTED_ITEM* item, int net ) SHAPE_POLY_SET pset; - const int segsPerCircle = 64; - - double correctionFactor = 1.0 / cos( M_PI / (double) segsPerCircle ); - - - item->TransformShapeWithClearanceToPolygon( pset, 1, segsPerCircle, correctionFactor ); + item->TransformShapeWithClearanceToPolygon( pset, 1, ARC_HIGH_DEF ); SHAPE_FILE_IO shapeIo; // default = stdout shapeIo.Write( &pset ); @@ -114,4 +109,4 @@ KI_TEST::UTILITY_PROGRAM polygon_generator_tool = { "polygon_generator", "Dump board geometry as a set of polygons", polygon_gererator_main, -}; \ No newline at end of file +};