56 virtual bool Run()
override;
58 virtual const wxString
GetName()
const override {
return wxT(
"creepage" ); };
65 double aMaxCreepage,
bool aHasConditional );
68 int testCreepageV2(
const std::vector<int>& aNetcodes,
double aMaxCreepage,
bool aHasConditional );
76 std::vector<std::unique_ptr<PCB_SHAPE>>& aOwned );
90 REPORT_AUX( wxT(
"No creepage constraints found. Tests not run." ) );
122 bool aHasConditional )
129 if( aHasConditional )
131 target = aMaxCreepage;
136 target = netConstraint.
Value().
Min();
148 if ( !netA || !netB )
154 std::shared_ptr<GRAPH_NODE> NetA = aGraph.
AddNetElements( aNetCodeA, aLayer, target );
155 std::shared_ptr<GRAPH_NODE> NetB = aGraph.
AddNetElements( aNetCodeB, aLayer, target );
159 std::vector<std::shared_ptr<GRAPH_NODE>> temp_nodes;
161 std::copy_if( aGraph.
m_nodes.begin(), aGraph.
m_nodes.end(), std::back_inserter( temp_nodes ),
162 []( std::shared_ptr<GRAPH_NODE> aNode )
164 return !!aNode && aNode->m_parent && !aNode->m_parent->IsConductive()
165 && !aNode->m_connectDirectly && aNode->m_type == GRAPH_NODE::POINT;
169 [&]( std::shared_ptr<GRAPH_NODE> aN1, std::shared_ptr<GRAPH_NODE> aN2 )
177 if( !( aN1->m_parent ) || !( aN2->m_parent ) )
180 if( ( aN1->m_parent ) != ( aN2->m_parent ) )
183 aN1->m_parent->ConnectChildren( aN1, aN2, aGraph );
186 std::vector<std::shared_ptr<GRAPH_CONNECTION>> shortestPath;
187 shortestPath.clear();
190 if( shortestPath.empty() || shortestPath.size() < 4 )
193 std::shared_ptr<GRAPH_CONNECTION> gc1 = shortestPath[1];
194 std::shared_ptr<GRAPH_CONNECTION> gc2 = shortestPath[shortestPath.size() - 2];
196 const BOARD_ITEM* item1 = gc1->n1 && gc1->n1->m_parent ? gc1->n1->m_parent->GetParent() :
nullptr;
197 const BOARD_ITEM* item2 = gc2->n2 && gc2->n2->m_parent ? gc2->n2->m_parent->GetParent() :
nullptr;
201 if( !aHasConditional )
202 constraint = netConstraint;
203 else if( item1 && item2 )
208 double creepageValue = constraint.
Value().
Min();
210 if( creepageValue <= 0 || distance - creepageValue >= 0 )
214 drcItem->SetErrorDetail(
formatMsg(
_(
"(%s creepage %s; actual %s)" ),
223 drcItem->SetItems( item1, item2 );
228 VECTOR2I startPoint = gc1->m_path.a2;
230 std::vector<PCB_SHAPE>
path;
232 for(
const std::shared_ptr<GRAPH_CONNECTION>& gc : shortestPath )
233 gc->GetShapes(
path );
238 aMarker->SetPath( path, startPoint, endPoint );
262 for(
auto it = nets.begin(); it != nets.end(); it++ )
263 aVector.push_back( it->first );
268 std::vector<std::unique_ptr<PCB_SHAPE>>& aOwned )
282 std::vector<int> netcodes;
287 if( maxConstraint <= 0 )
302 bool hasValidOutline =
m_board->GetBoardPolygonOutlines( outline,
false,
nullptr,
false,
true );
321 int beNodeSize = graph.
m_nodes.size();
323 bool prevTestChangedGraph =
false;
326 size_t total = ( netcodes.size() * ( netcodes.size() - 1 ) ) / 2 *
m_board->GetCopperLayerCount();
330 [&](
int aNet1,
int aNet2 )
335 for( auto it = layers.copper_layers_begin(); it != layers.copper_layers_end(); ++it )
337 PCB_LAYER_ID layer = *it;
339 reportProgress( current++, total );
341 if( prevTestChangedGraph )
342 graph.TruncateToPrefix( beNodeSize, beConnectionsSize );
344 prevTestChangedGraph = testCreepage( graph, aNet1, aNet2, layer,
345 maxConstraint, hasConditional );
364 drcItem->SetErrorDetail(
formatMsg(
_(
"(%s creepage %s; actual %s)" ), aConstraint.
GetName(),
373 aMarker->SetPath( aResult.m_path, aResult.m_start, aResult.m_end );
379 bool aHasConditional )
388 size_t total = ( aNetcodes.size() * ( aNetcodes.size() - 1 ) ) / 2 *
m_board->GetCopperLayerCount();
391 [&](
int aNet1,
int aNet2 )
396 for( auto it = layers.copper_layers_begin(); it != layers.copper_layers_end(); ++it )
398 PCB_LAYER_ID layer = *it;
400 reportProgress( current++, total );
404 DRC_CONSTRAINT netConstraint;
407 if( aHasConditional )
409 target = aMaxCreepage;
413 netConstraint = placeholderConstraint( aNet1, aNet2, layer );
414 target = netConstraint.Value().Min();
417 std::optional<CREEPAGE_RESULT> result =
418 engine.SolveNetPairWholeBoard( aNet1, aNet2, layer, target );
420 if( !result || !result->m_itemA || !result->m_itemB )
423 DRC_CONSTRAINT constraint =
425 ? m_drcEngine->EvalRules( CREEPAGE_CONSTRAINT, result->m_itemA,
426 result->m_itemB, layer )
428 double creepageValue = constraint.Value().Min();
430 if( creepageValue > 0 && result->m_distance - creepageValue < 0 )
431 reportCreepageViolation( *result, constraint, layer );
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
virtual bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
ecoord_type Distance(const Vec &aP) const
Reusable creepage solver shared by the batch DRC provider and the realtime drag overlay.
void SetMinGrooveWidth(int aWidth)
A graph with nodes and connections for creepage calculation.
void SetTarget(double aTarget)
double Solve(std::shared_ptr< GRAPH_NODE > &aFrom, std::shared_ptr< GRAPH_NODE > &aTo, std::vector< std::shared_ptr< GRAPH_CONNECTION > > &aResult)
std::vector< CREEP_SHAPE * > m_shapeCollection
void GeneratePaths(double aMaxWeight, PCB_LAYER_ID aLayer, const std::set< int > *aRelevantNets=nullptr)
Generate creepage paths between graph nodes.
void TransformEdgeToCreepShapes()
void TransformCreepShapesToNodes(std::vector< CREEP_SHAPE * > &aShapes)
SHAPE_POLY_SET * m_boardOutline
void RemoveDuplicatedShapes()
std::vector< BOARD_ITEM * > m_boardEdge
std::vector< std::shared_ptr< GRAPH_NODE > > m_nodes
std::vector< std::shared_ptr< GRAPH_CONNECTION > > m_connections
std::shared_ptr< GRAPH_NODE > AddNetElements(int aNetCode, PCB_LAYER_ID aLayer, int aMaxCreepage)
std::vector< std::unique_ptr< PCB_SHAPE > > m_ownedBoardEdges
MINOPTMAX< int > & Value()
const MINOPTMAX< int > & GetValue() const
DRC_RULE * GetParentRule() const
static std::shared_ptr< DRC_ITEM > Create(int aErrorCode)
Constructs a DRC_ITEM for the given error code.
virtual ~DRC_TEST_PROVIDER_CREEPAGE()=default
std::set< std::pair< const BOARD_ITEM *, const BOARD_ITEM * > > m_reportedPairs
double GetMaxConstraint()
virtual const wxString GetName() const override
DRC_CONSTRAINT placeholderConstraint(int aNetCodeA, int aNetCodeB, PCB_LAYER_ID aLayer)
Constraint from geometry-less net/layer placeholders; exact only when no rule is conditional.
void CollectBoardEdges(std::vector< BOARD_ITEM * > &aVector, std::vector< std::unique_ptr< PCB_SHAPE > > &aOwned)
virtual bool Run() override
Run this provider against the given PCB with configured options (if any).
DRC_TEST_PROVIDER_CREEPAGE()
void reportCreepageViolation(const CREEPAGE_RESULT &aResult, const DRC_CONSTRAINT &aConstraint, PCB_LAYER_ID aLayer)
void CollectNetCodes(std::vector< int > &aVector)
int testCreepageV2(const std::vector< int > &aNetcodes, double aMaxCreepage, bool aHasConditional)
Realtime (V2) batch path, gated by the RealtimeCreepage advanced config flag.
virtual bool reportPhase(const wxString &aStageName)
void reportViolation(std::shared_ptr< DRC_ITEM > &item, const VECTOR2I &aMarkerPos, int aMarkerLayer, const std::function< void(PCB_MARKER *)> &aPathGenerator=[](PCB_MARKER *){})
wxString formatMsg(const wxString &aFormatString, const wxString &aSource, double aConstraint, double aActual, EDA_DATA_TYPE aDataType=EDA_DATA_TYPE::DISTANCE)
LSET is a set of PCB_LAYER_IDs.
Handle the data for a net.
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Represent a set of closed polygons.
void BuildCreepageBoardEdges(BOARD &aBoard, std::vector< BOARD_ITEM * > &aVector, std::vector< std::unique_ptr< PCB_SHAPE > > &aOwned, const std::set< const BOARD_ITEM * > *aExclude)
Collect the board-edge items used by the creepage graph.
PCB_LAYER_ID
A quick note on layer IDs:
This file contains miscellaneous commonly used macros and functions.
void for_all_pairs(_InputIterator __first, _InputIterator __last, _Function __f)
Apply a function to every possible pair of elements of a sequence.
static DRC_REGISTER_TEST_PROVIDER< DRC_TEST_PROVIDER_ANNULAR_WIDTH > dummy
std::map< int, NETINFO_ITEM * > NETCODES_MAP
std::deque< BOARD_ITEM * > DRAWINGS
static float distance(const SFVEC2UI &a, const SFVEC2UI &b)
Result of a single creepage query between two nets on one layer.
const BOARD_ITEM * m_itemB
const BOARD_ITEM * m_itemA
VECTOR2< int32_t > VECTOR2I