Pcbnew, export Solder masks in Gerber Format: fix not working export when the solder mask minimal width is not 0 (the exported shapes were the same as if the vule = 0) with boost version >= 1.56

This is due to the fact the boost::pylygon function resize ( a inflate/deflate function) used for calculations does not work with boost version >= 1.56.
Use Clipper  inflate/deflate function instead. It is faster and works fine.
This commit is contained in:
jean-pierre charras 2014-12-01 15:54:33 +01:00
parent cf9a885c55
commit 479af2a7a8
5 changed files with 77 additions and 39 deletions

View File

@ -580,7 +580,10 @@ void D_PAD:: TransformShapeWithClearanceToPolygon( CPOLYGONS_LIST& aCornerBuffer
ClipperLib::Paths shapeWithClearance;
for( int ii = 0; ii < 4; ii++ )
{
corners[ii] += PadShapePos;
outline << ClipperLib::IntPoint( corners[ii].x, corners[ii].y );
}
ClipperLib::ClipperOffset offset_engine;
// Prepare an offset (inflate) transform, with edges connected by arcs
@ -600,19 +603,7 @@ void D_PAD:: TransformShapeWithClearanceToPolygon( CPOLYGONS_LIST& aCornerBuffer
offset_engine.Execute( shapeWithClearance, rounding_radius );
// get new outline (only one polygon is expected)
// For info, ClipperLib uses long long to handle integer coordinates
ClipperLib::Path& polygon = shapeWithClearance[0];
for( unsigned jj = 0; jj < polygon.size(); jj++ )
{
corner_position.x = int( polygon[jj].X );
corner_position.y = int( polygon[jj].Y );
corner_position += PadShapePos;
CPolyPt polypoint( corner_position.x, corner_position.y );
aCornerBuffer.Append( polypoint );
}
aCornerBuffer.CloseLastContour();
aCornerBuffer.ImportFrom( shapeWithClearance );
}
break;
}

View File

@ -898,3 +898,14 @@ wxString ZONE_CONTAINER::GetSelectMenuText() const
return msg;
}
/* Copy polygons stored in aKiPolyList to m_FilledPolysList
* The previous m_FilledPolysList contents is replaced.
*/
void ZONE_CONTAINER::CopyPolygonsFromClipperPathsToFilledPolysList(
ClipperLib::Paths& aClipperPolyList )
{
m_FilledPolysList.RemoveAllContours();
m_FilledPolysList.ImportFrom( aClipperPolyList );
}

View File

@ -305,6 +305,14 @@ public:
*/
void CopyPolygonsFromKiPolygonListToFilledPolysList( KI_POLYGON_SET& aKiPolyList );
/**
* Function CopyPolygonsFromClipperPathsToFilledPolysList
* Copy polygons stored in aKiPolyList to m_FilledPolysList
* The previous m_FilledPolysList contents is replaced.
* @param aClipperPolyList = a ClipperLib::Paths containing polygons.
*/
void CopyPolygonsFromClipperPathsToFilledPolysList( ClipperLib::Paths& aClipperPolyList );
/**
* Function CopyPolygonsFromFilledPolysListToKiPolygonList
* Copy polygons from m_FilledPolysList to aKiPolyList

View File

@ -41,9 +41,7 @@
#include <class_module.h>
/**
* Function Tracks_and_Vias_Size_Event
* Event handler for tracks and vias size selection (and some options)
/* Event handler for tracks and vias size selection (and some options)
* relative to toolbars and popup events
*/
void PCB_EDIT_FRAME::Tracks_and_Vias_Size_Event( wxCommandEvent& event )
@ -51,11 +49,11 @@ void PCB_EDIT_FRAME::Tracks_and_Vias_Size_Event( wxCommandEvent& event )
int ii;
int id = event.GetId();
/* Note: none of these events require aborting the current command (if any)
* (like move, edit or block command)
* so we do not test for a current command in progress and call
* m_canvas->m_endMouseCaptureCallback( m_canvas, &dc );
*/
/* Note: none of these events require aborting the current command (if any)
* (like move, edit or block command)
* so we do not test for a current command in progress and call
* m_canvas->m_endMouseCaptureCallback( m_canvas, &dc );
*/
switch( id )
{
case ID_AUX_TOOLBAR_PCB_SELECT_AUTO_WIDTH:
@ -142,5 +140,7 @@ void PCB_EDIT_FRAME::Tracks_and_Vias_Size_Event( wxCommandEvent& event )
}*/
//+hp
//Refresh canvas, that we can see changes instantly. I use this because it dont,t throw mouse up-left corner.
m_canvas->Refresh();
if( m_canvas->IsMouseCaptured() )
m_canvas->Refresh();
}

View File

@ -773,12 +773,25 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter,
zone->TransformOutlinesShapeWithClearanceToPolygon( bufferPolys,
inflate, true );
zone->TransformOutlinesShapeWithClearanceToPolygon( initialPolys,
0, true );
}
// To avoid a lot of code, use a ZONE_CONTAINER
// to handle and plot polygons, because our polygons look exactly like
// filled areas in zones
// Note, also this code is not optimized: it creates a lot of copy/duplicate data
// However it is not complex, and fast enough for plot purposes (copy/convert data
// is only a very small calculation time for these calculations)
ZONE_CONTAINER zone( aBoard );
zone.SetArcSegmentCount( 32 );
zone.SetMinThickness( 0 ); // trace polygons only
zone.SetLayer ( layer );
// Now:
// 1 - merge areas which are intersecting, i.e. remove gaps
// 1 - merge polygons which are intersecting, i.e. remove gaps
// having a thickness < aMinThickness
// 2 - deflate resulting areas by aMinThickness/2
// 2 - deflate resulting polygons by aMinThickness/2
KI_POLYGON_SET areasToMerge;
bufferPolys.ExportTo( areasToMerge );
KI_POLYGON_SET initialAreas;
@ -788,29 +801,44 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter,
// = aMinThickness/2, shapes too close ( dist < aMinThickness )
// will be merged, because they are overlapping
KI_POLYGON_SET areas;
areas |= areasToMerge;
areas |= areasToMerge; // Populates with merged polygons
// Deflate: remove the extra margin, to create the actual shapes
// Here I am using polygon:resize, because this function creates better shapes
// than deflate algo.
// Use here deflate with arc creation and 18 segments per circle to create arcs
// In boost polygon (at least v 1.54 and previous) in very rare cases resize crashes
// with 16 segments (perhaps related to 45 degrees pads). So using 18 segments
// is a workaround to try to avoid these crashes
areas = resize( areas, -inflate , true, 18 );
// Use here deflate made by Clipper, because:
// Clipper is (by far) faster and better, event using arcs to deflate shapes
// boost::polygon < 1.56 polygon resize function sometimes crashes when deflating using arcs
// boost::polygon >=1.56 polygon resize function just does not work
// Note also we combine polygons using boost::polygon, which works better than Clipper,
// especially with zones using holes linked to main outlines by overlapping segments
CPOLYGONS_LIST tmp;
tmp.ImportFrom( areas );
// Resize slightly changes shapes. So *ensure* initial shapes are kept
// Deflate area using Clipper, better than boost::polygon
ClipperLib::Paths areasDeflate;
tmp.ExportTo( areasDeflate );
// Deflate areas: they will have the right size after deflate
ClipperLib::ClipperOffset offset_engine;
circleToSegmentsCount = 16;
offset_engine.ArcTolerance = (double)inflate / 3.14 / circleToSegmentsCount;
offset_engine.AddPaths( areasDeflate, ClipperLib::jtRound, ClipperLib::etClosedPolygon );
offset_engine.Execute( areasDeflate, -inflate );
// 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
tmp.RemoveAllContours();
tmp.ImportFrom( areasDeflate );
areas.clear();
tmp.ExportTo( areas );
// Resize slightly changes shapes (the transform is not perfect).
// So *ensure* initial shapes are kept
areas |= initialAreas;
// To avoid a lot of code, use a ZONE_CONTAINER
// to plot polygons, because they are exactly like
// filled areas in zones
ZONE_CONTAINER zone( aBoard );
zone.SetArcSegmentCount( 32 );
zone.SetMinThickness( 0 ); // trace polygons only
zone.SetLayer ( layer );
zone.CopyPolygonsFromKiPolygonListToFilledPolysList( areas );
itemplotter.PlotFilledAreas( &zone );
}