Commit 25a801ed authored by jean-pierre charras's avatar jean-pierre charras

Modify usage of Inflate/deflate polygon in zone calculations, in order to be...

Modify usage of Inflate/deflate polygon in zone calculations, in order to be compatible with boost::polygon >= 1.56
Some code cleanup.
parent 4bba4b87
......@@ -1140,23 +1140,7 @@ void CreateThermalReliefPadPolygon( CPOLYGONS_LIST& aCornerBuffer,
clip_engine.Execute( ClipperLib::ctDifference, thermalShape );
// put thermal shapes (holes) to list:
wxPoint corner_position;
for( unsigned ii = 0; ii < thermalShape.size(); ii++ )
{
ClipperLib::Path& polygon = thermalShape[ii];
for( unsigned jj = 0; jj < polygon.size(); jj++ )
{
corner_position.x = int( polygon[jj].X );
corner_position.y = int( polygon[jj].Y );
CPolyPt polypoint( corner_position.x, corner_position.y );
aCornerBuffer.Append( polypoint );
}
aCornerBuffer.CloseLastContour();
}
aCornerBuffer.ImportFrom( thermalShape );
break;
}
......
......@@ -277,9 +277,10 @@ public:
/**
* Function BuildFilledSolidAreasPolygons
* Build the filled solid areas data from real outlines (stored in m_Poly)
* The solid areas can be more thna one on copper layers, and do not have holes
* The solid areas can be more than one on copper layers, and do not have holes
( holes are linked by overlapping segments to the main outline)
* in order to have drawable (and plottable) filled polygons
* @return true if OK, false if the solid polygons cannot be built
* @param aPcb: the current board (can be NULL for non copper zones)
* @param aCornerBuffer: A reference to a buffer to store polygon corners, or NULL
* if NULL (default:
......@@ -287,13 +288,14 @@ public:
* - on copper layers, tracks and other items shapes of other nets are
* removed from solid areas
* if not null:
* Only the zone outline (with holes, if any) are stored in aCornerBuffer
* with holes linked. Therfore only one polygon is created
* @return true if OK, false if the solid areas cannot be calculated
* This function calls AddClearanceAreasPolygonsToPolysList()
* to add holes for pads and tracks and other items not in net.
* Only the zone outline (with holes, if any) is stored in aOutlineBuffer
* with holes linked. Therefore only one polygon is created
*
* When aOutlineBuffer is not null, his function calls
* AddClearanceAreasPolygonsToPolysList() to add holes for pads and tracks
* and other items not in net.
*/
bool BuildFilledSolidAreasPolygons( BOARD* aPcb, CPOLYGONS_LIST* aCornerBuffer = NULL );
bool BuildFilledSolidAreasPolygons( BOARD* aPcb, CPOLYGONS_LIST* aOutlineBuffer = NULL );
/**
* Function CopyPolygonsFromKiPolygonListToFilledPolysList
......
......@@ -43,22 +43,19 @@
( holes are linked by overlapping segments to the main outline)
* aPcb: the current board (can be NULL for non copper zones)
* aCornerBuffer: A reference to a buffer to store polygon corners, or NULL
* if NULL:
* if aCornerBuffer == NULL:
* - m_FilledPolysList is used to store solid areas polygons.
* - on copper layers, tracks and other items shapes of other nets are
* removed from solid areas
* if not null:
* Only the zone outline (with holes, if any) are stored in aCornerBuffer
* with holes linked. Therfore only one polygon is created
* with holes linked. Therefore only one polygon is created
* This function calls AddClearanceAreasPolygonsToPolysList()
* to add holes for pads and tracks and other items not in net.
*/
bool ZONE_CONTAINER::BuildFilledSolidAreasPolygons( BOARD* aPcb, CPOLYGONS_LIST* aCornerBuffer )
bool ZONE_CONTAINER::BuildFilledSolidAreasPolygons( BOARD* aPcb, CPOLYGONS_LIST* aOutlineBuffer )
{
if( aCornerBuffer == NULL )
m_FilledPolysList.RemoveAllContours();
/* convert outlines + holes to outlines without holes (adding extra segments if necessary)
* m_Poly data is expected normalized, i.e. NormalizeAreaOutlines was used after building
* this zone
......@@ -90,47 +87,33 @@ bool ZONE_CONTAINER::BuildFilledSolidAreasPolygons( BOARD* aPcb, CPOLYGONS_LIST*
break;
}
if( aCornerBuffer )
ConvertPolysListWithHolesToOnePolygon( m_smoothedPoly->m_CornersList, *aCornerBuffer );
else
ConvertPolysListWithHolesToOnePolygon( m_smoothedPoly->m_CornersList, m_FilledPolysList );
if( aOutlineBuffer )
aOutlineBuffer->Append( m_smoothedPoly->m_CornersList );
/* For copper layers, we now must add holes in the Polygon list.
* holes are pads and tracks with their clearance area
* for non copper layers just recalculate the m_FilledPolysList
* with m_ZoneMinThickness taken in account
*/
if( !aCornerBuffer )
else
{
m_FilledPolysList.RemoveAllContours();
if( IsOnCopperLayer() )
AddClearanceAreasPolygonsToPolysList( aPcb );
else
{
// This KI_POLYGON_SET is the area(s) to fill, with m_ZoneMinThickness/2
KI_POLYGON_SET polyset_zone_solid_areas;
int margin = m_ZoneMinThickness / 2;
/* First, creates the main polygon (i.e. the filled area using only one outline)
* to reserve a m_ZoneMinThickness/2 margin around the outlines and holes
* this margin is the room to redraw outlines with segments having a width set to
* m_ZoneMinThickness
* so m_ZoneMinThickness is the min thickness of the filled zones areas
* the polygon is stored in polyset_zone_solid_areas
*/
CopyPolygonsFromFilledPolysListToKiPolygonList( polyset_zone_solid_areas );
polyset_zone_solid_areas -= margin;
// put solid area in m_FilledPolysList:
m_FilledPolysList.RemoveAllContours();
CopyPolygonsFromKiPolygonListToFilledPolysList( polyset_zone_solid_areas );
m_smoothedPoly->m_CornersList.InflateOutline(m_FilledPolysList, margin, true );
}
if( m_FillMode ) // if fill mode uses segments, create them:
FillZoneAreasWithSegments();
}
m_IsFilled = true;
}
return 1;
return true;
}
......
......@@ -138,6 +138,11 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
*/
s_Correction = 1.0 / cos( M_PI / s_CircleToSegmentsCount );
// this is a place to store holes (i.e. tracks, pads ... areas as polygons outlines)
// static to avoid unnecessary memory allocation when filling many zones.
static CPOLYGONS_LIST cornerBufferPolysToSubstract;
cornerBufferPolysToSubstract.RemoveAllContours();
// This KI_POLYGON_SET is the area(s) to fill, with m_ZoneMinThickness/2
KI_POLYGON_SET polyset_zone_solid_areas;
int margin = m_ZoneMinThickness / 2;
......@@ -149,13 +154,35 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
* so m_ZoneMinThickness is the min thickness of the filled zones areas
* the main polygon is stored in polyset_zone_solid_areas
*/
CopyPolygonsFromFilledPolysListToKiPolygonList( polyset_zone_solid_areas );
polyset_zone_solid_areas -= margin;
#if 1
m_smoothedPoly->m_CornersList.ExportTo( polyset_zone_solid_areas );
if( polyset_zone_solid_areas.size() == 0 )
return;
// Extract holes (cutout areas) and add them to the hole buffer
KI_POLYGON_SET outlineHoles;
while( polyset_zone_solid_areas.size() > 1 )
{
outlineHoles.push_back( polyset_zone_solid_areas.back() );
polyset_zone_solid_areas.pop_back();
}
// deflate main outline reserve room for thick outline
polyset_zone_solid_areas -= margin;
// inflate outline holes
if( outlineHoles.size() )
outlineHoles += margin;
if( outlineHoles.size() )
cornerBufferPolysToSubstract.ImportFrom( outlineHoles );
#else
CPOLYGONS_LIST tmp;
m_smoothedPoly->m_CornersList.InflateOutline( tmp, -margin, true );
tmp.ExportTo( polyset_zone_solid_areas );
#endif
/* Calculates the clearance value that meet DRC requirements
* from m_ZoneClearance and clearance from the corresponding netclass
* We have a "local" clearance in zones because most of time
......@@ -186,10 +213,6 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
*/
int item_clearance;
// static to avoid unnecessary memory allocation when filling many zones.
static CPOLYGONS_LIST cornerBufferPolysToSubstract;
cornerBufferPolysToSubstract.RemoveAllContours();
/* Use a dummy pad to calculate hole clerance when a pad is not on all copper layers
* and this pad has a hole
* This dummy pad has the size and shape of the hole
......
......@@ -51,12 +51,13 @@ void ZONE_CONTAINER::TransformOutlinesShapeWithClearanceToPolygon(
CPOLYGONS_LIST& aCornerBuffer,
int aClearanceValue, bool aAddClearance )
{
// Creates the zone outlines polygon (with linked holes if any)
CPOLYGONS_LIST zoneOutines;
BuildFilledSolidAreasPolygons( NULL, &zoneOutines );
// Creates the zone outline polygon (with linked holes if any)
CPOLYGONS_LIST zoneOutline;
BuildFilledSolidAreasPolygons( NULL, &zoneOutline );
// add clearance to outline
int clearance = 0;
if( aAddClearance )
{
clearance = GetClearance();
......@@ -64,51 +65,11 @@ void ZONE_CONTAINER::TransformOutlinesShapeWithClearanceToPolygon(
clearance = aClearanceValue;
}
// Calculate the polygon with clearance
// holes are linked to the main outline, so only one polygon should be created.
KI_POLYGON_SET polyset_zone_solid_areas;
std::vector<KI_POLY_POINT> cornerslist;
unsigned ic = 0;
unsigned corners_count = zoneOutines.GetCornersCount();
while( ic < corners_count )
{
cornerslist.clear();
KI_POLYGON poly;
{
for( ; ic < corners_count; ic++ )
{
CPolyPt* corner = &zoneOutines[ic];
cornerslist.push_back( KI_POLY_POINT( corner->x, corner->y ) );
if( corner->end_contour )
{
ic++;
break;
}
}
bpl::set_points( poly, cornerslist.begin(), cornerslist.end() );
polyset_zone_solid_areas.push_back( poly );
}
}
polyset_zone_solid_areas += clearance;
// Put the resulting polygon in aCornerBuffer corners list
for( unsigned ii = 0; ii < polyset_zone_solid_areas.size(); ii++ )
{
KI_POLYGON& poly = polyset_zone_solid_areas[ii];
CPolyPt corner( 0, 0, false );
for( unsigned jj = 0; jj < poly.size(); jj++ )
{
KI_POLY_POINT point = *(poly.begin() + jj);
corner.x = point.x();
corner.y = point.y();
corner.end_contour = false;
aCornerBuffer.Append( corner );
}
aCornerBuffer.CloseLastContour();
}
// holes are linked to the main outline, so only one polygon is created.
if( clearance )
zoneOutline.InflateOutline( aCornerBuffer, clearance, true );
else
ConvertPolysListWithHolesToOnePolygon( zoneOutline, aCornerBuffer );
}
......
......@@ -1347,6 +1347,44 @@ void CPOLYGONS_LIST::ExportTo( KI_POLYGON_SET& aPolygons ) const
}
}
/*
* Copy all contours to a ClipperLib::Paths& aPolygons
* Each contour is copied into a ClipperLib::Path, and each ClipperLib::Path
* is append to aPolygons
*/
void CPOLYGONS_LIST::ExportTo( ClipperLib::Paths& aPolygons ) const
{
unsigned corners_count = GetCornersCount();
// Count the number of polygons in aCornersBuffer
int polycount = 0;
for( unsigned ii = 0; ii < corners_count; ii++ )
{
if( IsEndContour( ii ) )
polycount++;
}
aPolygons.reserve( polycount );
for( unsigned icnt = 0; icnt < corners_count; )
{
ClipperLib::Path poly;
unsigned ii;
for( ii = icnt; ii < corners_count; ii++ )
{
poly << ClipperLib::IntPoint( GetX( ii ), GetY( ii ) );
if( IsEndContour( ii ) )
break;
}
aPolygons.push_back( poly );
icnt = ii + 1;
}
}
/* Imports all polygons found in a KI_POLYGON_SET in list
*/
......@@ -1372,6 +1410,72 @@ void CPOLYGONS_LIST::ImportFrom( KI_POLYGON_SET& aPolygons )
}
/* Imports all polygons found in a ClipperLib::Paths in list
*/
void CPOLYGONS_LIST::ImportFrom( ClipperLib::Paths& aPolygons )
{
CPolyPt corner;
for( unsigned ii = 0; ii < aPolygons.size(); ii++ )
{
ClipperLib::Path& polygon = aPolygons[ii];
for( unsigned jj = 0; jj < polygon.size(); jj++ )
{
corner.x = int( polygon[jj].X );
corner.y = int( polygon[jj].Y );
corner.end_contour = false;
AddCorner( corner );
}
CloseLastContour();
}
}
/* Inflate the outline stored in m_cornersList.
* The first polygon is the external outline. It is inflated
* The other polygons are holes. they are deflated
* aResult = the Inflated outline
* aInflateValue = the Inflate value. when < 0, this is a deflate transform
* aLinkHoles = if true, aResult contains only one polygon,
* with holes linked by overlapping segments
*/
void CPOLYGONS_LIST::InflateOutline( CPOLYGONS_LIST& aResult, int aInflateValue, bool aLinkHoles )
{
KI_POLYGON_SET polyset_outline;
ExportTo( polyset_outline );
// Extract holes (cutout areas) and add them to the hole buffer
KI_POLYGON_SET outlineHoles;
while( polyset_outline.size() > 1 )
{
outlineHoles.push_back( polyset_outline.back() );
polyset_outline.pop_back();
}
// inflate main outline
if( polyset_outline.size() )
polyset_outline += aInflateValue;
// deflate outline holes
if( outlineHoles.size() )
outlineHoles -= aInflateValue;
// Copy modified polygons
if( !aLinkHoles )
{
aResult.ImportFrom( polyset_outline );
if( outlineHoles.size() )
aResult.ImportFrom( outlineHoles );
}
else
{
polyset_outline -= outlineHoles;
aResult.ImportFrom( polyset_outline );
}
}
/**
* Function ConvertPolysListWithHolesToOnePolygon
......@@ -1438,26 +1542,14 @@ void ConvertPolysListWithHolesToOnePolygon( const CPOLYGONS_LIST& aPolysListWith
polysholes.push_back( poly_tmp );
}
}
mainpoly -= polysholes;
// copy polygon with no holes to destination
// Because all holes are now linked to the main outline
// by overlapping segments, we should have only one polygon in list
wxASSERT( mainpoly.size() == 1 );
KI_POLYGON& poly_nohole = mainpoly[0];
CPolyPt corner( 0, 0, false );
for( unsigned jj = 0; jj < poly_nohole.size(); jj++ )
{
KI_POLY_POINT point = *(poly_nohole.begin() + jj);
corner.x = point.x();
corner.y = point.y();
corner.end_contour = false;
aOnePolyList.AddCorner( corner );
}
aOnePolyList.CloseLastContour();
aOnePolyList.ImportFrom( mainpoly );
}
/**
......@@ -1553,3 +1645,22 @@ bool CPolyLine::IsPolygonSelfIntersecting()
return false;
}
/* converts the outline aOnePolyList (only one contour,
* holes are linked by overlapping segments) to
* to one main polygon and holes (polygons inside main polygon)
* aOnePolyList = a only one polygon ( holes are linked )
* aPolysListWithHoles = the list of corners of contours
* (main outline and holes)
*/
void ConvertOnePolygonToPolysListWithHoles( const CPOLYGONS_LIST& aOnePolyList,
CPOLYGONS_LIST& aPolysListWithHoles )
{
ClipperLib::Paths initialPoly;
ClipperLib::Paths modifiedPoly;
aOnePolyList.ExportTo( initialPoly );
SimplifyPolygon(initialPoly[0], modifiedPoly );
aPolysListWithHoles.ImportFrom( modifiedPoly );
}
......@@ -54,6 +54,7 @@
#include <layers_id_colors_and_visibility.h> // for LAYER_NUM definition
#include <class_eda_rect.h> // for EDA_RECT definition
#include <polygons_defs.h>
#include <clipper.hpp>
class CSegment
{
......@@ -186,10 +187,30 @@ public:
m_cornersList.insert( m_cornersList.begin() + aPosition + 1, aItem );
}
/**
* function AddCorner
* add a corner to the list
*/
void AddCorner( const CPolyPt& aCorner )
{
m_cornersList.push_back( aCorner );
}
/**
* function CloseLastContour
* Set the .end_contour member of the last corner in list to true
*/
void CloseLastContour()
{
if( m_cornersList.size() > 0 )
m_cornersList.back().end_contour = true;
}
/**
* Function ExportTo
* Copy all contours to a KI_POLYGON_SET
* @param aPolygons = the KI_POLYGON_WITH_HOLES to populate
* Copy all contours to a KI_POLYGON_SET, each contour is exported
* to a KI_POLYGON
* @param aPolygons = the KI_POLYGON_SET to populate
*/
void ExportTo( KI_POLYGON_SET& aPolygons ) const;
......@@ -201,6 +222,14 @@ public:
*/
void ExportTo( KI_POLYGON_WITH_HOLES& aPolygoneWithHole ) const;
/**
* Function ExportTo
* Copy all contours to a ClipperLib::Paths, each contour is exported
* to a ClipperLib::Path
* @param aPolygons = the ClipperLib::Paths to populate
*/
void ExportTo( ClipperLib::Paths& aPolygons ) const;
/**
* Function ImportFrom
* Copy all polygons from a KI_POLYGON_SET in list
......@@ -209,23 +238,23 @@ public:
void ImportFrom( KI_POLYGON_SET& aPolygons );
/**
* function AddCorner
* add a corner to the list
* Function ImportFrom
* Copy all polygons from a ClipperLib::Paths in list
* @param aPolygons = the ClipperLib::Paths to import
*/
void AddCorner( const CPolyPt& aCorner )
{
m_cornersList.push_back( aCorner );
}
void ImportFrom( ClipperLib::Paths& aPolygons );
/**
* function CloseLastContour
* Set the .end_contour member of the last corner in list to true
* Function InflateOutline
* Inflate the outline stored in m_cornersList.
* The first polygon is the external outline. It is inflated
* The other polygons are holes. they are deflated
* @param aResult = the Inflated outline
* @param aInflateValue = the Inflate value. when < 0, this is a deflate transform
* @param aLinkHoles = if true, aResult contains only one polygon,
* with holes linked by overlapping segments
*/
void CloseLastContour()
{
if( m_cornersList.size() > 0 )
m_cornersList.back().end_contour = true;
}
void InflateOutline( CPOLYGONS_LIST& aResult, int aInflateValue, bool aLinkHoles );
};
class CPolyLine
......@@ -489,4 +518,17 @@ public:
void ConvertPolysListWithHolesToOnePolygon( const CPOLYGONS_LIST& aPolysListWithHoles,
CPOLYGONS_LIST& aOnePolyList );
/**
* Function ConvertOnePolygonToPolysListWithHoles
* converts the outline aOnePolyList (only one contour,
* holes are linked by overlapping segments) to
* to one main polygon and holes (polygons inside main polygon)
* @param aOnePolyList = a polygon with no holes
* @param aPolysListWithHoles = the list of corners of contours
* (main outline and holes)
*/
void ConvertOnePolygonToPolysListWithHoles( const CPOLYGONS_LIST& aOnePolyList,
CPOLYGONS_LIST& aPolysListWithHoles );
#endif // #ifndef POLYLINE_H
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