Give Clipper1 a Viking funeral

Clears out the last spot where we were only using Clipper1 (how'd I
miss that?) and remove all calls to the Clipper1 structures
This commit is contained in:
Seth Hillbrand 2024-12-23 17:10:54 -08:00
parent fd137279c8
commit e9bc8cfe9d
88 changed files with 274 additions and 7298 deletions

View File

@ -947,9 +947,7 @@ bool BOARD_ADAPTER::createBoardPolygon( wxString* aErrorMsg )
success = BuildFootprintPolygonOutlines( m_board, m_board_poly,
m_board->GetDesignSettings().m_MaxError,
chainingEpsilon );
// Make polygon strictly simple to avoid issues (especially in 3D viewer)
m_board_poly.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
m_board_poly.Simplify();
if( !success && aErrorMsg )
{

View File

@ -650,7 +650,7 @@ void BOARD_ADAPTER::addShape( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aConta
aShape->TransformShapeToPolygon( polyList, UNDEFINED_LAYER, 0, ARC_HIGH_DEF,
ERROR_INSIDE );
polyList.Simplify( SHAPE_POLY_SET::PM_FAST );
polyList.Simplify();
if( margin != 0 )
{
@ -700,7 +700,7 @@ void BOARD_ADAPTER::addShape( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aConta
// Some polygons can be a bit complex (especially when coming from a
// picture ot a text converted to a polygon
// So call Simplify before calling ConvertPolygonToTriangles, just in case.
polyList.Simplify( SHAPE_POLY_SET::PM_FAST );
polyList.Simplify();
if( polyList.IsEmpty() ) // Just for caution
break;

View File

@ -780,10 +780,10 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
// End Build Copper layers
// This will make a union of all added contours
m_TH_ODPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
m_NPTH_ODPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
m_viaTH_ODPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
m_viaAnnuliPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
m_TH_ODPolys.Simplify();
m_NPTH_ODPolys.Simplify();
m_viaTH_ODPolys.Simplify();
m_viaAnnuliPolys.Simplify();
// Build Tech layers
// Based on:
@ -1022,7 +1022,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
}
// This will make a union of all added contours
layerPoly->Simplify( SHAPE_POLY_SET::PM_FAST );
layerPoly->Simplify();
}
}
// End Build Tech layers
@ -1061,14 +1061,12 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
// TRIM PLATED COPPER TO SOLDERMASK
if( m_layers_poly.find( F_Mask ) != m_layers_poly.end() )
{
m_frontPlatedCopperPolys->BooleanIntersection( *m_layers_poly.at( F_Mask ),
SHAPE_POLY_SET::PM_FAST );
m_frontPlatedCopperPolys->BooleanIntersection( *m_layers_poly.at( F_Mask ) );
}
if( m_layers_poly.find( B_Mask ) != m_layers_poly.end() )
{
m_backPlatedCopperPolys->BooleanIntersection( *m_layers_poly.at( B_Mask ),
SHAPE_POLY_SET::PM_FAST );
m_backPlatedCopperPolys->BooleanIntersection( *m_layers_poly.at( B_Mask ) );
}
// Subtract plated copper from unplated copper
@ -1077,15 +1075,15 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
if( m_layers_poly.find( F_Cu ) != m_layers_poly.end() )
{
m_layers_poly[F_Cu]->BooleanSubtract( *m_frontPlatedPadAndGraphicPolys, SHAPE_POLY_SET::PM_FAST );
m_layers_poly[F_Cu]->BooleanSubtract( *m_frontPlatedCopperPolys, SHAPE_POLY_SET::PM_FAST );
m_layers_poly[F_Cu]->BooleanSubtract( *m_frontPlatedPadAndGraphicPolys );
m_layers_poly[F_Cu]->BooleanSubtract( *m_frontPlatedCopperPolys );
hasF_Cu = true;
}
if( m_layers_poly.find( B_Cu ) != m_layers_poly.end() )
{
m_layers_poly[B_Cu]->BooleanSubtract( *m_backPlatedPadAndGraphicPolys, SHAPE_POLY_SET::PM_FAST );
m_layers_poly[B_Cu]->BooleanSubtract( *m_backPlatedCopperPolys, SHAPE_POLY_SET::PM_FAST );
m_layers_poly[B_Cu]->BooleanSubtract( *m_backPlatedPadAndGraphicPolys );
m_layers_poly[B_Cu]->BooleanSubtract( *m_backPlatedCopperPolys );
hasB_Cu = true;
}
@ -1096,10 +1094,10 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
if( hasB_Cu && m_backPlatedCopperPolys->OutlineCount() )
m_backPlatedPadAndGraphicPolys->Append( *m_backPlatedCopperPolys );
m_frontPlatedPadAndGraphicPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
m_backPlatedPadAndGraphicPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
m_frontPlatedCopperPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
m_backPlatedCopperPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
m_frontPlatedPadAndGraphicPolys->Simplify();
m_backPlatedPadAndGraphicPolys->Simplify();
m_frontPlatedCopperPolys->Simplify();
m_backPlatedCopperPolys->Simplify();
// ADD PLATED PADS
for( FOOTPRINT* footprint : m_board->Footprints() )
@ -1168,7 +1166,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
{
// This will make a union of all added contours
layerPoly->second->ClearArcs();
layerPoly->second->Simplify( SHAPE_POLY_SET::PM_FAST );
layerPoly->second->Simplify();
}
}
@ -1193,12 +1191,12 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
{
// found
SHAPE_POLY_SET *polyLayer = m_layerHoleOdPolys[layer];
polyLayer->Simplify( SHAPE_POLY_SET::PM_FAST );
polyLayer->Simplify();
wxASSERT( m_layerHoleIdPolys.find( layer ) != m_layerHoleIdPolys.end() );
polyLayer = m_layerHoleIdPolys[layer];
polyLayer->Simplify( SHAPE_POLY_SET::PM_FAST );
polyLayer->Simplify();
}
}

View File

@ -476,13 +476,12 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
m_antiBoardPolys.Append( VECTOR2I( -INT_MAX/2, INT_MAX/2 ) );
m_antiBoardPolys.Outline( 0 ).SetClosed( true );
m_antiBoardPolys.BooleanSubtract( m_boardAdapter.GetBoardPoly(),
SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
m_antiBoardPolys.BooleanSubtract( m_boardAdapter.GetBoardPoly() );
m_antiBoard = createBoard( m_antiBoardPolys );
SHAPE_POLY_SET board_poly_with_holes = m_boardAdapter.GetBoardPoly().CloneDropTriangulation();
board_poly_with_holes.BooleanSubtract( m_boardAdapter.GetTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
board_poly_with_holes.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
board_poly_with_holes.BooleanSubtract( m_boardAdapter.GetTH_ODPolys() );
board_poly_with_holes.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys() );
m_boardWithHoles = createBoard( board_poly_with_holes );
@ -495,8 +494,7 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
SHAPE_POLY_SET outerPolyTHT = m_boardAdapter.GetTH_ODPolys().CloneDropTriangulation();
outerPolyTHT.BooleanIntersection( m_boardAdapter.GetBoardPoly(),
SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
outerPolyTHT.BooleanIntersection( m_boardAdapter.GetBoardPoly() );
m_outerThroughHoles = generateHoles( m_boardAdapter.GetTH_ODs().GetList(), outerPolyTHT,
1.0f, 0.0f, false, &m_boardAdapter.GetTH_IDs() );
@ -575,29 +573,24 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
if( LSET::PhysicalLayersMask().test( layer ) )
{
polyListSubtracted.BooleanIntersection( m_boardAdapter.GetBoardPoly(),
SHAPE_POLY_SET::PM_FAST );
polyListSubtracted.BooleanIntersection( m_boardAdapter.GetBoardPoly() );
}
if( layer != B_Mask && layer != F_Mask )
{
polyListSubtracted.BooleanSubtract( m_boardAdapter.GetTH_ODPolys(),
SHAPE_POLY_SET::PM_FAST );
polyListSubtracted.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys(),
SHAPE_POLY_SET::PM_FAST );
polyListSubtracted.BooleanSubtract( m_boardAdapter.GetTH_ODPolys() );
polyListSubtracted.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys() );
}
if( m_boardAdapter.m_Cfg->m_Render.subtract_mask_from_silk )
{
if( layer == B_SilkS && map_poly.find( B_Mask ) != map_poly.end() )
{
polyListSubtracted.BooleanSubtract( *map_poly.at( B_Mask ),
SHAPE_POLY_SET::PM_FAST );
polyListSubtracted.BooleanSubtract( *map_poly.at( B_Mask ) );
}
else if( layer == F_SilkS && map_poly.find( F_Mask ) != map_poly.end() )
{
polyListSubtracted.BooleanSubtract( *map_poly.at( F_Mask ),
SHAPE_POLY_SET::PM_FAST );
polyListSubtracted.BooleanSubtract( *map_poly.at( F_Mask ) );
}
}
@ -620,9 +613,9 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
if( frontPlatedPadAndGraphicPolys )
{
SHAPE_POLY_SET poly = frontPlatedPadAndGraphicPolys->CloneDropTriangulation();
poly.BooleanIntersection( m_boardAdapter.GetBoardPoly(), SHAPE_POLY_SET::PM_FAST );
poly.BooleanSubtract( m_boardAdapter.GetTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
poly.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
poly.BooleanIntersection( m_boardAdapter.GetBoardPoly() );
poly.BooleanSubtract( m_boardAdapter.GetTH_ODPolys() );
poly.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys() );
m_platedPadsFront = generateLayerList( m_boardAdapter.GetPlatedPadsFront(), &poly, F_Cu );
@ -634,9 +627,9 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
if( backPlatedPadAndGraphicPolys )
{
SHAPE_POLY_SET poly = backPlatedPadAndGraphicPolys->CloneDropTriangulation();
poly.BooleanIntersection( m_boardAdapter.GetBoardPoly(), SHAPE_POLY_SET::PM_FAST );
poly.BooleanSubtract( m_boardAdapter.GetTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
poly.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
poly.BooleanIntersection( m_boardAdapter.GetBoardPoly() );
poly.BooleanSubtract( m_boardAdapter.GetTH_ODPolys() );
poly.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys() );
m_platedPadsBack = generateLayerList( m_boardAdapter.GetPlatedPadsBack(), &poly, B_Cu );
@ -839,9 +832,9 @@ void RENDER_3D_OPENGL::generateViasAndPads()
}
// Subtract the holes
tht_outer_holes_poly.BooleanSubtract( tht_inner_holes_poly, SHAPE_POLY_SET::PM_FAST );
tht_outer_holes_poly.BooleanSubtract( tht_inner_holes_poly );
tht_outer_holes_poly.BooleanSubtract( m_antiBoardPolys, SHAPE_POLY_SET::PM_FAST );
tht_outer_holes_poly.BooleanSubtract( m_antiBoardPolys );
CONTAINER_2D holesContainer;

View File

@ -415,8 +415,8 @@ void RENDER_3D_RAYTRACE_BASE::Reload( REPORTER* aStatusReporter, REPORTER* aWarn
buildBoardBoundingBoxPoly( m_boardAdapter.GetBoard(), antiboardPoly );
antiboardPoly.BooleanSubtract( boardPolyCopy, SHAPE_POLY_SET::PM_FAST );
antiboardPoly.Fracture( SHAPE_POLY_SET::PM_FAST );
antiboardPoly.BooleanSubtract( boardPolyCopy );
antiboardPoly.Fracture();
for( int ii = 0; ii < antiboardPoly.OutlineCount(); ii++ )
{
@ -427,7 +427,7 @@ void RENDER_3D_RAYTRACE_BASE::Reload( REPORTER* aStatusReporter, REPORTER* aWarn
m_antioutlineBoard2dObjects->BuildBVH();
boardPolyCopy.Fracture( SHAPE_POLY_SET::PM_FAST );
boardPolyCopy.Fracture();
for( int ii = 0; ii < outlineCount; ii++ )
{

View File

@ -612,10 +612,9 @@ void ConvertPolygonToBlocks( const SHAPE_POLY_SET& aMainPath, CONTAINER_2D_BASE&
subBlockPoly.AddOutline( sb );
// We need here a strictly simple polygon with outlines and holes
// We need here a simple polygon with outlines and holes
SHAPE_POLY_SET solution;
solution.BooleanIntersection( aMainPath, subBlockPoly,
SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
solution.BooleanIntersection( aMainPath, subBlockPoly );
OUTERS_AND_HOLES outersAndHoles;
@ -659,68 +658,3 @@ void ConvertPolygonToBlocks( const SHAPE_POLY_SET& aMainPath, CONTAINER_2D_BASE&
topToBottom += topToBottom_inc;
}
}
#ifdef DEBUG
static void polygon_Convert( const ClipperLib::Path& aPath, SEGMENTS& aOutSegment,
float aBiuTo3dUnitsScale )
{
aOutSegment.resize( aPath.size() );
for( unsigned i = 0; i < aPath.size(); i++ )
{
aOutSegment[i].m_Start = SFVEC2F(
(float) aPath[i].X * aBiuTo3dUnitsScale, (float) -aPath[i].Y * aBiuTo3dUnitsScale );
}
unsigned int i;
unsigned int j = aOutSegment.size() - 1;
for( i = 0; i < aOutSegment.size(); j = i++ )
{
// Calculate constants for each segment
aOutSegment[i].m_inv_JY_minus_IY =
1.0f / ( aOutSegment[j].m_Start.y - aOutSegment[i].m_Start.y );
aOutSegment[i].m_JX_minus_IX = ( aOutSegment[j].m_Start.x - aOutSegment[i].m_Start.x );
}
}
void Polygon2d_TestModule()
{
// "This structure contains a sequence of IntPoint vertices defining a single contour"
ClipperLib::Path aPath;
SEGMENTS aSegments;
aPath.resize( 4 );
aPath[0] = ClipperLib::IntPoint( -2, -2 );
aPath[1] = ClipperLib::IntPoint( 2, -2 );
aPath[2] = ClipperLib::IntPoint( 2, 2 );
aPath[3] = ClipperLib::IntPoint( -2, 2 );
// It must be an outer polygon
wxASSERT( ClipperLib::Orientation( aPath ) );
polygon_Convert( aPath, aSegments, 1.0f );
wxASSERT( aPath.size() == aSegments.size() );
wxASSERT( aSegments[0].m_Start == SFVEC2F( -2.0f, 2.0f ) );
wxASSERT( aSegments[1].m_Start == SFVEC2F( 2.0f, 2.0f ) );
wxASSERT( aSegments[2].m_Start == SFVEC2F( 2.0f, -2.0f ) );
wxASSERT( aSegments[3].m_Start == SFVEC2F( -2.0f, -2.0f ) );
wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( 0.0f, 0.0f ) ) );
wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( -1.9f, -1.9f ) ) );
wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( -1.9f, 1.9f ) ) );
wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( 1.9f, 1.9f ) ) );
wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( 1.9f, -1.9f ) ) );
wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( -2.1f, -2.0f ) ) == false );
wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( -2.1f, 2.0f ) ) == false );
wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( 2.1f, 2.0f ) ) == false );
wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( 2.1f, -2.0f ) ) == false );
}
#endif

View File

@ -152,6 +152,5 @@ void ConvertPolygonToBlocks( const SHAPE_POLY_SET& aMainPath, CONTAINER_2D_BASE&
float aBiuTo3dUnitsScale, float aDivFactor,
const BOARD_ITEM& aBoardItem, int aPolyIndex );
void Polygon2d_TestModule();
#endif // _CPOLYGON2D_H_

View File

@ -33,7 +33,6 @@
#include "../accelerators/container_2d.h"
#include <geometry/shape_line_chain.h>
#include <geometry/shape_poly_set.h>
#include <clipper.hpp>
class TRIANGLE_2D : public OBJECT_2D
{

View File

@ -524,15 +524,15 @@ void BITMAPCONV_INFO::createOutputData( BMP2CMP_MOD_LAYER aModLayer )
// at the end of a group of a positive path and its negative children, fill.
if( paths->next == nullptr || paths->next->sign == '+' )
{
polyset_areas.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
polyset_holes.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
polyset_areas.BooleanSubtract( polyset_holes, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
polyset_areas.Simplify();
polyset_holes.Simplify();
polyset_areas.BooleanSubtract( polyset_holes );
// Ensure there are no self intersecting polygons
if( polyset_areas.NormalizeAreaOutlines() )
{
// Convert polygon with holes to a unique polygon
polyset_areas.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
polyset_areas.Fracture();
// Output current resulting polygon(s)
for( int ii = 0; ii < polyset_areas.OutlineCount(); ii++ )

View File

@ -98,7 +98,6 @@ static const wxChar AllowManualCanvasScale[] = wxT( "AllowManualCanvasScale" );
static const wxChar UpdateUIEventInterval[] = wxT( "UpdateUIEventInterval" );
static const wxChar V3DRT_BevelHeight_um[] = wxT( "V3DRT_BevelHeight_um" );
static const wxChar V3DRT_BevelExtentFactor[] = wxT( "V3DRT_BevelExtentFactor" );
static const wxChar UseClipper2[] = wxT( "UseClipper2" );
static const wxChar EnableDesignBlocks[] = wxT( "EnableDesignBlocks" );
static const wxChar EnableGenerators[] = wxT( "EnableGenerators" );
static const wxChar EnableGit[] = wxT( "EnableGit" );
@ -263,7 +262,6 @@ ADVANCED_CFG::ADVANCED_CFG()
m_3DRT_BevelHeight_um = 30;
m_3DRT_BevelExtentFactor = 1.0 / 16.0;
m_UseClipper2 = true;
m_EnableAPILogging = false;
m_Use3DConnexionDriver = true;
@ -464,9 +462,6 @@ void ADVANCED_CFG::loadSettings( wxConfigBase& aCfg )
m_3DRT_BevelExtentFactor, 0.0, 100.0,
AC_GROUPS::V3D_RayTracing ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::UseClipper2,
&m_UseClipper2, m_UseClipper2 ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::Use3DConnexionDriver,
&m_Use3DConnexionDriver, m_Use3DConnexionDriver ) );

View File

@ -71,7 +71,7 @@ void CALLBACK_GAL::DrawGlyph( const KIFONT::GLYPH& aGlyph, int aNth, int aTotal
KIFONT::OUTLINE_GLYPH glyph = static_cast<const KIFONT::OUTLINE_GLYPH&>( aGlyph );
if( glyph.HasHoles() )
glyph.Fracture( SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
glyph.Fracture();
for( int ii = 0; ii < glyph.OutlineCount(); ++ii )
m_outlineCallback( glyph.Outline( ii ) );

View File

@ -1022,9 +1022,9 @@ void EDA_DRAW_FRAME::FocusOnLocation( const VECTOR2I& aPos )
{
GetCanvas()->GetView()->SetCenter( aPos, dialogScreenRects );
}
catch( const ClipperLib::clipperException& e )
catch( const Clipper2Lib::Clipper2Exception& e )
{
wxFAIL_MSG( wxString::Format( wxT( "Clipper exception occurred centering object: %s" ),
wxFAIL_MSG( wxString::Format( wxT( "Clipper2 exception occurred centering object: %s" ),
e.what() ) );
}
}

View File

@ -250,9 +250,9 @@ static void convertPolygon( std::list<std::unique_ptr<IMPORTED_SHAPE>>& aShapes,
upscaledPaths.push_back( lc );
}
SHAPE_POLY_SET result = SHAPE_POLY_SET::BuildPolysetFromOrientedPaths(
upscaledPaths, false, aFillRule == GRAPHICS_IMPORTER::PF_EVEN_ODD );
result.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
SHAPE_POLY_SET result;
result.BuildPolysetFromOrientedPaths( upscaledPaths, aFillRule == GRAPHICS_IMPORTER::PF_EVEN_ODD );
result.Fracture();
for( int outl = 0; outl < result.OutlineCount(); outl++ )
{

View File

@ -574,8 +574,8 @@ void DXF_PLOTTER::PlotPoly( const std::vector<VECTOR2I>& aCornerList, FILL_T aFi
// polygon and its thick outline
// create the outline which contains thick outline:
bufferPolybase.BooleanAdd( bufferOutline, SHAPE_POLY_SET::PM_FAST );
bufferPolybase.Fracture( SHAPE_POLY_SET::PM_FAST );
bufferPolybase.BooleanAdd( bufferOutline );
bufferPolybase.Fracture();
if( bufferPolybase.OutlineCount() < 1 ) // should not happen
return;

View File

@ -622,7 +622,7 @@ void VIEW::SetCenter( const VECTOR2D& aCenter, const std::vector<BOX2D>& obscuri
for( const BOX2D& obscuringScreenRect : obscuringScreenRects )
{
SHAPE_POLY_SET obscuringPoly( obscuringScreenRect );
unobscuredPoly.BooleanSubtract( obscuringPoly, SHAPE_POLY_SET::PM_FAST );
unobscuredPoly.BooleanSubtract( obscuringPoly );
}
/*

View File

@ -91,7 +91,7 @@ std::unordered_map<uint32_t, SHAPE_POLY_SET> ConvertImageToPolygons( wxImage im
for( auto& [color, polySet] : colorPolys )
{
polySet.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
polySet.Simplify();
for( int i = 0; i < polySet.OutlineCount(); i++ )
{
@ -114,7 +114,7 @@ void ConvertImageToLibShapes( LIB_SYMBOL* aSymbol, int unit, wxImage img, VECTOR
for( auto& [color, polySet] : colorPolys )
{
polySet.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
polySet.Fracture();
for( const SHAPE_POLY_SET::POLYGON& poly : polySet.CPolygons() )
{

View File

@ -664,8 +664,8 @@ static void knockoutText( KIGFX::GAL& aGal, const wxString& aText, const VECTOR2
finalPoly.Append( bbox.GetRight(), bbox.GetBottom() );
finalPoly.Append( bbox.GetLeft(), bbox.GetBottom() );
finalPoly.BooleanSubtract( knockouts, SHAPE_POLY_SET::PM_FAST );
finalPoly.Fracture( SHAPE_POLY_SET::PM_FAST );
finalPoly.BooleanSubtract( knockouts );
finalPoly.Fracture();
aGal.SetIsStroke( false );
aGal.SetIsFill( true );

View File

@ -124,19 +124,19 @@ SHAPE_POLY_SET* APERTURE_MACRO::GetApertureMacroShape( const GERBER_DRAW_ITEM* a
if( holeBuffer.OutlineCount() ) // we have a new hole in shape: remove the hole
{
m_shape.BooleanSubtract( holeBuffer, SHAPE_POLY_SET::PM_FAST );
m_shape.BooleanSubtract( holeBuffer );
holeBuffer.RemoveAllContours();
}
}
}
// Merge and cleanup basic shape polygons
m_shape.Simplify( SHAPE_POLY_SET::PM_FAST );
m_shape.Simplify();
// A hole can be is defined inside a polygon, or the polygons themselve can create
// a hole when merged, so we must fracture the polygon to be able to drawn it
// (i.e link holes by overlapping edges)
m_shape.Fracture( SHAPE_POLY_SET::PM_FAST );
m_shape.Fracture();
// Move m_shape to the actual draw position:
for( int icnt = 0; icnt < m_shape.OutlineCount(); icnt++ )

View File

@ -448,6 +448,6 @@ static void addHoleToPolygon( SHAPE_POLY_SET* aPolygon, APERTURE_DEF_HOLETYPE aH
holeBuffer.Append( VECTOR2I( currpos ) ); // close hole
}
aPolygon->BooleanSubtract( holeBuffer, SHAPE_POLY_SET::PM_FAST );
aPolygon->Fracture( SHAPE_POLY_SET::PM_FAST );
aPolygon->BooleanSubtract( holeBuffer );
aPolygon->Fracture();
}

View File

@ -574,7 +574,7 @@ void GBR_TO_PCB_EXPORTER::writePcbPolygon( const SHAPE_POLY_SET& aPolys, int aLa
void GBR_TO_PCB_EXPORTER::writePcbZoneItem( const GERBER_DRAW_ITEM* aGbrItem, int aLayer )
{
SHAPE_POLY_SET polys = aGbrItem->m_ShapeAsPolygon.CloneDropTriangulation();
polys.Simplify( SHAPE_POLY_SET::PM_FAST );
polys.Simplify();
if( polys.OutlineCount() == 0 )
return;

View File

@ -428,15 +428,6 @@ public:
*/
double m_3DRT_BevelExtentFactor;
/**
* Use Clipper2 instead of Clipper1.
*
* Setting name: "UseClipper2"
* Valid values: 0 or 1
* Default value: 1
*/
bool m_UseClipper2;
/**
* Use the 3DConnexion Driver.
*

View File

@ -299,7 +299,7 @@ public:
{
if( m_poly.HoleCount( ii ) )
{
m_poly.Fracture( SHAPE_POLY_SET::PM_FAST );
m_poly.Fracture();
break;
}
}

View File

@ -51,7 +51,6 @@ add_library( kimath STATIC
target_link_libraries( kimath
core
clipper
clipper2
othermath
rtree

View File

@ -51,7 +51,6 @@
#include <cmath>
#include <advanced_config.h>
#include <clipper.hpp>
#include <geometry/shape_line_chain.h>
#include <geometry/shape_poly_set.h>
#include <geometry/vertex_set.h>

View File

@ -27,7 +27,6 @@
#define __SHAPE_LINE_CHAIN
#include <clipper.hpp>
#include <clipper2/clipper.h>
#include <geometry/seg.h>
#include <geometry/shape.h>
@ -37,7 +36,7 @@
/**
* Holds information on each point of a SHAPE_LINE_CHAIN that is retrievable
* after an operation with ClipperLib
* after an operation with Clipper2Lib
*/
struct CLIPPER_Z_VALUE
{
@ -176,10 +175,6 @@ public:
SHAPE_LINE_CHAIN( const SHAPE_ARC& aArc, bool aClosed = false );
SHAPE_LINE_CHAIN( const ClipperLib::Path& aPath,
const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
const std::vector<SHAPE_ARC>& aArcBuffer );
SHAPE_LINE_CHAIN( const Clipper2Lib::Path64& aPath,
const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
const std::vector<SHAPE_ARC>& aArcBuffer );
@ -920,13 +915,6 @@ protected:
return m_shapes[aSegment].second;
}
/**
* Create a new Clipper path from the SHAPE_LINE_CHAIN in a given orientation
*/
ClipperLib::Path convertToClipper( bool aRequiredOrientation,
std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
std::vector<SHAPE_ARC>& aArcBuffer ) const;
/**
* Create a new Clipper2 path from the SHAPE_LINE_CHAIN in a given orientation
*/

View File

@ -39,7 +39,6 @@
#include <stdlib.h> // for abs
#include <vector>
#include <clipper.hpp> // for ClipType, PolyTree (ptr only)
#include <clipper2/clipper.h>
#include <core/mirror.h> // for FLIP_DIRECTION
#include <geometry/corner_strategy.h>
@ -986,55 +985,30 @@ public:
return CIterateSegments( aOutline, aOutline, true );
}
/**
* Operations on polygons use a \a aFastMode param
* if aFastMode is #PM_FAST (true) the result can be a weak polygon
* if aFastMode is #PM_STRICTLY_SIMPLE (false) (default) the result is (theoretically) a
* strictly simple polygon, but calculations can be really significantly time consuming
* Most of time #PM_FAST is preferable.
* #PM_STRICTLY_SIMPLE can be used in critical cases (Gerber output for instance)
*/
enum POLYGON_MODE
{
PM_FAST = true,
PM_STRICTLY_SIMPLE = false
};
/// Perform boolean polyset union
/// For \a aFastMode meaning, see function booleanOp
void BooleanAdd( const SHAPE_POLY_SET& b, POLYGON_MODE aFastMode );
void BooleanAdd( const SHAPE_POLY_SET& b );
/// Perform boolean polyset difference
/// For \a aFastMode meaning, see function booleanOp
void BooleanSubtract( const SHAPE_POLY_SET& b, POLYGON_MODE aFastMode );
void BooleanSubtract( const SHAPE_POLY_SET& b );
/// Perform boolean polyset intersection
/// For \a aFastMode meaning, see function booleanOp
void BooleanIntersection( const SHAPE_POLY_SET& b, POLYGON_MODE aFastMode );
void BooleanIntersection( const SHAPE_POLY_SET& b );
/// Perform boolean polyset exclusive or
/// For \a aFastMode meaning, see function booleanOp
void BooleanXor( const SHAPE_POLY_SET& b, POLYGON_MODE aFastMode );
void BooleanXor( const SHAPE_POLY_SET& b );
/// Perform boolean polyset union between a and b, store the result in it self
/// For \a aFastMode meaning, see function booleanOp
void BooleanAdd( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b,
POLYGON_MODE aFastMode );
void BooleanAdd( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b );
/// Perform boolean polyset difference between a and b, store the result in it self
/// For \a aFastMode meaning, see function booleanOp
void BooleanSubtract( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b,
POLYGON_MODE aFastMode );
void BooleanSubtract( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b );
/// Perform boolean polyset intersection between a and b, store the result in it self
/// For \a aFastMode meaning, see function booleanOp
void BooleanIntersection( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b,
POLYGON_MODE aFastMode );
void BooleanIntersection( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b );
/// Perform boolean polyset exclusive or between a and b, store the result in it self
/// For \a aFastMode meaning, see function booleanOp
void BooleanXor( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b,
POLYGON_MODE aFastMode );
void BooleanXor( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b );
/**
* Extract all contours from this polygon set, then recreate polygons with holes.
@ -1085,20 +1059,17 @@ public:
* Perform outline inflation/deflation, using round corners.
*
* Polygons can have holes and/or linked holes with main outlines. The resulting
* polygons are also polygons with linked holes to main outlines. For \a aFastMode
* meaning, see function booleanOp .
* polygons are also polygons with linked holes to main outlines.
*/
void InflateWithLinkedHoles( int aFactor, CORNER_STRATEGY aCornerStrategy, int aMaxError,
POLYGON_MODE aFastMode );
void InflateWithLinkedHoles( int aFactor, CORNER_STRATEGY aCornerStrategy, int aMaxError );
/// Convert a set of polygons with holes to a single outline with "slits"/"fractures"
/// connecting the outer ring to the inner holes
/// For \a aFastMode meaning, see function booleanOp
void Fracture( POLYGON_MODE aFastMode );
void Fracture();
/// Convert a single outline slitted ("fractured") polygon into a set ouf outlines
/// with holes.
void Unfracture( POLYGON_MODE aFastMode );
void Unfracture();
/// Return true if the polygon set has any holes.
bool HasHoles() const;
@ -1108,8 +1079,7 @@ public:
/// Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
/// For \a aFastMode meaning, see function booleanOp
void Simplify( POLYGON_MODE aFastMode );
void Simplify();
/**
* Simplifies the lines in the polyset. This checks intermediate points to see if they are
@ -1464,11 +1434,9 @@ public:
* Build a SHAPE_POLY_SET from a bunch of outlines in provided in random order.
*
* @param aPath set of closed outlines forming the polygon. Positive orientation = outline, negative = hole
* @param aReverseOrientation inverts the sign of the orientation of aPaths (so negative = outline)
* @param aEvenOdd forces the even-off fill rule (default is non zero)
* @return the constructed poly set
*/
static const SHAPE_POLY_SET BuildPolysetFromOrientedPaths( const std::vector<SHAPE_LINE_CHAIN>& aPaths, bool aReverseOrientation = false, bool aEvenOdd = false );
void BuildPolysetFromOrientedPaths( const std::vector<SHAPE_LINE_CHAIN>& aPaths, bool aEvenOdd = false );
void TransformToPolygon( SHAPE_POLY_SET& aBuffer, int aError,
ERROR_LOC aErrorLoc ) const override
@ -1487,9 +1455,6 @@ private:
void fractureSingle( POLYGON& paths );
void unfractureSingle ( POLYGON& path );
void importTree( ClipperLib::PolyTree* tree,
const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
const std::vector<SHAPE_ARC>& aArcBuffe );
void importTree( Clipper2Lib::PolyTree64& tree,
const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
const std::vector<SHAPE_ARC>& aArcBuffe );
@ -1500,7 +1465,6 @@ private:
const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
const std::vector<SHAPE_ARC>& aArcBuffer );
void inflate1( int aAmount, int aCircleSegCount, CORNER_STRATEGY aCornerStrategy );
void inflate2( int aAmount, int aCircleSegCount, CORNER_STRATEGY aCornerStrategy, bool aSimplify = false );
void inflateLine2( const SHAPE_LINE_CHAIN& aLine, int aAmount, int aCircleSegCount,
@ -1510,20 +1474,9 @@ private:
* This is the engine to execute all polygon boolean transforms (AND, OR, ... and polygon
* simplification (merging overlapping polygons).
*
* @param aType is the transform type ( see ClipperLib::ClipType )
* @param aType is the transform type ( see Clipper2Lib::ClipType )
* @param aOtherShape is the SHAPE_LINE_CHAIN to combine with me.
* @param aFastMode is an option to choose if the result can be a weak polygon
* or a strictly simple polygon.
* if aFastMode is PM_FAST the result can be a weak polygon
* if aFastMode is PM_STRICTLY_SIMPLE (default) the result is (theoretically) a strictly
* simple polygon, but calculations can be really significantly time consuming
*/
void booleanOp( ClipperLib::ClipType aType, const SHAPE_POLY_SET& aOtherShape,
POLYGON_MODE aFastMode );
void booleanOp( ClipperLib::ClipType aType, const SHAPE_POLY_SET& aShape,
const SHAPE_POLY_SET& aOtherShape, POLYGON_MODE aFastMode );
void booleanOp( Clipper2Lib::ClipType aType, const SHAPE_POLY_SET& aOtherShape );
void booleanOp( Clipper2Lib::ClipType aType, const SHAPE_POLY_SET& aShape,

View File

@ -214,7 +214,7 @@ void TransformOvalToPolygon( SHAPE_POLY_SET& aBuffer, const VECTOR2I& aStart, co
bbox.Append( corner.x, corner.y );
// Now, clamp the shape
polyshape.BooleanIntersection( bbox, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
polyshape.BooleanIntersection( bbox );
// Note the final polygon is a simple, convex polygon with no hole
// due to the shape of initial polygons
@ -663,6 +663,6 @@ void TransformRingToPolygon( SHAPE_POLY_SET& aBuffer, const VECTOR2I& aCentre, i
TransformCircleToPolygon( buffer.Hole( 0, 0 ), aCentre, inner_radius,
aError, inner_err_loc );
buffer.Fracture( SHAPE_POLY_SET::PM_FAST );
buffer.Fracture();
aBuffer.Append( buffer );
}

View File

@ -29,7 +29,6 @@
#include <map>
#include <string> // for basic_string
#include <clipper.hpp>
#include <clipper2/clipper.h>
#include <core/kicad_algo.h> // for alg::run_on_pair
#include <geometry/circle.h>
@ -79,50 +78,6 @@ SHAPE_LINE_CHAIN::SHAPE_LINE_CHAIN( const SHAPE_ARC& aArc, bool aClosed ) :
}
SHAPE_LINE_CHAIN::SHAPE_LINE_CHAIN( const ClipperLib::Path& aPath,
const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
const std::vector<SHAPE_ARC>& aArcBuffer ) :
SHAPE_LINE_CHAIN_BASE( SH_LINE_CHAIN ),
m_closed( true ), m_width( 0 )
{
std::map<ssize_t, ssize_t> loadedArcs;
m_points.reserve( aPath.size() );
m_shapes.reserve( aPath.size() );
auto loadArc =
[&]( ssize_t aArcIndex ) -> ssize_t
{
if( aArcIndex == SHAPE_IS_PT )
{
return SHAPE_IS_PT;
}
else if( loadedArcs.count( aArcIndex ) == 0 )
{
loadedArcs.insert( { aArcIndex, m_arcs.size() } );
m_arcs.push_back( aArcBuffer.at( aArcIndex ) );
}
return loadedArcs.at( aArcIndex );
};
for( size_t ii = 0; ii < aPath.size(); ++ii )
{
Append( aPath[ii].X, aPath[ii].Y );
m_shapes[ii].first = loadArc( aZValueBuffer[aPath[ii].Z].m_FirstArcIdx );
m_shapes[ii].second = loadArc( aZValueBuffer[aPath[ii].Z].m_SecondArcIdx );
}
// Clipper shouldn't return duplicate contiguous points. if it did, these would be
// removed during Append() and we would have different number of shapes to points
wxASSERT( m_shapes.size() == m_points.size() );
// Clipper might mess up the rotation of the indices such that an arc can be split between
// the end point and wrap around to the start point. Lets fix the indices up now
fixIndicesRotation();
}
SHAPE_LINE_CHAIN::SHAPE_LINE_CHAIN( const Clipper2Lib::Path64& aPath,
const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
const std::vector<SHAPE_ARC>& aArcBuffer ) :
@ -167,40 +122,6 @@ SHAPE_LINE_CHAIN::SHAPE_LINE_CHAIN( const Clipper2Lib::Path64& aPath,
}
ClipperLib::Path SHAPE_LINE_CHAIN::convertToClipper( bool aRequiredOrientation,
std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
std::vector<SHAPE_ARC>& aArcBuffer ) const
{
ClipperLib::Path c_path;
SHAPE_LINE_CHAIN input;
bool orientation = Area( false ) >= 0;
ssize_t shape_offset = aArcBuffer.size();
if( orientation != aRequiredOrientation )
input = Reverse();
else
input = *this;
int pointCount = input.PointCount();
c_path.reserve( pointCount );
for( int i = 0; i < pointCount; i++ )
{
const VECTOR2I& vertex = input.CPoint( i );
CLIPPER_Z_VALUE z_value( input.m_shapes[i], shape_offset );
size_t z_value_ptr = aZValueBuffer.size();
aZValueBuffer.push_back( z_value );
c_path.emplace_back( vertex.x, vertex.y, z_value_ptr );
}
aArcBuffer.insert( aArcBuffer.end(), input.m_arcs.begin(), input.m_arcs.end() );
return c_path;
}
Clipper2Lib::Path64 SHAPE_LINE_CHAIN::convertToClipper2( bool aRequiredOrientation,
std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
std::vector<SHAPE_ARC>& aArcBuffer ) const

View File

@ -744,118 +744,6 @@ void SHAPE_POLY_SET::RebuildHolesFromContours()
}
void SHAPE_POLY_SET::booleanOp( ClipperLib::ClipType aType, const SHAPE_POLY_SET& aOtherShape,
POLYGON_MODE aFastMode )
{
booleanOp( aType, *this, aOtherShape, aFastMode );
}
void SHAPE_POLY_SET::booleanOp( ClipperLib::ClipType aType, const SHAPE_POLY_SET& aShape,
const SHAPE_POLY_SET& aOtherShape, POLYGON_MODE aFastMode )
{
if( ( aShape.OutlineCount() > 1 || aOtherShape.OutlineCount() > 0 )
&& ( aShape.ArcCount() > 0 || aOtherShape.ArcCount() > 0 ) )
{
wxFAIL_MSG( wxT( "Boolean ops on curved polygons are not supported. You should call "
"ClearArcs() before carrying out the boolean operation." ) );
}
ClipperLib::Clipper c;
c.StrictlySimple( aFastMode == PM_STRICTLY_SIMPLE );
std::vector<CLIPPER_Z_VALUE> zValues;
std::vector<SHAPE_ARC> arcBuffer;
std::map<VECTOR2I, CLIPPER_Z_VALUE> newIntersectPoints;
for( const POLYGON& poly : aShape.m_polys )
{
for( size_t i = 0; i < poly.size(); i++ )
{
c.AddPath( poly[i].convertToClipper( i == 0, zValues, arcBuffer ),
ClipperLib::ptSubject, true );
}
}
for( const POLYGON& poly : aOtherShape.m_polys )
{
for( size_t i = 0; i < poly.size(); i++ )
{
c.AddPath( poly[i].convertToClipper( i == 0, zValues, arcBuffer ),
ClipperLib::ptClip, true );
}
}
ClipperLib::PolyTree solution;
ClipperLib::ZFillCallback callback =
[&]( ClipperLib::IntPoint & e1bot, ClipperLib::IntPoint & e1top,
ClipperLib::IntPoint & e2bot, ClipperLib::IntPoint & e2top,
ClipperLib::IntPoint & pt )
{
auto arcIndex =
[&]( const ssize_t& aZvalue, const ssize_t& aCompareVal = -1 ) -> ssize_t
{
ssize_t retval;
retval = zValues.at( aZvalue ).m_SecondArcIdx;
if( retval == -1 || ( aCompareVal > 0 && retval != aCompareVal ) )
retval = zValues.at( aZvalue ).m_FirstArcIdx;
return retval;
};
auto arcSegment =
[&]( const ssize_t& aBottomZ, const ssize_t aTopZ ) -> ssize_t
{
ssize_t retval = arcIndex( aBottomZ );
if( retval != -1 )
{
if( retval != arcIndex( aTopZ, retval ) )
retval = -1; // Not an arc segment as the two indices do not match
}
return retval;
};
ssize_t e1ArcSegmentIndex = arcSegment( e1bot.Z, e1top.Z );
ssize_t e2ArcSegmentIndex = arcSegment( e2bot.Z, e2top.Z );
CLIPPER_Z_VALUE newZval;
if( e1ArcSegmentIndex != -1 )
{
newZval.m_FirstArcIdx = e1ArcSegmentIndex;
newZval.m_SecondArcIdx = e2ArcSegmentIndex;
}
else
{
newZval.m_FirstArcIdx = e2ArcSegmentIndex;
newZval.m_SecondArcIdx = -1;
}
size_t z_value_ptr = zValues.size();
zValues.push_back( newZval );
// Only worry about arc segments for later processing
if( newZval.m_FirstArcIdx != -1 )
newIntersectPoints.insert( { VECTOR2I( pt.X, pt.Y ), newZval } );
pt.Z = z_value_ptr;
//@todo amend X,Y values to true intersection between arcs or arc and segment
};
c.ZFillFunction( std::move( callback ) ); // register callback
c.Execute( aType, solution, ClipperLib::pftNonZero, ClipperLib::pftNonZero );
importTree( &solution, zValues, arcBuffer );
}
void SHAPE_POLY_SET::booleanOp( Clipper2Lib::ClipType aType, const SHAPE_POLY_SET& aOtherShape )
{
booleanOp( aType, *this, aOtherShape );
@ -970,155 +858,60 @@ void SHAPE_POLY_SET::booleanOp( Clipper2Lib::ClipType aType, const SHAPE_POLY_SE
}
void SHAPE_POLY_SET::BooleanAdd( const SHAPE_POLY_SET& b, POLYGON_MODE aFastMode )
void SHAPE_POLY_SET::BooleanAdd( const SHAPE_POLY_SET& b )
{
booleanOp( Clipper2Lib::ClipType::Union, b );
}
void SHAPE_POLY_SET::BooleanSubtract( const SHAPE_POLY_SET& b, POLYGON_MODE aFastMode )
void SHAPE_POLY_SET::BooleanSubtract( const SHAPE_POLY_SET& b )
{
booleanOp( Clipper2Lib::ClipType::Difference, b );
}
void SHAPE_POLY_SET::BooleanIntersection( const SHAPE_POLY_SET& b, POLYGON_MODE aFastMode )
void SHAPE_POLY_SET::BooleanIntersection( const SHAPE_POLY_SET& b )
{
booleanOp( Clipper2Lib::ClipType::Intersection, b );
}
void SHAPE_POLY_SET::BooleanXor( const SHAPE_POLY_SET& b, POLYGON_MODE aFastMode )
void SHAPE_POLY_SET::BooleanXor( const SHAPE_POLY_SET& b )
{
booleanOp( Clipper2Lib::ClipType::Xor, b );
}
void SHAPE_POLY_SET::BooleanAdd( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b,
POLYGON_MODE aFastMode )
void SHAPE_POLY_SET::BooleanAdd( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b )
{
booleanOp( Clipper2Lib::ClipType::Union, a, b );
}
void SHAPE_POLY_SET::BooleanSubtract( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b,
POLYGON_MODE aFastMode )
void SHAPE_POLY_SET::BooleanSubtract( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b )
{
booleanOp( Clipper2Lib::ClipType::Difference, a, b );
}
void SHAPE_POLY_SET::BooleanIntersection( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b,
POLYGON_MODE aFastMode )
void SHAPE_POLY_SET::BooleanIntersection( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b )
{
booleanOp( Clipper2Lib::ClipType::Intersection, a, b );
}
void SHAPE_POLY_SET::BooleanXor( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b,
POLYGON_MODE aFastMode )
void SHAPE_POLY_SET::BooleanXor( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b )
{
booleanOp( Clipper2Lib::ClipType::Xor, a, b );
}
void SHAPE_POLY_SET::InflateWithLinkedHoles( int aFactor, CORNER_STRATEGY aCornerStrategy,
int aMaxError, POLYGON_MODE aFastMode )
int aMaxError )
{
Unfracture( aFastMode );
Unfracture();
Inflate( aFactor, aCornerStrategy, aMaxError );
Fracture( aFastMode );
}
void SHAPE_POLY_SET::inflate1( int aAmount, int aCircleSegCount, CORNER_STRATEGY aCornerStrategy )
{
using namespace ClipperLib;
// A static table to avoid repetitive calculations of the coefficient
// 1.0 - cos( M_PI / aCircleSegCount )
// aCircleSegCount is most of time <= 64 and usually 8, 12, 16, 32
#define SEG_CNT_MAX 64
static double arc_tolerance_factor[SEG_CNT_MAX + 1];
ClipperOffset c;
// N.B. see the Clipper documentation for jtSquare/jtMiter/jtRound. They are poorly named
// and are not what you'd think they are.
// http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Types/JoinType.htm
JoinType joinType = jtRound; // The way corners are offsetted
double miterLimit = 2.0; // Smaller value when using jtMiter for joinType
JoinType miterFallback = jtSquare;
switch( aCornerStrategy )
{
case CORNER_STRATEGY::ALLOW_ACUTE_CORNERS:
joinType = jtMiter;
miterLimit = 10; // Allows large spikes
miterFallback = jtSquare;
break;
case CORNER_STRATEGY::CHAMFER_ACUTE_CORNERS: // Acute angles are chamfered
joinType = jtMiter;
miterFallback = jtRound;
break;
case CORNER_STRATEGY::ROUND_ACUTE_CORNERS: // Acute angles are rounded
joinType = jtMiter;
miterFallback = jtSquare;
break;
case CORNER_STRATEGY::CHAMFER_ALL_CORNERS: // All angles are chamfered.
joinType = jtSquare;
miterFallback = jtSquare;
break;
case CORNER_STRATEGY::ROUND_ALL_CORNERS: // All angles are rounded.
joinType = jtRound;
miterFallback = jtSquare;
break;
}
std::vector<CLIPPER_Z_VALUE> zValues;
std::vector<SHAPE_ARC> arcBuffer;
for( const POLYGON& poly : m_polys )
{
for( size_t i = 0; i < poly.size(); i++ )
{
c.AddPath( poly[i].convertToClipper( i == 0, zValues, arcBuffer ),
joinType, etClosedPolygon );
}
}
PolyTree solution;
// Calculate the arc tolerance (arc error) from the seg count by circle. The seg count is
// nn = M_PI / acos(1.0 - c.ArcTolerance / abs(aAmount))
// http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Classes/ClipperOffset/Properties/ArcTolerance.htm
if( aCircleSegCount < 6 ) // avoid incorrect aCircleSegCount values
aCircleSegCount = 6;
double coeff;
if( aCircleSegCount > SEG_CNT_MAX || arc_tolerance_factor[aCircleSegCount] == 0 )
{
coeff = 1.0 - cos( M_PI / aCircleSegCount );
if( aCircleSegCount <= SEG_CNT_MAX )
arc_tolerance_factor[aCircleSegCount] = coeff;
}
else
{
coeff = arc_tolerance_factor[aCircleSegCount];
}
c.ArcTolerance = std::abs( aAmount ) * coeff;
c.MiterLimit = miterLimit;
c.MiterFallback = miterFallback;
c.Execute( solution, aAmount );
importTree( &solution, zValues, arcBuffer );
Fracture();
}
@ -1341,30 +1134,6 @@ void SHAPE_POLY_SET::OffsetLineChain( const SHAPE_LINE_CHAIN& aLine, int aAmount
}
void SHAPE_POLY_SET::importTree( ClipperLib::PolyTree* tree,
const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
const std::vector<SHAPE_ARC>& aArcBuffer )
{
m_polys.clear();
for( ClipperLib::PolyNode* n = tree->GetFirst(); n; n = n->GetNext() )
{
if( !n->IsHole() )
{
POLYGON paths;
paths.reserve( n->Childs.size() + 1 );
paths.emplace_back( n->Contour, aZValueBuffer, aArcBuffer );
for( unsigned int i = 0; i < n->Childs.size(); i++ )
paths.emplace_back( n->Childs[i]->Contour, aZValueBuffer, aArcBuffer );
m_polys.push_back( paths );
}
}
}
void SHAPE_POLY_SET::importPolyPath( const std::unique_ptr<Clipper2Lib::PolyPath64>& aPolyPath,
const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
const std::vector<SHAPE_ARC>& aArcBuffer )
@ -1886,9 +1655,9 @@ void SHAPE_POLY_SET::fractureSingle( POLYGON& paths )
}
void SHAPE_POLY_SET::Fracture( POLYGON_MODE aFastMode )
void SHAPE_POLY_SET::Fracture()
{
Simplify( aFastMode ); // remove overlapping holes/degeneracy
Simplify(); // remove overlapping holes/degeneracy
for( POLYGON& paths : m_polys )
fractureSingle( paths );
@ -2077,16 +1846,16 @@ bool SHAPE_POLY_SET::HasHoles() const
}
void SHAPE_POLY_SET::Unfracture( POLYGON_MODE aFastMode )
void SHAPE_POLY_SET::Unfracture()
{
for( POLYGON& path : m_polys )
unfractureSingle( path );
Simplify( aFastMode ); // remove overlapping holes/degeneracy
Simplify(); // remove overlapping holes/degeneracy
}
void SHAPE_POLY_SET::Simplify( POLYGON_MODE aFastMode )
void SHAPE_POLY_SET::Simplify()
{
SHAPE_POLY_SET empty;
@ -2110,7 +1879,7 @@ int SHAPE_POLY_SET::NormalizeAreaOutlines()
{
// We are expecting only one main outline, but this main outline can have holes
// if holes: combine holes and remove them from the main outline.
// Note also we are using SHAPE_POLY_SET::PM_STRICTLY_SIMPLE in polygon
// Note also we are usingin polygon
// calculations, but it is not mandatory. It is used mainly
// because there is usually only very few vertices in area outlines
SHAPE_POLY_SET::POLYGON& outline = Polygon( 0 );
@ -2124,13 +1893,13 @@ int SHAPE_POLY_SET::NormalizeAreaOutlines()
outline.pop_back();
}
Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
Simplify();
// If any hole, subtract it to main outline
if( holesBuffer.OutlineCount() )
{
holesBuffer.Simplify( SHAPE_POLY_SET::PM_FAST );
BooleanSubtract( holesBuffer, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
holesBuffer.Simplify();
BooleanSubtract( holesBuffer );
}
// In degenerate cases, simplify might return no outlines
@ -3210,10 +2979,10 @@ static SHAPE_POLY_SET partitionPolyIntoRegularCellGrid( const SHAPE_POLY_SET& aP
}
}
ps1.BooleanIntersection( maskSetOdd, SHAPE_POLY_SET::PM_FAST );
ps2.BooleanIntersection( maskSetEven, SHAPE_POLY_SET::PM_FAST );
ps1.Fracture( SHAPE_POLY_SET::PM_FAST );
ps2.Fracture( SHAPE_POLY_SET::PM_FAST );
ps1.BooleanIntersection( maskSetOdd );
ps2.BooleanIntersection( maskSetEven );
ps1.Fracture();
ps2.Fracture();
for( int i = 0; i < ps2.OutlineCount(); i++ )
ps1.AddOutline( ps2.COutline( i ) );
@ -3269,10 +3038,6 @@ void SHAPE_POLY_SET::cacheTriangulation( bool aPartition, bool aSimplify,
++pass;
if( pass == 1 )
{
polySet.Fracture( PM_FAST );
}
else if( pass == 2 )
{
polySet.SimplifyOutlines( TRIANGULATESIMPLIFICATIONLEVEL );
}
@ -3310,9 +3075,9 @@ void SHAPE_POLY_SET::cacheTriangulation( bool aPartition, bool aSimplify,
flattened.ClearArcs();
if( flattened.HasHoles() || flattened.IsSelfIntersecting() )
flattened.Fracture( PM_FAST );
flattened.Fracture();
else if( aSimplify )
flattened.Simplify( PM_FAST );
flattened.Simplify();
SHAPE_POLY_SET partitions = partitionPolyIntoRegularCellGrid( flattened, 1e7 );
@ -3336,8 +3101,7 @@ void SHAPE_POLY_SET::cacheTriangulation( bool aPartition, bool aSimplify,
SHAPE_POLY_SET tmpSet( *this );
tmpSet.ClearArcs();
tmpSet.Fracture( PM_FAST );
tmpSet.Fracture();
if( !triangulate( tmpSet, -1, m_triangulatedPolys, aHintData ) )
{
@ -3498,55 +3262,35 @@ SHAPE_POLY_SET::TRIANGULATED_POLYGON::~TRIANGULATED_POLYGON()
}
const SHAPE_POLY_SET
void
SHAPE_POLY_SET::BuildPolysetFromOrientedPaths( const std::vector<SHAPE_LINE_CHAIN>& aPaths,
bool aReverseOrientation, bool aEvenOdd )
bool aEvenOdd )
{
ClipperLib::Clipper clipper;
ClipperLib::PolyTree tree;
// fixme: do we need aReverseOrientation?
Clipper2Lib::Clipper64 clipper;
Clipper2Lib::PolyTree64 tree;
Clipper2Lib::Paths64 paths;
for( const SHAPE_LINE_CHAIN& path : aPaths )
{
ClipperLib::Path lc;
Clipper2Lib::Path64 lc;
lc.reserve( path.PointCount() );
for( int i = 0; i < path.PointCount(); i++ )
{
lc.emplace_back( path.CPoint( i ).x, path.CPoint( i ).y );
paths.push_back( lc );
}
clipper.AddPath( lc, ClipperLib::ptSubject, true );
}
clipper.AddSubject( paths );
clipper.Execute( Clipper2Lib::ClipType::Union, aEvenOdd ? Clipper2Lib::FillRule::EvenOdd
: Clipper2Lib::FillRule::NonZero, tree );
clipper.StrictlySimple( true );
clipper.Execute( ClipperLib::ctUnion, tree,
aEvenOdd ? ClipperLib::pftEvenOdd : ClipperLib::pftNonZero,
ClipperLib::pftNonZero );
SHAPE_POLY_SET result;
for( ClipperLib::PolyNode* n = tree.GetFirst(); n; n = n->GetNext() )
{
if( !n->IsHole() )
{
int outl = result.NewOutline();
std::vector<CLIPPER_Z_VALUE> zValues;
std::vector<SHAPE_ARC> arcBuffer;
for( unsigned int i = 0; i < n->Contour.size(); i++ )
result.Outline( outl ).Append( n->Contour[i].X, n->Contour[i].Y );
for( unsigned int i = 0; i < n->Childs.size(); i++ )
{
int outh = result.NewHole( outl );
for( unsigned int j = 0; j < n->Childs[i]->Contour.size(); j++ )
{
result.Hole( outl, outh )
.Append( n->Childs[i]->Contour[j].X, n->Childs[i]->Contour[j].Y );
}
}
}
}
return result;
importTree( tree, zValues, arcBuffer );
tree.Clear(); // Free used memory (not done in dtor)
}

View File

@ -146,7 +146,7 @@ bool AR_AUTOPLACER::fillMatrix()
// Create a single board outline:
SHAPE_POLY_SET brd_shape = m_boardShape.CloneDropTriangulation();
brd_shape.Fracture( SHAPE_POLY_SET::PM_FAST );
brd_shape.Fracture();
const SHAPE_LINE_CHAIN& outline = brd_shape.Outline(0);
const BOX2I& rect = outline.BBox();
@ -393,8 +393,8 @@ void AR_AUTOPLACER::genModuleOnRoutingMatrix( FOOTPRINT* Module )
buildFpAreas( Module, margin );
// Substract the shape to free areas
m_topFreeArea.BooleanSubtract( m_fpAreaTop, SHAPE_POLY_SET::PM_FAST );
m_bottomFreeArea.BooleanSubtract( m_fpAreaBottom, SHAPE_POLY_SET::PM_FAST );
m_topFreeArea.BooleanSubtract( m_fpAreaTop );
m_bottomFreeArea.BooleanSubtract( m_fpAreaBottom );
}
@ -802,7 +802,7 @@ void AR_AUTOPLACER::drawPlacementRoutingMatrix( )
m_overlay->SetIsStroke( false );
SHAPE_POLY_SET freeArea = m_topFreeArea.CloneDropTriangulation();
freeArea.Fracture( SHAPE_POLY_SET::PM_FAST );
freeArea.Fracture();
// Draw the free polygon areas, top side:
if( freeArea.OutlineCount() > 0 )
@ -814,7 +814,7 @@ void AR_AUTOPLACER::drawPlacementRoutingMatrix( )
}
freeArea = m_bottomFreeArea;
freeArea.Fracture( SHAPE_POLY_SET::PM_FAST );
freeArea.Fracture();
// Draw the free polygon areas, bottom side:
if( freeArea.OutlineCount() > 0 )

View File

@ -2541,7 +2541,7 @@ bool BOARD::GetBoardPolygonOutlines( SHAPE_POLY_SET& aOutlines,
}
// Make polygon strictly simple to avoid issues (especially in 3D viewer)
aOutlines.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
aOutlines.Simplify();
return success;
}

View File

@ -164,8 +164,7 @@ static bool isCopperOutside( const FOOTPRINT* aFootprint, SHAPE_POLY_SET& aShape
poly.ClearArcs();
poly.BooleanIntersection( *pad->GetEffectivePolygon( aLayer, ERROR_INSIDE ),
SHAPE_POLY_SET::PM_FAST );
poly.BooleanIntersection( *pad->GetEffectivePolygon( aLayer, ERROR_INSIDE ) );
if( poly.OutlineCount() == 0 )
{

View File

@ -283,7 +283,7 @@ bool DRC_TEST_PROVIDER_ANNULAR_WIDTH::Run()
otherPadHoles, 0, maxError, ERROR_INSIDE );
}
otherPadOutline.BooleanSubtract( otherPadHoles, SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
otherPadOutline.BooleanSubtract( otherPadHoles );
// If the pad hole under test intersects with another pad outline,
// the annular width calculated above is used.

View File

@ -384,7 +384,7 @@ bool DRC_TEST_PROVIDER_CONNECTION_WIDTH::Run()
ERROR_OUTSIDE );
}
itemsPoly.Poly.Fracture( SHAPE_POLY_SET::PM_FAST );
itemsPoly.Poly.Fracture();
done.fetch_add( calc_effort( itemsPoly.Items, aLayer ) );

View File

@ -132,7 +132,7 @@ bool DRC_TEST_PROVIDER_DISALLOW::Run()
// exclude it. This is particularly important for detecting copper fills as
// they will be exactly touching along the entire exclusion border.
SHAPE_POLY_SET areaPoly = ruleArea->Outline()->CloneDropTriangulation();
areaPoly.Fracture( SHAPE_POLY_SET::PM_FAST );
areaPoly.Fracture();
areaPoly.Deflate( epsilon, CORNER_STRATEGY::ALLOW_ACUTE_CORNERS, ARC_LOW_DEF );
DRC_RTREE* zoneRTree = board->m_CopperZoneRTreeCache[ copperZone ].get();

View File

@ -555,7 +555,7 @@ void DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::testZoneLayer( ZONE* aZone, PCB_LAYER
SHAPE_POLY_SET fill = aZone->GetFilledPolysList( aLayer )->CloneDropTriangulation();
// Turn fractured fill into outlines and holes
fill.Simplify( SHAPE_POLY_SET::PM_FAST );
fill.Simplify();
for( int outlineIdx = 0; outlineIdx < fill.OutlineCount(); ++outlineIdx )
{

View File

@ -155,7 +155,7 @@ bool DRC_TEST_PROVIDER_SLIVER_CHECKER::Run()
if( m_drcEngine->IsCancelled() )
return 0;
poly.Simplify( SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
poly.Simplify();
return 1;
};

View File

@ -122,8 +122,7 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::addItemToRTrees( BOARD_ITEM* aItem )
{
if( zone->IsOnLayer( layer ) )
{
solderMask->GetFill( layer )->BooleanAdd( *zone->GetFilledPolysList( layer ),
SHAPE_POLY_SET::PM_FAST );
solderMask->GetFill( layer )->BooleanAdd( *zone->GetFilledPolysList( layer ) );
}
}
}
@ -222,8 +221,8 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::buildRTrees()
return true;
} );
solderMask->GetFill( F_Mask )->Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
solderMask->GetFill( B_Mask )->Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
solderMask->GetFill( F_Mask )->Simplify();
solderMask->GetFill( B_Mask )->Simplify();
solderMask->GetFill( F_Mask )->Deflate( m_webWidth / 2, CORNER_STRATEGY::CHAMFER_ALL_CORNERS,
m_maxError );

View File

@ -177,7 +177,7 @@ bool DRC_TEST_PROVIDER_TEXT_DIMS::Run()
SHAPE_POLY_SET poly = outlineGlyph->CloneDropTriangulation();
poly.Deflate( constraint.Value().Min() / 2,
CORNER_STRATEGY::CHAMFER_ALL_CORNERS, ARC_LOW_DEF );
poly.Simplify( SHAPE_POLY_SET::PM_FAST );
poly.Simplify();
int resultingOutlineCount = poly.OutlineCount();
int resultingHoleCount = 0;

View File

@ -502,7 +502,7 @@ bool HYPERLYNX_EXPORTER::writeNetObjects( const std::vector<BOARD_ITEM*>& aObjec
const wxString layerName = m_board->GetLayerName( layer );
SHAPE_POLY_SET fill = zone->GetFilledPolysList( layer )->CloneDropTriangulation();
fill.Simplify( SHAPE_POLY_SET::PM_FAST );
fill.Simplify();
for( int i = 0; i < fill.OutlineCount(); i++ )
{

View File

@ -394,8 +394,8 @@ void EXPORTER_PCB_VRML::ExportVrmlSolderMask()
outlines = m_pcbOutlines;
m_board->ConvertBrdLayerToPolygonalContours( pcb_layer, holes );
outlines.BooleanSubtract( holes, SHAPE_POLY_SET::PM_FAST );
outlines.Fracture( SHAPE_POLY_SET::PM_FAST );
outlines.BooleanSubtract( holes );
outlines.Fracture();
ExportVrmlPolygonSet( vrmllayer, outlines );
pcb_layer = B_Mask;
@ -426,8 +426,8 @@ void EXPORTER_PCB_VRML::ExportStandardLayers()
outlines.RemoveAllContours();
m_board->ConvertBrdLayerToPolygonalContours( pcb_layer[lcnt], outlines );
outlines.BooleanIntersection( m_pcbOutlines, SHAPE_POLY_SET::PM_FAST );
outlines.Fracture( SHAPE_POLY_SET::PM_FAST );
outlines.BooleanIntersection( m_pcbOutlines );
outlines.Fracture();
ExportVrmlPolygonSet( vrmllayer[lcnt], outlines );
}

View File

@ -463,7 +463,7 @@ void EXPORTER_STEP::buildZones3DShape( VECTOR2D aOrigin )
{
SHAPE_POLY_SET fill_shape;
zone->TransformSolidAreasShapesToPolygon( layer, fill_shape );
fill_shape.Unfracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
fill_shape.Unfracture();
fill_shape.SimplifyOutlines( ADVANCED_CFG::GetCfg().m_TriangulateSimplificationLevel );
@ -640,31 +640,31 @@ bool EXPORTER_STEP::buildBoard3DShapes()
for( PCB_LAYER_ID pcblayer : m_layersToExport.Seq() )
{
SHAPE_POLY_SET poly = m_poly_shapes[pcblayer];
poly.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
poly.Simplify();
poly.SimplifyOutlines( pcbIUScale.mmToIU( 0.003 ) );
poly.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
poly.Simplify();
SHAPE_POLY_SET holes = m_poly_holes[pcblayer];
holes.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
holes.Simplify();
// Mask layer is negative
if( pcblayer == F_Mask || pcblayer == B_Mask )
{
SHAPE_POLY_SET mask = pcbOutlinesNoArcs;
mask.BooleanSubtract( poly, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
mask.BooleanSubtract( holes, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
mask.BooleanSubtract( poly );
mask.BooleanSubtract( holes );
poly = mask;
}
else
{
// Subtract holes
poly.BooleanSubtract( holes, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
poly.BooleanSubtract( holes );
// Clip to board outline
poly.BooleanIntersection( pcbOutlinesNoArcs, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
poly.BooleanIntersection( pcbOutlinesNoArcs );
}
m_pcbModel->AddPolygonShapes( &poly, pcblayer, origin );

View File

@ -1561,7 +1561,7 @@ bool STEP_PCB_MODEL::MakeShapes( std::vector<TopoDS_Shape>& aShapes, const SHAPE
double aThickness, double aZposition, const VECTOR2D& aOrigin )
{
SHAPE_POLY_SET workingPoly = aPolySet;
workingPoly.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
workingPoly.Simplify();
SHAPE_POLY_SET fallbackPoly = workingPoly;

View File

@ -2777,7 +2777,7 @@ double FOOTPRINT::GetCoverageArea( const BOARD_ITEM* aItem, const GENERAL_COLLEC
{
SHAPE_POLY_SET padPoly;
aItem->TransformShapeToPolygon( padPoly, aLayer, 0, ARC_LOW_DEF, ERROR_OUTSIDE );
poly.BooleanAdd( padPoly, SHAPE_POLY_SET::PM_FAST );
poly.BooleanAdd( padPoly );
} );
}
else
@ -2837,7 +2837,7 @@ double FOOTPRINT::CoverageRatio( const GENERAL_COLLECTOR& aCollector ) const
}
}
coveredRegion.BooleanIntersection( footprintRegion, SHAPE_POLY_SET::PM_FAST );
coveredRegion.BooleanIntersection( footprintRegion );
double footprintRegionArea = polygonArea( footprintRegion );
double uncoveredRegionArea = footprintRegionArea - polygonArea( coveredRegion );
@ -3327,7 +3327,7 @@ void FOOTPRINT::CheckNetTies( const std::function<void( const BOARD_ITEM* aItem,
}
}
copperOutlines.Simplify( SHAPE_POLY_SET::PM_FAST );
copperOutlines.Simplify();
// Index each pad to the outline in the set that it is part of.

View File

@ -1804,7 +1804,7 @@ SHAPE_LINE_CHAIN PCB_TUNING_PATTERN::getOutline() const
}
SHAPE_POLY_SET merged;
merged.BooleanAdd( chain1, chain2, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
merged.BooleanAdd( chain1, chain2 );
if( merged.OutlineCount() > 0 )
return merged.Outline( 0 );
@ -1832,7 +1832,7 @@ SHAPE_LINE_CHAIN PCB_TUNING_PATTERN::getOutline() const
CORNER_STRATEGY::ROUND_ALL_CORNERS, ARC_LOW_DEF, false );
SHAPE_POLY_SET merged;
merged.BooleanAdd( poly, polyCoupled, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
merged.BooleanAdd( poly, polyCoupled );
if( merged.OutlineCount() > 0 )
return merged.Outline( 0 );

View File

@ -1956,7 +1956,7 @@ void PAD::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer,
aClearance += aMaxError;
outline.Inflate( aClearance, CORNER_STRATEGY::ROUND_ALL_CORNERS, aMaxError );
outline.Fracture( SHAPE_POLY_SET::PM_FAST );
outline.Fracture();
}
else if( aClearance < 0 )
{
@ -1965,7 +1965,7 @@ void PAD::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer,
// aClearance is negative so this is actually a deflate
outline.Inflate( aClearance, CORNER_STRATEGY::ALLOW_ACUTE_CORNERS, aMaxError );
outline.Fracture( SHAPE_POLY_SET::PM_FAST );
outline.Fracture();
}
aBuffer.Append( outline );
@ -2008,7 +2008,7 @@ std::vector<PCB_SHAPE*> PAD::Recombine( bool aIsDryRun, int maxError )
SHAPE_POLY_SET drawPoly;
shape->TransformShapeToPolygon( drawPoly, aLayer, 0, maxError, ERROR_INSIDE );
drawPoly.BooleanIntersection( padPoly, SHAPE_POLY_SET::PM_FAST );
drawPoly.BooleanIntersection( padPoly );
if( !drawPoly.IsEmpty() )
return shape;
@ -2275,7 +2275,7 @@ void PAD::doCheckPad( PCB_LAYER_ID aLayer, UNITS_PROVIDER* aUnitsProvider,
hole->GetWidth(), ARC_HIGH_DEF, ERROR_OUTSIDE );
SHAPE_POLY_SET copper = padOutline;
copper.BooleanSubtract( holeOutline, SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
copper.BooleanSubtract( holeOutline );
if( copper.IsEmpty() )
{
@ -2284,7 +2284,7 @@ void PAD::doCheckPad( PCB_LAYER_ID aLayer, UNITS_PROVIDER* aUnitsProvider,
else
{
// Test if the pad hole is fully inside the copper area
holeOutline.BooleanSubtract( padOutline, SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
holeOutline.BooleanSubtract( padOutline );
if( !holeOutline.IsEmpty() )
aErrorHandler( DRCE_PADSTACK, _( "(PTH pad hole non fully inside copper)" ) );

View File

@ -45,7 +45,7 @@ void PAD::AddPrimitivePoly( PCB_LAYER_ID aLayer, const SHAPE_POLY_SET& aPoly, in
poly_no_hole.Append( aPoly );
if( poly_no_hole.HasHoles() )
poly_no_hole.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
poly_no_hole.Fracture();
// There should never be multiple shapes, but if there are, we split them into
// primitives so that we can edit them both.
@ -142,13 +142,13 @@ void PAD::addPadPrimitivesToPolygon( PCB_LAYER_ID aLayer, SHAPE_POLY_SET* aMerge
primitive->TransformShapeToPolygon( polyset, UNDEFINED_LAYER, 0, aError, aErrorLoc );
}
polyset.Simplify( SHAPE_POLY_SET::PM_FAST );
polyset.Simplify();
// Merge all polygons with the initial pad anchor shape
if( polyset.OutlineCount() )
{
aMergedPolygon->BooleanAdd( polyset, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
aMergedPolygon->Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
aMergedPolygon->BooleanAdd( polyset );
aMergedPolygon->Fracture();
}
}

View File

@ -320,7 +320,7 @@ void PCB_BASE_FRAME::FocusOnItems( std::vector<BOARD_ITEM*> aItems, PCB_LAYER_ID
try
{
viewportPoly.BooleanSubtract( dialogPoly, SHAPE_POLY_SET::PM_FAST );
viewportPoly.BooleanSubtract( dialogPoly );
}
catch( const std::exception& e )
{
@ -426,7 +426,7 @@ void PCB_BASE_FRAME::FocusOnItems( std::vector<BOARD_ITEM*> aItems, PCB_LAYER_ID
try
{
clippedPoly.BooleanIntersection( itemPoly, viewportPoly, SHAPE_POLY_SET::PM_FAST );
clippedPoly.BooleanIntersection( itemPoly, viewportPoly );
}
catch( const std::exception& e )
{

View File

@ -598,7 +598,7 @@ void ALTIUM_PCB::Parse( const ALTIUM_PCB_COMPOUND_FILE& altiumP
if( !zone->HasFilledPolysForLayer( layer ) )
continue;
zone->GetFilledPolysList( layer )->Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
zone->GetFilledPolysList( layer )->Fracture();
}
}
@ -2824,9 +2824,9 @@ void ALTIUM_PCB::ParseRegions6Data( const ALTIUM_PCB_COMPOUND_FILE& aAltiumP
}
if( zone->HasFilledPolysForLayer( klayer ) )
fill.BooleanAdd( *zone->GetFill( klayer ), SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
fill.BooleanAdd( *zone->GetFill( klayer ) );
fill.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
fill.Fracture();
zone->SetFilledPolysList( klayer, fill );
zone->SetIsFilled( true );

View File

@ -2173,7 +2173,7 @@ void CADSTAR_PCB_ARCHIVE_LOADER::loadCoppers()
}
poly.ClearArcs();
fill.BooleanAdd( poly, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
fill.BooleanAdd( poly );
}
}
@ -2186,11 +2186,10 @@ void CADSTAR_PCB_ARCHIVE_LOADER::loadCoppers()
if( pouredZone->HasFilledPolysForLayer( getKiCadLayer( csCopper.LayerID ) ) )
{
fill.BooleanAdd( *pouredZone->GetFill( getKiCadLayer( csCopper.LayerID ) ),
SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
fill.BooleanAdd( *pouredZone->GetFill( getKiCadLayer( csCopper.LayerID ) ) );
}
fill.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
fill.Fracture();
pouredZone->SetFilledPolysList( getKiCadLayer( csCopper.LayerID ), fill );
pouredZone->SetIsFilled( true );
@ -2270,7 +2269,7 @@ void CADSTAR_PCB_ARCHIVE_LOADER::loadCoppers()
zone->SetAssignedPriority( m_zonesMap.size() + 1 ); // Highest priority (always fill first)
SHAPE_POLY_SET fill( *zone->Outline() );
fill.Fracture( SHAPE_POLY_SET::POLYGON_MODE::PM_STRICTLY_SIMPLE );
fill.Fracture();
zone->SetFilledPolysList( getKiCadLayer( csCopper.LayerID ), fill );
}
@ -2822,7 +2821,7 @@ void CADSTAR_PCB_ARCHIVE_LOADER::drawCadstarShape( const SHAPE& aCadstarShape,
aScalingFactor, aTransformCentre,
aMirrorInvert );
shapePolys.Fracture( SHAPE_POLY_SET::POLYGON_MODE::PM_STRICTLY_SIMPLE );
shapePolys.Fracture();
shape->SetPolyShape( shapePolys );
shape->SetStroke( STROKE_PARAMS( aLineThickness, LINE_STYLE::SOLID ) );
@ -3770,9 +3769,9 @@ bool CADSTAR_PCB_ARCHIVE_LOADER::calculateZonePriorities( PCB_LAYER_ID& aLayer )
SHAPE_POLY_SET lowerZoneFill( *aLowerZone->GetFilledPolysList( aLayer ) );
SHAPE_POLY_SET lowerZoneOutline( *aLowerZone->Outline() );
lowerZoneOutline.BooleanSubtract( intersectShape, SHAPE_POLY_SET::PM_FAST );
lowerZoneOutline.BooleanSubtract( intersectShape );
lowerZoneFill.BooleanSubtract( lowerZoneOutline, SHAPE_POLY_SET::PM_FAST );
lowerZoneFill.BooleanSubtract( lowerZoneOutline );
double leftOverArea = lowerZoneFill.Area();
@ -3790,7 +3789,7 @@ bool CADSTAR_PCB_ARCHIVE_LOADER::calculateZonePriorities( PCB_LAYER_ID& aLayer )
outLineB.Inflate( inflateValue( aZoneA, aZoneB ), CORNER_STRATEGY::ROUND_ALL_CORNERS,
ARC_HIGH_DEF );
outLineA.BooleanIntersection( outLineB, SHAPE_POLY_SET::PM_FAST );
outLineA.BooleanIntersection( outLineB );
return outLineA.Area();
};

View File

@ -572,7 +572,7 @@ void PCB_IO_EASYEDA_PARSER::ParseToBoardItemContainer(
}
}
fillPolySet.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
fillPolySet.Fracture();
zone->SetFilledPolysList( layer, fillPolySet );
zone->SetIsFilled( true );

View File

@ -880,7 +880,7 @@ FOOTPRINT* PCB_IO_EASYEDAPRO_PARSER::ParseFootprint( const nlohmann::json&
true );
}
polySet.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
polySet.Simplify();
std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( footprint );
@ -1158,7 +1158,7 @@ void PCB_IO_EASYEDAPRO_PARSER::ParseBoard(
zoneFillPoly.AddOutline( contour );
zoneFillPoly.RebuildHolesFromContours();
zoneFillPoly.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
zoneFillPoly.Fracture();
std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aBoard );
@ -1771,7 +1771,7 @@ void PCB_IO_EASYEDAPRO_PARSER::ParseBoard(
// The contour can be self-intersecting
SHAPE_POLY_SET simple( contour );
simple.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
simple.Simplify();
if( dataId == 0 )
{
@ -1779,7 +1779,7 @@ void PCB_IO_EASYEDAPRO_PARSER::ParseBoard(
}
else
{
thisPoly.BooleanSubtract( simple, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
thisPoly.BooleanSubtract( simple );
}
}
else
@ -1801,16 +1801,16 @@ void PCB_IO_EASYEDAPRO_PARSER::ParseBoard(
if( !fillPolySet.IsEmpty() )
{
fillPolySet.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
fillPolySet.Simplify();
const int strokeWidth = pcbIUScale.MilsToIU( 8 ); // Seems to be 8 mils
fillPolySet.Inflate( strokeWidth / 2, CORNER_STRATEGY::ROUND_ALL_CORNERS,
ARC_HIGH_DEF, false );
fillPolySet.BooleanAdd( thermalSpokes, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
fillPolySet.BooleanAdd( thermalSpokes );
fillPolySet.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
fillPolySet.Fracture();
zone->SetFilledPolysList( zone->GetFirstLayer(), fillPolySet );
zone->SetNeedRefill( false );

View File

@ -2724,7 +2724,7 @@ bool FABMASTER::loadFootprints( BOARD* aBoard )
}
else
{
poly_outline.Fracture( SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
poly_outline.Fracture();
poly_outline.Move( -newpad->GetPosition() );
@ -3324,7 +3324,7 @@ bool FABMASTER::loadPolygon( BOARD* aBoard, const std::unique_ptr<FABMASTER::TRA
SHAPE_POLY_SET poly_outline = loadShapePolySet( aLine->segment );
poly_outline.Fracture( SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
poly_outline.Fracture();
if( poly_outline.OutlineCount() < 1 || poly_outline.COutline( 0 ).PointCount() < 3 )
return false;
@ -3552,7 +3552,7 @@ bool FABMASTER::loadGraphics( BOARD* aBoard )
{
SHAPE_POLY_SET poly_outline = loadShapePolySet( *( geom.elements ) );
poly_outline.Fracture( SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
poly_outline.Fracture();
if( poly_outline.OutlineCount() < 1 || poly_outline.COutline( 0 ).PointCount() < 3 )
continue;

View File

@ -606,7 +606,7 @@ void PCB_IO_IPC2581::addKnockoutText( wxXmlNode* aContentNode, PCB_TEXT* aText )
SHAPE_POLY_SET finalPoly;
aText->TransformTextToPolySet( finalPoly, 0, ARC_HIGH_DEF, ERROR_INSIDE );
finalPoly.Fracture( SHAPE_POLY_SET::PM_FAST );
finalPoly.Fracture();
for( int ii = 0; ii < finalPoly.OutlineCount(); ++ii )
addContourNode( aContentNode, finalPoly, ii );
@ -889,7 +889,7 @@ void PCB_IO_IPC2581::addShape( wxXmlNode* aContentNode, const PAD& aPad, PCB_LAY
if( expansion.x )
{
outline.InflateWithLinkedHoles( expansion.x, CORNER_STRATEGY::ROUND_ALL_CORNERS,
maxError, SHAPE_POLY_SET::PM_FAST );
maxError );
}
addContourNode( entry_node, outline );
@ -910,8 +910,7 @@ void PCB_IO_IPC2581::addShape( wxXmlNode* aContentNode, const PAD& aPad, PCB_LAY
if( expansion != VECTOR2I( 0, 0 ) )
{
shape.InflateWithLinkedHoles( std::max( expansion.x, expansion.y ),
CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError,
SHAPE_POLY_SET::PM_FAST );
CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError );
}
addContourNode( entry_node, shape );

View File

@ -2627,8 +2627,7 @@ void PCB_IO_KICAD_LEGACY::loadZONE_CONTAINER()
inflatedFill.InflateWithLinkedHoles( zc->GetMinThickness() / 2,
CORNER_STRATEGY::ROUND_ALL_CORNERS,
ARC_HIGH_DEF / 2,
SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
ARC_HIGH_DEF / 2 );
zc->SetFilledPolysList( layer, inflatedFill );
}

View File

@ -7231,8 +7231,7 @@ ZONE* PCB_IO_KICAD_SEXPR_PARSER::parseZONE( BOARD_ITEM_CONTAINER* aParent )
{
polyset.InflateWithLinkedHoles( zone->GetMinThickness() / 2,
CORNER_STRATEGY::ROUND_ALL_CORNERS,
ARC_HIGH_DEF / 2,
SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
ARC_HIGH_DEF / 2 );
}
}
}
@ -7271,7 +7270,7 @@ ZONE* PCB_IO_KICAD_SEXPR_PARSER::parseZONE( BOARD_ITEM_CONTAINER* aParent )
TransformOvalToPolygon( segPolygon, seg.A, seg.B, zone->GetMinThickness(),
ARC_HIGH_DEF, ERROR_OUTSIDE );
layerFill.BooleanAdd( segPolygon, SHAPE_POLY_SET::PM_FAST );
layerFill.BooleanAdd( segPolygon );
}

View File

@ -141,7 +141,7 @@ void FEATURES_MANAGER::AddShape( const PCB_SHAPE& aShape, PCB_LAYER_ID aLayer )
if( soldermask_min_thickness == 0 )
{
poly_set = aShape.GetPolyShape().CloneDropTriangulation();
poly_set.Fracture( SHAPE_POLY_SET::PM_FAST );
poly_set.Fracture();
}
else
{
@ -152,11 +152,11 @@ void FEATURES_MANAGER::AddShape( const PCB_SHAPE& aShape, PCB_LAYER_ID aLayer )
aShape.TransformShapeToPolygon( poly_set, aLayer, soldermask_min_thickness / 2 - 1,
maxError, ERROR_OUTSIDE );
poly_set.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
poly_set.Simplify();
poly_set.Deflate( soldermask_min_thickness / 2 - 1,
CORNER_STRATEGY::CHAMFER_ALL_CORNERS, maxError );
poly_set.BooleanAdd( initialPolys, SHAPE_POLY_SET::PM_FAST );
poly_set.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
poly_set.BooleanAdd( initialPolys );
poly_set.Fracture();
}
int strokeWidth = aShape.GetStroke().GetWidth();
@ -338,7 +338,7 @@ void FEATURES_MANAGER::AddPadShape( const PAD& aPad, PCB_LAYER_ID aLayer )
if( mask_clearance )
{
outline.InflateWithLinkedHoles( expansion.x, CORNER_STRATEGY::ROUND_ALL_CORNERS,
maxError, SHAPE_POLY_SET::PM_FAST );
maxError );
}
for( int ii = 0; ii < outline.OutlineCount(); ++ii )
@ -360,8 +360,7 @@ void FEATURES_MANAGER::AddPadShape( const PAD& aPad, PCB_LAYER_ID aLayer )
if( expansion != VECTOR2I( 0, 0 ) )
{
shape.InflateWithLinkedHoles( std::max( expansion.x, expansion.y ),
CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError,
SHAPE_POLY_SET::PM_FAST );
CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError );
}
for( int ii = 0; ii < shape.OutlineCount(); ++ii )
@ -644,7 +643,7 @@ void FEATURES_MANAGER::InitFeatureList( PCB_LAYER_ID aLayer, std::vector<BOARD_I
text->TransformTextToPolySet( finalpolyset, 0, m_board->GetDesignSettings().m_MaxError,
ERROR_INSIDE );
finalpolyset.Fracture( SHAPE_POLY_SET::PM_FAST );
finalpolyset.Fracture();
for( int ii = 0; ii < finalpolyset.OutlineCount(); ++ii )
{

View File

@ -2238,7 +2238,7 @@ void PCB_PAINTER::draw( const PCB_TEXT* aText, int aLayer )
{
SHAPE_POLY_SET finalPoly;
aText->TransformTextToPolySet( finalPoly, 0, m_maxError, ERROR_INSIDE );
finalPoly.Fracture( SHAPE_POLY_SET::PM_FAST );
finalPoly.Fracture();
m_gal->SetIsStroke( false );
m_gal->SetIsFill( true );

View File

@ -538,7 +538,7 @@ void PCB_TEXT::TransformTextToPolySet( SHAPE_POLY_SET& aBuffer, int aClearance,
} );
font->Draw( &callback_gal, GetShownText( true ), GetTextPos(), attrs, GetFontMetrics() );
textShape.Simplify( SHAPE_POLY_SET::PM_FAST );
textShape.Simplify();
if( IsKnockout() )
{
@ -546,7 +546,7 @@ void PCB_TEXT::TransformTextToPolySet( SHAPE_POLY_SET& aBuffer, int aClearance,
int margin = GetKnockoutTextMargin( attrs.m_Size, penWidth );
buildBoundingHull( &finalPoly, textShape, margin + aClearance );
finalPoly.BooleanSubtract( textShape, SHAPE_POLY_SET::PM_FAST );
finalPoly.BooleanSubtract( textShape );
aBuffer.Append( finalPoly );
}

View File

@ -665,7 +665,7 @@ void PCB_TEXTBOX::TransformTextToPolySet( SHAPE_POLY_SET& aBuffer, int aClearanc
}
else
{
buffer.Simplify( SHAPE_POLY_SET::PM_FAST );
buffer.Simplify();
}
aBuffer.Append( buffer );

View File

@ -860,8 +860,7 @@ static void enclosedByAreaFunc( LIBEVAL::CONTEXT* aCtx, void* self )
}
else
{
itemShape.BooleanSubtract( *aArea->Outline(),
SHAPE_POLY_SET::PM_FAST );
itemShape.BooleanSubtract( *aArea->Outline() );
enclosedByArea = itemShape.IsEmpty();
}

View File

@ -467,8 +467,7 @@ void PlotStandardLayer( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
// Shape polygon can have holes so use InflateWithLinkedHoles(), not Inflate()
// which can create bad shapes if margin.x is < 0
outline.InflateWithLinkedHoles( mask_clearance,
CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError,
SHAPE_POLY_SET::PM_FAST );
CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError );
dummy.DeletePrimitivesList();
dummy.AddPrimitivePoly( aLayer, outline, 0, true );
@ -518,8 +517,7 @@ void PlotStandardLayer( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
dummy.TransformShapeToPolygon( outline, UNDEFINED_LAYER, 0, maxError,
ERROR_INSIDE );
outline.InflateWithLinkedHoles( mask_clearance,
CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError,
SHAPE_POLY_SET::PM_FAST );
CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError );
// Initialize the dummy pad shape:
dummy.SetAnchorPadShape( aLayer, PAD_SHAPE::CIRCLE );
@ -554,8 +552,7 @@ void PlotStandardLayer( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
// Shape polygon can have holes so use InflateWithLinkedHoles(), not Inflate()
// which can create bad shapes if margin.x is < 0
shape.InflateWithLinkedHoles( mask_clearance,
CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError,
SHAPE_POLY_SET::PM_FAST );
CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError );
dummy.DeletePrimitivesList();
dummy.AddPrimitivePoly( aLayer, shape, 0, true );
@ -792,7 +789,7 @@ void PlotLayerOutlines( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
outlines.RemoveAllContours();
aBoard->ConvertBrdLayerToPolygonalContours( layer, outlines );
outlines.Simplify( SHAPE_POLY_SET::PM_FAST );
outlines.Simplify();
// Plot outlines
std::vector<VECTOR2I> cornerList;
@ -1046,7 +1043,7 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
// 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.Simplify();
areas.Deflate( inflate, CORNER_STRATEGY::CHAMFER_ALL_CORNERS, maxError );
// To avoid a lot of code, use a ZONE to handle and plot polygons, because our polygons look
@ -1060,8 +1057,8 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
// 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
areas.BooleanAdd( initialPolys, SHAPE_POLY_SET::PM_FAST );
areas.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
areas.BooleanAdd( initialPolys );
areas.Fracture();
itemplotter.PlotZone( &zone, layer, areas );
}

View File

@ -733,7 +733,7 @@ void BRDITEMS_PLOTTER::PlotText( const EDA_TEXT* aText, PCB_LAYER_ID aLayer, boo
text->TransformTextToPolySet( finalPoly, 0, m_board->GetDesignSettings().m_MaxError,
ERROR_INSIDE );
finalPoly.Fracture( SHAPE_POLY_SET::PM_FAST );
finalPoly.Fracture();
for( int ii = 0; ii < finalPoly.OutlineCount(); ++ii )
m_plotter->PlotPoly( finalPoly.Outline( ii ), FILL_T::FILLED_SHAPE, 0, &gbr_metadata );
@ -966,7 +966,7 @@ void BRDITEMS_PLOTTER::PlotShape( const PCB_SHAPE* aShape )
// This must be simplified and fractured to prevent overlapping polygons
// from generating invalid Gerber files
SHAPE_POLY_SET tmpPoly = aShape->GetPolyShape().CloneDropTriangulation();
tmpPoly.Fracture( SHAPE_POLY_SET::PM_FAST );
tmpPoly.Fracture();
if( margin < 0 )
{

View File

@ -89,7 +89,7 @@ const SHAPE_LINE_CHAIN HOLE::Hull( int aClearance, int aWalkaroundThickness, int
BuildHullForPrimitiveShape( shape, aClearance, aWalkaroundThickness ) );
}
hullSet.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
hullSet.Simplify();
return hullSet.Outline( 0 );
}
}

View File

@ -24,6 +24,7 @@
#define __PNS_ITEM_H
#include <memory>
#include <set>
#include <unordered_set>
#include <math/vector2d.h>

View File

@ -60,7 +60,7 @@ const SHAPE_LINE_CHAIN SOLID::Hull( int aClearance, int aWalkaroundThickness, in
aWalkaroundThickness ) );
}
hullSet.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
hullSet.Simplify();
return hullSet.Outline( 0 );
}
}

View File

@ -843,7 +843,7 @@ IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, FOOTPRINT* aFootprint )
TransformCircleToPolygon( polyBuffer, graphic->GetEnd() - move,
graphic->GetWidth() / 2, ARC_HIGH_DEF, ERROR_INSIDE );
polyBuffer.Simplify( SHAPE_POLY_SET::PM_FAST );
polyBuffer.Simplify();
SHAPE_LINE_CHAIN& poly = polyBuffer.Outline( 0 );
for( int ii = 0; ii < poly.PointCount(); ++ii )

View File

@ -388,7 +388,7 @@ bool TEARDROP_MANAGER::computeAnchorPoints( const TEARDROP_PARAMETERS& aParams,
clipping_rect.Move( ref_on_track );
// Clip the shape to the max allowed teadrop area
c_buffer.BooleanIntersection( clipping_rect, SHAPE_POLY_SET::PM_FAST );
c_buffer.BooleanIntersection( clipping_rect );
}
/* in aPts:

View File

@ -1320,11 +1320,10 @@ static bool mergeZones( EDA_DRAW_FRAME* aFrame, BOARD_COMMIT& aCommit,
for( unsigned int i = 1; i < aOriginZones.size(); i++ )
{
aOriginZones[0]->Outline()->BooleanAdd( *aOriginZones[i]->Outline(),
SHAPE_POLY_SET::PM_FAST );
aOriginZones[0]->Outline()->BooleanAdd( *aOriginZones[i]->Outline() );
}
aOriginZones[0]->Outline()->Simplify( SHAPE_POLY_SET::PM_FAST );
aOriginZones[0]->Outline()->Simplify();
// We should have one polygon, possibly with holes. If we end up with two polygons (either
// because the intersection was a single point or because the intersection was within one of

View File

@ -373,7 +373,7 @@ int CONVERT_TOOL::CreatePolys( const TOOL_EVENT& aEvent )
polySet.Append( makePolysFromOpenGraphics( selection.GetItems(), 0 ) );
polySet.ClearArcs();
polySet.Simplify( SHAPE_POLY_SET::PM_FAST );
polySet.Simplify();
// Now inflate the bounding hull by cfg.m_Gap
polySet.Inflate( cfg.m_Gap, CORNER_STRATEGY::ROUND_ALL_CORNERS, bds.m_MaxError,

View File

@ -571,8 +571,7 @@ std::optional<wxString> POLYGON_MERGE_ROUTINE::GetStatusMessage() const
bool POLYGON_MERGE_ROUTINE::ProcessSubsequentPolygon( const SHAPE_POLY_SET& aPolygon )
{
const SHAPE_POLY_SET::POLYGON_MODE poly_mode = SHAPE_POLY_SET::POLYGON_MODE::PM_FAST;
GetWorkingPolygons().BooleanAdd( aPolygon, poly_mode );
GetWorkingPolygons().BooleanAdd( aPolygon );
return true;
}
@ -599,11 +598,9 @@ std::optional<wxString> POLYGON_SUBTRACT_ROUTINE::GetStatusMessage() const
bool POLYGON_SUBTRACT_ROUTINE::ProcessSubsequentPolygon( const SHAPE_POLY_SET& aPolygon )
{
const SHAPE_POLY_SET::POLYGON_MODE poly_mode = SHAPE_POLY_SET::POLYGON_MODE::PM_FAST;
SHAPE_POLY_SET& working_polygons = GetWorkingPolygons();
SHAPE_POLY_SET working_copy = working_polygons;
working_copy.BooleanSubtract( aPolygon, poly_mode );
working_copy.BooleanSubtract( aPolygon );
// Subtraction can create holes or delete the polygon
// In theory we can allow holes as the EDA_SHAPE will fracture for us, but that's
@ -642,11 +639,9 @@ std::optional<wxString> POLYGON_INTERSECT_ROUTINE::GetStatusMessage() const
bool POLYGON_INTERSECT_ROUTINE::ProcessSubsequentPolygon( const SHAPE_POLY_SET& aPolygon )
{
const SHAPE_POLY_SET::POLYGON_MODE poly_mode = SHAPE_POLY_SET::POLYGON_MODE::PM_FAST;
SHAPE_POLY_SET& working_polygons = GetWorkingPolygons();
SHAPE_POLY_SET working_copy = working_polygons;
working_copy.BooleanIntersection( aPolygon, poly_mode );
working_copy.BooleanIntersection( aPolygon );
// Is there anything left?
if( working_copy.OutlineCount() == 0 )

View File

@ -36,7 +36,6 @@ using namespace std::placeholders;
#include <board.h>
#include <board_design_settings.h>
#include <board_item.h>
#include <clipper.hpp>
#include <pcb_reference_image.h>
#include <pcb_track.h>
#include <footprint.h>

View File

@ -171,7 +171,7 @@ void ZONE_CREATE_HELPER::performZoneCutout( ZONE& aZone, const ZONE& aCutout )
toolMgr->RunAction( PCB_ACTIONS::selectionClear );
SHAPE_POLY_SET originalOutline( *aZone.Outline() );
originalOutline.BooleanSubtract( *aCutout.Outline(), SHAPE_POLY_SET::PM_FAST );
originalOutline.BooleanSubtract( *aCutout.Outline() );
// After substracting the hole, originalOutline can have more than one main outline.
// But a zone can have only one main outline, so create as many zones as originalOutline

View File

@ -344,8 +344,7 @@ void TRACKS_CLEANER::deleteTracksInPads()
track->TransformShapeToPolygon( poly, track->GetLayer(), 0, ARC_HIGH_DEF,
ERROR_INSIDE );
poly.BooleanSubtract( *pad->GetEffectivePolygon( track->GetLayer(), ERROR_INSIDE ),
SHAPE_POLY_SET::PM_FAST );
poly.BooleanSubtract( *pad->GetEffectivePolygon( track->GetLayer(), ERROR_INSIDE ) );
if( poly.IsEmpty() )
{

View File

@ -991,7 +991,7 @@ void ZONE::RemoveCutout( int aOutlineIdx, int aHoleIdx )
SHAPE_POLY_SET cutPoly( m_Poly->Hole( aOutlineIdx, aHoleIdx ) );
// Add the cutout back to the zone
m_Poly->BooleanAdd( cutPoly, SHAPE_POLY_SET::PM_FAST );
m_Poly->BooleanAdd( cutPoly );
SetNeedRefill( true );
}
@ -1434,7 +1434,7 @@ bool ZONE::BuildSmoothedPoly( SHAPE_POLY_SET& aSmoothedPoly, PCB_LAYER_ID aLayer
{
withFillets = flattened;
smooth( withFillets );
withFillets.BooleanAdd( flattened, SHAPE_POLY_SET::PM_FAST );
withFillets.BooleanAdd( flattened );
maxExtents = &withFillets;
}
@ -1466,7 +1466,7 @@ bool ZONE::BuildSmoothedPoly( SHAPE_POLY_SET& aSmoothedPoly, PCB_LAYER_ID aLayer
if( diffNetZone->HigherPriority( sameNetZone )
&& diffNetZone->GetBoundingBox().Intersects( sameNetBoundingBox ) )
{
diffNetPoly.BooleanAdd( *diffNetZone->Outline(), SHAPE_POLY_SET::PM_FAST );
diffNetPoly.BooleanAdd( *diffNetZone->Outline() );
}
}
@ -1479,19 +1479,19 @@ bool ZONE::BuildSmoothedPoly( SHAPE_POLY_SET& aSmoothedPoly, PCB_LAYER_ID aLayer
{
SHAPE_POLY_SET thisPoly = Outline()->CloneDropTriangulation();
thisPoly.BooleanSubtract( diffNetPoly, SHAPE_POLY_SET::PM_FAST );
thisPoly.BooleanSubtract( diffNetPoly );
isolated = thisPoly.OutlineCount() == 0;
}
if( !isolated )
{
sameNetPoly.ClearArcs();
aSmoothedPoly.BooleanAdd( sameNetPoly, SHAPE_POLY_SET::PM_FAST );
aSmoothedPoly.BooleanAdd( sameNetPoly );
}
}
if( aBoardOutline )
aSmoothedPoly.BooleanIntersection( *aBoardOutline, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
aSmoothedPoly.BooleanIntersection( *aBoardOutline );
SHAPE_POLY_SET withSameNetIntersectingZones = aSmoothedPoly.CloneDropTriangulation();
@ -1508,13 +1508,13 @@ bool ZONE::BuildSmoothedPoly( SHAPE_POLY_SET& aSmoothedPoly, PCB_LAYER_ID aLayer
poly.Inflate( m_ZoneMinThickness, CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError );
if( !keepExternalFillets )
poly.BooleanIntersection( withSameNetIntersectingZones, SHAPE_POLY_SET::PM_FAST );
poly.BooleanIntersection( withSameNetIntersectingZones );
*aSmoothedPolyWithApron = aSmoothedPoly;
aSmoothedPolyWithApron->BooleanIntersection( poly, SHAPE_POLY_SET::PM_FAST );
aSmoothedPolyWithApron->BooleanIntersection( poly );
}
aSmoothedPoly.BooleanIntersection( *maxExtents, SHAPE_POLY_SET::PM_FAST );
aSmoothedPoly.BooleanIntersection( *maxExtents );
return true;
}
@ -1576,7 +1576,7 @@ void ZONE::TransformSmoothedOutlineToPolygon( SHAPE_POLY_SET& aBuffer, int aClea
polybuffer.Inflate( aClearance, CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError );
}
polybuffer.Fracture( SHAPE_POLY_SET::PM_FAST );
polybuffer.Fracture();
aBuffer.Append( polybuffer );
}
@ -1612,8 +1612,7 @@ void ZONE::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer
if( aErrorLoc == ERROR_OUTSIDE )
aClearance += aError;
temp_buf.InflateWithLinkedHoles( aClearance, CORNER_STRATEGY::ROUND_ALL_CORNERS, aError,
SHAPE_POLY_SET::PM_FAST );
temp_buf.InflateWithLinkedHoles( aClearance, CORNER_STRATEGY::ROUND_ALL_CORNERS, aError );
}
aBuffer.Append( temp_buf );

View File

@ -796,8 +796,7 @@ bool ZONE_FILLER::Fill( const std::vector<ZONE*>& aZones, bool aCheck, wxWindow*
island.AddOutline( test_poly );
intersection.BooleanIntersection( m_boardOutline, island,
SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
intersection.BooleanIntersection( m_boardOutline, island );
// Nominally, all of these areas should be either inside or outside the
// board outline. So this test should be able to just compare areas (if
@ -1118,7 +1117,7 @@ void ZONE_FILLER::knockoutThermalReliefs( const ZONE* aZone, PCB_LAYER_ID aLayer
}
}
aFill.BooleanSubtract( holes, SHAPE_POLY_SET::PM_FAST );
aFill.BooleanSubtract( holes );
}
@ -1505,7 +1504,7 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE* aZone, PCB_LAYER_ID aLa
}
}
aHoles.Simplify( SHAPE_POLY_SET::PM_FAST );
aHoles.Simplify();
}
@ -1533,7 +1532,7 @@ void ZONE_FILLER::subtractHigherPriorityZones( const ZONE* aZone, PCB_LAYER_ID a
SHAPE_POLY_SET outline = aKnockout->Outline()->CloneDropTriangulation();
outline.ClearArcs();
aRawFill.BooleanSubtract( outline, SHAPE_POLY_SET::PM_FAST );
aRawFill.BooleanSubtract( outline );
}
};
@ -1617,7 +1616,7 @@ void ZONE_FILLER::connect_nearby_polys( SHAPE_POLY_SET& aPolys, double aDistance
{ \
m_board->SetLayerName( b, c ); \
SHAPE_POLY_SET d = a; \
d.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE ); \
d.Fracture(); \
aFillPolys = d; \
return false; \
} \
@ -1699,7 +1698,7 @@ bool ZONE_FILLER::fillCopperZone( const ZONE* aZone, PCB_LAYER_ID aLayer, PCB_LA
// because the "real" subtract-clearance-holes has to be done after the spokes are added.
static const bool USE_BBOX_CACHES = true;
SHAPE_POLY_SET testAreas = aFillPolys.CloneDropTriangulation();
testAreas.BooleanSubtract( clearanceHoles, SHAPE_POLY_SET::PM_FAST );
testAreas.BooleanSubtract( clearanceHoles );
DUMP_POLYS_TO_COPPER_LAYER( testAreas, In4_Cu, wxT( "minus-clearance-holes" ) );
// Prune features that don't meet minimum-width criteria
@ -1767,7 +1766,7 @@ bool ZONE_FILLER::fillCopperZone( const ZONE* aZone, PCB_LAYER_ID aLayer, PCB_LA
if( m_progressReporter && m_progressReporter->IsCancelled() )
return false;
aFillPolys.BooleanSubtract( clearanceHoles, SHAPE_POLY_SET::PM_FAST );
aFillPolys.BooleanSubtract( clearanceHoles );
DUMP_POLYS_TO_COPPER_LAYER( aFillPolys, In8_Cu, wxT( "after-spoke-trimming" ) );
/* -------------------------------------------------------------------------------------
@ -1818,7 +1817,7 @@ bool ZONE_FILLER::fillCopperZone( const ZONE* aZone, PCB_LAYER_ID aLayer, PCB_LA
* Connect nearby polygons with zero-width lines in order to ensure correct
* re-inflation.
*/
aFillPolys.Fracture( SHAPE_POLY_SET::PM_FAST );
aFillPolys.Fracture();
connect_nearby_polys( aFillPolys, aZone->GetMinThickness() );
DUMP_POLYS_TO_COPPER_LAYER( aFillPolys, In10_Cu, wxT( "connected-nearby-polys" ) );
@ -1845,9 +1844,9 @@ bool ZONE_FILLER::fillCopperZone( const ZONE* aZone, PCB_LAYER_ID aLayer, PCB_LA
for( PAD* pad : thermalConnectionPads )
addHoleKnockout( pad, 0, clearanceHoles );
aFillPolys.BooleanIntersection( aMaxExtents, SHAPE_POLY_SET::PM_FAST );
aFillPolys.BooleanIntersection( aMaxExtents );
DUMP_POLYS_TO_COPPER_LAYER( aFillPolys, In16_Cu, wxT( "after-trim-to-outline" ) );
aFillPolys.BooleanSubtract( clearanceHoles, SHAPE_POLY_SET::PM_FAST );
aFillPolys.BooleanSubtract( clearanceHoles );
DUMP_POLYS_TO_COPPER_LAYER( aFillPolys, In17_Cu, wxT( "after-trim-to-clearance-holes" ) );
/* -------------------------------------------------------------------------------------
@ -1857,7 +1856,7 @@ bool ZONE_FILLER::fillCopperZone( const ZONE* aZone, PCB_LAYER_ID aLayer, PCB_LA
subtractHigherPriorityZones( aZone, aLayer, aFillPolys );
DUMP_POLYS_TO_COPPER_LAYER( aFillPolys, In18_Cu, wxT( "minus-higher-priority-zones" ) );
aFillPolys.Fracture( SHAPE_POLY_SET::PM_FAST );
aFillPolys.Fracture();
return true;
}
@ -1911,7 +1910,7 @@ bool ZONE_FILLER::fillNonCopperZone( const ZONE* aZone, PCB_LAYER_ID aLayer,
}
aFillPolys = aSmoothedOutline;
aFillPolys.BooleanSubtract( clearanceHoles, SHAPE_POLY_SET::PM_FAST );
aFillPolys.BooleanSubtract( clearanceHoles );
for( ZONE* keepout : m_board->Zones() )
{
@ -1927,13 +1926,13 @@ bool ZONE_FILLER::fillNonCopperZone( const ZONE* aZone, PCB_LAYER_ID aLayer,
{
if( keepout->Outline()->ArcCount() == 0 )
{
aFillPolys.BooleanSubtract( *keepout->Outline(), SHAPE_POLY_SET::PM_FAST );
aFillPolys.BooleanSubtract( *keepout->Outline() );
}
else
{
SHAPE_POLY_SET keepoutOutline( *keepout->Outline() );
keepoutOutline.ClearArcs();
aFillPolys.BooleanSubtract( keepoutOutline, SHAPE_POLY_SET::PM_FAST );
aFillPolys.BooleanSubtract( keepoutOutline );
}
}
}
@ -1958,7 +1957,7 @@ bool ZONE_FILLER::fillNonCopperZone( const ZONE* aZone, PCB_LAYER_ID aLayer,
if( half_min_width - epsilon > epsilon )
aFillPolys.Inflate( half_min_width - epsilon, CORNER_STRATEGY::ROUND_ALL_CORNERS, m_maxError );
aFillPolys.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
aFillPolys.Fracture();
return true;
}
@ -2375,12 +2374,12 @@ bool ZONE_FILLER::addHatchFillTypeOnZone( const ZONE* aZone, PCB_LAYER_ID aLayer
SHAPE_POLY_SET deflatedFilledPolys = aFillPolys.CloneDropTriangulation();
deflatedFilledPolys.Deflate( outline_margin - aZone->GetMinThickness(),
CORNER_STRATEGY::CHAMFER_ALL_CORNERS, maxError );
holes.BooleanIntersection( deflatedFilledPolys, SHAPE_POLY_SET::PM_FAST );
holes.BooleanIntersection( deflatedFilledPolys );
DUMP_POLYS_TO_COPPER_LAYER( holes, In11_Cu, wxT( "fill-clipped-hatch-holes" ) );
SHAPE_POLY_SET deflatedOutline = aZone->Outline()->CloneDropTriangulation();
deflatedOutline.Deflate( outline_margin, CORNER_STRATEGY::CHAMFER_ALL_CORNERS, maxError );
holes.BooleanIntersection( deflatedOutline, SHAPE_POLY_SET::PM_FAST );
holes.BooleanIntersection( deflatedOutline );
DUMP_POLYS_TO_COPPER_LAYER( holes, In12_Cu, wxT( "outline-clipped-hatch-holes" ) );
if( aZone->GetNetCode() != 0 )
@ -2438,7 +2437,7 @@ bool ZONE_FILLER::addHatchFillTypeOnZone( const ZONE* aZone, PCB_LAYER_ID aLayer
}
}
holes.BooleanSubtract( aprons, SHAPE_POLY_SET::PM_FAST );
holes.BooleanSubtract( aprons );
}
DUMP_POLYS_TO_COPPER_LAYER( holes, In13_Cu, wxT( "pad-via-clipped-hatch-holes" ) );
@ -2454,9 +2453,9 @@ bool ZONE_FILLER::addHatchFillTypeOnZone( const ZONE* aZone, PCB_LAYER_ID aLayer
++ii;
}
// create grid. Use SHAPE_POLY_SET::PM_STRICTLY_SIMPLE to
// create grid. Useto
// generate strictly simple polygons needed by Gerber files and Fracture()
aFillPolys.BooleanSubtract( aFillPolys, holes, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
aFillPolys.BooleanSubtract( aFillPolys, holes );
DUMP_POLYS_TO_COPPER_LAYER( aFillPolys, In14_Cu, wxT( "after-hatching" ) );
return true;

View File

@ -131,21 +131,6 @@ BOOST_AUTO_TEST_CASE( ClipperConstructorCase1 )
// Case of an arc followed by a segment
// The clipper path is not in order (on purpose), to simulate the typical return from clipper
ClipperLib::Path pathClipper1 = {
{ { 125663951, 120099260, 24 }, { 125388111, 120170850, 25 }, { 125124975, 120280270, 26 },
{ 124879705, 120425376, 27 }, { 124657110, 120603322, 28 }, { 124461556, 120810617, 29 },
{ 124296876, 121043198, 30 }, { 124166301, 121296503, 31 }, { 124072391, 121565564, 32 },
{ 124016988, 121845106, 33 }, { 124001177, 122129646, 34 }, { 124025270, 122413605, 35 },
{ 124088794, 122691414, 36 }, { 124190502, 122957625, 37 }, { 124328401, 123207018, 38 },
{ 124499787, 123434703, 39 }, { 124598846, 123537154, 40 }, { 127171000, 123786000, 4 },
{ 127287862, 123704439, 5 }, { 127499716, 123513831, 6 }, { 127682866, 123295498, 7 },
{ 127833720, 123053722, 8 }, { 127949321, 122793242, 9 }, { 128027402, 122519168, 10 },
{ 128066430, 122236874, 11 }, { 128065642, 121951896, 12 }, { 128025053, 121669823, 13 },
{ 127945457, 121396185, 14 }, { 127828417, 121136349, 15 }, { 127676227, 120895410, 16 },
{ 127491873, 120678094, 17 }, { 127278968, 120488661, 18 }, { 127041689, 120330827, 19 },
{ 126784688, 120207687, 20 }, { 126513005, 120121655, 21 }, { 126231968, 120074419, 22 },
{ 125947087, 120066905, 23 } }
};
Clipper2Lib::Path64 pathClipper2 = {
{ { 125663951, 120099260, 24 }, { 125388111, 120170850, 25 }, { 125124975, 120280270, 26 },
{ 124879705, 120425376, 27 }, { 124657110, 120603322, 28 }, { 124461556, 120810617, 29 },
@ -180,22 +165,16 @@ BOOST_AUTO_TEST_CASE( ClipperConstructorCase1 )
SHAPE_ARC( { 127171000, 123786000 }, { 126231718, 120077003 }, { 124598846, 123537154 }, 0 )
};
SHAPE_LINE_CHAIN clipper1chain( pathClipper1, z_values, arcs );
SHAPE_LINE_CHAIN clipper2chain( pathClipper2, z_values, arcs );
BOOST_CHECK( GEOM_TEST::IsOutlineValid( clipper1chain ) );
BOOST_CHECK( GEOM_TEST::IsOutlineValid( clipper2chain ) );
BOOST_CHECK_EQUAL( clipper1chain.PointCount(), 37 );
BOOST_CHECK_EQUAL( clipper2chain.PointCount(), 37 );
BOOST_CHECK_EQUAL( clipper1chain.ArcCount(), 1 );
BOOST_CHECK_EQUAL( clipper2chain.ArcCount(), 1 );
BOOST_CHECK_EQUAL( clipper1chain.ShapeCount(), 2 );
BOOST_CHECK_EQUAL( clipper2chain.ShapeCount(), 2 );
BOOST_CHECK_EQUAL( clipper1chain.IsClosed(), true );
BOOST_CHECK_EQUAL( clipper2chain.IsClosed(), true );
}

View File

@ -64,7 +64,7 @@ BOOST_AUTO_TEST_CASE( TestSimplify )
{
BOOST_TEST_CONTEXT( "Simplify Iteration " << i )
{
testPoly.Simplify( SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
testPoly.Simplify();
std::vector<SHAPE_ARC> foundArcs;
testPoly.GetArcs( foundArcs );
@ -119,14 +119,14 @@ BOOST_AUTO_TEST_CASE( TestIntersectUnion )
double opPolyArea = opPoly.Area();
SHAPE_POLY_SET intersectionPoly = testPoly;
intersectionPoly.BooleanIntersection( opPoly, SHAPE_POLY_SET::POLYGON_MODE::PM_STRICTLY_SIMPLE );
intersectionPoly.BooleanIntersection( opPoly );
double intersectArea = intersectionPoly.Area();
BOOST_CHECK( GEOM_TEST::IsPolySetValid( intersectionPoly ) );
SHAPE_POLY_SET unionPoly = testPoly;
unionPoly.BooleanAdd( opPoly, SHAPE_POLY_SET::POLYGON_MODE::PM_STRICTLY_SIMPLE );
unionPoly.BooleanAdd( opPoly );
double unionArea = unionPoly.Area();
BOOST_CHECK( GEOM_TEST::IsPolySetValid( unionPoly ) );

View File

@ -158,8 +158,7 @@ BOOST_FIXTURE_TEST_CASE( NotchedZones, ZONE_FILL_TEST_FIXTURE )
{
if( zone->GetLayerSet().Contains( F_Cu ) )
{
frontCopper.BooleanAdd( *zone->GetFilledPolysList( F_Cu ),
SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
frontCopper.BooleanAdd( *zone->GetFilledPolysList( F_Cu ) );
}
}

View File

@ -135,7 +135,7 @@ int runDRCProto( PROJECT_CONTEXT project, std::shared_ptr<KIGFX::VIEW_OVERLAY> a
{
drcEngine->RunTests( EDA_UNITS::MILLIMETRES, true, false );
}
catch( const ClipperLib::clipperException& e )
catch( const Clipper2Lib::Clipper2Exception& e )
{
consoleLog.Print( wxString::Format( "Clipper exception %s occurred.", e.what() ) );
}

View File

@ -246,7 +246,7 @@ int polygon_triangulation_main( int argc, char *argv[] )
ignore_unused( poly );
#if 0
PROF_TIMER unfrac("unfrac");
poly.Unfracture( SHAPE_POLY_SET::PM_FAST );
poly.Unfracture();
unfrac.Show();
PROF_TIMER triangulate("triangulate");

View File

@ -307,12 +307,12 @@ int playground_main_func( int argc, char* argv[] )
SHAPE_POLY_SET xorPad1ToPad2 = pad1Outline;
xorPad1ToPad2.BooleanXor( pad2Outline, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
xorPad1ToPad2.BooleanXor( pad2Outline );
xorPad1ToPad2.Move( VECTOR2I( pcbIUScale.mmToIU( 10 ), 0 ) );
SHAPE_POLY_SET andPad1ToPad2 = pad2Outline;
andPad1ToPad2.BooleanIntersection( pad1Outline, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
andPad1ToPad2.BooleanIntersection( pad1Outline );
andPad1ToPad2.Move( VECTOR2I( pcbIUScale.mmToIU( 20 ), 0 ) );
std::shared_ptr<SHAPE_SEGMENT> slot = pad2.GetEffectiveHoleShape();

View File

@ -34,7 +34,6 @@ set( CMAKE_POLICY_DEFAULT_CMP0077 NEW )
set( ARGPARSE_INSTALL OFF )
add_subdirectory( argparse )
add_subdirectory( clipper )
add_subdirectory( clipper2 )
add_subdirectory( compoundfilereader )
add_subdirectory( delaunator )

View File

@ -1,9 +0,0 @@
add_library( clipper OBJECT
clipper.cpp
)
target_include_directories( clipper
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)

View File

@ -1,23 +0,0 @@
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

View File

@ -1,4 +0,0 @@
This directory contains the Clipper library for interacting with polygons.
https://sourceforge.net/projects/polyclipping/
It is licensed under the Boost Software License, with the license text in this directory.

File diff suppressed because it is too large Load Diff

View File

@ -1,457 +0,0 @@
/*******************************************************************************
* *
* Author : Angus Johnson *
* Version : 6.4.2 *
* Date : 27 February 2017 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2017 *
* *
* License: *
* Use, modification & distribution is subject to Boost Software License Ver 1. *
* http://www.boost.org/LICENSE_1_0.txt *
* *
* Attributions: *
* The code in this library is an extension of Bala Vatti's clipping algorithm: *
* "A generic solution to polygon clipping" *
* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. *
* http://portal.acm.org/citation.cfm?id=129906 *
* *
* Computer graphics and geometric modeling: implementation and algorithms *
* By Max K. Agoston *
* Springer; 1 edition (January 4, 2005) *
* http://books.google.com/books?q=vatti+clipping+agoston *
* *
* See also: *
* "Polygon Offsetting by Computing Winding Numbers" *
* Paper no. DETC2005-85513 pp. 565-575 *
* ASME 2005 International Design Engineering Technical Conferences *
* and Computers and Information in Engineering Conference (IDETC/CIE2005) *
* September 24-28, 2005 , Long Beach, California, USA *
* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf *
* *
*******************************************************************************/
#ifndef clipper_hpp
#define clipper_hpp
#define CLIPPER_VERSION "6.4.2"
// use_int32: When enabled 32bit ints are used instead of 64bit ints. This
// improve performance but coordinate values are limited to the range +/- 46340
// #define use_int32
// use_xyz: adds a Z member to IntPoint. Adds a minor cost to perfomance.
#define use_xyz
// use_lines: Enables line clipping. Adds a very minor cost to performance.
#define use_lines
// use_deprecated: Enables temporary support for the obsolete functions
// #define use_deprecated
#include <functional>
#include <vector>
#include <list>
#include <set>
#include <stdexcept>
#include <cstring>
#include <cstdlib>
#include <ostream>
#include <functional>
#include <queue>
namespace ClipperLib {
enum ClipType
{
ctIntersection, ctUnion, ctDifference, ctXor
};
enum PolyType
{
ptSubject, ptClip
};
// By far the most widely used winding rules for polygon filling are
// EvenOdd & NonZero (GDI, GDI+, XLib, OpenGL, Cairo, AGG, Quartz, SVG, Gr32)
// Others rules include Positive, Negative and ABS_GTR_EQ_TWO (only in OpenGL)
// see http://glprogramming.com/red/chapter11.html
enum PolyFillType
{
pftEvenOdd, pftNonZero, pftPositive, pftNegative
};
#ifdef use_int32
typedef int cInt;
static cInt const loRange = 0x7FFF;
static cInt const hiRange = 0x7FFF;
#else
typedef signed long long cInt;
static cInt const loRange = 0x3FFFFFFF;
static cInt const hiRange = 0x3FFFFFFFFFFFFFFFLL;
typedef signed long long long64; // used by Int128 class
typedef unsigned long long ulong64;
#endif
struct IntPoint
{
cInt X;
cInt Y;
#ifdef use_xyz
cInt Z;
IntPoint( cInt x = 0, cInt y = 0, cInt z = 0 ) : X( x ), Y( y ), Z( z ) {};
#else
IntPoint( cInt x = 0, cInt y = 0 ) : X( x ), Y( y ) {};
#endif
friend inline bool operator==( const IntPoint& a, const IntPoint& b )
{
return a.X == b.X && a.Y == b.Y;
}
friend inline bool operator!=( const IntPoint& a, const IntPoint& b )
{
return a.X != b.X || a.Y != b.Y;
}
};
// ------------------------------------------------------------------------------
typedef std::vector<IntPoint> Path;
typedef std::vector<Path> Paths;
inline Path& operator <<( Path& poly, const IntPoint& p )
{
poly.push_back( p ); return poly;
}
inline Paths& operator <<( Paths& polys, const Path& p )
{
polys.push_back( p ); return polys;
}
std::ostream& operator <<( std::ostream& s, const IntPoint& p );
std::ostream& operator <<( std::ostream& s, const Path& p );
std::ostream& operator <<( std::ostream& s, const Paths& p );
struct DoublePoint
{
double X;
double Y;
DoublePoint( double x = 0, double y = 0 ) : X( x ), Y( y ) {}
DoublePoint( IntPoint ip ) : X( (double) ip.X ), Y( (double) ip.Y ) {}
};
// ------------------------------------------------------------------------------
#ifdef use_xyz
typedef std::function<void( IntPoint& e1bot, IntPoint& e1top, IntPoint& e2bot, IntPoint& e2top,
IntPoint& pt )> ZFillCallback;
#endif
enum InitOptions
{
ioReverseSolution = 1, ioStrictlySimple = 2, ioPreserveCollinear = 4
};
enum JoinType
{
jtSquare, jtRound, jtMiter
};
enum EndType
{
etClosedPolygon, etClosedLine, etOpenButt, etOpenSquare, etOpenRound
};
class PolyNode;
typedef std::vector<PolyNode*> PolyNodes;
class PolyNode
{
public:
PolyNode();
virtual ~PolyNode() {};
Path Contour;
PolyNodes Childs;
PolyNode* Parent;
PolyNode* GetNext() const;
bool IsHole() const;
bool IsOpen() const;
int ChildCount() const;
private:
// PolyNode& operator =(PolyNode& other);
unsigned Index; // node index in Parent.Childs
bool m_IsOpen;
JoinType m_jointype;
EndType m_endtype;
PolyNode* GetNextSiblingUp() const;
void AddChild( PolyNode& child );
friend class Clipper; // to access Index
friend class ClipperOffset;
};
class PolyTree : public PolyNode
{
public:
~PolyTree() { Clear(); };
PolyNode* GetFirst() const;
void Clear();
int Total() const;
private:
// PolyTree& operator =(PolyTree& other);
PolyNodes AllNodes;
friend class Clipper; // to access AllNodes
};
bool Orientation( const Path& poly );
double Area( const Path& poly );
int PointInPolygon( const IntPoint& pt, const Path& path );
void SimplifyPolygon( const Path& in_poly, Paths& out_polys,
PolyFillType fillType = pftEvenOdd );
void SimplifyPolygons( const Paths& in_polys,
Paths& out_polys,
PolyFillType fillType = pftEvenOdd );
void SimplifyPolygons( Paths& polys, PolyFillType fillType = pftEvenOdd );
void CleanPolygon( const Path& in_poly, Path& out_poly, double distance = 1.415 );
void CleanPolygon( Path& poly, double distance = 1.415 );
void CleanPolygons( const Paths& in_polys, Paths& out_polys, double distance = 1.415 );
void CleanPolygons( Paths& polys, double distance = 1.415 );
void MinkowskiSum( const Path& pattern, const Path& path, Paths& solution, bool pathIsClosed );
void MinkowskiSum( const Path& pattern, const Paths& paths, Paths& solution, bool pathIsClosed );
void MinkowskiDiff( const Path& poly1, const Path& poly2, Paths& solution );
void PolyTreeToPaths( const PolyTree& polytree, Paths& paths );
void ClosedPathsFromPolyTree( const PolyTree& polytree, Paths& paths );
void OpenPathsFromPolyTree( PolyTree& polytree, Paths& paths );
void ReversePath( Path& p );
void ReversePaths( Paths& p );
struct IntRect
{
cInt left; cInt top; cInt right; cInt bottom;
};
// enums that are used internally ...
enum EdgeSide
{
esLeft = 1, esRight = 2
};
// forward declarations (for stuff used internally) ...
struct TEdge;
struct IntersectNode;
struct LocalMinimum;
struct OutPt;
struct OutRec;
struct Join;
typedef std::vector <OutRec*> PolyOutList;
typedef std::vector <TEdge*> EdgeList;
typedef std::vector <Join*> JoinList;
typedef std::vector <IntersectNode*> IntersectList;
// ------------------------------------------------------------------------------
// ClipperBase is the ancestor to the Clipper class. It should not be
// instantiated directly. This class simply abstracts the conversion of sets of
// polygon coordinates into edge objects that are stored in a LocalMinima list.
class ClipperBase
{
public:
ClipperBase();
virtual ~ClipperBase();
virtual bool AddPath( const Path& pg, PolyType PolyTyp, bool Closed );
bool AddPaths( const Paths& ppg, PolyType PolyTyp, bool Closed );
virtual void Clear();
IntRect GetBounds();
bool PreserveCollinear() { return m_PreserveCollinear; };
void PreserveCollinear( bool value ) { m_PreserveCollinear = value; };
protected:
void DisposeLocalMinimaList();
TEdge* AddBoundsToLML( TEdge* e, bool IsClosed );
virtual void Reset();
TEdge* ProcessBound( TEdge* E, bool IsClockwise );
void InsertScanbeam( const cInt Y );
bool PopScanbeam( cInt& Y );
bool LocalMinimaPending();
bool PopLocalMinima( cInt Y, const LocalMinimum*& locMin );
OutRec* CreateOutRec();
void DisposeAllOutRecs();
void DisposeOutRec( PolyOutList::size_type index );
void SwapPositionsInAEL( TEdge* edge1, TEdge* edge2 );
void DeleteFromAEL( TEdge* e );
void UpdateEdgeIntoAEL( TEdge*& e );
typedef std::vector<LocalMinimum> MinimaList;
MinimaList::iterator m_CurrentLM;
MinimaList m_MinimaList;
bool m_UseFullRange;
EdgeList m_edges;
bool m_PreserveCollinear;
bool m_HasOpenPaths;
PolyOutList m_PolyOuts;
TEdge* m_ActiveEdges;
typedef std::priority_queue<cInt> ScanbeamList;
ScanbeamList m_Scanbeam;
};
// ------------------------------------------------------------------------------
class Clipper : public virtual ClipperBase
{
public:
Clipper( int initOptions = 0 );
bool Execute( ClipType clipType,
Paths& solution,
PolyFillType fillType = pftEvenOdd );
bool Execute( ClipType clipType,
Paths& solution,
PolyFillType subjFillType,
PolyFillType clipFillType );
bool Execute( ClipType clipType,
PolyTree& polytree,
PolyFillType fillType = pftEvenOdd );
bool Execute( ClipType clipType,
PolyTree& polytree,
PolyFillType subjFillType,
PolyFillType clipFillType );
bool ReverseSolution() { return m_ReverseOutput; };
void ReverseSolution( bool value ) { m_ReverseOutput = value; };
bool StrictlySimple() { return m_StrictSimple; };
void StrictlySimple( bool value ) { m_StrictSimple = value; };
// set the callback function for z value filling on intersections (otherwise Z is 0)
#ifdef use_xyz
void ZFillFunction( ZFillCallback zFillFunc );
#endif
protected:
virtual bool ExecuteInternal();
private:
JoinList m_Joins;
JoinList m_GhostJoins;
IntersectList m_IntersectList;
ClipType m_ClipType;
typedef std::list<cInt> MaximaList;
MaximaList m_Maxima;
TEdge* m_SortedEdges;
bool m_ExecuteLocked;
PolyFillType m_ClipFillType;
PolyFillType m_SubjFillType;
bool m_ReverseOutput;
bool m_UsingPolyTree;
bool m_StrictSimple;
#ifdef use_xyz
ZFillCallback m_ZFill; // custom callback
#endif
void SetWindingCount( TEdge& edge );
bool IsEvenOddFillType( const TEdge& edge ) const;
bool IsEvenOddAltFillType( const TEdge& edge ) const;
void InsertLocalMinimaIntoAEL( const cInt botY );
void InsertEdgeIntoAEL( TEdge* edge, TEdge* startEdge );
void AddEdgeToSEL( TEdge* edge );
bool PopEdgeFromSEL( TEdge*& edge );
void CopyAELToSEL();
void DeleteFromSEL( TEdge* e );
void SwapPositionsInSEL( TEdge* edge1, TEdge* edge2 );
bool IsContributing( const TEdge& edge ) const;
bool IsTopHorz( const cInt XPos );
void DoMaxima( TEdge* e );
void ProcessHorizontals();
void ProcessHorizontal( TEdge* horzEdge );
void AddLocalMaxPoly( TEdge* e1, TEdge* e2, const IntPoint& pt );
OutPt* AddLocalMinPoly( TEdge* e1, TEdge* e2, const IntPoint& pt );
OutRec* GetOutRec( int idx );
void AppendPolygon( TEdge* e1, TEdge* e2 );
void IntersectEdges( TEdge* e1, TEdge* e2, IntPoint& pt );
OutPt* AddOutPt( TEdge* e, const IntPoint& pt );
OutPt* GetLastOutPt( TEdge* e );
bool ProcessIntersections( const cInt topY );
void BuildIntersectList( const cInt topY );
void ProcessIntersectList();
void ProcessEdgesAtTopOfScanbeam( const cInt topY );
void BuildResult( Paths& polys );
void BuildResult2( PolyTree& polytree );
void SetHoleState( TEdge* e, OutRec* outrec );
void DisposeIntersectNodes();
bool FixupIntersectionOrder();
void FixupOutPolygon( OutRec& outrec );
void FixupOutPolyline( OutRec& outrec );
bool IsHole( TEdge* e );
bool FindOwnerFromSplitRecs( OutRec& outRec, OutRec*& currOrfl );
void FixHoleLinkage( OutRec& outrec );
void AddJoin( OutPt* op1, OutPt* op2, const IntPoint offPt );
void ClearJoins();
void ClearGhostJoins();
void AddGhostJoin( OutPt* op, const IntPoint offPt );
bool JoinPoints( Join* j, OutRec* outRec1, OutRec* outRec2 );
void JoinCommonEdges();
void DoSimplePolygons();
void FixupFirstLefts1( OutRec* OldOutRec, OutRec* NewOutRec );
void FixupFirstLefts2( OutRec* InnerOutRec, OutRec* OuterOutRec );
void FixupFirstLefts3( OutRec* OldOutRec, OutRec* NewOutRec );
#ifdef use_xyz
void SetZ( IntPoint& pt, TEdge& e1, TEdge& e2 );
#endif
};
// ------------------------------------------------------------------------------
class ClipperOffset
{
public:
ClipperOffset( double miterLimit = 2.0, double roundPrecision = 0.25 );
~ClipperOffset();
void AddPath( const Path& path, JoinType joinType, EndType endType );
void AddPaths( const Paths& paths, JoinType joinType, EndType endType );
void Execute( Paths& solution, double delta );
void Execute( PolyTree& solution, double delta );
void Clear();
double MiterLimit;
JoinType MiterFallback;
double ArcTolerance;
private:
Paths m_destPolys;
Path m_srcPoly;
Path m_destPoly;
std::vector<DoublePoint> m_normals;
double m_delta, m_sinA, m_sin, m_cos;
double m_miterLim, m_StepsPerRad;
IntPoint m_lowest;
PolyNode m_polyNodes;
void FixOrientations();
void DoOffset( double delta );
void OffsetPoint( int j, int& k, JoinType jointype );
void DoSquare( int j, int k );
void DoMiter( int j, int k, double r );
void DoRound( int j, int k );
};
// ------------------------------------------------------------------------------
class clipperException : public std::exception
{
public:
clipperException( const char* description ) : m_descr( description ) {}
virtual ~clipperException() throw() {}
virtual const char* what() const throw()override { return m_descr.c_str(); }
private:
std::string m_descr;
};
// ------------------------------------------------------------------------------
} // ClipperLib namespace
#endif // clipper_hpp