Remove a long-standing hack to keep divots out of adjacent zones.
The new algorithm unions any adjacent zones before doing the chamfer/fillet and then subtracts the other zones back out afterwards. Fixes https://gitlab.com/kicad/code/kicad/issues/3812
This commit is contained in:
parent
a6d44676b3
commit
463100d67f
|
@ -774,7 +774,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
||||||
auto layerContainer = m_layers_poly.find( layer );
|
auto layerContainer = m_layers_poly.find( layer );
|
||||||
|
|
||||||
if( layerContainer != m_layers_poly.end() )
|
if( layerContainer != m_layers_poly.end() )
|
||||||
zone->TransformSolidAreasShapesToPolygonSet( layer, *layerContainer->second );
|
zone->TransformSolidAreasShapesToPolygon( layer, *layerContainer->second );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1050,7 +1050,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
||||||
if( !zone->IsOnLayer( curr_layer_id ) )
|
if( !zone->IsOnLayer( curr_layer_id ) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
zone->TransformSolidAreasShapesToPolygonSet( curr_layer_id, *layerPoly );
|
zone->TransformSolidAreasShapesToPolygon( curr_layer_id, *layerPoly );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1151,11 +1151,9 @@ class SHAPE_POLY_SET : public SHAPE
|
||||||
* returns a chamfered version of the aIndex-th polygon.
|
* returns a chamfered version of the aIndex-th polygon.
|
||||||
* @param aDistance is the chamfering distance.
|
* @param aDistance is the chamfering distance.
|
||||||
* @param aIndex is the index of the polygon to be chamfered.
|
* @param aIndex is the index of the polygon to be chamfered.
|
||||||
* @param aPreserveCorners an optional set of corners which should not be chamfered.
|
|
||||||
* @return POLYGON - A polygon containing the chamfered version of the aIndex-th polygon.
|
* @return POLYGON - A polygon containing the chamfered version of the aIndex-th polygon.
|
||||||
*/
|
*/
|
||||||
POLYGON ChamferPolygon( unsigned int aDistance, int aIndex,
|
POLYGON ChamferPolygon( unsigned int aDistance, int aIndex );
|
||||||
std::set<VECTOR2I>* aPreserveCorners );
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function Fillet
|
* Function Fillet
|
||||||
|
@ -1163,32 +1161,26 @@ class SHAPE_POLY_SET : public SHAPE
|
||||||
* @param aRadius is the fillet radius.
|
* @param aRadius is the fillet radius.
|
||||||
* @param aErrorMax is the maximum allowable deviation of the polygon from the circle
|
* @param aErrorMax is the maximum allowable deviation of the polygon from the circle
|
||||||
* @param aIndex is the index of the polygon to be filleted
|
* @param aIndex is the index of the polygon to be filleted
|
||||||
* @param aPreserveCorners an optional set of corners which should not be filleted.
|
|
||||||
* @return POLYGON - A polygon containing the filleted version of the aIndex-th polygon.
|
* @return POLYGON - A polygon containing the filleted version of the aIndex-th polygon.
|
||||||
*/
|
*/
|
||||||
POLYGON FilletPolygon( unsigned int aRadius, int aErrorMax, int aIndex,
|
POLYGON FilletPolygon( unsigned int aRadius, int aErrorMax, int aIndex );
|
||||||
std::set<VECTOR2I>* aPreserveCorners = nullptr );
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function Chamfer
|
* Function Chamfer
|
||||||
* returns a chamfered version of the polygon set.
|
* returns a chamfered version of the polygon set.
|
||||||
* @param aDistance is the chamfering distance.
|
* @param aDistance is the chamfering distance.
|
||||||
* @param aPreserveCorners an optional set of corners which should not be chamfered.
|
|
||||||
* @return SHAPE_POLY_SET - A set containing the chamfered version of this set.
|
* @return SHAPE_POLY_SET - A set containing the chamfered version of this set.
|
||||||
*/
|
*/
|
||||||
SHAPE_POLY_SET Chamfer( int aDistance,
|
SHAPE_POLY_SET Chamfer( int aDistance );
|
||||||
std::set<VECTOR2I>* aPreserveCorners = nullptr );
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function Fillet
|
* Function Fillet
|
||||||
* returns a filleted version of the polygon set.
|
* returns a filleted version of the polygon set.
|
||||||
* @param aRadius is the fillet radius.
|
* @param aRadius is the fillet radius.
|
||||||
* @param aErrorMax is the maximum allowable deviation of the polygon from the circle
|
* @param aErrorMax is the maximum allowable deviation of the polygon from the circle
|
||||||
* @param aPreserveCorners an optional set of corners which should not be filleted.
|
|
||||||
* @return SHAPE_POLY_SET - A set containing the filleted version of this set.
|
* @return SHAPE_POLY_SET - A set containing the filleted version of this set.
|
||||||
*/
|
*/
|
||||||
SHAPE_POLY_SET Fillet( int aRadius, int aErrorMax,
|
SHAPE_POLY_SET Fillet( int aRadius, int aErrorMax );
|
||||||
std::set<VECTOR2I>* aPreserveCorners = nullptr );
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function DistanceToPolygon
|
* Function DistanceToPolygon
|
||||||
|
@ -1306,12 +1298,10 @@ class SHAPE_POLY_SET : public SHAPE
|
||||||
* @param aIndex is the index of the polygon that will be chamfered/filleted.
|
* @param aIndex is the index of the polygon that will be chamfered/filleted.
|
||||||
* @param aErrorMax is the maximum allowable deviation of the polygon from the circle
|
* @param aErrorMax is the maximum allowable deviation of the polygon from the circle
|
||||||
* if aMode = FILLETED. If aMode = CHAMFERED, it is unused.
|
* if aMode = FILLETED. If aMode = CHAMFERED, it is unused.
|
||||||
* @param aPreserveCorners an optional set of corners which should be skipped.
|
|
||||||
* @return POLYGON - the chamfered/filleted version of the polygon.
|
* @return POLYGON - the chamfered/filleted version of the polygon.
|
||||||
*/
|
*/
|
||||||
POLYGON chamferFilletPolygon( CORNER_MODE aMode, unsigned int aDistance,
|
POLYGON chamferFilletPolygon( CORNER_MODE aMode, unsigned int aDistance,
|
||||||
int aIndex, int aErrorMax,
|
int aIndex, int aErrorMax );
|
||||||
std::set<VECTOR2I>* aPreserveCorners );
|
|
||||||
|
|
||||||
///> Returns true if the polygon set has any holes that touch share a vertex.
|
///> Returns true if the polygon set has any holes that touch share a vertex.
|
||||||
bool hasTouchingHoles( const POLYGON& aPoly ) const;
|
bool hasTouchingHoles( const POLYGON& aPoly ) const;
|
||||||
|
|
|
@ -1556,18 +1556,16 @@ int SHAPE_POLY_SET::TotalVertices() const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SHAPE_POLY_SET::POLYGON SHAPE_POLY_SET::ChamferPolygon( unsigned int aDistance, int aIndex,
|
SHAPE_POLY_SET::POLYGON SHAPE_POLY_SET::ChamferPolygon( unsigned int aDistance, int aIndex )
|
||||||
std::set<VECTOR2I>* aPreserveCorners )
|
|
||||||
{
|
{
|
||||||
return chamferFilletPolygon( CHAMFERED, aDistance, aIndex, 0, aPreserveCorners );
|
return chamferFilletPolygon( CHAMFERED, aDistance, aIndex, 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SHAPE_POLY_SET::POLYGON SHAPE_POLY_SET::FilletPolygon( unsigned int aRadius, int aErrorMax,
|
SHAPE_POLY_SET::POLYGON SHAPE_POLY_SET::FilletPolygon( unsigned int aRadius, int aErrorMax,
|
||||||
int aIndex,
|
int aIndex )
|
||||||
std::set<VECTOR2I>* aPreserveCorners )
|
|
||||||
{
|
{
|
||||||
return chamferFilletPolygon( FILLETED, aRadius, aIndex, aErrorMax, aPreserveCorners );
|
return chamferFilletPolygon( FILLETED, aRadius, aIndex, aErrorMax );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1676,32 +1674,30 @@ bool SHAPE_POLY_SET::IsVertexInHole( int aGlobalIdx )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SHAPE_POLY_SET SHAPE_POLY_SET::Chamfer( int aDistance, std::set<VECTOR2I>* aPreserveCorners )
|
SHAPE_POLY_SET SHAPE_POLY_SET::Chamfer( int aDistance )
|
||||||
{
|
{
|
||||||
SHAPE_POLY_SET chamfered;
|
SHAPE_POLY_SET chamfered;
|
||||||
|
|
||||||
for( unsigned int idx = 0; idx < m_polys.size(); idx++ )
|
for( unsigned int idx = 0; idx < m_polys.size(); idx++ )
|
||||||
chamfered.m_polys.push_back( ChamferPolygon( aDistance, idx, aPreserveCorners ) );
|
chamfered.m_polys.push_back( ChamferPolygon( aDistance, idx ) );
|
||||||
|
|
||||||
return chamfered;
|
return chamfered;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SHAPE_POLY_SET SHAPE_POLY_SET::Fillet( int aRadius, int aErrorMax,
|
SHAPE_POLY_SET SHAPE_POLY_SET::Fillet( int aRadius, int aErrorMax )
|
||||||
std::set<VECTOR2I>* aPreserveCorners )
|
|
||||||
{
|
{
|
||||||
SHAPE_POLY_SET filleted;
|
SHAPE_POLY_SET filleted;
|
||||||
|
|
||||||
for( size_t idx = 0; idx < m_polys.size(); idx++ )
|
for( size_t idx = 0; idx < m_polys.size(); idx++ )
|
||||||
filleted.m_polys.push_back( FilletPolygon( aRadius, aErrorMax, idx, aPreserveCorners ) );
|
filleted.m_polys.push_back( FilletPolygon( aRadius, aErrorMax, idx ) );
|
||||||
|
|
||||||
return filleted;
|
return filleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SHAPE_POLY_SET::POLYGON SHAPE_POLY_SET::chamferFilletPolygon( CORNER_MODE aMode,
|
SHAPE_POLY_SET::POLYGON SHAPE_POLY_SET::chamferFilletPolygon( CORNER_MODE aMode,
|
||||||
unsigned int aDistance, int aIndex, int aErrorMax,
|
unsigned int aDistance, int aIndex, int aErrorMax )
|
||||||
std::set<VECTOR2I>* aPreserveCorners )
|
|
||||||
{
|
{
|
||||||
// Null segments create serious issues in calculations. Remove them:
|
// Null segments create serious issues in calculations. Remove them:
|
||||||
RemoveNullSegments();
|
RemoveNullSegments();
|
||||||
|
@ -1728,12 +1724,6 @@ SHAPE_POLY_SET::POLYGON SHAPE_POLY_SET::chamferFilletPolygon( CORNER_MODE aMode,
|
||||||
int x1 = currContour.CPoint( currVertex ).x;
|
int x1 = currContour.CPoint( currVertex ).x;
|
||||||
int y1 = currContour.CPoint( currVertex ).y;
|
int y1 = currContour.CPoint( currVertex ).y;
|
||||||
|
|
||||||
if( aPreserveCorners && aPreserveCorners->count( VECTOR2I( x1, y1 ) ) > 0 )
|
|
||||||
{
|
|
||||||
newContour.Append( x1, y1 );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Indices for previous and next vertices.
|
// Indices for previous and next vertices.
|
||||||
int prevVertex;
|
int prevVertex;
|
||||||
int nextVertex;
|
int nextVertex;
|
||||||
|
|
|
@ -91,7 +91,7 @@ void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, SHAPE_POLY_
|
||||||
ZONE_CONTAINER* zone = GetArea( ii );
|
ZONE_CONTAINER* zone = GetArea( ii );
|
||||||
|
|
||||||
if( zone->GetLayerSet().test( aLayer ) )
|
if( zone->GetLayerSet().test( aLayer ) )
|
||||||
zone->TransformSolidAreasShapesToPolygonSet( aLayer, aOutlines );
|
zone->TransformSolidAreasShapesToPolygon( aLayer, aOutlines );
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert graphic items on copper layers (texts)
|
// convert graphic items on copper layers (texts)
|
||||||
|
@ -244,9 +244,9 @@ void MODULE::TransformGraphicShapesWithClearanceToPolygonSet( PCB_LAYER_ID aLaye
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ZONE_CONTAINER::TransformSolidAreasShapesToPolygonSet( PCB_LAYER_ID aLayer,
|
void ZONE_CONTAINER::TransformSolidAreasShapesToPolygon( PCB_LAYER_ID aLayer,
|
||||||
SHAPE_POLY_SET& aCornerBuffer,
|
SHAPE_POLY_SET& aCornerBuffer,
|
||||||
int aError ) const
|
int aError ) const
|
||||||
{
|
{
|
||||||
if( !m_FilledPolysList.count( aLayer ) || m_FilledPolysList.at( aLayer ).IsEmpty() )
|
if( !m_FilledPolysList.count( aLayer ) || m_FilledPolysList.at( aLayer ).IsEmpty() )
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1164,65 +1164,55 @@ bool ZONE_CONTAINER::IsIsland( PCB_LAYER_ID aLayer, int aPolyIdx )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
void ZONE_CONTAINER::GetInteractingZones( PCB_LAYER_ID aLayer,
|
||||||
* Some intersecting zones, despite being on the same layer with the same net, cannot be
|
std::vector<ZONE_CONTAINER*>* aZones ) const
|
||||||
* merged due to other parameters such as fillet radius. The copper pour will end up
|
|
||||||
* effectively merged though, so we want to keep the corners of such intersections sharp.
|
|
||||||
*/
|
|
||||||
void ZONE_CONTAINER::GetColinearCorners( BOARD* aBoard, std::set<VECTOR2I>& aCorners )
|
|
||||||
{
|
{
|
||||||
int epsilon = Millimeter2iu( 0.001 );
|
int epsilon = Millimeter2iu( 0.001 );
|
||||||
|
|
||||||
// Things get messy when zone of different nets intersect. To do it right we'd need to
|
for( ZONE_CONTAINER* candidate : GetBoard()->Zones() )
|
||||||
// run our colinear test with the final filled regions rather than the outline regions.
|
|
||||||
// However, since there's no order dependance the only way to do that is to iterate
|
|
||||||
// through successive zone fills until the results are no longer changing -- and that's
|
|
||||||
// not going to happen. So we punt and ignore any "messy" corners.
|
|
||||||
std::set<VECTOR2I> colinearCorners;
|
|
||||||
std::set<VECTOR2I> messyCorners;
|
|
||||||
|
|
||||||
for( ZONE_CONTAINER* candidate : aBoard->Zones() )
|
|
||||||
{
|
{
|
||||||
if( candidate == this )
|
if( candidate == this )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if( candidate->GetLayerSet() != GetLayerSet() )
|
if( !candidate->GetLayerSet().test( aLayer ) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if( candidate->GetIsKeepout() != GetIsKeepout() )
|
if( candidate->GetIsKeepout() )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( candidate->GetNetCode() != GetNetCode() )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for( auto iter = m_Poly->CIterate(); iter; iter++ )
|
for( auto iter = m_Poly->CIterate(); iter; iter++ )
|
||||||
{
|
{
|
||||||
if( candidate->m_Poly->Collide( iter.Get(), epsilon ) )
|
if( candidate->m_Poly->Collide( iter.Get(), epsilon ) )
|
||||||
{
|
{
|
||||||
if( candidate->GetNetCode() == GetNetCode() )
|
aZones->push_back( candidate );
|
||||||
colinearCorners.insert( VECTOR2I( iter.Get() ) );
|
break;
|
||||||
else
|
|
||||||
messyCorners.insert( VECTOR2I( iter.Get() ) );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for( VECTOR2I corner : colinearCorners )
|
|
||||||
{
|
|
||||||
if( messyCorners.count( corner ) == 0 )
|
|
||||||
aCorners.insert( corner );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool ZONE_CONTAINER::BuildSmoothedPoly( SHAPE_POLY_SET& aSmoothedPoly,
|
bool ZONE_CONTAINER::BuildSmoothedPoly( SHAPE_POLY_SET& aSmoothedPoly, PCB_LAYER_ID aLayer ) const
|
||||||
std::set<VECTOR2I>* aPreserveCorners ) const
|
|
||||||
{
|
{
|
||||||
if( GetNumCorners() <= 2 ) // malformed zone. polygon calculations do not like it ...
|
if( GetNumCorners() <= 2 ) // malformed zone. polygon calculations do not like it ...
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
std::vector<ZONE_CONTAINER*> interactingZones;
|
||||||
|
GetInteractingZones( aLayer, &interactingZones );
|
||||||
|
|
||||||
|
aSmoothedPoly = *m_Poly;
|
||||||
|
|
||||||
|
for( ZONE_CONTAINER* zone : interactingZones )
|
||||||
|
aSmoothedPoly.BooleanAdd( *zone->Outline(), SHAPE_POLY_SET::PM_FAST );
|
||||||
|
|
||||||
// Make a smoothed polygon out of the user-drawn polygon if required
|
// Make a smoothed polygon out of the user-drawn polygon if required
|
||||||
switch( m_cornerSmoothingType )
|
switch( m_cornerSmoothingType )
|
||||||
{
|
{
|
||||||
case ZONE_SETTINGS::SMOOTHING_CHAMFER:
|
case ZONE_SETTINGS::SMOOTHING_CHAMFER:
|
||||||
aSmoothedPoly = m_Poly->Chamfer( m_cornerRadius, aPreserveCorners );
|
aSmoothedPoly = aSmoothedPoly.Chamfer( m_cornerRadius );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZONE_SETTINGS::SMOOTHING_FILLET:
|
case ZONE_SETTINGS::SMOOTHING_FILLET:
|
||||||
|
@ -1233,7 +1223,7 @@ bool ZONE_CONTAINER::BuildSmoothedPoly( SHAPE_POLY_SET& aSmoothedPoly,
|
||||||
if( board )
|
if( board )
|
||||||
maxError = board->GetDesignSettings().m_MaxError;
|
maxError = board->GetDesignSettings().m_MaxError;
|
||||||
|
|
||||||
aSmoothedPoly = m_Poly->Fillet( m_cornerRadius, maxError, aPreserveCorners );
|
aSmoothedPoly = aSmoothedPoly.Fillet( m_cornerRadius, maxError );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -1242,10 +1232,13 @@ bool ZONE_CONTAINER::BuildSmoothedPoly( SHAPE_POLY_SET& aSmoothedPoly,
|
||||||
// We can avoid issues by creating a very small chamfer which remove acute angles,
|
// We can avoid issues by creating a very small chamfer which remove acute angles,
|
||||||
// or left it without chamfer and use only CPOLYGONS_LIST::InflateOutline to create
|
// or left it without chamfer and use only CPOLYGONS_LIST::InflateOutline to create
|
||||||
// clearance areas
|
// clearance areas
|
||||||
aSmoothedPoly = m_Poly->Chamfer( Millimeter2iu( 0.0 ), aPreserveCorners );
|
aSmoothedPoly = aSmoothedPoly.Chamfer( Millimeter2iu( 0.0 ) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( interactingZones.size() )
|
||||||
|
aSmoothedPoly.BooleanIntersection( *m_Poly, SHAPE_POLY_SET::PM_FAST );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1283,11 +1276,11 @@ double ZONE_CONTAINER::CalculateFilledArea()
|
||||||
* @param aPreserveCorners an optional set of corners which should not be chamfered/filleted
|
* @param aPreserveCorners an optional set of corners which should not be chamfered/filleted
|
||||||
*/
|
*/
|
||||||
void ZONE_CONTAINER::TransformOutlinesShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
|
void ZONE_CONTAINER::TransformOutlinesShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
|
||||||
int aClearance, std::set<VECTOR2I>* aPreserveCorners ) const
|
int aClearance ) const
|
||||||
{
|
{
|
||||||
// Creates the zone outline polygon (with holes if any)
|
// Creates the zone outline polygon (with holes if any)
|
||||||
SHAPE_POLY_SET polybuffer;
|
SHAPE_POLY_SET polybuffer;
|
||||||
BuildSmoothedPoly( polybuffer, aPreserveCorners );
|
BuildSmoothedPoly( polybuffer, GetLayer() );
|
||||||
|
|
||||||
// Calculate the polygon with clearance
|
// Calculate the polygon with clearance
|
||||||
// holes are linked to the main outline, so only one polygon is created.
|
// holes are linked to the main outline, so only one polygon is created.
|
||||||
|
|
|
@ -318,16 +318,15 @@ public:
|
||||||
return HitTestCutout( VECTOR2I( aRefPos.x, aRefPos.y ), aOutlineIdx, aHoleIdx );
|
return HitTestCutout( VECTOR2I( aRefPos.x, aRefPos.y ), aOutlineIdx, aHoleIdx );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Some intersecting zones, despite being on the same layer with the same net, cannot be
|
* Some intersecting zones, despite being on the same layer with the same net, cannot be
|
||||||
* merged due to other parameters such as fillet radius. The copper pour will end up
|
* merged due to other parameters such as fillet radius. The copper pour will end up
|
||||||
* effectively merged though, so we want to keep the corners of such intersections sharp.
|
* effectively merged though, so we need to do some calculations with them in mind.
|
||||||
*/
|
*/
|
||||||
void GetColinearCorners( BOARD* aBoard, std::set<VECTOR2I>& colinearCorners );
|
void GetInteractingZones( PCB_LAYER_ID aLayer, std::vector<ZONE_CONTAINER*>* aZones ) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function TransformSolidAreasShapesToPolygonSet
|
* Function TransformSolidAreasShapesToPolygon
|
||||||
* Convert solid areas full shapes to polygon set
|
* Convert solid areas full shapes to polygon set
|
||||||
* (the full shape is the polygon area with a thick outline)
|
* (the full shape is the polygon area with a thick outline)
|
||||||
* Used in 3D view
|
* Used in 3D view
|
||||||
|
@ -336,8 +335,8 @@ public:
|
||||||
* @param aCornerBuffer = a buffer to store the polygons
|
* @param aCornerBuffer = a buffer to store the polygons
|
||||||
* @param aError = Maximum error allowed between true arc and polygon approx
|
* @param aError = Maximum error allowed between true arc and polygon approx
|
||||||
*/
|
*/
|
||||||
void TransformSolidAreasShapesToPolygonSet( PCB_LAYER_ID aLayer,
|
void TransformSolidAreasShapesToPolygon( PCB_LAYER_ID aLayer, SHAPE_POLY_SET& aCornerBuffer,
|
||||||
SHAPE_POLY_SET& aCornerBuffer, int aError = ARC_HIGH_DEF ) const;
|
int aError = ARC_HIGH_DEF ) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function TransformOutlinesShapeWithClearanceToPolygon
|
* Function TransformOutlinesShapeWithClearanceToPolygon
|
||||||
|
@ -348,14 +347,9 @@ public:
|
||||||
* Circles (vias) and arcs (ends of tracks) are approximated by segments
|
* Circles (vias) and arcs (ends of tracks) are approximated by segments
|
||||||
* @param aCornerBuffer = a buffer to store the polygon
|
* @param aCornerBuffer = a buffer to store the polygon
|
||||||
* @param aMinClearanceValue = the min clearance around outlines
|
* @param aMinClearanceValue = the min clearance around outlines
|
||||||
* @param aUseNetClearance = true to use a clearance which is the max value between
|
|
||||||
* aMinClearanceValue and the net clearance
|
|
||||||
* false to use aMinClearanceValue only
|
|
||||||
* @param aPreserveCorners an optional set of corners which should not be smoothed.
|
|
||||||
* if both aMinClearanceValue = 0 and aUseNetClearance = false: create the zone outline polygon.
|
|
||||||
*/
|
*/
|
||||||
void TransformOutlinesShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
|
void TransformOutlinesShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
|
||||||
int aMinClearanceValue, std::set<VECTOR2I>* aPreserveCorners = nullptr ) const;
|
int aMinClearanceValue ) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function TransformShapeWithClearanceToPolygon
|
* Function TransformShapeWithClearanceToPolygon
|
||||||
|
@ -370,8 +364,8 @@ public:
|
||||||
* for visualization
|
* for visualization
|
||||||
*/
|
*/
|
||||||
void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
|
void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
|
||||||
int aClearanceValue, int aError = ARC_HIGH_DEF,
|
int aClearanceValue, int aError = ARC_HIGH_DEF,
|
||||||
bool ignoreLineWidth = false ) const override;
|
bool ignoreLineWidth = false ) const override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function HitTestForCorner
|
* Function HitTestForCorner
|
||||||
|
@ -652,12 +646,8 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function GetSmoothedPoly
|
* Function GetSmoothedPoly
|
||||||
* returns a pointer to the corner-smoothed version of m_Poly.
|
|
||||||
* @param aPreserveCorners - set of corners which should /not/ be smoothed
|
|
||||||
* @return SHAPE_POLY_SET* - pointer to the polygon.
|
|
||||||
*/
|
*/
|
||||||
bool BuildSmoothedPoly( SHAPE_POLY_SET& aSmoothedPoly,
|
bool BuildSmoothedPoly( SHAPE_POLY_SET& aSmoothedPoly, PCB_LAYER_ID aLayer ) const;
|
||||||
std::set<VECTOR2I>* aPreserveCorners ) const;
|
|
||||||
|
|
||||||
void SetCornerSmoothingType( int aType ) { m_cornerSmoothingType = aType; };
|
void SetCornerSmoothingType( int aType ) { m_cornerSmoothingType = aType; };
|
||||||
|
|
||||||
|
|
|
@ -684,11 +684,8 @@ void DRC::testZones( BOARD_COMMIT& aCommit )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ZONE_CONTAINER* zoneRef = m_pcb->GetArea( ii );
|
ZONE_CONTAINER* zoneRef = m_pcb->GetArea( ii );
|
||||||
std::set<VECTOR2I> colinearCorners;
|
zoneRef->BuildSmoothedPoly( smoothed_polys[ii], zoneRef->GetLayer() );
|
||||||
zoneRef->GetColinearCorners( m_pcb, colinearCorners );
|
|
||||||
|
|
||||||
zoneRef->BuildSmoothedPoly( smoothed_polys[ii], &colinearCorners );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// iterate through all areas
|
// iterate through all areas
|
||||||
|
|
|
@ -868,18 +868,10 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
|
||||||
if( zone->GetLayer() != layer )
|
if( zone->GetLayer() != layer )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Some intersecting zones, despite being on the same layer, cannot be
|
|
||||||
// merged due to other parameters such as fillet radius. The filled areas will end up
|
|
||||||
// effectively merged though, so we want to keep the corners of such intersections sharp.
|
|
||||||
std::set<VECTOR2I> colinearCorners;
|
|
||||||
zone->GetColinearCorners( aBoard, colinearCorners );
|
|
||||||
|
|
||||||
// add shapes inflated by aMinThickness/2 in areas
|
// add shapes inflated by aMinThickness/2 in areas
|
||||||
zone->TransformOutlinesShapeWithClearanceToPolygon( areas, inflate + zone_margin,
|
zone->TransformOutlinesShapeWithClearanceToPolygon( areas, inflate + zone_margin );
|
||||||
&colinearCorners );
|
|
||||||
// add shapes with their exact mask layer size in initialPolys
|
// add shapes with their exact mask layer size in initialPolys
|
||||||
zone->TransformOutlinesShapeWithClearanceToPolygon( initialPolys, zone_margin,
|
zone->TransformOutlinesShapeWithClearanceToPolygon( initialPolys, zone_margin );
|
||||||
&colinearCorners );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int maxError = aBoard->GetDesignSettings().m_MaxError;
|
int maxError = aBoard->GetDesignSettings().m_MaxError;
|
||||||
|
|
|
@ -736,36 +736,30 @@ bool PNS_KICAD_IFACE_BASE::syncZone( PNS::NODE* aWorld, ZONE_CONTAINER* aZone )
|
||||||
if( !aZone->GetIsKeepout() || !aZone->GetDoNotAllowTracks() )
|
if( !aZone->GetIsKeepout() || !aZone->GetDoNotAllowTracks() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Some intersecting zones, despite being on the same layer with the same net, cannot be
|
|
||||||
// merged due to other parameters such as fillet radius. The copper pour will end up
|
|
||||||
// effectively merged though, so we want to keep the corners of such intersections sharp.
|
|
||||||
std::set<VECTOR2I> colinearCorners;
|
|
||||||
aZone->GetColinearCorners( m_board, colinearCorners );
|
|
||||||
|
|
||||||
aZone->BuildSmoothedPoly( poly, &colinearCorners );
|
|
||||||
poly.CacheTriangulation();
|
|
||||||
|
|
||||||
if( !poly.IsTriangulationUpToDate() )
|
|
||||||
{
|
|
||||||
KIDIALOG dlg( nullptr, wxString::Format( _( "Malformed keep-out zone at (%d, %d)" ),
|
|
||||||
aZone->GetPosition().x, aZone->GetPosition().y ), KIDIALOG::KD_WARNING );
|
|
||||||
dlg.ShowDetailedText(
|
|
||||||
wxString::Format( _( "%s\nThis zone cannot be handled by the track layout tool.\n"
|
|
||||||
"Please verify it is not a self-intersecting polygon." ),
|
|
||||||
aZone->GetSelectMenuText( EDA_UNITS::MILLIMETRES ) ) );
|
|
||||||
dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
|
|
||||||
dlg.ShowModal();
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
LSET layers = aZone->GetLayerSet();
|
LSET layers = aZone->GetLayerSet();
|
||||||
|
|
||||||
for( int layer = F_Cu; layer <= B_Cu; layer++ )
|
for( int layer = F_Cu; layer <= B_Cu; layer++ )
|
||||||
{
|
{
|
||||||
if ( ! layers[layer] )
|
if( ! layers[ layer ] )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
aZone->BuildSmoothedPoly( poly, ToLAYER_ID( layer ) );
|
||||||
|
poly.CacheTriangulation();
|
||||||
|
|
||||||
|
if( !poly.IsTriangulationUpToDate() )
|
||||||
|
{
|
||||||
|
KIDIALOG dlg( nullptr, wxString::Format( _( "Malformed keep-out zone at (%d, %d)" ),
|
||||||
|
aZone->GetPosition().x, aZone->GetPosition().y ), KIDIALOG::KD_WARNING );
|
||||||
|
dlg.ShowDetailedText(
|
||||||
|
wxString::Format( _( "%s\nThis zone cannot be handled by the track layout tool.\n"
|
||||||
|
"Please verify it is not a self-intersecting polygon." ),
|
||||||
|
aZone->GetSelectMenuText( EDA_UNITS::MILLIMETRES ) ) );
|
||||||
|
dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
|
||||||
|
dlg.ShowModal();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for( int outline = 0; outline < poly.OutlineCount(); outline++ )
|
for( int outline = 0; outline < poly.OutlineCount(); outline++ )
|
||||||
{
|
{
|
||||||
auto tri = poly.TriangulatedPolygon( outline );
|
auto tri = poly.TriangulatedPolygon( outline );
|
||||||
|
|
|
@ -741,7 +741,6 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE_CONTAINER* aZone, PCB_LA
|
||||||
*/
|
*/
|
||||||
void ZONE_FILLER::computeRawFilledArea( const ZONE_CONTAINER* aZone, PCB_LAYER_ID aLayer,
|
void ZONE_FILLER::computeRawFilledArea( const ZONE_CONTAINER* aZone, PCB_LAYER_ID aLayer,
|
||||||
const SHAPE_POLY_SET& aSmoothedOutline,
|
const SHAPE_POLY_SET& aSmoothedOutline,
|
||||||
std::set<VECTOR2I>* aPreserveCorners,
|
|
||||||
SHAPE_POLY_SET& aRawPolys,
|
SHAPE_POLY_SET& aRawPolys,
|
||||||
SHAPE_POLY_SET& aFinalPolys )
|
SHAPE_POLY_SET& aFinalPolys )
|
||||||
{
|
{
|
||||||
|
@ -928,15 +927,13 @@ bool ZONE_FILLER::fillSingleZone( ZONE_CONTAINER* aZone, PCB_LAYER_ID aLayer,
|
||||||
SHAPE_POLY_SET& aRawPolys, SHAPE_POLY_SET& aFinalPolys )
|
SHAPE_POLY_SET& aRawPolys, SHAPE_POLY_SET& aFinalPolys )
|
||||||
{
|
{
|
||||||
SHAPE_POLY_SET smoothedPoly;
|
SHAPE_POLY_SET smoothedPoly;
|
||||||
std::set<VECTOR2I> colinearCorners;
|
|
||||||
aZone->GetColinearCorners( m_board, colinearCorners );
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* convert outlines + holes to outlines without holes (adding extra segments if necessary)
|
* 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
|
* m_Poly data is expected normalized, i.e. NormalizeAreaOutlines was used after building
|
||||||
* this zone
|
* this zone
|
||||||
*/
|
*/
|
||||||
if ( !aZone->BuildSmoothedPoly( smoothedPoly, &colinearCorners ) )
|
if ( !aZone->BuildSmoothedPoly( smoothedPoly, aLayer ) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if( m_progressReporter && m_progressReporter->IsCancelled() )
|
if( m_progressReporter && m_progressReporter->IsCancelled() )
|
||||||
|
@ -944,8 +941,7 @@ bool ZONE_FILLER::fillSingleZone( ZONE_CONTAINER* aZone, PCB_LAYER_ID aLayer,
|
||||||
|
|
||||||
if( aZone->IsOnCopperLayer() )
|
if( aZone->IsOnCopperLayer() )
|
||||||
{
|
{
|
||||||
computeRawFilledArea( aZone, aLayer, smoothedPoly, &colinearCorners, aRawPolys,
|
computeRawFilledArea( aZone, aLayer, smoothedPoly, aRawPolys, aFinalPolys );
|
||||||
aFinalPolys );
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -70,7 +70,6 @@ private:
|
||||||
*/
|
*/
|
||||||
void computeRawFilledArea( const ZONE_CONTAINER* aZone, PCB_LAYER_ID aLayer,
|
void computeRawFilledArea( const ZONE_CONTAINER* aZone, PCB_LAYER_ID aLayer,
|
||||||
const SHAPE_POLY_SET& aSmoothedOutline,
|
const SHAPE_POLY_SET& aSmoothedOutline,
|
||||||
std::set<VECTOR2I>* aPreserveCorners,
|
|
||||||
SHAPE_POLY_SET& aRawPolys, SHAPE_POLY_SET& aFinalPolys );
|
SHAPE_POLY_SET& aRawPolys, SHAPE_POLY_SET& aFinalPolys );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -669,11 +669,9 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZones()
|
||||||
for( int ii = 0; ii < m_board->GetAreaCount(); ii++ )
|
for( int ii = 0; ii < m_board->GetAreaCount(); ii++ )
|
||||||
{
|
{
|
||||||
ZONE_CONTAINER* zone = m_board->GetArea( ii );
|
ZONE_CONTAINER* zone = m_board->GetArea( ii );
|
||||||
ZONE_CONTAINER* zoneRef = m_board->GetArea( ii );
|
ZONE_CONTAINER* zoneRef = m_board->GetArea( ii );
|
||||||
std::set<VECTOR2I> colinearCorners;
|
|
||||||
|
|
||||||
zoneRef->GetColinearCorners( m_board, colinearCorners );
|
zoneRef->BuildSmoothedPoly( smoothed_polys[ii], zoneRef->GetLayer() );
|
||||||
zoneRef->BuildSmoothedPoly( smoothed_polys[ii], &colinearCorners );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// iterate through all areas
|
// iterate through all areas
|
||||||
|
|
Loading…
Reference in New Issue