mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-14 18:23:15 +02:00
Plot DXF: better generation of filled zone polygons.
This commit is contained in:
parent
645e17684d
commit
41e41b95f8
@ -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
|
|||||||
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 @@
|
|||||||
#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
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
|
if( aFill )
|
||||||
|
{
|
||||||
|
if( aCornerList[last] != aCornerList[0] )
|
||||||
|
LineTo( aCornerList[0] );
|
||||||
|
}
|
||||||
|
|
||||||
|
PenFinish();
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close polygon if 'fill' requested
|
|
||||||
unsigned last = aCornerList.size() - 1;
|
|
||||||
|
|
||||||
if( aFill )
|
// if the polygon outline has thickness, and is not filled
|
||||||
{
|
// (i.e. is a polyline) plot outlines with thick segments
|
||||||
if( aCornerList[last] != aCornerList[0] )
|
if( aWidth > 0 && !aFill )
|
||||||
LineTo( aCornerList[0] );
|
|
||||||
}
|
|
||||||
|
|
||||||
PenFinish();
|
|
||||||
|
|
||||||
// if the polygon outline has thickness, plot outlines with thick segments
|
|
||||||
if( aWidth > 0 )
|
|
||||||
{
|
{
|
||||||
MoveTo( aCornerList[0] );
|
MoveTo( aCornerList[0] );
|
||||||
|
|
||||||
@ -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,
|
|||||||
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,
|
|||||||
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++ )
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -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 )
|
|||||||
// 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 )
|
|||||||
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
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user