More improvements to new selection disambiguation.

Also a rationalization of text polygon generators, with the "standard"
version inherited from BOARD_ITEM now giving the bounding box.  This
requires callers who want the (much) more expensive stroke-based one
to call it explicitly (and brings PCB_TEXT in line with the was FP_TEXT
already was.

Fixes https://gitlab.com/kicad/code/kicad/issues/6525
This commit is contained in:
Jeff Young 2020-11-29 14:00:39 +00:00
parent 37178e3751
commit 889408c96a
11 changed files with 195 additions and 129 deletions

View File

@ -82,7 +82,7 @@ void addTextSegmToContainer( int x0, int y0, int xf, int yf, void* aData )
// Based on
// void PCB_TEXT::TransformShapeWithClearanceToPolygon
// void PCB_TEXT::TransformTextShapeWithClearanceToPolygon
// board_items_to_polygon_shape_transform.cpp
void BOARD_ADAPTER::AddShapeWithClearanceToContainer( const PCB_TEXT* aText,
CGENERICCONTAINER2D *aDstContainer,

View File

@ -631,7 +631,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
CBVHCONTAINER2D *layerContainer = m_layers_container2D[curr_layer_id];
// Add graphic items on copper layers (texts and other graphics)
for( auto item : m_board->Drawings() )
for( BOARD_ITEM* item : m_board->Drawings() )
{
if( !item->IsOnLayer( curr_layer_id ) )
continue;
@ -683,11 +683,19 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
switch( item->Type() )
{
case PCB_SHAPE_T:
case PCB_TEXT_T:
item->TransformShapeWithClearanceToPolygon( *layerPoly, cur_layer_id, 0,
ARC_HIGH_DEF, ERROR_INSIDE );
break;
case PCB_TEXT_T:
{
PCB_TEXT* text = static_cast<PCB_TEXT*>( item );
text->TransformTextShapeWithClearanceToPolygon( *layerPoly, cur_layer_id, 0,
ARC_HIGH_DEF, ERROR_INSIDE );
}
break;
default:
wxLogTrace( m_logTrace, wxT( "createLayers: item type: %d not implemented" ),
item->Type() );
@ -781,7 +789,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
if( m_F_Cu_PlatedPads_poly && ( m_layers_poly.find( F_Cu ) != m_layers_poly.end() ) )
{
SHAPE_POLY_SET *layerPoly_F_Cu = m_layers_poly[F_Cu];
layerPoly_F_Cu->BooleanSubtract( *m_F_Cu_PlatedPads_poly, SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
layerPoly_F_Cu->BooleanSubtract( *m_F_Cu_PlatedPads_poly, SHAPE_POLY_SET::PM_FAST );
m_F_Cu_PlatedPads_poly->Simplify( SHAPE_POLY_SET::PM_FAST );
}
@ -789,7 +797,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
if( m_B_Cu_PlatedPads_poly && ( m_layers_poly.find( B_Cu ) != m_layers_poly.end() ) )
{
SHAPE_POLY_SET *layerPoly_B_Cu = m_layers_poly[B_Cu];
layerPoly_B_Cu->BooleanSubtract( *m_B_Cu_PlatedPads_poly, SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
layerPoly_B_Cu->BooleanSubtract( *m_B_Cu_PlatedPads_poly, SHAPE_POLY_SET::PM_FAST );
m_B_Cu_PlatedPads_poly->Simplify( SHAPE_POLY_SET::PM_FAST );
}
@ -822,9 +830,11 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
size_t parallelThreadCount = std::min<size_t>(
std::max<size_t>( std::thread::hardware_concurrency(), 2 ),
selected_layer_id.size() );
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
{
std::thread t = std::thread( [&nextItem, &threadsFinished, &selected_layer_id, this]()
std::thread t = std::thread(
[&nextItem, &threadsFinished, &selected_layer_id, this]()
{
for( size_t i = nextItem.fetch_add( 1 );
i < selected_layer_id.size();
@ -927,27 +937,21 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
switch( item->Type() )
{
case PCB_SHAPE_T:
AddShapeWithClearanceToContainer( (PCB_SHAPE*) item,
layerContainer,
curr_layer_id,
0 );
AddShapeWithClearanceToContainer( static_cast<PCB_SHAPE*>( item ), layerContainer,
curr_layer_id, 0 );
break;
case PCB_TEXT_T:
AddShapeWithClearanceToContainer( (PCB_TEXT*) item,
layerContainer,
curr_layer_id,
0 );
AddShapeWithClearanceToContainer( static_cast<PCB_TEXT*>( item ), layerContainer,
curr_layer_id, 0 );
break;
case PCB_DIM_ALIGNED_T:
case PCB_DIM_CENTER_T:
case PCB_DIM_ORTHOGONAL_T:
case PCB_DIM_LEADER_T:
AddShapeWithClearanceToContainer( (DIMENSION_BASE*) item,
layerContainer,
curr_layer_id,
0 );
AddShapeWithClearanceToContainer( static_cast<DIMENSION_BASE*>( item ),
layerContainer, curr_layer_id, 0 );
break;
default:
@ -965,11 +969,19 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
switch( item->Type() )
{
case PCB_SHAPE_T:
case PCB_TEXT_T:
item->TransformShapeWithClearanceToPolygon( *layerPoly, curr_layer_id, 0,
ARC_HIGH_DEF, ERROR_INSIDE );
break;
case PCB_TEXT_T:
{
PCB_TEXT* text = static_cast<PCB_TEXT*>( item );
text->TransformTextShapeWithClearanceToPolygon( *layerPoly, curr_layer_id, 0,
ARC_HIGH_DEF, ERROR_INSIDE );
}
break;
default:
break;
}

View File

@ -67,7 +67,7 @@ void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, SHAPE_POLY_
int maxError = GetDesignSettings().m_MaxError;
// convert tracks and vias:
for( auto track : m_tracks )
for( TRACK* track : m_tracks )
{
if( !track->IsOnLayer( aLayer ) )
continue;
@ -76,7 +76,7 @@ void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, SHAPE_POLY_
ERROR_INSIDE );
}
// convert pads
// convert pads and other copper items in footprints
for( FOOTPRINT* footprint : m_footprints )
{
footprint->TransformPadsWithClearanceToPolygon( aOutlines, aLayer, 0, maxError,
@ -84,7 +84,15 @@ void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, SHAPE_POLY_
// Micro-wave footprints may have items on copper layers
footprint->TransformFPShapesWithClearanceToPolygon( aOutlines, aLayer, 0, maxError,
ERROR_INSIDE );
ERROR_INSIDE,
true, /* include text */
true /* include shapes */ );
for( ZONE* zone : footprint->Zones() )
{
if( zone->GetLayerSet().test( aLayer ) )
zone->TransformSolidAreasShapesToPolygon( aLayer, aOutlines );
}
}
// convert copper zones
@ -113,7 +121,7 @@ void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, SHAPE_POLY_
case PCB_TEXT_T:
{
PCB_TEXT* text = static_cast<PCB_TEXT*>( item );
text->TransformShapeWithClearanceToPolygon( aOutlines, aLayer, 0, maxError,
text->TransformTextShapeWithClearanceToPolygon( aOutlines, aLayer, 0, maxError,
ERROR_INSIDE );
}
break;
@ -270,10 +278,16 @@ void FOOTPRINT::TransformFPShapesWithClearanceToPolygon( SHAPE_POLY_SET& aCorner
}
/**
* Function TransformTextShapeWithClearanceToPolygon
* Convert the text to a polygonSet describing the actual character strokes (one per segment).
* @aCornerBuffer = SHAPE_POLY_SET to store the polygon corners
* @aClearanceValue = the clearance around the text
* @aError = the maximum error to allow when approximating curves
*/
void FP_TEXT::TransformTextShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
enum PCB_LAYER_ID aLayer,
int aClearance, int aError,
ERROR_LOC aErrorLoc ) const
PCB_LAYER_ID aLayer, int aClearance,
int aError, ERROR_LOC aErrorLoc ) const
{
bool forceBold = true;
int penWidth = 0; // force max width for bold text
@ -291,6 +305,15 @@ void FP_TEXT::TransformTextShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerB
}
void FP_TEXT::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
PCB_LAYER_ID aLayer, int aClearance,
int aError, ERROR_LOC aErrorLoc,
bool aIgnoreLineWidth ) const
{
EDA_TEXT::TransformBoundingBoxWithClearanceToPolygon( &aCornerBuffer, aClearance );
}
void ZONE::TransformSolidAreasShapesToPolygon( PCB_LAYER_ID aLayer, SHAPE_POLY_SET& aCornerBuffer,
int aError ) const
{
@ -354,16 +377,15 @@ void EDA_TEXT::TransformBoundingBoxWithClearanceToPolygon( SHAPE_POLY_SET* aCorn
/**
* Function TransformShapeWithClearanceToPolygon
* Convert the text shape to a set of polygons (one per segment).
* Function TransformTextShapeWithClearanceToPolygon
* Convert the text to a polygonSet describing the actual character strokes (one per segment).
* @aCornerBuffer = SHAPE_POLY_SET to store the polygon corners
* @aClearanceValue = the clearance around the text
* @aError = the maximum error to allow when approximating curves
*/
void PCB_TEXT::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
void PCB_TEXT::TransformTextShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
PCB_LAYER_ID aLayer, int aClearanceValue,
int aError, ERROR_LOC aErrorLoc,
bool aIgnoreLineWidth ) const
int aError, ERROR_LOC aErrorLoc ) const
{
wxSize size = GetTextSize();
@ -401,6 +423,15 @@ void PCB_TEXT::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuff
}
void PCB_TEXT::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
PCB_LAYER_ID aLayer, int aClearance,
int aError, ERROR_LOC aErrorLoc,
bool aIgnoreLineWidth ) const
{
EDA_TEXT::TransformBoundingBoxWithClearanceToPolygon( &aCornerBuffer, aClearance );
}
void PCB_SHAPE::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
PCB_LAYER_ID aLayer, int aClearanceValue,
int aError, ERROR_LOC aErrorLoc,

View File

@ -34,12 +34,13 @@
#include <board.h>
#include <fp_shape.h>
#include <pcb_text.h>
#include <pcb_marker.h>
#include <footprint.h>
#include <view/view.h>
#include <geometry/shape_null.h>
#include <i18n_utility.h>
#include <convert_drawsegment_list_to_polygon.h>
#include <geometry/convex_hull.h>
FOOTPRINT::FOOTPRINT( BOARD* parent ) :
BOARD_ITEM_CONTAINER((BOARD_ITEM*) parent, PCB_FOOTPRINT_T ),
@ -675,51 +676,51 @@ const EDA_RECT FOOTPRINT::GetBoundingBox( bool aIncludeInvisibleText ) const
}
/**
* This is a bit hacky right now for performance reasons.
*
* We assume that most footprints will have features aligned to the axes in
* the zero-rotation state. Therefore, if the footprint is rotated, we
* temporarily rotate back to zero, get the bounding box (excluding reference
* and value text) and then rotate the resulting poly back to the correct
* orientation.
*
* This is more accurate than using the AABB when most footprints are rotated
* off of the axes, but less accurate than computing some kind of bounding hull.
* We should consider doing that instead at some point in the future if we can
* use a performant algorithm and cache the result to avoid extra computing.
*/
SHAPE_POLY_SET FOOTPRINT::GetBoundingPoly() const
SHAPE_POLY_SET FOOTPRINT::GetBoundingHull() const
{
SHAPE_POLY_SET poly;
double orientation = GetOrientationRadians();
FOOTPRINT temp = *this;
SHAPE_POLY_SET rawPolys;
temp.SetOrientation( 0.0 );
BOX2I area = temp.GetFootprintRect();
poly.NewOutline();
VECTOR2I p = area.GetPosition();
poly.Append( p );
p.x = area.GetRight();
poly.Append( p );
p.y = area.GetBottom();
poly.Append( p );
p.x = area.GetX();
poly.Append( p );
BOARD* board = GetBoard();
if( board )
for( BOARD_ITEM* item : m_drawings )
{
int biggest_clearance = board->GetDesignSettings().GetBiggestClearanceValue();
poly.Inflate( biggest_clearance, 4 );
if( item->Type() == PCB_FP_SHAPE_T )
{
item->TransformShapeWithClearanceToPolygon( rawPolys, UNDEFINED_LAYER, 0, ARC_LOW_DEF,
ERROR_OUTSIDE );
}
poly.Inflate( Millimeter2iu( 0.01 ), 4 );
poly.Rotate( -orientation, m_pos );
// We intentionally exclude footprint text from the bounding hull.
}
return poly;
for( PAD* pad : m_pads )
{
pad->TransformShapeWithClearanceToPolygon( rawPolys, UNDEFINED_LAYER, 0, ARC_LOW_DEF,
ERROR_OUTSIDE );
}
for( FP_ZONE* zone : m_fp_zones )
{
for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
{
SHAPE_POLY_SET layerPoly = zone->GetFilledPolysList( layer );
for( int ii = 0; ii < layerPoly.OutlineCount(); ii++ )
{
const SHAPE_LINE_CHAIN& poly = layerPoly.COutline( ii );
rawPolys.AddOutline( poly );
}
}
}
std::vector<wxPoint> convex_hull;
BuildConvexHull( convex_hull, rawPolys );
SHAPE_POLY_SET hullPoly;
hullPoly.NewOutline();
for( const wxPoint& pt : convex_hull )
hullPoly.Append( pt );
return hullPoly;
}
@ -823,7 +824,7 @@ bool FOOTPRINT::HitTest( const wxPoint& aPosition, int aAccuracy ) const
bool FOOTPRINT::HitTestAccurate( const wxPoint& aPosition, int aAccuracy ) const
{
return GetBoundingPoly().Collide( aPosition, aAccuracy );
return GetBoundingHull().Collide( aPosition, aAccuracy );
}
@ -1633,11 +1634,19 @@ double FOOTPRINT::GetCoverageArea( const BOARD_ITEM* aItem, const GENERAL_COLLEC
int textMargin = KiROUND( 5 * aCollector.GetGuide()->OnePixelInIU() );
SHAPE_POLY_SET poly;
if( aItem->Type() == PCB_FOOTPRINT_T )
if( aItem->Type() == PCB_MARKER_T )
{
const PCB_MARKER* marker = static_cast<const PCB_MARKER*>( aItem );
SHAPE_LINE_CHAIN markerShape;
marker->ShapeToPolygon( markerShape );
return markerShape.Area();
}
else if( aItem->Type() == PCB_FOOTPRINT_T )
{
const FOOTPRINT* footprint = static_cast<const FOOTPRINT*>( aItem );
return footprint->GetFootprintRect().GetArea();
poly = footprint->GetBoundingHull();
}
else if( aItem->Type() == PCB_FP_TEXT_T )
{
@ -1662,7 +1671,7 @@ double FOOTPRINT::CoverageRatio( const GENERAL_COLLECTOR& aCollector ) const
{
int textMargin = KiROUND( 5 * aCollector.GetGuide()->OnePixelInIU() );
SHAPE_POLY_SET footprintRegion( GetBoundingPoly() );
SHAPE_POLY_SET footprintRegion( GetBoundingHull() );
SHAPE_POLY_SET coveredRegion;
TransformPadsWithClearanceToPolygon( coveredRegion, UNDEFINED_LAYER, 0, ARC_LOW_DEF,
@ -1683,7 +1692,7 @@ double FOOTPRINT::CoverageRatio( const GENERAL_COLLECTOR& aCollector ) const
case PCB_FP_SHAPE_T:
if( item->GetParent() != this )
{
item->TransformShapeWithClearanceToPolygon( coveredRegion, UNDEFINED_LAYER, 1,
item->TransformShapeWithClearanceToPolygon( coveredRegion, UNDEFINED_LAYER, 0,
ARC_LOW_DEF, ERROR_OUTSIDE );
}
break;
@ -1693,10 +1702,18 @@ double FOOTPRINT::CoverageRatio( const GENERAL_COLLECTOR& aCollector ) const
case PCB_TRACE_T:
case PCB_ARC_T:
case PCB_VIA_T:
item->TransformShapeWithClearanceToPolygon( coveredRegion, UNDEFINED_LAYER, 1,
item->TransformShapeWithClearanceToPolygon( coveredRegion, UNDEFINED_LAYER, 0,
ARC_LOW_DEF, ERROR_OUTSIDE );
break;
case PCB_FOOTPRINT_T:
if( item != this )
{
const FOOTPRINT* footprint = static_cast<const FOOTPRINT*>( item );
coveredRegion.AddOutline( footprint->GetBoundingHull().Outline( 0 ) );
}
break;
default:
break;
}

View File

@ -173,7 +173,7 @@ public:
* Returns a bounding polygon for the shapes and pads in the footprint
* This operation is slower but more accurate than calculating a bounding box
*/
SHAPE_POLY_SET GetBoundingPoly() const;
SHAPE_POLY_SET GetBoundingHull() const;
// Virtual function
const EDA_RECT GetBoundingBox() const override;

View File

@ -198,6 +198,10 @@ public:
return TextHitTest( aRect, aContained, aAccuracy );
}
void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, PCB_LAYER_ID aLayer,
int aClearance, int aError, ERROR_LOC aErrorLoc,
bool aIgnoreLineWidth ) const override;
void TransformTextShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
PCB_LAYER_ID aLayer, int aClearanceValue,
int aError, ERROR_LOC aErrorLoc ) const;

View File

@ -111,14 +111,18 @@ public:
}
/**
* Function TransformShapeWithClearanceToPolygon
* Convert the text shape to a set of polygons (one by segment)
* Function TransformTextShapeWithClearanceToPolygon
* Convert the text to a polygonSet describing the actual character strokes (one per segment).
* Used in 3D viewer
* Circles and arcs are approximated by segments
* @param aCornerBuffer = a buffer to store the polygon
* @param aClearanceValue = the clearance around the text
* @param aError = deviation from true arc position to segment approx
* @aCornerBuffer = SHAPE_POLY_SET to store the polygon corners
* @aClearanceValue = the clearance around the text
* @aError = the maximum error to allow when approximating curves
*/
void TransformTextShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
PCB_LAYER_ID aLayer, int aClearanceValue,
int aError, ERROR_LOC aErrorLoc ) const;
void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, PCB_LAYER_ID aLayer,
int aClearanceValue, int aError, ERROR_LOC aErrorLoc,
bool aIgnoreLineWidth = false ) const override;

View File

@ -623,16 +623,16 @@ void PAD_TOOL::recombinePad( PAD* aPad )
for( BOARD_ITEM* item : board()->GetFirstFootprint()->GraphicalItems() )
{
PCB_SHAPE* draw = dynamic_cast<PCB_SHAPE*>( item );
PCB_SHAPE* shape = dynamic_cast<PCB_SHAPE*>( item );
if( !draw || ( draw->GetEditFlags() & STRUCT_DELETED ) )
if( !shape || ( shape->GetEditFlags() & STRUCT_DELETED ) )
continue;
if( draw->GetLayer() != aLayer )
if( shape->GetLayer() != aLayer )
continue;
SHAPE_POLY_SET drawPoly;
draw->TransformShapeWithClearanceToPolygon( drawPoly, aLayer, 0, maxError,
shape->TransformShapeWithClearanceToPolygon( drawPoly, aLayer, 0, maxError,
ERROR_INSIDE );
drawPoly.BooleanIntersection( padPoly, SHAPE_POLY_SET::PM_FAST );

View File

@ -34,6 +34,7 @@ using namespace std::placeholders;
#include <footprint.h>
#include <pcb_shape.h>
#include <pcb_text.h>
#include <pcb_marker.h>
#include <zone.h>
#include <collectors.h>
#include <confirm.h>
@ -2265,7 +2266,7 @@ void SELECTION_TOOL::GuessSelectionCandidates( GENERAL_COLLECTOR& aCollector,
{
FOOTPRINT* footprint = static_cast<FOOTPRINT*>( item );
footprint->GetBoundingPoly().Collide( loc, maxSlop * pixel, &actualSlop );
footprint->GetBoundingHull().Collide( loc, maxSlop * pixel, &actualSlop );
// Consider footprints larger than the viewport only as a last resort
if( item->ViewBBox().GetHeight() > viewport.GetHeight()
@ -2276,6 +2277,17 @@ void SELECTION_TOOL::GuessSelectionCandidates( GENERAL_COLLECTOR& aCollector,
}
break;
case PCB_MARKER_T:
{
PCB_MARKER* marker = static_cast<PCB_MARKER*>( item );
SHAPE_LINE_CHAIN polygon;
marker->ShapeToPolygon( polygon );
polygon.Move( marker->GetPos() );
polygon.Collide( loc, maxSlop * pixel, &actualSlop );
}
break;
default:
item->GetEffectiveShape()->Collide( loc, maxSlop * pixel, &actualSlop );
break;

View File

@ -572,34 +572,24 @@ void ZONE_FILLER::addKnockout( BOARD_ITEM* aItem, PCB_LAYER_ID aLayer, int aGap,
switch( aItem->Type() )
{
case PCB_SHAPE_T:
{
PCB_SHAPE* shape = (PCB_SHAPE*) aItem;
shape->TransformShapeWithClearanceToPolygon( aHoles, aLayer, aGap, m_maxError,
ERROR_OUTSIDE, aIgnoreLineWidth );
break;
}
case PCB_TEXT_T:
{
PCB_TEXT* text = (PCB_TEXT*) aItem;
text->TransformBoundingBoxWithClearanceToPolygon( &aHoles, aGap );
break;
}
case PCB_FP_SHAPE_T:
{
FP_SHAPE* shape = (FP_SHAPE*) aItem;
shape->TransformShapeWithClearanceToPolygon( aHoles, aLayer, aGap, m_maxError,
aItem->TransformShapeWithClearanceToPolygon( aHoles, aLayer, aGap, m_maxError,
ERROR_OUTSIDE, aIgnoreLineWidth );
break;
}
case PCB_FP_TEXT_T:
{
FP_TEXT* text = (FP_TEXT*) aItem;
FP_TEXT* text = static_cast<FP_TEXT*>( aItem );
if( text->IsVisible() )
text->TransformBoundingBoxWithClearanceToPolygon( &aHoles, aGap );
break;
{
text->TransformShapeWithClearanceToPolygon( aHoles, aLayer, aGap, m_maxError,
ERROR_OUTSIDE, aIgnoreLineWidth );
}
}
break;
default:
break;
}

View File

@ -61,9 +61,7 @@ enum POLY_GEN_RET_CODES
int polygon_gererator_main( int argc, char* argv[] )
{
if( argc < 2 )
{
return KI_TEST::RET_CODES::BAD_CMDLINE;
}
std::string filename;
@ -73,22 +71,20 @@ int polygon_gererator_main( int argc, char* argv[] )
auto brd = KI_TEST::ReadBoardFromFileOrStream( filename );
if( !brd )
{
return POLY_GEN_RET_CODES::LOAD_FAILED;
}
for( unsigned net = 0; net < brd->GetNetCount(); net++ )
{
for( auto track : brd->Tracks() )
for( TRACK* track : brd->Tracks() )
process( track, net );
for( auto mod : brd->Footprints() )
for( FOOTPRINT* fp : brd->Footprints() )
{
for( auto pad : mod->Pads() )
for( PAD* pad : fp->Pads() )
process( pad, net );
}
for( auto zone : brd->Zones() )
for( ZONE* zone : brd->Zones() )
process( zone, net );
}