KiCad PCB EDA Suite
Loading...
Searching...
No Matches
board_inspection_tool.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include <bitmaps.h>
25#include <pcb_group.h>
26#include <tool/tool_manager.h>
29#include <tools/edit_tool.h>
30#include <pcb_painter.h>
32#include <drc/drc_engine.h>
37#include <string_utils.h>
39#include <fp_lib_table.h>
40#include <pcb_shape.h>
41#include <pcbnew_settings.h>
45#include <drc/drc_item.h>
46#include <pad.h>
47#include <project_pcb.h>
48#include <view/view_controls.h>
49
50
52 PCB_TOOL_BASE( "pcbnew.InspectionTool" ),
53 m_frame( nullptr )
54{
55 m_dynamicData = nullptr;
56}
57
58
60{
61public:
63 {
64 SetIcon( BITMAPS::show_ratsnest );
65 SetTitle( _( "Net Inspection Tools" ) );
66
69 AppendSeparator();
72 }
73
74private:
75 ACTION_MENU* create() const override
76 {
77 return new NET_CONTEXT_MENU();
78 }
79};
80
81
83{
85
86 std::shared_ptr<NET_CONTEXT_MENU> netSubMenu = std::make_shared<NET_CONTEXT_MENU>();
87 netSubMenu->SetTool( this );
88
89 // Only show the net menu if all items in the selection are connectable
90 auto showNetMenuFunc =
91 []( const SELECTION& aSelection )
92 {
93 if( aSelection.Empty() )
94 return false;
95
96 for( const EDA_ITEM* item : aSelection )
97 {
98 switch( item->Type() )
99 {
100 case PCB_TRACE_T:
101 case PCB_ARC_T:
102 case PCB_VIA_T:
103 case PCB_PAD_T:
104 case PCB_ZONE_T:
105 continue;
106
107 case PCB_SHAPE_T:
108 {
109 if( !static_cast<const PCB_SHAPE*>( item )->IsOnCopperLayer() )
110 return false;
111 else
112 continue;
113 }
114
115 default:
116 return false;
117 }
118 }
119
120 return true;
121 };
122
123 CONDITIONAL_MENU& menu = selectionTool->GetToolMenu().GetMenu();
124
125 selectionTool->GetToolMenu().RegisterSubMenu( netSubMenu );
126
127 menu.AddMenu( netSubMenu.get(), showNetMenuFunc, 100 );
128
129 return true;
130}
131
132
134{
135 m_frame = getEditFrame<PCB_EDIT_FRAME>();
136}
137
138
140{
142 dialog.ShowModal();
143 return 0;
144}
145
146
147std::unique_ptr<DRC_ENGINE> BOARD_INSPECTION_TOOL::makeDRCEngine( bool* aCompileError,
148 bool* aCourtyardError )
149{
150 auto engine = std::make_unique<DRC_ENGINE>( m_frame->GetBoard(),
152
153 try
154 {
155 engine->InitEngine( m_frame->GetDesignRulesPath() );
156 }
157 catch( PARSE_ERROR& )
158 {
159 if( aCompileError )
160 *aCompileError = true;
161 }
162
163 for( ZONE* zone : m_frame->GetBoard()->Zones() )
164 zone->CacheBoundingBox();
165
167 {
168 for( ZONE* zone : footprint->Zones() )
169 zone->CacheBoundingBox();
170
172
173 if( aCourtyardError && ( footprint->GetFlags() & MALFORMED_COURTYARDS ) != 0 )
174 *aCourtyardError = true;
175 }
176
177 return engine;
178}
179
180
181bool isNPTHPad( BOARD_ITEM* aItem )
182{
183 return aItem->Type() == PCB_PAD_T
184 && static_cast<PAD*>( aItem )->GetAttribute() == PAD_ATTRIB::NPTH;
185}
186
187
189{
190 // Null items have no description
191 if( !aItem )
192 return wxString();
193
194 wxString msg = aItem->GetItemDescription( m_frame, true );
195
196 if( aItem->IsConnected() && !isNPTHPad( aItem ) )
197 {
198 BOARD_CONNECTED_ITEM* cItem = static_cast<BOARD_CONNECTED_ITEM*>( aItem );
199
200 msg += wxS( " " )
201 + wxString::Format( _( "[netclass %s]" ),
203 }
204
205 return msg;
206};
207
208
210{
211 r->Report( "" );
212 r->Report( _( "Report incomplete: could not compile custom design rules." )
213 + wxS( "&nbsp;&nbsp;" )
214 + wxS( "<a href='$CUSTOM_RULES'>" ) + _( "Show design rules." ) + wxS( "</a>" ) );
215}
216
217
218void BOARD_INSPECTION_TOOL::reportHeader( const wxString& aTitle, BOARD_ITEM* a, REPORTER* r )
219{
220 r->Report( wxT( "<h7>" ) + EscapeHTML( aTitle ) + wxT( "</h7>" ) );
221 r->Report( wxT( "<ul><li>" ) + EscapeHTML( getItemDescription( a ) ) + wxT( "</li></ul>" ) );
222}
223
224
225void BOARD_INSPECTION_TOOL::reportHeader( const wxString& aTitle, BOARD_ITEM* a, BOARD_ITEM* b,
226 REPORTER* r )
227{
228 r->Report( wxT( "<h7>" ) + EscapeHTML( aTitle ) + wxT( "</h7>" ) );
229 r->Report( wxT( "<ul><li>" ) + EscapeHTML( getItemDescription( a ) ) + wxT( "</li>" )
230 + wxT( "<li>" ) + EscapeHTML( getItemDescription( b ) ) + wxT( "</li></ul>" ) );
231}
232
233
234void BOARD_INSPECTION_TOOL::reportHeader( const wxString& aTitle, BOARD_ITEM* a, BOARD_ITEM* b,
235 PCB_LAYER_ID aLayer, REPORTER* r )
236{
237 wxString layerStr = _( "Layer" ) + wxS( " " ) + m_frame->GetBoard()->GetLayerName( aLayer );
238
239 r->Report( wxT( "<h7>" ) + EscapeHTML( aTitle ) + wxT( "</h7>" ) );
240 r->Report( wxT( "<ul><li>" ) + EscapeHTML( layerStr ) + wxT( "</li>" )
241 + wxT( "<li>" ) + EscapeHTML( getItemDescription( a ) ) + wxT( "</li>" )
242 + wxT( "<li>" ) + EscapeHTML( getItemDescription( b ) ) + wxT( "</li></ul>" ) );
243}
244
245
246wxString reportMin( PCB_BASE_FRAME* aFrame, DRC_CONSTRAINT& aConstraint )
247{
248 if( aConstraint.m_Value.HasMin() )
249 return aFrame->StringFromValue( aConstraint.m_Value.Min(), true );
250 else
251 return wxT( "<i>" ) + _( "undefined" ) + wxT( "</i>" );
252}
253
254
255wxString reportOpt( PCB_BASE_FRAME* aFrame, DRC_CONSTRAINT& aConstraint )
256{
257 if( aConstraint.m_Value.HasOpt() )
258 return aFrame->StringFromValue( aConstraint.m_Value.Opt(), true );
259 else
260 return wxT( "<i>" ) + _( "undefined" ) + wxT( "</i>" );
261}
262
263
264wxString reportMax( PCB_BASE_FRAME* aFrame, DRC_CONSTRAINT& aConstraint )
265{
266 if( aConstraint.m_Value.HasMax() )
267 return aFrame->StringFromValue( aConstraint.m_Value.Max(), true );
268 else
269 return wxT( "<i>" ) + _( "undefined" ) + wxT( "</i>" );
270}
271
272
273wxString BOARD_INSPECTION_TOOL::InspectDRCErrorMenuText( const std::shared_ptr<RC_ITEM>& aDRCItem )
274{
275 auto menuDescription =
276 [&]( const TOOL_ACTION& aAction )
277 {
278 wxString menuItemLabel = aAction.GetMenuLabel();
279 wxMenuBar* menuBar = m_frame->GetMenuBar();
280
281 for( size_t ii = 0; ii < menuBar->GetMenuCount(); ++ii )
282 {
283 for( wxMenuItem* menuItem : menuBar->GetMenu( ii )->GetMenuItems() )
284 {
285 if( menuItem->GetItemLabelText() == menuItemLabel )
286 {
287 wxString menuTitleLabel = menuBar->GetMenuLabelText( ii );
288
289 menuTitleLabel.Replace( wxS( "&" ), wxS( "&&" ) );
290 menuItemLabel.Replace( wxS( "&" ), wxS( "&&" ) );
291
292 return wxString::Format( _( "Run %s > %s" ),
293 menuTitleLabel,
294 menuItemLabel );
295 }
296 }
297 }
298
299 return wxString::Format( _( "Run %s" ), aAction.GetFriendlyName() );
300 };
301
302 if( aDRCItem->GetErrorCode() == DRCE_CLEARANCE
303 || aDRCItem->GetErrorCode() == DRCE_EDGE_CLEARANCE
304 || aDRCItem->GetErrorCode() == DRCE_HOLE_CLEARANCE
305 || aDRCItem->GetErrorCode() == DRCE_DRILLED_HOLES_TOO_CLOSE )
306 {
307 return menuDescription( PCB_ACTIONS::inspectClearance );
308 }
309 else if( aDRCItem->GetErrorCode() == DRCE_TEXT_HEIGHT
310 || aDRCItem->GetErrorCode() == DRCE_TEXT_THICKNESS
311 || aDRCItem->GetErrorCode() == DRCE_DIFF_PAIR_UNCOUPLED_LENGTH_TOO_LONG
312 || aDRCItem->GetErrorCode() == DRCE_TRACK_WIDTH
313 || aDRCItem->GetErrorCode() == DRCE_TRACK_ANGLE
314 || aDRCItem->GetErrorCode() == DRCE_TRACK_SEGMENT_LENGTH
315 || aDRCItem->GetErrorCode() == DRCE_VIA_DIAMETER
316 || aDRCItem->GetErrorCode() == DRCE_ANNULAR_WIDTH
317 || aDRCItem->GetErrorCode() == DRCE_DRILL_OUT_OF_RANGE
318 || aDRCItem->GetErrorCode() == DRCE_MICROVIA_DRILL_OUT_OF_RANGE
319 || aDRCItem->GetErrorCode() == DRCE_CONNECTION_WIDTH
320 || aDRCItem->GetErrorCode() == DRCE_ASSERTION_FAILURE )
321 {
322 return menuDescription( PCB_ACTIONS::inspectConstraints );
323 }
324 else if( aDRCItem->GetErrorCode() == DRCE_LIB_FOOTPRINT_MISMATCH )
325 {
326 return menuDescription( PCB_ACTIONS::diffFootprint );
327 }
328 else if( aDRCItem->GetErrorCode() == DRCE_DANGLING_TRACK
329 || aDRCItem->GetErrorCode() == DRCE_DANGLING_VIA )
330 {
331 return menuDescription( PCB_ACTIONS::cleanupTracksAndVias );
332 }
333
334 return wxEmptyString;
335}
336
337
338void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr<RC_ITEM>& aDRCItem )
339{
340 wxCHECK( m_frame, /* void */ );
341
342 BOARD_ITEM* a = m_frame->GetBoard()->GetItem( aDRCItem->GetMainItemID() );
343 BOARD_ITEM* b = m_frame->GetBoard()->GetItem( aDRCItem->GetAuxItemID() );
344 BOARD_CONNECTED_ITEM* ac = dynamic_cast<BOARD_CONNECTED_ITEM*>( a );
345 BOARD_CONNECTED_ITEM* bc = dynamic_cast<BOARD_CONNECTED_ITEM*>( b );
347
348 if( aDRCItem->GetErrorCode() == DRCE_LIB_FOOTPRINT_MISMATCH )
349 {
350 if( FOOTPRINT* footprint = dynamic_cast<FOOTPRINT*>( a ) )
352
353 return;
354 }
355 else if( aDRCItem->GetErrorCode() == DRCE_DANGLING_TRACK
356 || aDRCItem->GetErrorCode() == DRCE_DANGLING_VIA )
357 {
359 return;
360 }
361
363 wxCHECK( dialog, /* void */ );
364
365 dialog->DeleteAllPages();
366
367 bool compileError = false;
368 bool courtyardError = false;
369 std::unique_ptr<DRC_ENGINE> drcEngine = makeDRCEngine( &compileError, &courtyardError );
370
371 WX_HTML_REPORT_BOX* r = nullptr;
372 DRC_CONSTRAINT constraint;
373 int clearance = 0;
374 wxString clearanceStr;
375
376 switch( aDRCItem->GetErrorCode() )
377 {
379 {
380 for( KIID id : aDRCItem->GetIDs() )
381 {
382 bc = dynamic_cast<BOARD_CONNECTED_ITEM*>( m_frame->GetBoard()->GetItem( id ) );
383
384 if( ac && bc && ac->GetNetCode() != bc->GetNetCode() )
385 break;
386 }
387
388 r = dialog->AddHTMLPage( _( "Uncoupled Length" ) );
389 reportHeader( _( "Diff pair uncoupled length resolution for:" ), ac, bc, r );
390
391 if( compileError )
393
394 constraint = drcEngine->EvalRules( MAX_UNCOUPLED_CONSTRAINT, a, b, layer, r );
395
396 r->Report( "" );
397 r->Report( wxString::Format( _( "Resolved max uncoupled length: %s." ),
398 reportMax( m_frame, constraint ) ) );
399 break;
400 }
401
402 case DRCE_TEXT_HEIGHT:
403 r = dialog->AddHTMLPage( _( "Text Height" ) );
404 reportHeader( _( "Text height resolution for:" ), a, r );
405
406 if( compileError )
408
409 constraint = drcEngine->EvalRules( TEXT_HEIGHT_CONSTRAINT, a, b, layer, r );
410
411 r->Report( "" );
412 r->Report( wxString::Format( _( "Resolved height constraints: min %s; max %s." ),
413 reportMin( m_frame, constraint ),
414 reportMax( m_frame, constraint ) ) );
415 break;
416
418 r = dialog->AddHTMLPage( _( "Text Thickness" ) );
419 reportHeader( _( "Text thickness resolution for:" ), a, r );
420
421 if( compileError )
423
424 constraint = drcEngine->EvalRules( TEXT_THICKNESS_CONSTRAINT, a, b, layer, r );
425
426 r->Report( "" );
427 r->Report( wxString::Format( _( "Resolved thickness constraints: min %s; max %s." ),
428 reportMin( m_frame, constraint ),
429 reportMax( m_frame, constraint ) ) );
430 break;
431
432 case DRCE_TRACK_WIDTH:
433 r = dialog->AddHTMLPage( _( "Track Width" ) );
434 reportHeader( _( "Track width resolution for:" ), a, r );
435
436 if( compileError )
438
439 constraint = drcEngine->EvalRules( TRACK_WIDTH_CONSTRAINT, a, b, layer, r );
440
441 r->Report( "" );
442 r->Report( wxString::Format( _( "Resolved width constraints: min %s; max %s." ),
443 reportMin( m_frame, constraint ),
444 reportMax( m_frame, constraint ) ) );
445 break;
446
447 case DRCE_TRACK_ANGLE:
448 r = dialog->AddHTMLPage( _( "Track Angle" ) );
449 reportHeader( _( "Track Angle resolution for:" ), a, r );
450
451 if( compileError )
453
454 constraint = drcEngine->EvalRules( TRACK_ANGLE_CONSTRAINT, a, b, layer, r );
455
456 r->Report( "" );
457 r->Report( wxString::Format( _( "Resolved angle constraints: min %s; max %s." ),
458 reportMin( m_frame, constraint ),
459 reportMax( m_frame, constraint ) ) );
460 break;
461
463 r = dialog->AddHTMLPage( _( "Track Segment Length" ) );
464 reportHeader( _( "Track segment length resolution for:" ), a, r );
465
466 if( compileError )
468
469 constraint = drcEngine->EvalRules( TRACK_SEGMENT_LENGTH_CONSTRAINT, a, b, layer, r );
470
471 r->Report( "" );
472 r->Report( wxString::Format( _( "Resolved segment length constraints: min %s; max %s." ),
473 reportMin( m_frame, constraint ),
474 reportMax( m_frame, constraint ) ) );
475 break;
476
478 r = dialog->AddHTMLPage( _( "Connection Width" ) );
479 reportHeader( _( "Connection width resolution for:" ), a, b, r );
480
481 if( compileError )
483
484 constraint = drcEngine->EvalRules( CONNECTION_WIDTH_CONSTRAINT, a, b, layer, r );
485
486 r->Report( "" );
487 r->Report( wxString::Format( _( "Resolved min connection width: %s." ),
488 reportMin( m_frame, constraint ) ) );
489 break;
490
492 r = dialog->AddHTMLPage( _( "Via Diameter" ) );
493 reportHeader( _( "Via diameter resolution for:" ), a, r );
494
495 if( compileError )
497
498 constraint = drcEngine->EvalRules( VIA_DIAMETER_CONSTRAINT, a, b, layer, r );
499
500 r->Report( "" );
501 r->Report( wxString::Format( _( "Resolved diameter constraints: min %s; max %s." ),
502 reportMin( m_frame, constraint ),
503 reportMax( m_frame, constraint ) ) );
504 break;
505
507 r = dialog->AddHTMLPage( _( "Via Annulus" ) );
508 reportHeader( _( "Via annular width resolution for:" ), a, r );
509
510 if( compileError )
512
513 constraint = drcEngine->EvalRules( ANNULAR_WIDTH_CONSTRAINT, a, b, layer, r );
514
515 r->Report( "" );
516 r->Report( wxString::Format( _( "Resolved annular width constraints: min %s; max %s." ),
517 reportMin( m_frame, constraint ),
518 reportMax( m_frame, constraint ) ) );
519 break;
520
523 r = dialog->AddHTMLPage( _( "Hole Size" ) );
524 reportHeader( _( "Hole size resolution for:" ), a, r );
525
526 if( compileError )
528
529 constraint = drcEngine->EvalRules( HOLE_SIZE_CONSTRAINT, a, b, layer, r );
530
531 r->Report( "" );
532 r->Report( wxString::Format( _( "Resolved hole size constraints: min %s; max %s." ),
533 reportMin( m_frame, constraint ),
534 reportMax( m_frame, constraint ) ) );
535 break;
536
538 r = dialog->AddHTMLPage( _( "Hole Clearance" ) );
539 reportHeader( _( "Hole clearance resolution for:" ), a, b, r );
540
541 if( compileError )
543
544 if( ac && bc && ac->GetNetCode() == bc->GetNetCode() )
545 {
546 r->Report( "" );
547 r->Report( _( "Items belong to the same net. Clearance is 0." ) );
548 }
549 else
550 {
551 constraint = drcEngine->EvalRules( HOLE_CLEARANCE_CONSTRAINT, a, b, layer, r );
552 clearance = constraint.m_Value.Min();
553 clearanceStr = m_frame->StringFromValue( clearance, true );
554
555 r->Report( "" );
556 r->Report( wxString::Format( _( "Resolved min clearance: %s." ), clearanceStr ) );
557 }
558
559 r->Report( "" );
560 r->Report( "" );
561 r->Report( "" );
562 reportHeader( _( "Physical hole clearance resolution for:" ), a, b, layer, r );
563
564 constraint = drcEngine->EvalRules( PHYSICAL_HOLE_CLEARANCE_CONSTRAINT, a, b, layer, r );
565 clearance = constraint.m_Value.Min();
566 clearanceStr = m_frame->StringFromValue( clearance, true );
567
568 if( !drcEngine->HasRulesForConstraintType( PHYSICAL_HOLE_CLEARANCE_CONSTRAINT ) )
569 {
570 r->Report( "" );
571 r->Report( _( "No 'physical_hole_clearance' constraints defined." ) );
572 }
573 else
574 {
575 r->Report( "" );
576 r->Report( wxString::Format( _( "Resolved min clearance: %s." ), clearanceStr ) );
577 }
578
579 break;
580
582 r = dialog->AddHTMLPage( _( "Hole to Hole" ) );
583 reportHeader( _( "Hole-to-hole clearance resolution for:" ), a, b, r );
584
585 if( compileError )
587
588 constraint = drcEngine->EvalRules( HOLE_TO_HOLE_CONSTRAINT, a, b, UNDEFINED_LAYER, r );
589 clearance = constraint.m_Value.Min();
590 clearanceStr = m_frame->StringFromValue( clearance, true );
591
592 r->Report( "" );
593 r->Report( wxString::Format( _( "Resolved min clearance: %s." ), clearanceStr ) );
594 break;
595
597 r = dialog->AddHTMLPage( _( "Edge Clearance" ) );
598 reportHeader( _( "Edge clearance resolution for:" ), a, b, r );
599
600 if( compileError )
602
603 constraint = drcEngine->EvalRules( EDGE_CLEARANCE_CONSTRAINT, a, b, layer, r );
604 clearance = constraint.m_Value.Min();
605 clearanceStr = m_frame->StringFromValue( clearance, true );
606
607 r->Report( "" );
608 r->Report( wxString::Format( _( "Resolved min clearance: %s." ), clearanceStr ) );
609 break;
610
611 case DRCE_CLEARANCE:
612 if( a->Type() == PCB_TRACE_T || a->Type() == PCB_ARC_T )
613 {
614 layer = a->GetLayer();
615 }
616 else if( b->Type() == PCB_TRACE_T || b->Type() == PCB_ARC_T )
617 {
618 layer = b->GetLayer();
619 }
620 else if( a->Type() == PCB_PAD_T
621 && static_cast<PAD*>( a )->GetAttribute() == PAD_ATTRIB::SMD )
622 {
623 PAD* pad = static_cast<PAD*>( a );
624
625 if( pad->IsOnLayer( F_Cu ) )
626 layer = F_Cu;
627 else
628 layer = B_Cu;
629 }
630 else if( b->Type() == PCB_PAD_T
631 && static_cast<PAD*>( a )->GetAttribute() == PAD_ATTRIB::SMD )
632 {
633 PAD* pad = static_cast<PAD*>( b );
634
635 if( pad->IsOnLayer( F_Cu ) )
636 layer = F_Cu;
637 else
638 layer = B_Cu;
639 }
640
641 r = dialog->AddHTMLPage( _( "Clearance" ) );
642 reportHeader( _( "Clearance resolution for:" ), a, b, layer, r );
643
644 if( compileError )
646
647 if( ac && bc && ac->GetNetCode() == bc->GetNetCode() )
648 {
649 r->Report( "" );
650 r->Report( _( "Items belong to the same net. Clearance is 0." ) );
651 }
652 else
653 {
654 constraint = drcEngine->EvalRules( CLEARANCE_CONSTRAINT, a, b, layer, r );
655 clearance = constraint.m_Value.Min();
656 clearanceStr = m_frame->StringFromValue( clearance, true );
657
658 r->Report( "" );
659 r->Report( wxString::Format( _( "Resolved min clearance: %s." ), clearanceStr ) );
660 }
661
662 r->Report( "" );
663 r->Report( "" );
664 r->Report( "" );
665 reportHeader( _( "Physical clearance resolution for:" ), a, b, layer, r );
666
667 constraint = drcEngine->EvalRules( PHYSICAL_CLEARANCE_CONSTRAINT, a, b, layer, r );
668 clearance = constraint.m_Value.Min();
669 clearanceStr = m_frame->StringFromValue( clearance, true );
670
671 if( !drcEngine->HasRulesForConstraintType( PHYSICAL_CLEARANCE_CONSTRAINT ) )
672 {
673 r->Report( "" );
674 r->Report( _( "No 'physical_clearance' constraints defined." ) );
675 }
676 else
677 {
678 r->Report( "" );
679 r->Report( wxString::Format( _( "Resolved min clearance: %s." ), clearanceStr ) );
680 }
681
682 break;
683
685 r = dialog->AddHTMLPage( _( "Assertions" ) );
686 reportHeader( _( "Assertions for:" ), a, r );
687
688 if( compileError )
690
691 drcEngine->ProcessAssertions( a, []( const DRC_CONSTRAINT* c ){}, r );
692 break;
693
694 default:
695 return;
696 }
697
698 r->Flush();
699
700 dialog->Raise();
701 dialog->Show( true );
702}
703
704
706{
707 wxCHECK( m_frame, 0 );
708
710
711 wxCHECK( selTool, 0 );
712
713 const PCB_SELECTION& selection = selTool->GetSelection();
714
715 if( selection.Size() != 2 )
716 {
717 m_frame->ShowInfoBarError( _( "Select two items for a clearance resolution report." ) );
718 return 0;
719 }
720
722 return 0;
723
724 BOARD_ITEM* a = static_cast<BOARD_ITEM*>( selection.GetItem( 0 ) );
725 BOARD_ITEM* b = static_cast<BOARD_ITEM*>( selection.GetItem( 1 ) );
726
727 if( a->Type() == PCB_GROUP_T )
728 {
729 PCB_GROUP* ag = static_cast<PCB_GROUP*>( a );
730
731 if( ag->GetItems().empty() )
732 {
733 m_frame->ShowInfoBarError( _( "Cannot generate clearance report on empty group." ) );
734 return 0;
735 }
736
737 a = *ag->GetItems().begin();
738 }
739
740 if( b->Type() == PCB_GROUP_T )
741 {
742 PCB_GROUP* bg = static_cast<PCB_GROUP*>( b );
743
744 if( bg->GetItems().empty() )
745 {
746 m_frame->ShowInfoBarError( _( "Cannot generate clearance report on empty group." ) );
747 return 0;
748 }
749
750 b = *bg->GetItems().begin();
751 }
752
753 // a or b could be null after group tests above.
754 if( !a || !b )
755 return 0;
756
757 auto checkFootprint =
758 [&]( FOOTPRINT* footprint ) -> BOARD_ITEM*
759 {
760 PAD* foundPad = nullptr;
761
762 for( PAD* pad : footprint->Pads() )
763 {
764 if( !foundPad || pad->SameLogicalPadAs( foundPad ) )
765 foundPad = pad;
766 else
767 return footprint;
768 }
769
770 if( !foundPad )
771 return footprint;
772
773 return foundPad;
774 };
775
776 if( a->Type() == PCB_FOOTPRINT_T )
777 a = checkFootprint( static_cast<FOOTPRINT*>( a ) );
778
779 if( b->Type() == PCB_FOOTPRINT_T )
780 b = checkFootprint( static_cast<FOOTPRINT*>( b ) );
781
782 // a or b could be null after footprint tests above.
783 if( !a || !b )
784 return 0;
785
787
788 wxCHECK( dialog, 0 );
789
790 dialog->DeleteAllPages();
791
792 if( a->Type() != PCB_ZONE_T && b->Type() == PCB_ZONE_T )
793 std::swap( a, b );
794 else if( !a->IsConnected() && b->IsConnected() )
795 std::swap( a, b );
796
797 WX_HTML_REPORT_BOX* r = nullptr;
799 LSET layerIntersection = a->GetLayerSet() & b->GetLayerSet();
800 LSET copperIntersection = layerIntersection & LSET::AllCuMask();
801 BOARD_CONNECTED_ITEM* ac = dynamic_cast<BOARD_CONNECTED_ITEM*>( a );
802 BOARD_CONNECTED_ITEM* bc = dynamic_cast<BOARD_CONNECTED_ITEM*>( b );
803 ZONE* zone = dynamic_cast<ZONE*>( a );
804 PAD* pad = dynamic_cast<PAD*>( b );
805 FOOTPRINT* aFP = dynamic_cast<FOOTPRINT*>( a );
806 FOOTPRINT* bFP = dynamic_cast<FOOTPRINT*>( b );
807 DRC_CONSTRAINT constraint;
808 int clearance = 0;
809
810 bool compileError = false;
811 bool courtyardError = false;
812 std::unique_ptr<DRC_ENGINE> drcEngine = makeDRCEngine( &compileError, &courtyardError );
813
814 if( copperIntersection.any() && zone && pad && zone->GetNetCode() == pad->GetNetCode() )
815 {
817
818 if( zone->IsOnLayer( active ) )
819 layer = active;
820 else if( zone->GetLayerSet().count() > 0 )
821 layer = zone->GetLayerSet().Seq().front();
822
823 r = dialog->AddHTMLPage( _( "Zone" ) );
824 reportHeader( _( "Zone connection resolution for:" ), a, b, layer, r );
825
826 constraint = drcEngine->EvalZoneConnection( pad, zone, layer, r );
827
828 if( constraint.m_ZoneConnection == ZONE_CONNECTION::THERMAL )
829 {
830 r->Report( "" );
831 r->Report( "" );
832 reportHeader( _( "Thermal-relief gap resolution for:" ), a, b, layer, r );
833
834 constraint = drcEngine->EvalRules( THERMAL_RELIEF_GAP_CONSTRAINT, pad, zone, layer, r );
835 int gap = constraint.m_Value.Min();
836
837 if( compileError )
839
840 r->Report( "" );
841 r->Report( wxString::Format( _( "Resolved thermal relief gap: %s." ),
842 m_frame->StringFromValue( gap, true ) ) );
843
844 r->Report( "" );
845 r->Report( "" );
846 reportHeader( _( "Thermal-relief spoke width resolution for:" ), a, b, layer, r );
847
848 constraint = drcEngine->EvalRules( THERMAL_SPOKE_WIDTH_CONSTRAINT, pad, zone, layer, r );
849 int width = constraint.m_Value.Opt();
850
851 if( compileError )
853
854 r->Report( "" );
855 r->Report( wxString::Format( _( "Resolved spoke width: %s." ),
856 m_frame->StringFromValue( width, true ) ) );
857
858 r->Report( "" );
859 r->Report( "" );
860 reportHeader( _( "Thermal-relief min spoke count resolution for:" ), a, b, layer, r );
861
862 constraint = drcEngine->EvalRules( MIN_RESOLVED_SPOKES_CONSTRAINT, pad, zone, layer, r );
863 int minSpokes = constraint.m_Value.Min();
864
865 if( compileError )
867
868 r->Report( "" );
869 r->Report( wxString::Format( _( "Resolved min spoke count: %d." ),
870 minSpokes ) );
871
872 std::shared_ptr<CONNECTIVITY_DATA> connectivity = pad->GetBoard()->GetConnectivity();
873 }
874 else if( constraint.m_ZoneConnection == ZONE_CONNECTION::NONE )
875 {
876 r->Report( "" );
877 r->Report( "" );
878 reportHeader( _( "Zone clearance resolution for:" ), a, b, layer, r );
879
880 clearance = zone->GetLocalClearance().value();
881 r->Report( "" );
882 r->Report( wxString::Format( _( "Zone clearance: %s." ),
883 m_frame->StringFromValue( clearance, true ) ) );
884
885 constraint = drcEngine->EvalRules( PHYSICAL_CLEARANCE_CONSTRAINT, pad, zone, layer, r );
886
887 if( constraint.m_Value.Min() > clearance )
888 {
889 clearance = constraint.m_Value.Min();
890
891 r->Report( "" );
892 r->Report( wxString::Format( _( "Overridden by larger physical clearance from %s;"
893 "clearance: %s." ),
894 EscapeHTML( constraint.GetName() ),
895 m_frame->StringFromValue( clearance, true ) ) );
896 }
897
898 if( !pad->FlashLayer( layer ) )
899 {
900 constraint = drcEngine->EvalRules( PHYSICAL_HOLE_CLEARANCE_CONSTRAINT, pad, zone,
901 layer, r );
902
903 if( constraint.m_Value.Min() > clearance )
904 {
905 clearance = constraint.m_Value.Min();
906
907 r->Report( "" );
908 r->Report( wxString::Format( _( "Overridden by larger physical hole clearance "
909 "from %s; clearance: %s." ),
910 EscapeHTML( constraint.GetName() ),
911 m_frame->StringFromValue( clearance, true ) ) );
912 }
913 }
914
915 if( compileError )
917
918 r->Report( "" );
919 r->Report( wxString::Format( _( "Resolved min clearance: %s." ),
920 m_frame->StringFromValue( clearance, true ) ) );
921 }
922 else
923 {
924 r->Report( "" );
925 r->Report( "" );
926 reportHeader( _( "Zone clearance resolution for:" ), a, b, layer, r );
927
928 if( compileError )
930
931 // Report a 0 clearance for solid connections
932 r->Report( "" );
933 r->Report( wxString::Format( _( "Resolved min clearance: %s." ),
934 m_frame->StringFromValue( 0, true ) ) );
935 }
936
937 r->Flush();
938 }
939 else if( copperIntersection.any() && !aFP && !bFP )
940 {
941 PCB_LAYER_ID layer = active;
942
943 if( !copperIntersection.test( layer ) )
944 layer = copperIntersection.Seq().front();
945
946 r = dialog->AddHTMLPage( m_frame->GetBoard()->GetLayerName( layer ) );
947 reportHeader( _( "Clearance resolution for:" ), a, b, layer, r );
948
949 if( ac && bc && ac->GetNetCode() > 0 && ac->GetNetCode() == bc->GetNetCode() )
950 {
951 // Same nets....
952 r->Report( _( "Items belong to the same net. Min clearance is 0." ) );
953 }
954 else
955 {
956 // Different nets (or one or both unconnected)....
957 constraint = drcEngine->EvalRules( CLEARANCE_CONSTRAINT, a, b, layer, r );
958 clearance = constraint.m_Value.Min();
959
960 if( compileError )
962
963 r->Report( "" );
964
965 if( constraint.IsNull() )
966 {
967 r->Report( _( "Min clearance is 0." ) );
968 }
969 else if( clearance < 0 )
970 {
971 r->Report( wxString::Format( _( "Resolved clearance: %s; clearance will not be "
972 "tested." ),
973 m_frame->StringFromValue( clearance, true ) ) );
974 }
975 else
976 {
977 r->Report( wxString::Format( _( "Resolved min clearance: %s." ),
978 m_frame->StringFromValue( clearance, true ) ) );
979 }
980 }
981
982 r->Flush();
983 }
984
985 if( ac && bc )
986 {
987 NETINFO_ITEM* refNet = ac->GetNet();
988 wxString coupledNet;
989 wxString dummy;
990
991 if( DRC_ENGINE::MatchDpSuffix( refNet->GetNetname(), coupledNet, dummy )
992 && bc->GetNetname() == coupledNet )
993 {
994 r = dialog->AddHTMLPage( _( "Diff Pair" ) );
995 reportHeader( _( "Diff-pair gap resolution for:" ), ac, bc, active, r );
996
997 constraint = drcEngine->EvalRules( DIFF_PAIR_GAP_CONSTRAINT, ac, bc, active, r );
998
999 r->Report( "" );
1000 r->Report( wxString::Format( _( "Resolved gap constraints: min %s; opt %s; max %s." ),
1001 reportMin( m_frame, constraint ),
1002 reportOpt( m_frame, constraint ),
1003 reportMax( m_frame, constraint ) ) );
1004
1005 r->Report( "" );
1006 r->Report( "" );
1007 r->Report( "" );
1008 reportHeader( _( "Diff-pair max uncoupled length resolution for:" ), ac, bc,
1009 active, r );
1010
1011 if( !drcEngine->HasRulesForConstraintType( MAX_UNCOUPLED_CONSTRAINT ) )
1012 {
1013 r->Report( "" );
1014 r->Report( _( "No 'diff_pair_uncoupled' constraints defined." ) );
1015 }
1016 else
1017 {
1018 constraint = drcEngine->EvalRules( MAX_UNCOUPLED_CONSTRAINT, ac, bc, active, r );
1019
1020 r->Report( "" );
1021 r->Report( wxString::Format( _( "Resolved max uncoupled length: %s." ),
1022 reportMax( m_frame, constraint ) ) );
1023 }
1024 r->Flush();
1025 }
1026 }
1027
1028 auto isOnCorrespondingLayer=
1029 [&]( BOARD_ITEM* aItem, PCB_LAYER_ID aLayer, wxString* aWarning )
1030 {
1031 if( aItem->IsOnLayer( aLayer ) )
1032 return true;
1033
1034 PCB_LAYER_ID correspondingMask = IsFrontLayer( aLayer ) ? F_Mask : B_Mask;
1035 PCB_LAYER_ID correspondingCopper = IsFrontLayer( aLayer ) ? F_Cu : B_Cu;
1036
1037 if( aItem->IsOnLayer( aLayer ) )
1038 return true;
1039
1040 if( aItem->IsOnLayer( correspondingMask ) )
1041 return true;
1042
1043 if( aItem->IsTented( correspondingMask ) && aItem->IsOnLayer( correspondingCopper ) )
1044 {
1045 *aWarning = wxString::Format( _( "Note: %s is tented; clearance will only be "
1046 "applied to holes." ),
1047 getItemDescription( aItem ) );
1048 return true;
1049 }
1050
1051 return false;
1052 };
1053
1054 for( PCB_LAYER_ID layer : { F_SilkS, B_SilkS } )
1055 {
1056 wxString warning;
1057
1058 if( ( a->IsOnLayer( layer ) && isOnCorrespondingLayer( b, layer, &warning ) )
1059 || ( b->IsOnLayer( layer ) && isOnCorrespondingLayer( a, layer, &warning ) ) )
1060 {
1061 r = dialog->AddHTMLPage( m_frame->GetBoard()->GetLayerName( layer ) );
1062 reportHeader( _( "Silkscreen clearance resolution for:" ), a, b, layer, r );
1063
1064 constraint = drcEngine->EvalRules( SILK_CLEARANCE_CONSTRAINT, a, b, layer, r );
1065 clearance = constraint.m_Value.Min();
1066
1067 if( compileError )
1068 reportCompileError( r );
1069
1070 r->Report( "" );
1071
1072 if( !warning.IsEmpty() )
1073 r->Report( warning );
1074
1075 r->Report( wxString::Format( _( "Resolved min clearance: %s." ),
1076 m_frame->StringFromValue( clearance, true ) ) );
1077
1078 r->Flush();
1079 }
1080 }
1081
1082 for( PCB_LAYER_ID layer : { F_CrtYd, B_CrtYd } )
1083 {
1084 bool aCourtyard = aFP && !aFP->GetCourtyard( layer ).IsEmpty();
1085 bool bCourtyard = bFP && !bFP->GetCourtyard( layer ).IsEmpty();
1086
1087 if( aCourtyard && bCourtyard )
1088 {
1089 r = dialog->AddHTMLPage( m_frame->GetBoard()->GetLayerName( layer ) );
1090 reportHeader( _( "Courtyard clearance resolution for:" ), a, b, layer, r );
1091
1092 constraint = drcEngine->EvalRules( COURTYARD_CLEARANCE_CONSTRAINT, a, b, layer, r );
1093 clearance = constraint.m_Value.Min();
1094
1095 if( compileError )
1096 reportCompileError( r );
1097
1098 r->Report( "" );
1099 r->Report( wxString::Format( _( "Resolved min clearance: %s." ),
1100 m_frame->StringFromValue( clearance, true ) ) );
1101
1102 r->Flush();
1103 }
1104 }
1105
1106 if( a->HasHole() || b->HasHole() )
1107 {
1109 bool pageAdded = false;
1110
1111 if( a->HasHole() && b->IsOnLayer( active ) && IsCopperLayer( active ) )
1112 layer = active;
1113 else if( b->HasHole() && a->IsOnLayer( active ) && IsCopperLayer( active ) )
1114 layer = active;
1115 else if( a->HasHole() && b->IsOnCopperLayer() )
1116 layer = b->GetLayer();
1117 else if( b->HasHole() && b->IsOnCopperLayer() )
1118 layer = a->GetLayer();
1119
1120 if( layer >= 0 )
1121 {
1122 if( !pageAdded )
1123 {
1124 r = dialog->AddHTMLPage( _( "Hole" ) );
1125 pageAdded = true;
1126 }
1127 else
1128 {
1129 r->Report( "" );
1130 r->Report( "" );
1131 r->Report( "" );
1132 }
1133
1134 reportHeader( _( "Hole clearance resolution for:" ), a, b, layer, r );
1135
1136 constraint = drcEngine->EvalRules( HOLE_CLEARANCE_CONSTRAINT, a, b, layer, r );
1137 clearance = constraint.m_Value.Min();
1138
1139 if( compileError )
1140 reportCompileError( r );
1141
1142 r->Report( "" );
1143 r->Report( wxString::Format( _( "Resolved min clearance: %s." ),
1144 m_frame->StringFromValue( clearance, true ) ) );
1145
1146 r->Flush();
1147 }
1148
1149 if( a->HasDrilledHole() || b->HasDrilledHole() )
1150 {
1151 if( !pageAdded )
1152 {
1153 r = dialog->AddHTMLPage( _( "Hole" ) );
1154 pageAdded = true;
1155 }
1156 else
1157 {
1158 r->Report( "" );
1159 r->Report( "" );
1160 r->Report( "" );
1161 }
1162
1163 reportHeader( _( "Hole-to-hole clearance resolution for:" ), a, b, r );
1164
1165 constraint = drcEngine->EvalRules( HOLE_TO_HOLE_CONSTRAINT, a, b, UNDEFINED_LAYER, r );
1166 clearance = constraint.m_Value.Min();
1167
1168 if( compileError )
1169 reportCompileError( r );
1170
1171 r->Report( "" );
1172 r->Report( wxString::Format( _( "Resolved min clearance: %s." ),
1173 m_frame->StringFromValue( clearance, true ) ) );
1174
1175 r->Flush();
1176 }
1177 }
1178
1179 for( PCB_LAYER_ID edgeLayer : { Edge_Cuts, Margin } )
1180 {
1182
1183 if( a->IsOnLayer( edgeLayer ) && b->Type() != PCB_FOOTPRINT_T )
1184 {
1185 if( b->IsOnLayer( active ) && IsCopperLayer( active ) )
1186 layer = active;
1187 else if( IsCopperLayer( b->GetLayer() ) )
1188 layer = b->GetLayer();
1189 }
1190 else if( b->IsOnLayer( edgeLayer ) && a->Type() != PCB_FOOTPRINT_T )
1191 {
1192 if( a->IsOnLayer( active ) && IsCopperLayer( active ) )
1193 layer = active;
1194 else if( IsCopperLayer( a->GetLayer() ) )
1195 layer = a->GetLayer();
1196 }
1197
1198 if( layer >= 0 )
1199 {
1200 wxString layerName = m_frame->GetBoard()->GetLayerName( edgeLayer );
1201 r = dialog->AddHTMLPage( layerName + wxS( " " ) + _( "Clearance" ) );
1202 reportHeader( _( "Edge clearance resolution for:" ), a, b, layer, r );
1203
1204 constraint = drcEngine->EvalRules( EDGE_CLEARANCE_CONSTRAINT, a, b, layer, r );
1205 clearance = constraint.m_Value.Min();
1206
1207 if( compileError )
1208 reportCompileError( r );
1209
1210 r->Report( "" );
1211 r->Report( wxString::Format( _( "Resolved min clearance: %s." ),
1212 m_frame->StringFromValue( clearance, true ) ) );
1213
1214 r->Flush();
1215 }
1216 }
1217
1218 r = dialog->AddHTMLPage( _( "Physical Clearances" ) );
1219
1220 auto reportPhysicalClearance =
1221 [&]( PCB_LAYER_ID aLayer )
1222 {
1223 reportHeader( _( "Physical clearance resolution for:" ), a, b, aLayer, r );
1224
1225 constraint = drcEngine->EvalRules( PHYSICAL_CLEARANCE_CONSTRAINT, a, b, aLayer, r );
1226 clearance = constraint.m_Value.Min();
1227
1228 if( compileError )
1229 {
1230 reportCompileError( r );
1231 }
1232 else if( !drcEngine->HasRulesForConstraintType( PHYSICAL_CLEARANCE_CONSTRAINT ) )
1233 {
1234 r->Report( "" );
1235 r->Report( _( "No 'physical_clearance' constraints defined." ) );
1236 }
1237 else
1238 {
1239 r->Report( "" );
1240 r->Report( wxString::Format( _( "Resolved min clearance: %s." ),
1241 m_frame->StringFromValue( clearance, true ) ) );
1242 }
1243
1244 r->Report( "" );
1245 r->Report( "" );
1246 r->Report( "" );
1247 };
1248
1249 if( layerIntersection.any() )
1250 {
1251 PCB_LAYER_ID layer = active;
1252
1253 if( !layerIntersection.test( layer ) )
1254 layer = layerIntersection.Seq().front();
1255
1256 reportPhysicalClearance( layer );
1257 }
1258
1259 if( aFP && b->IsOnLayer( Edge_Cuts ) )
1260 {
1261 if( !aFP->GetCourtyard( F_CrtYd ).IsEmpty() )
1262 reportPhysicalClearance( F_CrtYd );
1263
1264 if( !aFP->GetCourtyard( B_CrtYd ).IsEmpty() )
1265 reportPhysicalClearance( B_CrtYd );
1266 }
1267 else if( bFP && a->IsOnLayer( Edge_Cuts ) )
1268 {
1269 if( !bFP->GetCourtyard( F_CrtYd ).IsEmpty() )
1270 reportPhysicalClearance( F_CrtYd );
1271
1272 if( !bFP->GetCourtyard( B_CrtYd ).IsEmpty() )
1273 reportPhysicalClearance( B_CrtYd );
1274 }
1275
1276 if( a->HasHole() || b->HasHole() )
1277 {
1278 PCB_LAYER_ID layer;
1279
1280 if( a->HasHole() && b->IsOnLayer( active ) )
1281 layer = active;
1282 else if( b->HasHole() && a->IsOnLayer( active ) )
1283 layer = active;
1284 else if( a->HasHole() )
1285 layer = b->GetLayer();
1286 else
1287 layer = a->GetLayer();
1288
1289 reportHeader( _( "Physical hole clearance resolution for:" ), a, b, layer, r );
1290
1291 constraint = drcEngine->EvalRules( PHYSICAL_HOLE_CLEARANCE_CONSTRAINT, a, b, layer, r );
1292 clearance = constraint.m_Value.Min();
1293
1294 if( compileError )
1295 {
1296 reportCompileError( r );
1297 }
1298 else if( !drcEngine->HasRulesForConstraintType( PHYSICAL_HOLE_CLEARANCE_CONSTRAINT ) )
1299 {
1300 r->Report( "" );
1301 r->Report( _( "No 'physical_hole_clearance' constraints defined." ) );
1302 }
1303 else
1304 {
1305 r->Report( "" );
1306 r->Report( wxString::Format( _( "Resolved min clearance: %s." ),
1307 m_frame->StringFromValue( clearance, true ) ) );
1308 }
1309 }
1310
1311 r->Flush();
1312
1313 dialog->Raise();
1314 dialog->Show( true );
1315 return 0;
1316}
1317
1318
1320{
1321#define EVAL_RULES( constraint, a, b, layer, r ) drcEngine->EvalRules( constraint, a, b, layer, r )
1322
1323 wxCHECK( m_frame, 0 );
1324
1326
1327 wxCHECK( selTool, 0 );
1328
1329 const PCB_SELECTION& selection = selTool->GetSelection();
1330
1331 if( selection.Size() != 1 )
1332 {
1333 m_frame->ShowInfoBarError( _( "Select an item for a constraints resolution report." ) );
1334 return 0;
1335 }
1336
1338
1339 wxCHECK( dialog, 0 );
1340
1341 dialog->DeleteAllPages();
1342
1343 if( !selection.GetItem( 0 )->IsBOARD_ITEM() )
1344 return 0;
1345
1346 BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.GetItem( 0 ) );
1347 DRC_CONSTRAINT constraint;
1348
1349 bool compileError = false;
1350 bool courtyardError = false;
1351 std::unique_ptr<DRC_ENGINE> drcEngine = makeDRCEngine( &compileError, &courtyardError );
1352
1353 WX_HTML_REPORT_BOX* r = nullptr;
1354
1355 if( item->Type() == PCB_TRACE_T )
1356 {
1357 r = dialog->AddHTMLPage( _( "Track Width" ) );
1358 reportHeader( _( "Track width resolution for:" ), item, r );
1359
1360 constraint = EVAL_RULES( TRACK_WIDTH_CONSTRAINT, item, nullptr, item->GetLayer(), r );
1361
1362 if( compileError )
1363 reportCompileError( r );
1364
1365 r->Report( "" );
1366 r->Report( wxString::Format( _( "Resolved width constraints: min %s; opt %s; max %s." ),
1367 reportMin( m_frame, constraint ),
1368 reportOpt( m_frame, constraint ),
1369 reportMax( m_frame, constraint ) ) );
1370
1371 r->Flush();
1372 }
1373
1374 if( item->Type() == PCB_VIA_T )
1375 {
1376 r = dialog->AddHTMLPage( _( "Via Diameter" ) );
1377 reportHeader( _( "Via diameter resolution for:" ), item, r );
1378
1379 // PADSTACKS TODO: once we have padstacks we'll need to run this per-layer....
1380 constraint = EVAL_RULES( VIA_DIAMETER_CONSTRAINT, item, nullptr, UNDEFINED_LAYER, r );
1381
1382 if( compileError )
1383 reportCompileError( r );
1384
1385 r->Report( "" );
1386 r->Report( wxString::Format( _( "Resolved diameter constraints: min %s; opt %s; max %s." ),
1387 reportMin( m_frame, constraint ),
1388 reportOpt( m_frame, constraint ),
1389 reportMax( m_frame, constraint ) ) );
1390
1391 r->Flush();
1392
1393 r = dialog->AddHTMLPage( _( "Via Annular Width" ) );
1394 reportHeader( _( "Via annular width resolution for:" ), item, r );
1395
1396 // PADSTACKS TODO: once we have padstacks we'll need to run this per-layer....
1397 constraint = EVAL_RULES( ANNULAR_WIDTH_CONSTRAINT, item, nullptr, UNDEFINED_LAYER, r );
1398
1399 if( compileError )
1400 reportCompileError( r );
1401
1402 r->Report( "" );
1403 r->Report( wxString::Format( _( "Resolved annular width constraints: min %s; opt %s; max %s." ),
1404 reportMin( m_frame, constraint ),
1405 reportOpt( m_frame, constraint ),
1406 reportMax( m_frame, constraint ) ) );
1407
1408 r->Flush();
1409 }
1410
1411 if( ( item->Type() == PCB_PAD_T && static_cast<PAD*>( item )->GetDrillSize().x > 0 )
1412 || item->Type() == PCB_VIA_T )
1413 {
1414 r = dialog->AddHTMLPage( _( "Hole Size" ) );
1415 reportHeader( _( "Hole size resolution for:" ), item, r );
1416
1417 // PADSTACKS TODO: once we have padstacks we'll need to run this per-layer....
1418 constraint = EVAL_RULES( HOLE_SIZE_CONSTRAINT, item, nullptr, UNDEFINED_LAYER, r );
1419
1420 if( compileError )
1421 reportCompileError( r );
1422
1423 r->Report( "" );
1424 r->Report( wxString::Format( _( "Resolved hole size constraints: min %s; opt %s; max %s." ),
1425 reportMin( m_frame, constraint ),
1426 reportOpt( m_frame, constraint ),
1427 reportMax( m_frame, constraint ) ) );
1428
1429 r->Flush();
1430 }
1431
1432 if( item->Type() == PCB_FIELD_T || item->Type() == PCB_TEXT_T || item->Type() == PCB_TEXTBOX_T )
1433 {
1434 r = dialog->AddHTMLPage( _( "Text Size" ) );
1435 reportHeader( _( "Text height resolution for:" ), item, r );
1436
1437 constraint = EVAL_RULES( TEXT_HEIGHT_CONSTRAINT, item, nullptr, UNDEFINED_LAYER, r );
1438
1439 if( compileError )
1440 reportCompileError( r );
1441
1442 r->Report( "" );
1443 r->Report( wxString::Format( _( "Resolved height constraints: min %s; opt %s; max %s." ),
1444 reportMin( m_frame, constraint ),
1445 reportOpt( m_frame, constraint ),
1446 reportMax( m_frame, constraint ) ) );
1447
1448 r->Report( "" );
1449 r->Report( "" );
1450 r->Report( "" );
1451 reportHeader( _( "Text thickness resolution for:" ), item, r );
1452
1453 constraint = EVAL_RULES( TEXT_THICKNESS_CONSTRAINT, item, nullptr, UNDEFINED_LAYER, r );
1454
1455 if( compileError )
1456 reportCompileError( r );
1457
1458 r->Report( "" );
1459 r->Report( wxString::Format( _( "Resolved thickness constraints: min %s; opt %s; max %s." ),
1460 reportMin( m_frame, constraint ),
1461 reportOpt( m_frame, constraint ),
1462 reportMax( m_frame, constraint ) ) );
1463
1464 r->Flush();
1465 }
1466
1467 r = dialog->AddHTMLPage( _( "Keepouts" ) );
1468 reportHeader( _( "Keepout resolution for:" ), item, r );
1469
1470 constraint = EVAL_RULES( DISALLOW_CONSTRAINT, item, nullptr, item->GetLayer(), r );
1471
1472 if( compileError )
1473 reportCompileError( r );
1474
1475 if( courtyardError )
1476 {
1477 r->Report( "" );
1478 r->Report( _( "Report may be incomplete: some footprint courtyards are malformed." )
1479 + wxS( "&nbsp;&nbsp;" )
1480 + wxS( "<a href='$DRC'>" ) + _( "Run DRC for a full analysis." )
1481 + wxS( "</a>" ) );
1482 }
1483
1484 r->Report( "" );
1485
1486 if( constraint.m_DisallowFlags )
1487 r->Report( _( "Item <b>disallowed</b> at current location." ) );
1488 else
1489 r->Report( _( "Item allowed at current location." ) );
1490
1491 r->Flush();
1492
1493 r = dialog->AddHTMLPage( _( "Assertions" ) );
1494 reportHeader( _( "Assertions for:" ), item, r );
1495
1496 if( compileError )
1497 reportCompileError( r );
1498
1499 if( courtyardError )
1500 {
1501 r->Report( "" );
1502 r->Report( _( "Report may be incomplete: some footprint courtyards are malformed." )
1503 + wxS( "&nbsp;&nbsp;" )
1504 + wxS( "<a href='$DRC'>" ) + _( "Run DRC for a full analysis." )
1505 + wxS( "</a>" ) );
1506 }
1507
1508 drcEngine->ProcessAssertions( item, []( const DRC_CONSTRAINT* c ){}, r );
1509 r->Flush();
1510
1511 dialog->Raise();
1512 dialog->Show( true );
1513 return 0;
1514}
1515
1516
1518{
1519 wxCHECK( m_frame, 0 );
1520
1522
1523 wxCHECK( selTool, 0 );
1524
1525 const PCB_SELECTION& selection = selTool->RequestSelection(
1526 []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
1527 {
1528 // Iterate from the back so we don't have to worry about removals.
1529 for( int i = aCollector.GetCount() - 1; i >= 0; --i )
1530 {
1531 BOARD_ITEM* item = aCollector[ i ];
1532
1533 if( !dynamic_cast<FOOTPRINT*>( item ) )
1534 aCollector.Remove( item );
1535 }
1536 },
1537 false /* ignore locked flag */ );
1538
1539 if( selection.Size() == 1 )
1540 DiffFootprint( static_cast<FOOTPRINT*>( selection.GetItem( 0 ) ) );
1541 else
1542 m_frame->ShowInfoBarError( _( "Select a footprint to diff with its library equivalent." ) );
1543
1544 return 0;
1545}
1546
1547
1549{
1550 wxCHECK( m_frame, 0 );
1551
1553
1554 wxCHECK( selTool, 0 );
1555
1556 const PCB_SELECTION& selection = selTool->GetSelection();
1557
1558 if( selection.Size() != 1 || selection.Front()->Type() != PCB_FOOTPRINT_T )
1559 {
1560 m_frame->ShowInfoBarError( _( "Select a footprint for a footprint associations report." ) );
1561 return 0;
1562 }
1563
1565
1566 dlg.ShowModal();
1567
1568 return 0;
1569}
1570
1571
1573{
1575
1576 wxCHECK( dialog, /* void */ );
1577
1578 dialog->DeleteAllPages();
1579
1580 LIB_ID fpID = aFootprint->GetFPID();
1581 wxString libName = fpID.GetLibNickname();
1582 wxString fpName = fpID.GetLibItemName();
1583 WX_HTML_REPORT_BOX* r = nullptr;
1584
1585 r = dialog->AddHTMLPage( _( "Summary" ) );
1586
1587 r->Report( wxS( "<h7>" ) + _( "Board vs library diff for:" ) + wxS( "</h7>" ) );
1588 r->Report( wxS( "<ul><li>" ) + EscapeHTML( getItemDescription( aFootprint ) ) + wxS( "</li>" )
1589 + wxS( "<li>" ) + _( "Library: " ) + EscapeHTML( libName ) + wxS( "</li>" )
1590 + wxS( "<li>" ) + _( "Library item: " ) + EscapeHTML( fpName ) + wxS( "</li></ul>" ) );
1591
1592 r->Report( "" );
1593
1594 PROJECT* project = aFootprint->GetBoard()->GetProject();
1596 const LIB_TABLE_ROW* libTableRow = nullptr;
1597
1598 try
1599 {
1600 libTableRow = libTable->FindRow( libName );
1601 }
1602 catch( const IO_ERROR& )
1603 {
1604 }
1605
1606 if( !libTableRow )
1607 {
1608 r->Report( _( "The library is not included in the current configuration." )
1609 + wxS( "&nbsp;&nbsp;&nbsp" )
1610 + wxS( "<a href='$CONFIG'>" ) + _( "Manage Footprint Libraries" )
1611 + wxS( "</a>" ) );
1612
1613 }
1614 else if( !libTable->HasLibrary( libName, true ) )
1615 {
1616 r->Report( _( "The library is not enabled in the current configuration." )
1617 + wxS( "&nbsp;&nbsp;&nbsp" )
1618 + wxS( "<a href='$CONFIG'>" ) + _( "Manage Footprint Libraries" )
1619 + wxS( "</a>" ) );
1620
1621 }
1622 else
1623 {
1624 std::shared_ptr<FOOTPRINT> libFootprint;
1625
1626 try
1627 {
1628 libFootprint.reset( libTable->FootprintLoad( libName, fpName, true ) );
1629 }
1630 catch( const IO_ERROR& )
1631 {
1632 }
1633
1634 if( !libFootprint )
1635 {
1636 r->Report( wxString::Format( _( "The library no longer contains the item %s." ),
1637 fpName) );
1638 }
1639 else
1640 {
1641 if( !aFootprint->FootprintNeedsUpdate( libFootprint.get(), 0, r ) )
1642 r->Report( _( "No relevant differences detected." ) );
1643
1644 wxPanel* panel = dialog->AddBlankPage( _( "Visual" ) );
1646
1647 diff->DisplayDiff( aFootprint, libFootprint );
1648 }
1649 }
1650
1651 r->Flush();
1652
1653 dialog->Raise();
1654 dialog->Show( true );
1655}
1656
1657
1659{
1660 wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
1661
1662 FOOTPRINT_DIFF_WIDGET* diffWidget = new FOOTPRINT_DIFF_WIDGET( aParentPanel, m_frame->Kiway() );
1663
1664 sizer->Add( diffWidget, 1, wxEXPAND | wxALL, 5 );
1665 aParentPanel->SetSizer( sizer );
1666 aParentPanel->Layout();
1667
1668 return diffWidget;
1669}
1670
1671
1673{
1674 BOARD_ITEM* item = aEvent.Parameter<BOARD_ITEM*>();
1675
1676 m_frame->m_probingSchToPcb = true; // recursion guard
1677 {
1679
1680 if( item )
1682 }
1683 m_frame->m_probingSchToPcb = false;
1684
1685 bool request3DviewRedraw = frame()->GetPcbNewSettings()->m_Display.m_Live3DRefresh;
1686
1687 if( item && item->Type() != PCB_FOOTPRINT_T )
1688 request3DviewRedraw = false;
1689
1690 // Update 3D viewer highlighting
1691 if( request3DviewRedraw )
1692 m_frame->Update3DView( false, true );
1693
1694 return 0;
1695}
1696
1697
1698 bool BOARD_INSPECTION_TOOL::highlightNet( const VECTOR2D& aPosition, bool aUseSelection )
1699{
1700 BOARD* board = static_cast<BOARD*>( m_toolMgr->GetModel() );
1703
1704 int net = -1;
1705 bool enableHighlight = false;
1706
1707 if( aUseSelection )
1708 {
1709 const PCB_SELECTION& selection = selectionTool->GetSelection();
1710 std::set<int> netcodes;
1711
1712 for( EDA_ITEM* item : selection )
1713 {
1714 if( BOARD_CONNECTED_ITEM* ci = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
1715 netcodes.insert( ci->GetNetCode() );
1716 }
1717
1718 enableHighlight = !netcodes.empty();
1719
1720 if( enableHighlight && netcodes.size() > 1 )
1721 {
1722 // If we are doing a multi-highlight, cross-probing back and other stuff is not
1723 // yet supported
1724 settings->SetHighlight( netcodes );
1726
1727 for( int multiNet : netcodes )
1728 board->SetHighLightNet( multiNet, true );
1729
1730 board->HighLightON();
1732 m_currentlyHighlighted = netcodes;
1733 return true;
1734 }
1735 else if( enableHighlight )
1736 {
1737 net = *netcodes.begin();
1738 }
1739 }
1740
1741 // If we didn't get a net to highlight from the selection, use the cursor
1742 if( net < 0 )
1743 {
1745 guide.SetIgnoreZoneFills( false );
1746
1747 PCB_LAYER_ID activeLayer = static_cast<PCB_LAYER_ID>( view()->GetTopLayer() );
1748 guide.SetPreferredLayer( activeLayer );
1749
1750 GENERAL_COLLECTOR collector;
1751 collector.Collect( board, { PCB_PAD_T, PCB_VIA_T, PCB_TRACE_T, PCB_ARC_T, PCB_SHAPE_T }, aPosition,
1752 guide );
1753
1754 if( collector.GetCount() == 0 )
1755 collector.Collect( board, { PCB_ZONE_T }, aPosition, guide );
1756
1757 // Apply the active selection filter, except we want to allow picking locked items for
1758 // highlighting even if the user has disabled them for selection
1759 PCB_SELECTION_FILTER_OPTIONS& filter = selectionTool->GetFilter();
1760
1761 bool saved = filter.lockedItems;
1762 filter.lockedItems = true;
1763
1764 selectionTool->FilterCollectedItems( collector, true );
1765
1766 filter.lockedItems = saved;
1767
1768 // Clear the previous highlight
1769 //m_frame->SendMessageToEESCHEMA( nullptr );
1770
1771 bool highContrast = settings->GetHighContrast();
1772 PCB_LAYER_ID contrastLayer = settings->GetPrimaryHighContrastLayer();
1773
1774 for( int i = collector.GetCount() - 1; i >= 0; i-- )
1775 {
1776 LSET itemLayers = collector[i]->GetLayerSet();
1777
1778 if( ( itemLayers & LSET::AllCuMask() ).none() ||
1779 ( highContrast && !itemLayers.Contains( contrastLayer ) ) )
1780 {
1781 collector.Remove( i );
1782 continue;
1783 }
1784 }
1785
1786 enableHighlight = ( collector.GetCount() > 0 );
1787
1788 // Obtain net code for the clicked item
1789 if( enableHighlight )
1790 {
1791 BOARD_CONNECTED_ITEM* targetItem = static_cast<BOARD_CONNECTED_ITEM*>( collector[0] );
1792
1793 if( targetItem->Type() == PCB_PAD_T )
1794 m_frame->SendCrossProbeItem( targetItem );
1795
1796 net = targetItem->GetNetCode();
1797 }
1798 }
1799
1800 const std::set<int>& netcodes = settings->GetHighlightNetCodes();
1801
1802 // Toggle highlight when the same net was picked
1803 if( !aUseSelection && netcodes.size() == 1 && netcodes.contains( net ) )
1804 enableHighlight = !settings->IsHighlightEnabled();
1805
1806 if( enableHighlight != settings->IsHighlightEnabled() || !netcodes.count( net ) )
1807 {
1808 if( !netcodes.empty() )
1809 m_lastHighlighted = netcodes;
1810
1811 settings->SetHighlight( enableHighlight, net );
1812 m_toolMgr->GetView()->UpdateAllLayersColor();
1813 }
1814
1815 // Store the highlighted netcode in the current board (for dialogs for instance)
1816 if( enableHighlight && net >= 0 )
1817 {
1818 m_currentlyHighlighted = netcodes;
1819 board->SetHighLightNet( net );
1820 board->HighLightON();
1821
1822 NETINFO_ITEM* netinfo = board->FindNet( net );
1823
1824 if( netinfo )
1825 {
1826 std::vector<MSG_PANEL_ITEM> items;
1827 netinfo->GetMsgPanelInfo( m_frame, items );
1828 m_frame->SetMsgPanel( items );
1829 m_frame->SendCrossProbeNetName( netinfo->GetNetname() );
1830 }
1831 }
1832 else
1833 {
1834 m_currentlyHighlighted.clear();
1835 board->ResetNetHighLight();
1836 m_frame->SetMsgPanel( board );
1837 m_frame->SendCrossProbeNetName( "" );
1838 }
1839
1840 return true;
1841}
1842
1843
1845{
1846 int netcode = aEvent.Parameter<int>();
1848 const std::set<int>& highlighted = settings->GetHighlightNetCodes();
1849
1850 if( netcode > 0 )
1851 {
1852 m_lastHighlighted = highlighted;
1853 settings->SetHighlight( true, netcode );
1855 m_currentlyHighlighted.clear();
1856 m_currentlyHighlighted.insert( netcode );
1857 }
1858 else if( aEvent.IsAction( &PCB_ACTIONS::highlightNetSelection ) )
1859 {
1860 // Highlight selection (cursor position will be ignored)
1861 highlightNet( getViewControls()->GetMousePosition(), true );
1862 }
1863 else if( aEvent.IsAction( &PCB_ACTIONS::toggleLastNetHighlight ) )
1864 {
1865 std::set<int> temp = highlighted;
1866 settings->SetHighlight( m_lastHighlighted );
1869 m_lastHighlighted = std::move( temp );
1870 }
1871 else if( aEvent.IsAction( &PCB_ACTIONS::toggleNetHighlight ) )
1872 {
1873 bool turnOn = highlighted.empty() && !m_currentlyHighlighted.empty();
1874 settings->SetHighlight( m_currentlyHighlighted, turnOn );
1876 }
1877 else // Highlight the net belonging to the item under the cursor
1878 {
1879 highlightNet( getViewControls()->GetMousePosition(), false );
1880 }
1881
1882 return 0;
1883}
1884
1885
1887{
1888 BOARD* board = static_cast<BOARD*>( m_toolMgr->GetModel() );
1890
1891 m_currentlyHighlighted.clear();
1892 m_lastHighlighted.clear();
1893
1895 settings->SetHighlight( false );
1899 return 0;
1900}
1901
1902
1904{
1906 BOARD* board = getModel<BOARD>();
1907
1908 // Deactivate other tools; particularly important if another PICKER is currently running
1909 Activate();
1910
1911 picker->SetCursor( KICURSOR::BULLSEYE );
1912
1913 picker->SetClickHandler(
1914 [this, board]( const VECTOR2D& pt ) -> bool
1915 {
1917
1921
1922 PCB_SELECTION& selection = selectionTool->GetSelection();
1923
1924 if( selection.Empty() )
1925 {
1928 selection = selectionTool->GetSelection();
1929 }
1930
1931 if( selection.Empty() )
1932 {
1933 // Clear the previous local ratsnest if we click off all items
1934 for( FOOTPRINT* fp : board->Footprints() )
1935 {
1936 for( PAD* pad : fp->Pads() )
1937 pad->SetLocalRatsnestVisible( displayOptions().m_ShowGlobalRatsnest );
1938 }
1939 }
1940 else
1941 {
1942 for( EDA_ITEM* item : selection )
1943 {
1944 if( PAD* pad = dyn_cast<PAD*>( item) )
1945 {
1946 pad->SetLocalRatsnestVisible( !pad->GetLocalRatsnestVisible() );
1947 }
1948 else if( FOOTPRINT* fp = dyn_cast<FOOTPRINT*>( item) )
1949 {
1950 if( !fp->Pads().empty() )
1951 {
1952 bool enable = !fp->Pads()[0]->GetLocalRatsnestVisible();
1953
1954 for( PAD* childPad : fp->Pads() )
1955 childPad->SetLocalRatsnestVisible( enable );
1956 }
1957 }
1958 }
1959 }
1960
1962
1963 return true;
1964 } );
1965
1966 picker->SetFinalizeHandler(
1967 [this, board]( int aCondition )
1968 {
1969 if( aCondition != PCB_PICKER_TOOL::END_ACTIVATE )
1970 {
1971 for( FOOTPRINT* fp : board->Footprints() )
1972 {
1973 for( PAD* pad : fp->Pads() )
1974 pad->SetLocalRatsnestVisible( displayOptions().m_ShowGlobalRatsnest );
1975 }
1976 }
1977 } );
1978
1980
1981 return 0;
1982}
1983
1984
1986{
1987 VECTOR2I delta = aEvent.Parameter<VECTOR2I>();
1988
1989 if( delta == VECTOR2I() )
1990 {
1991 // We can delete the existing map to force a recalculation
1992 delete m_dynamicData;
1993 m_dynamicData = nullptr;
1994 }
1995
1996 auto selectionTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
1997 auto& selection = selectionTool->GetSelection();
1998 auto connectivity = getModel<BOARD>()->GetConnectivity();
1999
2000 if( selection.Empty() )
2001 {
2002 connectivity->ClearLocalRatsnest();
2003 delete m_dynamicData;
2004 m_dynamicData = nullptr;
2005 }
2006 else
2007 {
2009 }
2010
2011 return 0;
2012}
2013
2014
2016{
2017 getModel<BOARD>()->GetConnectivity()->ClearLocalRatsnest();
2018 delete m_dynamicData;
2019 m_dynamicData = nullptr;
2020
2021 return 0;
2022}
2023
2024
2026{
2028 SELECTION& selection = selectionTool->GetSelection();
2029 std::shared_ptr<CONNECTIVITY_DATA> connectivity = board()->GetConnectivity();
2030 std::vector<BOARD_ITEM*> items;
2031 std::deque<EDA_ITEM*> queued_items( selection.begin(), selection.end() );
2032
2033 for( std::size_t i = 0; i < queued_items.size(); ++i )
2034 {
2035 if( !queued_items[i]->IsBOARD_ITEM() )
2036 continue;
2037
2038 BOARD_ITEM* item = static_cast<BOARD_ITEM*>( queued_items[i] );
2039
2040 wxCHECK2( item, continue );
2041
2042 if( item->Type() == PCB_FOOTPRINT_T )
2043 {
2044 for( PAD* pad : static_cast<FOOTPRINT*>( item )->Pads() )
2045 {
2046 if( pad->GetLocalRatsnestVisible() || displayOptions().m_ShowModuleRatsnest )
2047 items.push_back( pad );
2048 }
2049 }
2050 else if( item->Type() == PCB_GROUP_T || item->Type() == PCB_GENERATOR_T )
2051 {
2052 item->RunOnDescendants( [ &queued_items ]( BOARD_ITEM *aItem )
2053 {
2054 queued_items.push_back( aItem );
2055 } );
2056 }
2057 else if( BOARD_CONNECTED_ITEM* boardItem = dyn_cast<BOARD_CONNECTED_ITEM*>( item ) )
2058 {
2059 if( boardItem->GetLocalRatsnestVisible() || displayOptions().m_ShowModuleRatsnest )
2060 items.push_back( boardItem );
2061 }
2062 }
2063
2064 if( items.empty() || std::none_of( items.begin(), items.end(),
2065 []( const BOARD_ITEM* aItem )
2066 {
2067 return( aItem->Type() == PCB_TRACE_T
2068 || aItem->Type() == PCB_PAD_T
2069 || aItem->Type() == PCB_ARC_T
2070 || aItem->Type() == PCB_ZONE_T
2071 || aItem->Type() == PCB_FOOTPRINT_T
2072 || aItem->Type() == PCB_VIA_T
2073 || aItem->Type() == PCB_SHAPE_T );
2074 } ) )
2075 {
2076 return;
2077 }
2078
2079 if( !m_dynamicData )
2080 {
2081 m_dynamicData = new CONNECTIVITY_DATA( board()->GetConnectivity(), items, true );
2082 connectivity->BlockRatsnestItems( items );
2083 }
2084 else
2085 {
2086 m_dynamicData->Move( aDelta );
2087 }
2088
2089 connectivity->ComputeLocalRatsnest( items, m_dynamicData );
2090}
2091
2092
2094{
2095 doHideRatsnestNet( aEvent.Parameter<int>(), true );
2096 return 0;
2097}
2098
2099
2101{
2102 doHideRatsnestNet( aEvent.Parameter<int>(), false );
2103 return 0;
2104}
2105
2106
2107void BOARD_INSPECTION_TOOL::doHideRatsnestNet( int aNetCode, bool aHide )
2108{
2111
2113 SELECTION& selection = selectionTool->GetSelection();
2114
2115 if( aNetCode <= 0 && !selection.Empty() )
2116 {
2117 for( EDA_ITEM* item : selection )
2118 {
2119 if( BOARD_CONNECTED_ITEM* bci = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
2120 {
2121 if( bci->GetNetCode() > 0 )
2122 doHideRatsnestNet( bci->GetNetCode(), aHide );
2123 }
2124 }
2125
2126 return;
2127 }
2128
2129 if( aHide )
2130 rs->GetHiddenNets().insert( aNetCode );
2131 else
2132 rs->GetHiddenNets().erase( aNetCode );
2133
2135 {
2138
2139 m_frame->GetAppearancePanel()->OnNetVisibilityChanged( aNetCode, !aHide );
2140 }
2141}
2142
2143
2145{
2149
2155
2162
2165}
#define EVAL_RULES(constraint, a, b, layer, r)
wxString reportMax(PCB_BASE_FRAME *aFrame, DRC_CONSTRAINT &aConstraint)
bool isNPTHPad(BOARD_ITEM *aItem)
wxString reportMin(PCB_BASE_FRAME *aFrame, DRC_CONSTRAINT &aConstraint)
wxString reportOpt(PCB_BASE_FRAME *aFrame, DRC_CONSTRAINT &aConstraint)
static TOOL_ACTION pickerTool
Definition: actions.h:204
Define the structure of a menu based on ACTIONs.
Definition: action_menu.h:49
void SetTitle(const wxString &aTitle) override
Set title for the menu.
Definition: action_menu.cpp:92
void SetIcon(BITMAPS aIcon)
Assign an icon for the entry.
Definition: action_menu.cpp:78
wxMenuItem * Add(const wxString &aLabel, int aId, BITMAPS aIcon)
Add a wxWidgets-style entry to the menu.
void OnNetVisibilityChanged(int aNetCode, bool aVisibility)
Notifies the panel when a net has been hidden or shown via the external tool.
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
virtual NETCLASS * GetEffectiveNetClass() const
Return the NETCLASS for this item.
NETINFO_ITEM * GetNet() const
Return #NET_INFO object for a given item.
void InspectDRCError(const std::shared_ptr< RC_ITEM > &aDRCItem)
Show the clearance resolution for two selected items.
int HighlightNet(const TOOL_EVENT &aEvent)
Clear all board highlights.
void calculateSelectionRatsnest(const VECTOR2I &aDelta)
< Recalculate dynamic ratsnest for the current selection.
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
int ShowBoardStatistics(const TOOL_EVENT &aEvent)
Show dialog with board statistics.
wxString InspectDRCErrorMenuText(const std::shared_ptr< RC_ITEM > &aDRCItem)
bool highlightNet(const VECTOR2D &aPosition, bool aUseSelection)
Look for a BOARD_CONNECTED_ITEM in a given spot and if one is found - it enables highlight for its ne...
int DiffFootprint(const TOOL_EVENT &aEvent)
int LocalRatsnestTool(const TOOL_EVENT &aEvent)
Hide the ratsnest for a given net.
std::set< int > m_lastHighlighted
bool Init() override
Init() is called once upon a registration of the tool.
int ShowNetInRatsnest(const TOOL_EVENT &aEvent)
void reportCompileError(REPORTER *r)
int ClearHighlight(const TOOL_EVENT &aEvent)
Perform the appropriate action in response to an Eeschema cross-probe.
std::unique_ptr< DRC_ENGINE > makeDRCEngine(bool *aCompileError, bool *aCourtyardError)
int HideNetInRatsnest(const TOOL_EVENT &aEvent)
Show the ratsnest for a given net.
int InspectConstraints(const TOOL_EVENT &aEvent)
void doHideRatsnestNet(int aNetCode, bool aHide)
Bind handlers to corresponding TOOL_ACTIONs.
wxString getItemDescription(BOARD_ITEM *aItem)
CONNECTIVITY_DATA * m_dynamicData
int ShowFootprintLinks(const TOOL_EVENT &aEvent)
void reportHeader(const wxString &aTitle, BOARD_ITEM *a, REPORTER *r)
FOOTPRINT_DIFF_WIDGET * constructDiffPanel(wxPanel *aParentPanel)
int InspectClearance(const TOOL_EVENT &aEvent)
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
std::set< int > m_currentlyHighlighted
int UpdateLocalRatsnest(const TOOL_EVENT &aEvent)
Hide ratsnest for selected items. Called when there are no items selected.
int HideLocalRatsnest(const TOOL_EVENT &aEvent)
Show local ratsnest of a component.
int HighlightItem(const TOOL_EVENT &aEvent)
Update ratsnest for selected items.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:79
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:239
virtual bool IsConnected() const
Returns information if the object is derived from BOARD_CONNECTED_ITEM.
Definition: board_item.h:133
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Test to see if this object is on the given layer.
Definition: board_item.h:321
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:47
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:259
virtual bool IsTented(PCB_LAYER_ID aLayer) const
Checks if the given object is tented (its copper shape is covered by solder mask) on a given side of ...
Definition: board_item.h:172
virtual bool HasDrilledHole() const
Definition: board_item.h:160
virtual bool IsOnCopperLayer() const
Definition: board_item.h:150
virtual void RunOnDescendants(const std::function< void(BOARD_ITEM *)> &aFunction, int aDepth=0) const
Invoke a function on all descendants.
Definition: board_item.h:214
virtual bool HasHole() const
Definition: board_item.h:155
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:295
void SetHighLightNet(int aNetCode, bool aMulti=false)
Select the netcode to be highlighted.
Definition: board.cpp:2777
BOARD_ITEM * GetItem(const KIID &aID) const
Definition: board.cpp:1451
const ZONES & Zones() const
Definition: board.h:340
void ResetNetHighLight()
Reset all high light data to the init state.
Definition: board.cpp:2768
const FOOTPRINTS & Footprints() const
Definition: board.h:336
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:613
PROJECT * GetProject() const
Definition: board.h:499
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:934
void HighLightON(bool aValue=true)
Enable or disable net highlighting.
Definition: board.cpp:2790
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:483
int GetCount() const
Return the number of objects in the list.
Definition: collector.h:81
void AddMenu(ACTION_MENU *aMenu, const SELECTION_CONDITION &aCondition=SELECTION_CONDITIONS::ShowAlways, int aOrder=ANY_ORDER)
Add a submenu to the menu.
void Move(const VECTOR2I &aDelta)
Moves the connectivity list anchors.
Dialog to show common board info.
wxPanel * AddBlankPage(const wxString &aTitle)
WX_HTML_REPORT_BOX * AddHTMLPage(const wxString &aTitle)
Dialog to show footprint library and symbol links.
bool Show(bool show) override
int ShowModal() override
wxString GetName() const
Definition: drc_rule.h:160
int m_DisallowFlags
Definition: drc_rule.h:191
ZONE_CONNECTION m_ZoneConnection
Definition: drc_rule.h:192
MINOPTMAX< int > m_Value
Definition: drc_rule.h:190
bool IsNull() const
Definition: drc_rule.h:147
static int MatchDpSuffix(const wxString &aNetName, wxString &aComplementNet, wxString &aBaseDpName)
Check if the given net is a diff pair, returning its polarity and complement if so.
void ShowInfoBarError(const wxString &aErrorMsg, bool aShowCloseButton=false, WX_INFOBAR::MESSAGE_TYPE aType=WX_INFOBAR::MESSAGE_TYPE::GENERIC)
Show the WX_INFOBAR displayed on the top of the canvas with a message and an error icon on the left o...
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:89
virtual wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const
Return a user-visible description string of this item.
Definition: eda_item.cpp:111
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:101
EDA_ITEM_FLAGS GetFlags() const
Definition: eda_item.h:130
static void PadFilter(const VECTOR2I &, GENERAL_COLLECTOR &aCollector, PCB_SELECTION_TOOL *sTool)
A selection filter which prunes the selection to contain only items of type PCB_PAD_T.
Definition: edit_tool.cpp:3086
static void FootprintFilter(const VECTOR2I &, GENERAL_COLLECTOR &aCollector, PCB_SELECTION_TOOL *sTool)
A selection filter which prunes the selection to contain only items of type #PCB_MODULE_T.
Definition: edit_tool.cpp:3097
void DisplayDiff(FOOTPRINT *aBoardFootprint, std::shared_ptr< FOOTPRINT > &aLibFootprint)
Set the currently displayed symbol.
ZONES & Zones()
Definition: footprint.h:210
bool FootprintNeedsUpdate(const FOOTPRINT *aLibFP, int aCompareFlags=0, REPORTER *aReporter=nullptr)
Return true if a board footprint differs from the library version.
std::deque< PAD * > & Pads()
Definition: footprint.h:204
const LIB_ID & GetFPID() const
Definition: footprint.h:246
void BuildCourtyardCaches(OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr)
Build complex polygons of the courtyard areas from graphic items on the courtyard layers.
Definition: footprint.cpp:3001
const SHAPE_POLY_SET & GetCourtyard(PCB_LAYER_ID aLayer) const
Used in DRC to test the courtyard area (a complex polygon).
Definition: footprint.cpp:2978
const FP_LIB_TABLE_ROW * FindRow(const wxString &aNickName, bool aCheckIfEnabled=false)
Return an FP_LIB_TABLE_ROW if aNickName is found in this table or in any chained fall back table frag...
FOOTPRINT * FootprintLoad(const wxString &aNickname, const wxString &aFootprintName, bool aKeepUUID=false)
Load a footprint having aFootprintName from the library given by aNickname.
A general implementation of a COLLECTORS_GUIDE.
Definition: collectors.h:319
void SetIgnoreZoneFills(bool ignore)
Definition: collectors.h:467
void SetPreferredLayer(PCB_LAYER_ID aLayer)
Definition: collectors.h:384
Used when the right click button is pressed, or when the select tool is in effect.
Definition: collectors.h:202
void Collect(BOARD_ITEM *aItem, const std::vector< KICAD_T > &aScanList, const VECTOR2I &aRefPos, const COLLECTORS_GUIDE &aGuide)
Scan a BOARD_ITEM using this class's Inspector method, which does the collection.
Definition: collectors.cpp:482
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:77
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
PCB specific render settings.
Definition: pcb_painter.h:78
std::set< int > & GetHiddenNets()
Definition: pcb_painter.h:138
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
const std::set< int > & GetHighlightNetCodes() const
Return the netcode of currently highlighted net.
PCB_LAYER_ID GetPrimaryHighContrastLayer() const
Return the board layer which is in high-contrast mode.
bool GetHighContrast() const
void SetHighlight(bool aEnabled, int aNetcode=-1, bool aMulti=false)
Turns on/off highlighting.
bool IsBOARD_ITEM() const
Definition: view_item.h:102
void UpdateAllLayersColor()
Apply the new coloring scheme to all layers.
Definition: view.cpp:765
virtual int GetTopLayer() const
Definition: view.cpp:820
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:216
void MarkTargetDirty(int aTarget)
Set or clear target 'dirty' flag.
Definition: view.h:635
Definition: kiid.h:49
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
Definition: kiway_holder.h:55
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:49
const UTF8 & GetLibItemName() const
Definition: lib_id.h:102
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:87
Hold a record identifying a library accessed by the appropriate plug in object in the LIB_TABLE.
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library table.
LSET is a set of PCB_LAYER_IDs.
Definition: lset.h:37
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:562
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:295
bool Contains(PCB_LAYER_ID aLayer) const
See if the layer set contains a PCB layer.
Definition: lset.h:63
T Min() const
Definition: minoptmax.h:33
bool HasMax() const
Definition: minoptmax.h:38
bool HasMin() const
Definition: minoptmax.h:37
T Max() const
Definition: minoptmax.h:34
T Opt() const
Definition: minoptmax.h:35
bool HasOpt() const
Definition: minoptmax.h:39
const wxString GetHumanReadableName() const
Gets the consolidated name of this netclass (which may be an aggregate).
Definition: netclass.cpp:286
Handle the data for a net.
Definition: netinfo.h:56
const wxString & GetNetname() const
Definition: netinfo.h:114
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Return the information about the NETINFO_ITEM in aList to display in the message panel.
ACTION_MENU * create() const override
Return an instance of this class. It has to be overridden in inheriting classes.
Definition: pad.h:54
const VECTOR2I & GetDrillSize() const
Definition: pad.h:303
PAD_ATTRIB GetAttribute() const
Definition: pad.h:438
static TOOL_ACTION highlightItem
Definition: pcb_actions.h:562
static TOOL_ACTION toggleNetHighlight
Definition: pcb_actions.h:560
static TOOL_ACTION selectionCursor
Select a single item under the cursor position.
Definition: pcb_actions.h:65
static TOOL_ACTION highlightNet
Definition: pcb_actions.h:558
static TOOL_ACTION hideNetInRatsnest
Definition: pcb_actions.h:565
static TOOL_ACTION hideLocalRatsnest
Definition: pcb_actions.h:568
static TOOL_ACTION showNetInRatsnest
Definition: pcb_actions.h:566
static TOOL_ACTION cleanupTracksAndVias
Definition: pcb_actions.h:426
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:68
static TOOL_ACTION toggleLastNetHighlight
Definition: pcb_actions.h:559
static TOOL_ACTION inspectConstraints
Definition: pcb_actions.h:552
static TOOL_ACTION clearHighlight
Definition: pcb_actions.h:557
static TOOL_ACTION inspectClearance
Definition: pcb_actions.h:551
static TOOL_ACTION updateLocalRatsnest
Definition: pcb_actions.h:569
static TOOL_ACTION diffFootprint
Definition: pcb_actions.h:553
static TOOL_ACTION selectItem
Select an item (specified as the event parameter).
Definition: pcb_actions.h:71
static TOOL_ACTION showFootprintAssociations
Definition: pcb_actions.h:554
static TOOL_ACTION highlightNetSelection
Definition: pcb_actions.h:561
static TOOL_ACTION boardStatistics
Definition: pcb_actions.h:547
static TOOL_ACTION localRatsnestTool
Definition: pcb_actions.h:567
wxString GetDesignRulesPath()
Return the absolute path to the design rules file for the currently-loaded board.
APPEARANCE_CONTROLS * GetAppearancePanel()
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
virtual PCB_LAYER_ID GetActiveLayer() const
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
BOARD * GetBoard() const
GENERAL_COLLECTORS_GUIDE GetCollectorsGuide()
virtual void Update3DView(bool aMarkDirty, bool aRefresh, const wxString *aTitle=nullptr)
Update the 3D view, if the viewer is opened by this frame.
void RedrawRatsnest()
Return the bounding box of the view that should be used if model is not valid.
DIALOG_BOOK_REPORTER * GetInspectDrcErrorDialog()
void SendCrossProbeItem(BOARD_ITEM *aSyncItem)
Send a message to the schematic editor so that it may move its cursor to an item with the same refere...
DIALOG_BOOK_REPORTER * GetFootprintDiffDialog()
DIALOG_BOOK_REPORTER * GetInspectClearanceDialog()
void SendCrossProbeNetName(const wxString &aNetName)
Send a net name to Eeschema for highlighting.
DIALOG_BOOK_REPORTER * GetInspectConstraintsDialog()
A set of BOARD_ITEMs (i.e., without duplicates).
Definition: pcb_group.h:52
std::unordered_set< BOARD_ITEM * > & GetItems()
Definition: pcb_group.h:69
Generic tool for picking an item.
The selection tool: currently supports:
PCB_SELECTION & RequestSelection(CLIENT_SELECTION_FILTER aClientFilter, bool aConfirmLockedItems=false)
Return the current selection, filtered according to aClientFilter.
void FilterCollectedItems(GENERAL_COLLECTOR &aCollector, bool aMultiSelect)
Apply the SELECTION_FITLER_OPTIONS to the collector.
PCB_SELECTION_FILTER_OPTIONS & GetFilter()
Set up handlers for various events.
PCB_SELECTION & GetSelection()
T * frame() const
KIGFX::PCB_VIEW * view() const
BOARD * board() const
PCBNEW_SETTINGS::DISPLAY_OPTIONS & displayOptions() const
const PCB_SELECTION & selection() const
FOOTPRINT * footprint() const
void SetClickHandler(CLICK_HANDLER aHandler)
Set a handler for mouse click event.
Definition: picker_tool.h:73
void SetCursor(KICURSOR aCursor)
Definition: picker_tool.h:64
void SetFinalizeHandler(FINALIZE_HANDLER aHandler)
Set a handler for the finalize event.
Definition: picker_tool.h:104
static FP_LIB_TABLE * PcbFootprintLibs(PROJECT *aProject)
Return the table of footprint libraries without Kiway.
Definition: project_pcb.cpp:37
Container for project specific data.
Definition: project.h:64
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:72
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
virtual KIGFX::VIEW_ITEM * GetItem(unsigned int aIdx) const override
Definition: selection.cpp:75
ITER end()
Definition: selection.h:75
ITER begin()
Definition: selection.h:74
EDA_ITEM * Front() const
Definition: selection.h:172
int Size() const
Returns the number of selected parts.
Definition: selection.h:116
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:110
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
Represent a single user action.
Definition: tool_action.h:269
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition: tool_base.cpp:44
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:220
KIGFX::VIEW * getView() const
Returns the instance of #VIEW object used in the application.
Definition: tool_base.cpp:38
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:78
Generic, UI-independent tool event.
Definition: tool_event.h:168
bool IsAction(const TOOL_ACTION *aAction) const
Test if the event contains an action issued upon activation of the given TOOL_ACTION.
Definition: tool_event.cpp:82
T Parameter() const
Return a parameter assigned to the event.
Definition: tool_event.h:465
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Define which state (aStateFunc) to go when a certain event arrives (aConditions).
TOOL_MENU & GetToolMenu()
void Activate()
Run the tool.
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
Definition: tool_manager.h:150
EDA_ITEM * GetModel() const
Definition: tool_manager.h:398
KIGFX::VIEW * GetView() const
Definition: tool_manager.h:391
CONDITIONAL_MENU & GetMenu()
Definition: tool_menu.cpp:44
void RegisterSubMenu(std::shared_ptr< ACTION_MENU > aSubMenu)
Store a submenu of this menu model.
Definition: tool_menu.cpp:50
wxString StringFromValue(double aValue, bool aAddUnitLabel=false, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
Converts aValue in internal units into a united string.
A slimmed down version of WX_HTML_REPORT_PANEL.
REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Report a string with a given severity.
void Flush()
Build the HTML messages page.
Handle a list of polygons defining a copper zone.
Definition: zone.h:73
std::optional< int > GetLocalClearance() const override
Definition: zone.cpp:717
virtual bool IsOnLayer(PCB_LAYER_ID) const override
Test to see if this object is on the given layer.
Definition: zone.cpp:564
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: zone.h:133
@ DRCE_HOLE_CLEARANCE
Definition: drc_item.h:54
@ DRCE_VIA_DIAMETER
Definition: drc_item.h:61
@ DRCE_TRACK_WIDTH
Definition: drc_item.h:55
@ DRCE_DRILL_OUT_OF_RANGE
Definition: drc_item.h:60
@ DRCE_EDGE_CLEARANCE
Definition: drc_item.h:46
@ DRCE_TRACK_SEGMENT_LENGTH
Definition: drc_item.h:57
@ DRCE_TRACK_ANGLE
Definition: drc_item.h:56
@ DRCE_CLEARANCE
Definition: drc_item.h:43
@ DRCE_DRILLED_HOLES_TOO_CLOSE
Definition: drc_item.h:52
@ DRCE_DIFF_PAIR_UNCOUPLED_LENGTH_TOO_LONG
Definition: drc_item.h:107
@ DRCE_MICROVIA_DRILL_OUT_OF_RANGE
Definition: drc_item.h:64
@ DRCE_DANGLING_VIA
Definition: drc_item.h:50
@ DRCE_DANGLING_TRACK
Definition: drc_item.h:51
@ DRCE_TEXT_HEIGHT
Definition: drc_item.h:99
@ DRCE_ASSERTION_FAILURE
Definition: drc_item.h:88
@ DRCE_LIB_FOOTPRINT_MISMATCH
Definition: drc_item.h:83
@ DRCE_TEXT_THICKNESS
Definition: drc_item.h:100
@ DRCE_CONNECTION_WIDTH
Definition: drc_item.h:59
@ DRCE_ANNULAR_WIDTH
Definition: drc_item.h:58
@ ANNULAR_WIDTH_CONSTRAINT
Definition: drc_rule.h:61
@ COURTYARD_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:55
@ VIA_DIAMETER_CONSTRAINT
Definition: drc_rule.h:67
@ DIFF_PAIR_GAP_CONSTRAINT
Definition: drc_rule.h:70
@ DISALLOW_CONSTRAINT
Definition: drc_rule.h:66
@ TRACK_WIDTH_CONSTRAINT
Definition: drc_rule.h:59
@ SILK_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:56
@ EDGE_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:53
@ MIN_RESOLVED_SPOKES_CONSTRAINT
Definition: drc_rule.h:65
@ TRACK_SEGMENT_LENGTH_CONSTRAINT
Definition: drc_rule.h:60
@ TEXT_THICKNESS_CONSTRAINT
Definition: drc_rule.h:58
@ PHYSICAL_HOLE_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:75
@ CLEARANCE_CONSTRAINT
Definition: drc_rule.h:49
@ THERMAL_SPOKE_WIDTH_CONSTRAINT
Definition: drc_rule.h:64
@ CONNECTION_WIDTH_CONSTRAINT
Definition: drc_rule.h:77
@ THERMAL_RELIEF_GAP_CONSTRAINT
Definition: drc_rule.h:63
@ MAX_UNCOUPLED_CONSTRAINT
Definition: drc_rule.h:71
@ HOLE_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:51
@ TRACK_ANGLE_CONSTRAINT
Definition: drc_rule.h:78
@ HOLE_SIZE_CONSTRAINT
Definition: drc_rule.h:54
@ TEXT_HEIGHT_CONSTRAINT
Definition: drc_rule.h:57
@ PHYSICAL_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:74
@ HOLE_TO_HOLE_CONSTRAINT
Definition: drc_rule.h:52
#define _(s)
#define MALFORMED_COURTYARDS
bool IsFrontLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a front layer.
Definition: layer_ids.h:682
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition: layer_ids.h:581
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ F_CrtYd
Definition: layer_ids.h:116
@ Edge_Cuts
Definition: layer_ids.h:112
@ B_Mask
Definition: layer_ids.h:98
@ B_Cu
Definition: layer_ids.h:65
@ F_Mask
Definition: layer_ids.h:97
@ Margin
Definition: layer_ids.h:113
@ F_SilkS
Definition: layer_ids.h:100
@ B_CrtYd
Definition: layer_ids.h:115
@ UNDEFINED_LAYER
Definition: layer_ids.h:61
@ B_SilkS
Definition: layer_ids.h:101
@ F_Cu
Definition: layer_ids.h:64
@ TARGET_OVERLAY
Items that may change while the view stays the same (noncached)
Definition: definitions.h:39
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
Class to handle a set of BOARD_ITEMs.
std::function< void(const VECTOR2I &, GENERAL_COLLECTOR &, PCB_SELECTION_TOOL *)> CLIENT_SELECTION_FILTER
std::vector< FAB_LAYER_COLOR > dummy
wxString EscapeHTML(const wxString &aString)
Return a new wxString escaped for embedding in HTML.
A filename or source description, a problem input line, a line number, a byte offset,...
Definition: ki_exception.h:120
This file contains data structures that are saved in the project file or project local settings file ...
constexpr int delta
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:88
@ PCB_GENERATOR_T
class PCB_GENERATOR, generator on a layer
Definition: typeinfo.h:91
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
Definition: typeinfo.h:110
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition: typeinfo.h:93
@ PCB_ZONE_T
class ZONE, a copper pour area
Definition: typeinfo.h:107
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition: typeinfo.h:92
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
Definition: typeinfo.h:90
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
Definition: typeinfo.h:86
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition: typeinfo.h:87
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:98
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:96
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:695