Commit 479af2a7 authored by jean-pierre charras's avatar jean-pierre charras

Pcbnew, export Solder masks in Gerber Format: fix not working export when the...

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.
parent cf9a885c
...@@ -580,7 +580,10 @@ void D_PAD:: TransformShapeWithClearanceToPolygon( CPOLYGONS_LIST& aCornerBuffer ...@@ -580,7 +580,10 @@ void D_PAD:: TransformShapeWithClearanceToPolygon( CPOLYGONS_LIST& aCornerBuffer
ClipperLib::Paths shapeWithClearance; ClipperLib::Paths shapeWithClearance;
for( int ii = 0; ii < 4; ii++ ) for( int ii = 0; ii < 4; ii++ )
{
corners[ii] += PadShapePos;
outline << ClipperLib::IntPoint( corners[ii].x, corners[ii].y ); outline << ClipperLib::IntPoint( corners[ii].x, corners[ii].y );
}
ClipperLib::ClipperOffset offset_engine; ClipperLib::ClipperOffset offset_engine;
// Prepare an offset (inflate) transform, with edges connected by arcs // Prepare an offset (inflate) transform, with edges connected by arcs
...@@ -600,19 +603,7 @@ void D_PAD:: TransformShapeWithClearanceToPolygon( CPOLYGONS_LIST& aCornerBuffer ...@@ -600,19 +603,7 @@ void D_PAD:: TransformShapeWithClearanceToPolygon( CPOLYGONS_LIST& aCornerBuffer
offset_engine.Execute( shapeWithClearance, rounding_radius ); offset_engine.Execute( shapeWithClearance, rounding_radius );
// get new outline (only one polygon is expected) // get new outline (only one polygon is expected)
// For info, ClipperLib uses long long to handle integer coordinates aCornerBuffer.ImportFrom( shapeWithClearance );
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();
} }
break; break;
} }
......
...@@ -898,3 +898,14 @@ wxString ZONE_CONTAINER::GetSelectMenuText() const ...@@ -898,3 +898,14 @@ wxString ZONE_CONTAINER::GetSelectMenuText() const
return msg; 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 );
}
...@@ -305,6 +305,14 @@ public: ...@@ -305,6 +305,14 @@ public:
*/ */
void CopyPolygonsFromKiPolygonListToFilledPolysList( KI_POLYGON_SET& aKiPolyList ); 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 * Function CopyPolygonsFromFilledPolysListToKiPolygonList
* Copy polygons from m_FilledPolysList to aKiPolyList * Copy polygons from m_FilledPolysList to aKiPolyList
......
...@@ -41,9 +41,7 @@ ...@@ -41,9 +41,7 @@
#include <class_module.h> #include <class_module.h>
/** /* Event handler for tracks and vias size selection (and some options)
* Function Tracks_and_Vias_Size_Event
* Event handler for tracks and vias size selection (and some options)
* relative to toolbars and popup events * relative to toolbars and popup events
*/ */
void PCB_EDIT_FRAME::Tracks_and_Vias_Size_Event( wxCommandEvent& event ) void PCB_EDIT_FRAME::Tracks_and_Vias_Size_Event( wxCommandEvent& event )
...@@ -51,7 +49,7 @@ void PCB_EDIT_FRAME::Tracks_and_Vias_Size_Event( wxCommandEvent& event ) ...@@ -51,7 +49,7 @@ void PCB_EDIT_FRAME::Tracks_and_Vias_Size_Event( wxCommandEvent& event )
int ii; int ii;
int id = event.GetId(); int id = event.GetId();
/* Note: none of these events require aborting the current command (if any) /* Note: none of these events require aborting the current command (if any)
* (like move, edit or block command) * (like move, edit or block command)
* so we do not test for a current command in progress and call * so we do not test for a current command in progress and call
* m_canvas->m_endMouseCaptureCallback( m_canvas, &dc ); * m_canvas->m_endMouseCaptureCallback( m_canvas, &dc );
...@@ -142,5 +140,7 @@ void PCB_EDIT_FRAME::Tracks_and_Vias_Size_Event( wxCommandEvent& event ) ...@@ -142,5 +140,7 @@ void PCB_EDIT_FRAME::Tracks_and_Vias_Size_Event( wxCommandEvent& event )
}*/ }*/
//+hp //+hp
//Refresh canvas, that we can see changes instantly. I use this because it dont,t throw mouse up-left corner. //Refresh canvas, that we can see changes instantly. I use this because it dont,t throw mouse up-left corner.
if( m_canvas->IsMouseCaptured() )
m_canvas->Refresh(); m_canvas->Refresh();
} }
...@@ -773,12 +773,25 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, ...@@ -773,12 +773,25 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter,
zone->TransformOutlinesShapeWithClearanceToPolygon( bufferPolys, zone->TransformOutlinesShapeWithClearanceToPolygon( bufferPolys,
inflate, true ); 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: // 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 // having a thickness < aMinThickness
// 2 - deflate resulting areas by aMinThickness/2 // 2 - deflate resulting polygons by aMinThickness/2
KI_POLYGON_SET areasToMerge; KI_POLYGON_SET areasToMerge;
bufferPolys.ExportTo( areasToMerge ); bufferPolys.ExportTo( areasToMerge );
KI_POLYGON_SET initialAreas; KI_POLYGON_SET initialAreas;
...@@ -788,29 +801,44 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, ...@@ -788,29 +801,44 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter,
// = aMinThickness/2, shapes too close ( dist < aMinThickness ) // = aMinThickness/2, shapes too close ( dist < aMinThickness )
// will be merged, because they are overlapping // will be merged, because they are overlapping
KI_POLYGON_SET areas; KI_POLYGON_SET areas;
areas |= areasToMerge; areas |= areasToMerge; // Populates with merged polygons
// Deflate: remove the extra margin, to create the actual shapes // Deflate: remove the extra margin, to create the actual shapes
// Here I am using polygon:resize, because this function creates better shapes // Here I am using polygon:resize, because this function creates better shapes
// than deflate algo. // than deflate algo.
// Use here deflate with arc creation and 18 segments per circle to create arcs // Use here deflate made by Clipper, because:
// In boost polygon (at least v 1.54 and previous) in very rare cases resize crashes // Clipper is (by far) faster and better, event using arcs to deflate shapes
// with 16 segments (perhaps related to 45 degrees pads). So using 18 segments // boost::polygon < 1.56 polygon resize function sometimes crashes when deflating using arcs
// is a workaround to try to avoid these crashes // boost::polygon >=1.56 polygon resize function just does not work
areas = resize( areas, -inflate , true, 18 ); // 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
// Resize slightly changes shapes. So *ensure* initial shapes are kept CPOLYGONS_LIST tmp;
tmp.ImportFrom( areas );
// 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; 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 ); zone.CopyPolygonsFromKiPolygonListToFilledPolysList( areas );
itemplotter.PlotFilledAreas( &zone ); itemplotter.PlotFilledAreas( &zone );
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment