79            constexpr std::size_t prime = 19937;
 
   81            return hash<int>()( k.
Netcode ) ^ ( hash<int>()( k.
Layer ) * prime );
 
 
 
   95    virtual bool Run() 
override;
 
   97    virtual const wxString 
GetName()
 const override { 
return wxT( 
"copper width" ); };
 
 
  123        std::set<VERTEX*> all_hits;
 
  130            if( ( all_hits.empty() || all_hits.count( p ) == 0 ) && ( match = 
getKink( p ) ) != 
nullptr )
 
  132                if( !all_hits.count( match ) && 
m_hits.emplace( p->
i, match->
i ).second )
 
  134                    all_hits.emplace( p );
 
  135                    all_hits.emplace( match );
 
  136                    all_hits.emplace( p->
next );
 
  137                    all_hits.emplace( p->
prev );
 
  138                    all_hits.emplace( match->
next );
 
  139                    all_hits.emplace( match->
prev );
 
 
  164        bool x_change = 
false;
 
  165        bool y_change = 
false;
 
  177                && checked < total_pts          
 
  178                && !( x_change && y_change ) )  
 
  196        wxCHECK_MSG( checked < total_pts, 
false, wxT( 
"Invalid polygon detected.  Missing points to check" ) );
 
  198        if( !
same_point( p, aA ) && ( !x_change || !y_change ) )
 
  209                && checked < total_pts          
 
  210                && !( x_change && y_change ) )  
 
  229        wxCHECK_MSG( checked < total_pts, 
false, wxT( 
"Invalid polygon detected.  Missing points to check" ) );
 
  231        return ( 
same_point( p, aA ) || ( x_change && y_change ) );
 
 
  247        SEG::ecoord min_dist = std::numeric_limits<SEG::ecoord>::max();
 
  250        while( p && p->
z <= maxZ )
 
  256            if( delta_i > 1 && dist2 < limit2 && dist2 < min_dist && dist2 > 0
 
  268        while( p && p->
z >= minZ )
 
  274            if( delta_i > 1 && dist2 < limit2 && dist2 < min_dist && dist2 > 0
 
 
 
  294    return wxString::Format( wxT( 
"(%s)" ), 
m_drcEngine->GetBoard()->GetLayerName( aLayer ) );
 
 
  302        REPORT_AUX( wxT( 
"Connection width violations ignored. Tests not run." ) );
 
  306    if( !
reportPhase( 
_( 
"Checking nets for minimum connection width..." ) ) )
 
  331        std::set<BOARD_ITEM*> Items;
 
  335    std::unordered_map<NETCODE_LAYER_CACHE_KEY, ITEMS_POLY> dataset;
 
  336    std::atomic<size_t> done( 1 );
 
  339            [&]( 
const std::set<BOARD_ITEM*>& items, 
PCB_LAYER_ID aLayer ) -> 
size_t 
  347                        ZONE* zone = 
static_cast<ZONE*
>( item );
 
  363    auto build_netlayer_polys =
 
  364            [&]( 
int aNetcode, 
const PCB_LAYER_ID aLayer ) -> 
size_t 
  369                ITEMS_POLY& itemsPoly = dataset[ { aNetcode, aLayer } ];
 
  374                itemsPoly.Poly.Fracture();
 
  376                done.fetch_add( calc_effort( itemsPoly.Items, aLayer ) );
 
  385            [&]( 
const ITEMS_POLY& aItemsPoly, 
const PCB_LAYER_ID aLayer, 
int aMinWidth ) -> 
size_t 
  390                int testWidth = aMinWidth - 
epsilon;
 
  394                for( 
int ii = 0; ii < aItemsPoly.Poly.OutlineCount(); ++ii )
 
  399                    auto& ret = 
test.GetVertices();
 
  401                    for( 
const std::pair<int, int>& pt : ret )
 
  413                        SEG      span( 
chain.CPoint( pt.first ), 
chain.CPoint( pt.second ) );
 
  415                        int      dist = ( span.
A - span.
B ).EuclideanNorm();
 
  417                        std::vector<BOARD_ITEM*> contributingItems;
 
  422                            if( item->HitTest( 
location, aMinWidth ) )
 
  423                                contributingItems.push_back( item );
 
  431                            auto obj_list = rtree->GetObjectsAt( 
location, aLayer, aMinWidth );
 
  433                            if( !obj_list.empty() && zone->HitTestFilledArea( aLayer, 
location, aMinWidth ) )
 
  434                                contributingItems.push_back( zone );
 
  437                        if( !contributingItems.empty() )
 
  440                            BOARD_ITEM* item2 = contributingItems.size() > 1 ? contributingItems[1]
 
  443                                                                       item1, item2, aLayer );
 
  450                                msg = 
formatMsg( 
_( 
"(%s minimum connection width %s; actual %s)" ),
 
  457                                drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( 
" " ) + msg );
 
  461                                    drcItem->AddItem( item );
 
  469                done.fetch_add( calc_effort( aItemsPoly.Items, aLayer ) );
 
  479                dataset[ { zone->
GetNetCode(), layer } ].Items.emplace( zone );
 
  486                if( 
via->FlashLayer( 
static_cast<int>( layer ) ) )
 
  487                    dataset[ { 
via->GetNetCode(), layer } ].Items.emplace( 
via );
 
  489            else if( track->IsOnLayer( layer ) )
 
  491                dataset[ { track->GetNetCode(), layer } ].Items.emplace( track );
 
  497            for( 
PAD* 
pad : fp->Pads() )
 
  499                if( 
pad->FlashLayer( 
static_cast<int>( layer ) ) )
 
  500                    dataset[ { 
pad->GetNetCode(), layer } ].Items.emplace( 
pad );
 
  508    size_t                           total_effort = 0;
 
  510    for( 
const auto& [ netLayer, itemsPoly ] : dataset )
 
  511        total_effort += calc_effort( itemsPoly.Items, netLayer.Layer );
 
  513    total_effort += std::max( (
size_t) 1, total_effort ) * distinctMinWidths.size();
 
  515    std::vector<std::future<size_t>> returns;
 
  516    returns.reserve( dataset.size() );
 
  518    for( 
const auto& [ netLayer, itemsPoly ] : dataset )
 
  520        int netcode = netLayer.Netcode;
 
  522        returns.emplace_back( 
tp.submit_task(
 
  523                [&, netcode, layer]()
 
  525                    return build_netlayer_polys( netcode, layer );
 
  529    for( 
auto& ret : returns )
 
  531        std::future_status status = ret.wait_for( std::chrono::milliseconds( 250 ) );
 
  533        while( status != std::future_status::ready )
 
  536            status = ret.wait_for( std::chrono::milliseconds( 250 ) );
 
  541    returns.reserve( dataset.size() * distinctMinWidths.size() );
 
  543    for( 
const auto& [ netLayer, itemsPoly ] : dataset )
 
  545        for( 
int minWidth : distinctMinWidths )
 
  550            returns.emplace_back( 
tp.submit_task(
 
  551                    [min_checker, &itemsPoly, &netLayer, minWidth]()
 
  553                        return min_checker( itemsPoly, netLayer.Layer, minWidth );
 
  558    for( 
auto& ret : returns )
 
  560        std::future_status status = ret.wait_for( std::chrono::milliseconds( 250 ) );
 
  562        while( status != std::future_status::ready )
 
  565            status = ret.wait_for( std::chrono::milliseconds( 250 ) );
 
 
constexpr int ARC_HIGH_DEF
 
constexpr EDA_IU_SCALE pcbIUScale
 
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
 
int GetDRCEpsilon() const
Return an epsilon which accounts for rounding errors, etc.
 
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
 
virtual void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const
Convert the item shape to a closed polygon.
 
Information pertinent to a Pcbnew printed circuit board.
 
std::vector< ZONE * > m_DRCCopperZones
 
int GetCopperLayerCount() const
 
const FOOTPRINTS & Footprints() const
 
const TRACKS & Tracks() const
 
std::shared_ptr< DRC_RTREE > m_CopperItemRTreeCache
 
std::unordered_map< ZONE *, std::unique_ptr< DRC_RTREE > > m_CopperZoneRTreeCache
 
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
 
MINOPTMAX< int > & Value()
 
DRC_RULE * GetParentRule() const
 
static std::shared_ptr< DRC_ITEM > Create(int aErrorCode)
Constructs a DRC_ITEM for the given error code.
 
std::unordered_set< BOARD_ITEM * > GetObjectsAt(const VECTOR2I &aPt, PCB_LAYER_ID aLayer, int aClearance=0)
Gets the BOARD_ITEMs that overlap the specified point/layer.
 
virtual ~DRC_TEST_PROVIDER_CONNECTION_WIDTH()=default
 
virtual const wxString GetName() const override
 
virtual bool Run() override
Run this provider against the given PCB with configured options (if any).
 
DRC_TEST_PROVIDER_CONNECTION_WIDTH()
 
wxString layerDesc(PCB_LAYER_ID aLayer)
 
virtual bool reportPhase(const wxString &aStageName)
 
void reportTwoPointGeometry(std::shared_ptr< DRC_ITEM > &aDrcItem, const VECTOR2I &aMarkerPos, const VECTOR2I &ptA, const VECTOR2I &ptB, PCB_LAYER_ID aLayer)
 
wxString formatMsg(const wxString &aFormatString, const wxString &aSource, double aConstraint, double aActual, EDA_DATA_TYPE aDataType=EDA_DATA_TYPE::DISTANCE)
 
virtual bool reportProgress(size_t aCount, size_t aSize, size_t aDelta=1)
 
static LSET AllCuMask(int aCuLayerCount)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
 
bool isSubstantial(const VERTEX *aA, const VERTEX *aB) const
Checks to see if there is a "substantial" protrusion in each polygon produced by the cut from aA to a...
 
VERTEX * getKink(VERTEX *aPt) const
 
bool FindPairs(const SHAPE_LINE_CHAIN &aPoly)
 
std::set< std::pair< int, int > > & GetVertices()
 
std::set< std::pair< int, int > > m_hits
 
VECTOR2I::extended_type ecoord
 
static SEG::ecoord Square(int a)
 
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
 
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
 
Represent a set of closed polygons.
 
int FullPointCount() const
Return the number of points in the shape poly set.
 
constexpr extended_type SquaredEuclideanNorm() const
Compute the squared euclidean norm of the vector, which is defined as (x ** 2 + y ** 2).
 
std::deque< VERTEX > m_vertices
 
VERTEX * createList(const SHAPE_LINE_CHAIN &points, VERTEX *aTail=nullptr, void *aUserData=nullptr)
Create a list of vertices from a line chain.
 
bool locallyInside(const VERTEX *a, const VERTEX *b) const
Check whether the segment from vertex a -> vertex b is inside the polygon around the immediate area o...
 
VERTEX * getPrevOutlineVertex(const VERTEX *aPt) const
Get the previous vertex in the outline, avoiding steiner points and points that overlap with splits.
 
VERTEX_SET(int aSimplificationLevel)
 
VERTEX * getNextOutlineVertex(const VERTEX *aPt) const
Get the next vertex in the outline, avoiding steiner points and points that overlap with splits.
 
uint32_t zOrder(const double aX, const double aY) const
Note that while the inputs are doubles, these are scaled by the size of the bounding box to fit into ...
 
bool same_point(const VERTEX *aA, const VERTEX *aB) const
Check if two vertices are at the same point.
 
Handle a list of polygons defining a copper zone.
 
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
 
const std::shared_ptr< SHAPE_POLY_SET > & GetFilledPolysList(PCB_LAYER_ID aLayer) const
 
virtual bool IsOnLayer(PCB_LAYER_ID) const override
Test to see if this object is on the given layer.
 
@ CONNECTION_WIDTH_CONSTRAINT
 
PCB_LAYER_ID
A quick note on layer IDs:
 
static DRC_REGISTER_TEST_PROVIDER< DRC_TEST_PROVIDER_ANNULAR_WIDTH > dummy
 
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
 
bool operator==(const NETCODE_LAYER_CACHE_KEY &other) const
 
std::size_t operator()(const NETCODE_LAYER_CACHE_KEY &k) const
 
const SHAPE_LINE_CHAIN chain
 
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
 
BS::thread_pool< 0 > thread_pool
 
@ PCB_ZONE_T
class ZONE, a copper pour area
 
VECTOR2< int32_t > VECTOR2I
 
VECTOR2< double > VECTOR2D