Commit 41e41b95 authored by jean-pierre charras's avatar jean-pierre charras

Plot DXF: better generation of filled zone polygons.

parent 645e1768
...@@ -163,6 +163,7 @@ set( COMMON_SRCS ...@@ -163,6 +163,7 @@ set( COMMON_SRCS
config_params.cpp config_params.cpp
confirm.cpp confirm.cpp
copy_to_clipboard.cpp copy_to_clipboard.cpp
convert_basic_shapes_to_polygon.cpp
dialog_shim.cpp dialog_shim.cpp
displlst.cpp displlst.cpp
draw_frame.cpp draw_frame.cpp
...@@ -247,7 +248,6 @@ set( PCB_COMMON_SRCS ...@@ -247,7 +248,6 @@ set( PCB_COMMON_SRCS
base_screen.cpp base_screen.cpp
eda_text.cpp eda_text.cpp
class_page_info.cpp class_page_info.cpp
convert_basic_shapes_to_polygon.cpp
pcbcommon.cpp pcbcommon.cpp
footprint_info.cpp footprint_info.cpp
../pcbnew/basepcbframe.cpp ../pcbnew/basepcbframe.cpp
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <plot_common.h> #include <plot_common.h>
#include <macros.h> #include <macros.h>
#include <kicad_string.h> #include <kicad_string.h>
#include <convert_basic_shapes_to_polygon.h>
/** /**
* Oblique angle for DXF native text * Oblique angle for DXF native text
...@@ -319,35 +320,43 @@ void DXF_PLOTTER::Circle( const wxPoint& centre, int diameter, FILL_T fill, int ...@@ -319,35 +320,43 @@ void DXF_PLOTTER::Circle( const wxPoint& centre, int diameter, FILL_T fill, int
/** /**
* DXF polygon: doesn't fill it but at least it close the filled ones * DXF polygon: doesn't fill it but at least it close the filled ones
* DXF does not know thick outline.
* It does not know thhick segments, therefore filled polygons with thick outline
* are converted to inflated polygon by aWidth/2
*/ */
#include "clipper.hpp"
void DXF_PLOTTER::PlotPoly( const std::vector< wxPoint >& aCornerList, void DXF_PLOTTER::PlotPoly( const std::vector< wxPoint >& aCornerList,
FILL_T aFill, int aWidth) FILL_T aFill, int aWidth)
{ {
if( aCornerList.size() <= 1 ) if( aCornerList.size() <= 1 )
return; return;
unsigned last = aCornerList.size() - 1;
// Plot outlines with lines (thickness = 0) to define the polygon // Plot outlines with lines (thickness = 0) to define the polygon
if( aWidth == 0 || aFill ) if( aWidth <= 0 )
{ {
MoveTo( aCornerList[0] ); MoveTo( aCornerList[0] );
for( unsigned ii = 1; ii < aCornerList.size(); ii++ ) for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
LineTo( aCornerList[ii] ); LineTo( aCornerList[ii] );
}
// Close polygon if 'fill' requested // Close polygon if 'fill' requested
unsigned last = aCornerList.size() - 1; if( aFill )
{
if( aCornerList[last] != aCornerList[0] )
LineTo( aCornerList[0] );
}
if( aFill ) PenFinish();
{
if( aCornerList[last] != aCornerList[0] ) return;
LineTo( aCornerList[0] );
} }
PenFinish();
// if the polygon outline has thickness, plot outlines with thick segments // if the polygon outline has thickness, and is not filled
if( aWidth > 0 ) // (i.e. is a polyline) plot outlines with thick segments
if( aWidth > 0 && !aFill )
{ {
MoveTo( aCornerList[0] ); MoveTo( aCornerList[0] );
...@@ -355,10 +364,72 @@ void DXF_PLOTTER::PlotPoly( const std::vector< wxPoint >& aCornerList, ...@@ -355,10 +364,72 @@ void DXF_PLOTTER::PlotPoly( const std::vector< wxPoint >& aCornerList,
ThickSegment( aCornerList[ii-1], aCornerList[ii], ThickSegment( aCornerList[ii-1], aCornerList[ii],
aWidth, FILLED ); aWidth, FILLED );
if( aCornerList[last] != aCornerList[0] ) return;
ThickSegment( aCornerList[last], aCornerList[0], }
aWidth, FILLED );
// The polygon outline has thickness, and is filled
// Build and plot the polygon which contains the initial
// polygon and its thick outline
CPOLYGONS_LIST bufferOutline;
CPOLYGONS_LIST bufferPolybase;
const int circleToSegmentsCount = 16;
// enter outline as polygon:
for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
{
TransformRoundedEndsSegmentToPolygon( bufferOutline,
aCornerList[ii-1], aCornerList[ii], circleToSegmentsCount, aWidth );
}
// enter the initial polygon:
for( unsigned ii = 0; ii < aCornerList.size(); ii++ )
{
CPolyPt polypoint( aCornerList[ii].x, aCornerList[ii].y );
bufferPolybase.Append( polypoint );
}
bufferPolybase.CloseLastContour();
// Merge polygons to build the polygon which contains the initial
// polygon and its thick outline
KI_POLYGON_SET polysBase; // Store the main outline and the final outline
KI_POLYGON_SET polysOutline; // Store the thick segments to draw the outline
bufferPolybase.ExportTo( polysBase );
bufferOutline.ExportTo( polysOutline );
polysBase += polysOutline; // create the outline which contains thick outline
// We should have only one polygon in list, now.
wxASSERT( polysBase.size() == 1 );
if( polysBase.size() < 1 ) // should not happen
return;
KI_POLYGON poly = polysBase[0]; // Expected only one polygon here
if( poly.size() < 2 ) // should not happen
return;
// Now, output the final polygon to DXF file:
last = poly.size() - 1;
KI_POLY_POINT point = *(poly.begin());
wxPoint startPoint( point.x(), point.y() );
MoveTo( startPoint );
for( unsigned ii = 1; ii < poly.size(); ii++ )
{
point = *( poly.begin() + ii );
LineTo( wxPoint( point.x(), point.y() ) );
} }
// Close polygon, if needed
point = *(poly.begin() + last);
wxPoint endPoint( point.x(), point.y() );
if( endPoint != startPoint )
LineTo( startPoint );
PenFinish();
} }
......
...@@ -325,25 +325,32 @@ void GERBER_PLOTTER::PlotPoly( const std::vector< wxPoint >& aCornerList, ...@@ -325,25 +325,32 @@ void GERBER_PLOTTER::PlotPoly( const std::vector< wxPoint >& aCornerList,
if( aCornerList.size() <= 1 ) if( aCornerList.size() <= 1 )
return; return;
// Gerber format does not know filled polygons with thick outline
// Thereore, to plot a filled polygon with outline having a thickness,
// one should plot outline as thick segments
SetCurrentLineWidth( aWidth ); SetCurrentLineWidth( aWidth );
if( aFill ) if( aFill )
{
fputs( "G36*\n", outputFile ); fputs( "G36*\n", outputFile );
MoveTo( aCornerList[0] ); MoveTo( aCornerList[0] );
for( unsigned ii = 1; ii < aCornerList.size(); ii++ ) for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
{ LineTo( aCornerList[ii] );
LineTo( aCornerList[ii] );
}
if( aFill )
{
FinishTo( aCornerList[0] ); FinishTo( aCornerList[0] );
fputs( "G37*\n", outputFile ); fputs( "G37*\n", outputFile );
} }
else
if( aWidth > 0 )
{ {
MoveTo( aCornerList[0] );
for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
LineTo( aCornerList[ii] );
PenFinish(); PenFinish();
} }
} }
......
...@@ -264,6 +264,8 @@ void HPGL_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList, ...@@ -264,6 +264,8 @@ void HPGL_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList,
if( aCornerList.size() <= 1 ) if( aCornerList.size() <= 1 )
return; return;
SetCurrentLineWidth( aWidth );
MoveTo( aCornerList[0] ); MoveTo( aCornerList[0] );
for( unsigned ii = 1; ii < aCornerList.size(); ii++ ) for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -775,6 +775,8 @@ void DIALOG_PLOT::Plot( wxCommandEvent& event ) ...@@ -775,6 +775,8 @@ void DIALOG_PLOT::Plot( wxCommandEvent& event )
// Save the current plot options in the board // Save the current plot options in the board
m_parent->SetPlotSettings( m_plotOpts ); m_parent->SetPlotSettings( m_plotOpts );
wxBusyCursor dummy;
for( LAYER_NUM layer = FIRST_LAYER; layer < NB_PCB_LAYERS; ++layer ) for( LAYER_NUM layer = FIRST_LAYER; layer < NB_PCB_LAYERS; ++layer )
{ {
if( m_plotOpts.GetLayerSelection() & GetLayerMask( layer ) ) if( m_plotOpts.GetLayerSelection() & GetLayerMask( layer ) )
......
...@@ -539,13 +539,14 @@ void BRDITEMS_PLOTTER::PlotFilledAreas( ZONE_CONTAINER* aZone ) ...@@ -539,13 +539,14 @@ void BRDITEMS_PLOTTER::PlotFilledAreas( ZONE_CONTAINER* aZone )
// Plot the current filled area and its outline // Plot the current filled area and its outline
if( GetMode() == FILLED ) if( GetMode() == FILLED )
{ {
// Plot the current filled area polygon // Plot the filled area polygon.
if( aZone->GetFillMode() == 0 ) // We are using solid polygons // The area can be filled by segments or uses solid polygons
{ // (if != 0: using segments ) if( aZone->GetFillMode() == 0 ) // We are using solid polygons
m_plotter->PlotPoly( cornerList, FILLED_SHAPE ); {
m_plotter->PlotPoly( cornerList, FILLED_SHAPE, aZone->GetMinThickness() );
} }
else // We are using areas filled by else // We are using areas filled by segments: plot segments and outline
{ // segments: plot them ) {
for( unsigned iseg = 0; iseg < aZone->FillSegments().size(); iseg++ ) for( unsigned iseg = 0; iseg < aZone->FillSegments().size(); iseg++ )
{ {
wxPoint start = aZone->FillSegments()[iseg].m_Start; wxPoint start = aZone->FillSegments()[iseg].m_Start;
...@@ -554,11 +555,11 @@ void BRDITEMS_PLOTTER::PlotFilledAreas( ZONE_CONTAINER* aZone ) ...@@ -554,11 +555,11 @@ void BRDITEMS_PLOTTER::PlotFilledAreas( ZONE_CONTAINER* aZone )
aZone->GetMinThickness(), aZone->GetMinThickness(),
GetMode() ); GetMode() );
} }
}
// Plot the current filled area outline // Plot the area outline only
if( aZone->GetMinThickness() > 0 ) if( aZone->GetMinThickness() > 0 )
m_plotter->PlotPoly( cornerList, NO_FILL, aZone->GetMinThickness() ); m_plotter->PlotPoly( cornerList, NO_FILL, aZone->GetMinThickness() );
}
} }
else else
{ {
......
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