13
13
#include " util/util.hpp"
14
14
#include " board_rules_check_util.hpp"
15
15
#include < iostream>
16
- #include " board_rules_check_util.hpp"
17
16
18
17
namespace horizon {
19
18
@@ -363,13 +362,7 @@ RulesCheckResult BoardRules::check_clearance_copper_keepout(const Board &brd, Ru
363
362
status_cb (" Getting patches" );
364
363
auto rules = get_rules_sorted<RuleClearanceCopperKeepout>();
365
364
auto &c = cache.get_cache <RulesCheckCacheBoardImage>();
366
- std::set<int > layers;
367
365
const auto &patches = c.get_canvas ().get_patches ();
368
- for (const auto &it : patches) { // collect copper layers
369
- if (brd.get_layers ().count (it.first .layer ) && brd.get_layers ().at (it.first .layer ).copper ) {
370
- layers.emplace (it.first .layer );
371
- }
372
- }
373
366
auto keepout_contours = brd.get_keepout_contours ();
374
367
auto n_patches = patches.size ();
375
368
auto n_keepouts = keepout_contours.size ();
@@ -390,7 +383,7 @@ RulesCheckResult BoardRules::check_clearance_copper_keepout(const Board &brd, Ru
390
383
status_cb (ss.str ());
391
384
}
392
385
if (BoardLayers::is_copper (it.first .layer )
393
- && (it.first .layer == keepout->polygon ->layer || keepout->all_cu_layers )
386
+ && (it.first .layer . overlaps ( keepout->polygon ->layer ) || keepout->all_cu_layers )
394
387
&& keepout->patch_types_cu .count (it.first .type )) {
395
388
396
389
const Net *net = it.first .net ? &brd.block ->nets .at (it.first .net ) : nullptr ;
@@ -434,9 +427,9 @@ RulesCheckResult BoardRules::check_clearance_copper_keepout(const Board &brd, Ru
434
427
}
435
428
e.location = acc.get ();
436
429
e.comment = patch_type_names.at (it.first .type ) + " (" + (net ? net->name : " " ) + " ) on layer"
437
- + brd.get_layers (). at ( it.first .layer ). name + " near keepout" ;
430
+ + brd.get_layer_name ( it.first .layer ) + " near keepout" ;
438
431
e.error_polygons = {ite};
439
- e.layers . insert ( it.first .layer );
432
+ e.add_layer_range (brd, it.first .layer );
440
433
}
441
434
}
442
435
}
@@ -454,77 +447,77 @@ RulesCheckResult BoardRules::check_clearance_same_net(const Board &brd, RulesChe
454
447
status_cb (" Getting patches" );
455
448
auto rules = get_rules_sorted<RuleClearanceSameNet>();
456
449
auto &c = cache.get_cache <RulesCheckCacheBoardImage>();
457
- std::set<int > layers;
458
450
const auto &patches = c.get_canvas ().get_patches ();
459
- for (const auto &it : patches) { // collect copper layers
460
- if (brd.get_layers ().count (it.first .layer ) && brd.get_layers ().at (it.first .layer ).copper ) {
461
- layers.emplace (it.first .layer );
462
- }
463
- }
451
+
464
452
if (r.check_cancelled (cancel))
465
453
return r;
466
454
status_cb (" Building patch pairs" );
467
455
468
456
static const std::set<PatchType> patch_types = {PatchType::PAD, PatchType::PAD_TH, PatchType::VIA,
469
457
PatchType::HOLE_NPTH};
470
-
471
- for (const auto layer : layers) { // check each layer individually
472
- // assemble a list of patch pairs we'll need to check
473
- std::set<std::pair<CanvasPatch::PatchKey, CanvasPatch::PatchKey>> patch_pairs;
474
- for (const auto &it : patches) {
475
- for (const auto &it_other : patches) {
476
- if (layer == it.first .layer && it.first .layer == it_other.first .layer
477
- && patch_types.count (it.first .type ) && patch_types.count (it_other.first .type )
478
- && it.first .type != it_other.first .type && it.first .net == it_other.first .net ) {
479
- std::pair<CanvasPatch::PatchKey, CanvasPatch::PatchKey> k = {it.first , it_other.first };
480
- auto k2 = k;
481
- std::swap (k2.first , k2.second );
482
- if (patch_pairs.count (k) == 0 && patch_pairs.count (k2) == 0 ) {
483
- patch_pairs.emplace (k);
484
- }
458
+ std::set<std::pair<CanvasPatch::PatchKey, CanvasPatch::PatchKey>> patch_pairs;
459
+
460
+
461
+ // assemble a list of patch pairs we'll need to check
462
+ for (const auto &it : patches) {
463
+ for (const auto &it_other : patches) {
464
+ if (it.first .layer .overlaps (it_other.first .layer ) && patch_types.count (it.first .type )
465
+ && patch_types.count (it_other.first .type ) && it.first .type != it_other.first .type
466
+ && it.first .net == it_other.first .net ) {
467
+ std::pair<CanvasPatch::PatchKey, CanvasPatch::PatchKey> k = {it.first , it_other.first };
468
+ auto k2 = k;
469
+ std::swap (k2.first , k2.second );
470
+ if (patch_pairs.count (k) == 0 && patch_pairs.count (k2) == 0 ) {
471
+ patch_pairs.emplace (k);
485
472
}
486
473
}
487
- if (r.check_cancelled (cancel))
488
- return r;
489
474
}
475
+ if (r.check_cancelled (cancel))
476
+ return r;
477
+ }
490
478
491
- for (const auto &[p1, p2] : patch_pairs) {
492
- if (r.check_cancelled (cancel))
493
- return r;
494
- const Net *net = p1.net ? &brd.block ->nets .at (p1.net ) : nullptr ;
495
- const auto &rule = get_clearance_same_net (net, layer);
496
- auto clearance = rule.get_clearance (p1.type , p2.type );
497
- if (clearance >= 0 ) {
498
- // expand p1 patch by clearance
499
- ClipperLib::ClipperOffset ofs;
500
- ofs.ArcTolerance = 10e3 ;
501
- ofs.AddPaths (patches.at (p1), ClipperLib::jtRound, ClipperLib::etClosedPolygon);
502
- ClipperLib::Paths paths_ofs;
503
- ofs.Execute (paths_ofs, clearance);
504
-
505
- // intersect expanded and this patch
506
- ClipperLib::Clipper clipper;
507
- clipper.AddPaths (paths_ofs, ClipperLib::ptClip, true );
508
- clipper.AddPaths (patches.at (p2), ClipperLib::ptSubject, true );
509
- ClipperLib::Paths errors;
510
- clipper.Execute (ClipperLib::ctIntersection, errors, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
479
+ for (const auto &[p1, p2] : patch_pairs) {
480
+ if (r.check_cancelled (cancel))
481
+ return r;
511
482
512
- // no intersection: no clearance violation
513
- if (errors.size () > 0 ) {
514
- for (const auto &ite : errors) {
515
- r.errors .emplace_back (RulesCheckErrorLevel::FAIL);
516
- auto &e = r.errors .back ();
517
- e.has_location = true ;
518
- Accumulator<Coordi> acc;
519
- for (const auto &ite2 : ite) {
520
- acc.accumulate ({ite2.X , ite2.Y });
521
- }
522
- e.location = acc.get ();
523
- e.comment = patch_type_names.at (p1.type ) + " near " + patch_type_names.at (p2.type ) + " "
524
- + get_net_name (net) + " on layer " + brd.get_layers ().at (layer).name ;
525
- e.error_polygons = {ite};
526
- e.layers .insert (layer);
483
+ const Net *net = p1.net ? &brd.block ->nets .at (p1.net ) : nullptr ;
484
+
485
+ const auto layer_isect = p1.layer .intersection (p2.layer ).value ();
486
+
487
+ auto clearance =
488
+ find_clearance (*this , &BoardRules::get_clearance_same_net, brd.get_layers_for_range (layer_isect),
489
+ std::forward_as_tuple (net), std::forward_as_tuple (p1.type , p2.type ));
490
+
491
+ if (clearance >= 0 ) {
492
+ // expand p1 patch by clearance
493
+ ClipperLib::ClipperOffset ofs;
494
+ ofs.ArcTolerance = 10e3 ;
495
+ ofs.AddPaths (patches.at (p1), ClipperLib::jtRound, ClipperLib::etClosedPolygon);
496
+ ClipperLib::Paths paths_ofs;
497
+ ofs.Execute (paths_ofs, clearance);
498
+
499
+ // intersect expanded and this patch
500
+ ClipperLib::Clipper clipper;
501
+ clipper.AddPaths (paths_ofs, ClipperLib::ptClip, true );
502
+ clipper.AddPaths (patches.at (p2), ClipperLib::ptSubject, true );
503
+ ClipperLib::Paths errors;
504
+ clipper.Execute (ClipperLib::ctIntersection, errors, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
505
+
506
+ // no intersection: no clearance violation
507
+ if (errors.size () > 0 ) {
508
+ for (const auto &ite : errors) {
509
+ r.errors .emplace_back (RulesCheckErrorLevel::FAIL);
510
+ auto &e = r.errors .back ();
511
+ e.has_location = true ;
512
+ Accumulator<Coordi> acc;
513
+ for (const auto &ite2 : ite) {
514
+ acc.accumulate ({ite2.X , ite2.Y });
527
515
}
516
+ e.location = acc.get ();
517
+ e.comment = patch_type_names.at (p1.type ) + " near " + patch_type_names.at (p2.type ) + " "
518
+ + get_net_name (net) + " on layer " + brd.get_layer_name (layer_isect);
519
+ e.error_polygons = {ite};
520
+ e.add_layer_range (brd, layer_isect);
528
521
}
529
522
}
530
523
}
0 commit comments