|
|
@ -45,6 +45,7 @@ |
|
|
|
*/ |
|
|
|
|
|
|
|
#include <cmath>
|
|
|
|
#include <sstream>
|
|
|
|
|
|
|
|
#include <fctsys.h>
|
|
|
|
#include <polygons_defs.h>
|
|
|
@ -58,11 +59,16 @@ |
|
|
|
#include <class_drawsegment.h>
|
|
|
|
#include <class_pcb_text.h>
|
|
|
|
#include <class_zone.h>
|
|
|
|
#include <project.h>
|
|
|
|
|
|
|
|
#include <pcbnew.h>
|
|
|
|
#include <zones.h>
|
|
|
|
#include <convert_basic_shapes_to_polygon.h>
|
|
|
|
|
|
|
|
#include <geometry/shape_poly_set.h>
|
|
|
|
#include <geometry/shape_file_io.h>
|
|
|
|
|
|
|
|
#include <boost/foreach.hpp>
|
|
|
|
|
|
|
|
extern void BuildUnconnectedThermalStubsPolygonList( CPOLYGONS_LIST& aCornerBuffer, |
|
|
|
BOARD* aPcb, ZONE_CONTAINER* aZone, |
|
|
@ -84,116 +90,28 @@ extern void CreateThermalReliefPadPolygon( CPOLYGONS_LIST& aCornerBuffer, |
|
|
|
// Local Variables:
|
|
|
|
static double s_thermalRot = 450; // angle of stubs in thermal reliefs for round pads
|
|
|
|
|
|
|
|
// how many segments are used to create a polygon from a circle:
|
|
|
|
static int s_CircleToSegmentsCount = ARC_APPROX_SEGMENTS_COUNT_LOW_DEF; /* default value. the real value will be changed to
|
|
|
|
* ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF |
|
|
|
* if m_ArcToSegmentsCount == ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF |
|
|
|
*/ |
|
|
|
double s_Correction; /* mult coeff used to enlarge rounded and oval pads (and vias)
|
|
|
|
* because the segment approximation for arcs and circles |
|
|
|
* create a smaller gap than a true circle |
|
|
|
*/ |
|
|
|
|
|
|
|
/**
|
|
|
|
* Function AddClearanceAreasPolygonsToPolysList |
|
|
|
* Supports a min thickness area constraint. |
|
|
|
* Add non copper areas polygons (pads and tracks with clearance) |
|
|
|
* to the filled copper area found |
|
|
|
* in BuildFilledPolysListData after calculating filled areas in a zone |
|
|
|
* Non filled copper areas are pads and track and their clearance areas |
|
|
|
* The filled copper area must be computed just before. |
|
|
|
* BuildFilledPolysListData() call this function just after creating the |
|
|
|
* filled copper area polygon (without clearance areas) |
|
|
|
* to do that this function: |
|
|
|
* 1 - Creates the main outline (zone outline) using a correction to shrink the resulting area |
|
|
|
* with m_ZoneMinThickness/2 value. |
|
|
|
* The result is areas with a margin of m_ZoneMinThickness/2 |
|
|
|
* When drawing outline with segments having a thickness of m_ZoneMinThickness, the |
|
|
|
* outlines will match exactly the initial outlines |
|
|
|
* 3 - Add all non filled areas (pads, tracks) in group B with a clearance of m_Clearance + |
|
|
|
* m_ZoneMinThickness/2 |
|
|
|
* in a buffer |
|
|
|
* - If Thermal shapes are wanted, add non filled area, in order to create these thermal shapes |
|
|
|
* 4 - calculates the polygon A - B |
|
|
|
* 5 - put resulting list of polygons (filled areas) in m_FilledPolysList |
|
|
|
* This zone contains pads with the same net. |
|
|
|
* 6 - Remove insulated copper islands |
|
|
|
* 7 - If Thermal shapes are wanted, remove unconnected stubs in thermal shapes: |
|
|
|
* creates a buffer of polygons corresponding to stubs to remove |
|
|
|
* sub them to the filled areas. |
|
|
|
* Remove new insulated copper islands |
|
|
|
*/ |
|
|
|
void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) |
|
|
|
void ZONE_CONTAINER::buildFeatureHoleList( BOARD* aPcb, CPOLYGONS_LIST& aFeatures ) |
|
|
|
{ |
|
|
|
int segsPerCircle; |
|
|
|
double correctionFactor; |
|
|
|
|
|
|
|
// Set the number of segments in arc approximations
|
|
|
|
if( m_ArcToSegmentsCount == ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF ) |
|
|
|
s_CircleToSegmentsCount = ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF; |
|
|
|
segsPerCircle = ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF; |
|
|
|
else |
|
|
|
s_CircleToSegmentsCount = ARC_APPROX_SEGMENTS_COUNT_LOW_DEF; |
|
|
|
segsPerCircle = ARC_APPROX_SEGMENTS_COUNT_LOW_DEF; |
|
|
|
|
|
|
|
/* calculates the coeff to compensate radius reduction of holes clearance
|
|
|
|
* due to the segment approx. |
|
|
|
* For a circle the min radius is radius * cos( 2PI / s_CircleToSegmentsCount / 2) |
|
|
|
* s_Correction is 1 /cos( PI/s_CircleToSegmentsCount ) |
|
|
|
*/ |
|
|
|
s_Correction = 1.0 / cos( M_PI / s_CircleToSegmentsCount ); |
|
|
|
correctionFactor = 1.0 / cos( M_PI / (double) segsPerCircle ); |
|
|
|
|
|
|
|
// 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(); |
|
|
|
aFeatures.RemoveAllContours(); |
|
|
|
|
|
|
|
// This KI_POLYGON_SET is the area(s) to fill, with m_ZoneMinThickness/2
|
|
|
|
KI_POLYGON_SET polyset_zone_solid_areas; |
|
|
|
int outline_half_thickness = 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 main polygon is stored in polyset_zone_solid_areas |
|
|
|
*/ |
|
|
|
#if 0
|
|
|
|
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 -= outline_half_thickness; |
|
|
|
// inflate outline holes
|
|
|
|
if( outlineHoles.size() ) |
|
|
|
outlineHoles += outline_half_thickness; |
|
|
|
|
|
|
|
if( outlineHoles.size() ) |
|
|
|
cornerBufferPolysToSubstract.ImportFrom( outlineHoles ); |
|
|
|
#else
|
|
|
|
CPOLYGONS_LIST tmp; |
|
|
|
m_smoothedPoly->m_CornersList.InflateOutline( tmp, -outline_half_thickness, true ); |
|
|
|
tmp.ExportTo( polyset_zone_solid_areas ); |
|
|
|
|
|
|
|
if( polyset_zone_solid_areas.size() == 0 ) |
|
|
|
return; |
|
|
|
#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 |
|
|
|
* clearance between a zone and others items is bigger than the netclass clearance |
|
|
|
* this is more true for small clearance values |
|
|
|
* Note also the "local" clearance is used for clearance between non copper items |
|
|
|
* or items like texts on copper layers |
|
|
|
*/ |
|
|
|
int zone_clearance = std::max( m_ZoneClearance, GetClearance() ); |
|
|
|
zone_clearance += outline_half_thickness; |
|
|
|
|
|
|
@ -266,10 +184,10 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) |
|
|
|
if( item_boundingbox.Intersects( zone_boundingbox ) ) |
|
|
|
{ |
|
|
|
int clearance = std::max( zone_clearance, item_clearance ); |
|
|
|
pad->TransformShapeWithClearanceToPolygon( cornerBufferPolysToSubstract, |
|
|
|
pad->TransformShapeWithClearanceToPolygon( aFeatures, |
|
|
|
clearance, |
|
|
|
s_CircleToSegmentsCount, |
|
|
|
s_Correction ); |
|
|
|
segsPerCircle, |
|
|
|
correctionFactor ); |
|
|
|
} |
|
|
|
|
|
|
|
continue; |
|
|
@ -284,10 +202,10 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) |
|
|
|
|
|
|
|
if( item_boundingbox.Intersects( zone_boundingbox ) ) |
|
|
|
{ |
|
|
|
pad->TransformShapeWithClearanceToPolygon( cornerBufferPolysToSubstract, |
|
|
|
pad->TransformShapeWithClearanceToPolygon( aFeatures, |
|
|
|
gap, |
|
|
|
s_CircleToSegmentsCount, |
|
|
|
s_Correction ); |
|
|
|
segsPerCircle, |
|
|
|
correctionFactor ); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -310,10 +228,10 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) |
|
|
|
if( item_boundingbox.Intersects( zone_boundingbox ) ) |
|
|
|
{ |
|
|
|
int clearance = std::max( zone_clearance, item_clearance ); |
|
|
|
track->TransformShapeWithClearanceToPolygon( cornerBufferPolysToSubstract, |
|
|
|
track->TransformShapeWithClearanceToPolygon( aFeatures, |
|
|
|
clearance, |
|
|
|
s_CircleToSegmentsCount, |
|
|
|
s_Correction ); |
|
|
|
segsPerCircle, |
|
|
|
correctionFactor ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -336,8 +254,8 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) |
|
|
|
if( item_boundingbox.Intersects( zone_boundingbox ) ) |
|
|
|
{ |
|
|
|
( (EDGE_MODULE*) item )->TransformShapeWithClearanceToPolygon( |
|
|
|
cornerBufferPolysToSubstract, zone_clearance, |
|
|
|
s_CircleToSegmentsCount, s_Correction ); |
|
|
|
aFeatures, zone_clearance, |
|
|
|
segsPerCircle, correctionFactor ); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -352,13 +270,13 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) |
|
|
|
{ |
|
|
|
case PCB_LINE_T: |
|
|
|
( (DRAWSEGMENT*) item )->TransformShapeWithClearanceToPolygon( |
|
|
|
cornerBufferPolysToSubstract, |
|
|
|
zone_clearance, s_CircleToSegmentsCount, s_Correction ); |
|
|
|
aFeatures, |
|
|
|
zone_clearance, segsPerCircle, correctionFactor ); |
|
|
|
break; |
|
|
|
|
|
|
|
case PCB_TEXT_T: |
|
|
|
( (TEXTE_PCB*) item )->TransformBoundingBoxWithClearanceToPolygon( |
|
|
|
cornerBufferPolysToSubstract, zone_clearance ); |
|
|
|
aFeatures, zone_clearance ); |
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
@ -409,7 +327,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) |
|
|
|
} |
|
|
|
|
|
|
|
zone->TransformOutlinesShapeWithClearanceToPolygon( |
|
|
|
cornerBufferPolysToSubstract, |
|
|
|
aFeatures, |
|
|
|
min_clearance, use_net_clearance ); |
|
|
|
} |
|
|
|
|
|
|
@ -438,26 +356,304 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) |
|
|
|
|
|
|
|
if( item_boundingbox.Intersects( zone_boundingbox ) ) |
|
|
|
{ |
|
|
|
CreateThermalReliefPadPolygon( cornerBufferPolysToSubstract, |
|
|
|
CreateThermalReliefPadPolygon( aFeatures, |
|
|
|
*pad, thermalGap, |
|
|
|
GetThermalReliefCopperBridge( pad ), |
|
|
|
m_ZoneMinThickness, |
|
|
|
s_CircleToSegmentsCount, |
|
|
|
s_Correction, s_thermalRot ); |
|
|
|
segsPerCircle, |
|
|
|
correctionFactor, s_thermalRot ); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
static const SHAPE_POLY_SET convertPolyListToPolySet(const CPOLYGONS_LIST& aList) |
|
|
|
{ |
|
|
|
SHAPE_POLY_SET rv; |
|
|
|
|
|
|
|
unsigned corners_count = aList.GetCornersCount(); |
|
|
|
|
|
|
|
// Enter main outline: this is the first contour
|
|
|
|
unsigned ic = 0; |
|
|
|
|
|
|
|
if(!corners_count) |
|
|
|
return rv; |
|
|
|
|
|
|
|
while( ic < corners_count ) |
|
|
|
{ |
|
|
|
rv.NewOutline( ); |
|
|
|
|
|
|
|
while( ic < corners_count ) |
|
|
|
{ |
|
|
|
rv.AppendVertex( aList.GetX(ic), aList.GetY(ic) ); |
|
|
|
if( aList.IsEndContour( ic ) ) |
|
|
|
break; |
|
|
|
|
|
|
|
ic++; |
|
|
|
} |
|
|
|
ic++; |
|
|
|
} |
|
|
|
|
|
|
|
return rv; |
|
|
|
} |
|
|
|
|
|
|
|
static const CPOLYGONS_LIST convertPolySetToPolyList(const SHAPE_POLY_SET& aPolyset) |
|
|
|
{ |
|
|
|
CPOLYGONS_LIST list; |
|
|
|
|
|
|
|
CPolyPt corner, firstCorner; |
|
|
|
|
|
|
|
for( int ii = 0; ii < aPolyset.OutlineCount(); ii++ ) |
|
|
|
{ |
|
|
|
|
|
|
|
for( int jj = 0; jj < aPolyset.VertexCount(ii); jj++ ) |
|
|
|
{ |
|
|
|
VECTOR2I v = aPolyset.GetVertex( jj, ii ); |
|
|
|
|
|
|
|
|
|
|
|
corner.x = v.x; |
|
|
|
corner.y = v.y; |
|
|
|
corner.end_contour = false; |
|
|
|
|
|
|
|
if(!jj) |
|
|
|
firstCorner = corner; |
|
|
|
|
|
|
|
list.AddCorner( corner ); |
|
|
|
} |
|
|
|
|
|
|
|
firstCorner.end_contour = true; |
|
|
|
list.AddCorner( firstCorner ); |
|
|
|
} |
|
|
|
|
|
|
|
return list; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
static const SHAPE_POLY_SET convertBoostToPolySet ( const KI_POLYGON_SET& aSet ) |
|
|
|
{ |
|
|
|
SHAPE_POLY_SET rv; |
|
|
|
|
|
|
|
BOOST_FOREACH ( const KI_POLYGON &poly, aSet ) |
|
|
|
{ |
|
|
|
rv.NewOutline(); |
|
|
|
for ( KI_POLYGON::iterator_type corner = poly.begin(); corner != poly.end(); ++ corner ) |
|
|
|
{ |
|
|
|
rv.AppendVertex ( corner->x(), corner->y() ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return rv; |
|
|
|
} |
|
|
|
|
|
|
|
/**
|
|
|
|
* Function AddClearanceAreasPolygonsToPolysList |
|
|
|
* Supports a min thickness area constraint. |
|
|
|
* Add non copper areas polygons (pads and tracks with clearance) |
|
|
|
* to the filled copper area found |
|
|
|
* in BuildFilledPolysListData after calculating filled areas in a zone |
|
|
|
* Non filled copper areas are pads and track and their clearance areas |
|
|
|
* The filled copper area must be computed just before. |
|
|
|
* BuildFilledPolysListData() call this function just after creating the |
|
|
|
* filled copper area polygon (without clearance areas) |
|
|
|
* to do that this function: |
|
|
|
* 1 - Creates the main outline (zone outline) using a correction to shrink the resulting area |
|
|
|
* with m_ZoneMinThickness/2 value. |
|
|
|
* The result is areas with a margin of m_ZoneMinThickness/2 |
|
|
|
* When drawing outline with segments having a thickness of m_ZoneMinThickness, the |
|
|
|
* outlines will match exactly the initial outlines |
|
|
|
* 3 - Add all non filled areas (pads, tracks) in group B with a clearance of m_Clearance + |
|
|
|
* m_ZoneMinThickness/2 |
|
|
|
* in a buffer |
|
|
|
* - If Thermal shapes are wanted, add non filled area, in order to create these thermal shapes |
|
|
|
* 4 - calculates the polygon A - B |
|
|
|
* 5 - put resulting list of polygons (filled areas) in m_FilledPolysList |
|
|
|
* This zone contains pads with the same net. |
|
|
|
* 6 - Remove insulated copper islands |
|
|
|
* 7 - If Thermal shapes are wanted, remove unconnected stubs in thermal shapes: |
|
|
|
* creates a buffer of polygons corresponding to stubs to remove |
|
|
|
* sub them to the filled areas. |
|
|
|
* Remove new insulated copper islands |
|
|
|
*/ |
|
|
|
|
|
|
|
void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList_NG( BOARD* aPcb ) |
|
|
|
{ |
|
|
|
int segsPerCircle; |
|
|
|
double correctionFactor; |
|
|
|
int outline_half_thickness = m_ZoneMinThickness / 2; |
|
|
|
|
|
|
|
std::auto_ptr<SHAPE_FILE_IO> dumper( new SHAPE_FILE_IO( "zones_dump.txt", true ) ); |
|
|
|
|
|
|
|
// Set the number of segments in arc approximations
|
|
|
|
if( m_ArcToSegmentsCount == ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF ) |
|
|
|
segsPerCircle = ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF; |
|
|
|
else |
|
|
|
segsPerCircle = ARC_APPROX_SEGMENTS_COUNT_LOW_DEF; |
|
|
|
|
|
|
|
/* calculates the coeff to compensate radius reduction of holes clearance
|
|
|
|
* due to the segment approx. |
|
|
|
* For a circle the min radius is radius * cos( 2PI / s_CircleToSegmentsCount / 2) |
|
|
|
* s_Correction is 1 /cos( PI/s_CircleToSegmentsCount ) |
|
|
|
*/ |
|
|
|
correctionFactor = 1.0 / cos( M_PI / (double) segsPerCircle ); |
|
|
|
|
|
|
|
CPOLYGONS_LIST tmp; |
|
|
|
|
|
|
|
if(g_DumpZonesWhenFilling) |
|
|
|
dumper->BeginGroup("clipper-zone"); |
|
|
|
|
|
|
|
m_smoothedPoly->m_CornersList.InflateOutline( tmp, -outline_half_thickness, true ); |
|
|
|
SHAPE_POLY_SET solidAreas = convertPolyListToPolySet( tmp ); |
|
|
|
|
|
|
|
if(g_DumpZonesWhenFilling) |
|
|
|
dumper->Write ( &solidAreas, "solid-areas" ); |
|
|
|
|
|
|
|
|
|
|
|
tmp.RemoveAllContours(); |
|
|
|
buildFeatureHoleList( aPcb, tmp ); |
|
|
|
SHAPE_POLY_SET holes = convertPolyListToPolySet( tmp ); |
|
|
|
|
|
|
|
if(g_DumpZonesWhenFilling) |
|
|
|
dumper->Write ( &holes, "feature-holes" ); |
|
|
|
|
|
|
|
holes.Simplify(); |
|
|
|
|
|
|
|
if (g_DumpZonesWhenFilling) |
|
|
|
dumper->Write ( &holes, "feature-holes-postsimplify" ); |
|
|
|
|
|
|
|
solidAreas.Subtract ( holes ); |
|
|
|
|
|
|
|
if (g_DumpZonesWhenFilling) |
|
|
|
dumper->Write ( &solidAreas, "solid-areas-minus-holes" ); |
|
|
|
|
|
|
|
m_FilledPolysList.RemoveAllContours(); |
|
|
|
|
|
|
|
SHAPE_POLY_SET fractured = solidAreas; |
|
|
|
fractured.Fracture(); |
|
|
|
|
|
|
|
if (g_DumpZonesWhenFilling) |
|
|
|
dumper->Write ( &fractured, "fractured" ); |
|
|
|
|
|
|
|
m_FilledPolysList = convertPolySetToPolyList( fractured ); |
|
|
|
|
|
|
|
if (g_DumpZonesWhenFilling) |
|
|
|
{ |
|
|
|
SHAPE_POLY_SET dupa = convertPolyListToPolySet ( m_FilledPolysList ); |
|
|
|
dumper->Write ( &dupa, "verify-conv" ); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Remove insulated islands:
|
|
|
|
if( GetNetCode() > 0 ) |
|
|
|
TestForCopperIslandAndRemoveInsulatedIslands( aPcb ); |
|
|
|
|
|
|
|
tmp.RemoveAllContours(); |
|
|
|
// Test thermal stubs connections and add polygons to remove unconnected stubs.
|
|
|
|
// (this is a refinement for thermal relief shapes)
|
|
|
|
if( GetNetCode() > 0 ) |
|
|
|
BuildUnconnectedThermalStubsPolygonList( tmp, aPcb, this, |
|
|
|
correctionFactor, s_thermalRot ); |
|
|
|
|
|
|
|
// remove copper areas corresponding to not connected stubs
|
|
|
|
if( tmp.GetCornersCount() ) |
|
|
|
{ |
|
|
|
SHAPE_POLY_SET thermalHoles = convertPolyListToPolySet ( tmp ); |
|
|
|
thermalHoles.Simplify(); |
|
|
|
// Remove unconnected stubs
|
|
|
|
solidAreas.Subtract ( thermalHoles ); |
|
|
|
|
|
|
|
if (g_DumpZonesWhenFilling) |
|
|
|
dumper->Write ( &thermalHoles, "thermal-holes" ); |
|
|
|
|
|
|
|
|
|
|
|
// put these areas in m_FilledPolysList
|
|
|
|
m_FilledPolysList.RemoveAllContours(); |
|
|
|
|
|
|
|
SHAPE_POLY_SET fractured = solidAreas; |
|
|
|
fractured.Fracture(); |
|
|
|
|
|
|
|
if (g_DumpZonesWhenFilling) |
|
|
|
dumper->Write ( &fractured, "fractured" ); |
|
|
|
|
|
|
|
m_FilledPolysList = convertPolySetToPolyList( fractured ); |
|
|
|
|
|
|
|
if( GetNetCode() > 0 ) |
|
|
|
TestForCopperIslandAndRemoveInsulatedIslands( aPcb ); |
|
|
|
} |
|
|
|
|
|
|
|
if(g_DumpZonesWhenFilling) |
|
|
|
dumper->EndGroup(); |
|
|
|
} |
|
|
|
|
|
|
|
void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) |
|
|
|
{ |
|
|
|
int segsPerCircle; |
|
|
|
double correctionFactor; |
|
|
|
|
|
|
|
std::auto_ptr<SHAPE_FILE_IO> dumper( new SHAPE_FILE_IO( "zones_dump.txt", true ) ); |
|
|
|
|
|
|
|
|
|
|
|
if(g_DumpZonesWhenFilling) |
|
|
|
dumper->BeginGroup("boost-zone"); |
|
|
|
|
|
|
|
// Set the number of segments in arc approximations
|
|
|
|
if( m_ArcToSegmentsCount == ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF ) |
|
|
|
segsPerCircle = ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF; |
|
|
|
else |
|
|
|
segsPerCircle = ARC_APPROX_SEGMENTS_COUNT_LOW_DEF; |
|
|
|
|
|
|
|
/* calculates the coeff to compensate radius reduction of holes clearance
|
|
|
|
* due to the segment approx. |
|
|
|
* For a circle the min radius is radius * cos( 2PI / s_CircleToSegmentsCount / 2) |
|
|
|
* s_Correction is 1 /cos( PI/s_CircleToSegmentsCount ) |
|
|
|
*/ |
|
|
|
correctionFactor = 1.0 / cos( M_PI / (double) segsPerCircle ); |
|
|
|
|
|
|
|
// 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.
|
|
|
|
CPOLYGONS_LIST cornerBufferPolysToSubstract; |
|
|
|
|
|
|
|
// This KI_POLYGON_SET is the area(s) to fill, with m_ZoneMinThickness/2
|
|
|
|
KI_POLYGON_SET polyset_zone_solid_areas; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int outline_half_thickness = 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 main polygon is stored in polyset_zone_solid_areas |
|
|
|
*/ |
|
|
|
CPOLYGONS_LIST tmp; |
|
|
|
m_smoothedPoly->m_CornersList.InflateOutline( tmp, -outline_half_thickness, true ); |
|
|
|
tmp.ExportTo( polyset_zone_solid_areas ); |
|
|
|
|
|
|
|
if( polyset_zone_solid_areas.size() == 0 ) |
|
|
|
return; |
|
|
|
|
|
|
|
if (g_DumpZonesWhenFilling) |
|
|
|
dumper->Write ( convertBoostToPolySet( polyset_zone_solid_areas ), "solid-areas" ); |
|
|
|
|
|
|
|
buildFeatureHoleList( aPcb, cornerBufferPolysToSubstract ); |
|
|
|
|
|
|
|
// cornerBufferPolysToSubstract contains polygons to substract.
|
|
|
|
// polyset_zone_solid_areas contains the main filled area
|
|
|
|
// Calculate now actual solid areas
|
|
|
|
if( cornerBufferPolysToSubstract.GetCornersCount() > 0 ) |
|
|
|
{ |
|
|
|
KI_POLYGON_SET polyset_holes; |
|
|
|
|
|
|
|
cornerBufferPolysToSubstract.ExportTo( polyset_holes ); |
|
|
|
|
|
|
|
if (g_DumpZonesWhenFilling) |
|
|
|
dumper->Write ( convertBoostToPolySet( polyset_holes ), "feature-holes" ); |
|
|
|
|
|
|
|
// Remove holes from initial area.:
|
|
|
|
polyset_zone_solid_areas -= polyset_holes; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// put solid areas in m_FilledPolysList:
|
|
|
|
m_FilledPolysList.RemoveAllContours(); |
|
|
@ -474,7 +670,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) |
|
|
|
// (this is a refinement for thermal relief shapes)
|
|
|
|
if( GetNetCode() > 0 ) |
|
|
|
BuildUnconnectedThermalStubsPolygonList( cornerBufferPolysToSubstract, aPcb, this, |
|
|
|
s_Correction, s_thermalRot ); |
|
|
|
correctionFactor, s_thermalRot ); |
|
|
|
|
|
|
|
// remove copper areas corresponding to not connected stubs
|
|
|
|
if( cornerBufferPolysToSubstract.GetCornersCount() ) |
|
|
@ -482,6 +678,9 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) |
|
|
|
KI_POLYGON_SET polyset_holes; |
|
|
|
cornerBufferPolysToSubstract.ExportTo( polyset_holes ); |
|
|
|
|
|
|
|
if (g_DumpZonesWhenFilling) |
|
|
|
dumper->Write ( convertBoostToPolySet( polyset_holes ), "thermal-holes" ); |
|
|
|
|
|
|
|
// Remove unconnected stubs
|
|
|
|
polyset_zone_solid_areas -= polyset_holes; |
|
|
|
|
|
|
@ -493,6 +692,10 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) |
|
|
|
TestForCopperIslandAndRemoveInsulatedIslands( aPcb ); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (g_DumpZonesWhenFilling) |
|
|
|
dumper->Write ( convertBoostToPolySet( polyset_zone_solid_areas ), "complete" ); |
|
|
|
|
|
|
|
cornerBufferPolysToSubstract.RemoveAllContours(); |
|
|
|
} |
|
|
|
|
|
|
@ -502,9 +705,3 @@ void ZONE_CONTAINER::CopyPolygonsFromKiPolygonListToFilledPolysList( KI_POLYGON_ |
|
|
|
m_FilledPolysList.RemoveAllContours(); |
|
|
|
m_FilledPolysList.ImportFrom( aKiPolyList ); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void ZONE_CONTAINER::CopyPolygonsFromFilledPolysListToKiPolygonList( KI_POLYGON_SET& aKiPolyList ) |
|
|
|
{ |
|
|
|
m_FilledPolysList.ExportTo( aKiPolyList ); |
|
|
|
} |