KiCad PCB EDA Suite
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
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 || aDRCItem->GetErrorCode() == DRCE_STARVED_THERMAL )
307 {
308 return menuDescription( PCB_ACTIONS::inspectClearance );
309 }
310 else if( aDRCItem->GetErrorCode() == DRCE_TEXT_HEIGHT
311 || aDRCItem->GetErrorCode() == DRCE_TEXT_THICKNESS
312 || aDRCItem->GetErrorCode() == DRCE_DIFF_PAIR_UNCOUPLED_LENGTH_TOO_LONG
313 || aDRCItem->GetErrorCode() == DRCE_TRACK_WIDTH
314 || aDRCItem->GetErrorCode() == DRCE_TRACK_ANGLE
315 || aDRCItem->GetErrorCode() == DRCE_TRACK_SEGMENT_LENGTH
316 || aDRCItem->GetErrorCode() == DRCE_VIA_DIAMETER
317 || aDRCItem->GetErrorCode() == DRCE_ANNULAR_WIDTH
318 || aDRCItem->GetErrorCode() == DRCE_DRILL_OUT_OF_RANGE
319 || aDRCItem->GetErrorCode() == DRCE_MICROVIA_DRILL_OUT_OF_RANGE
320 || aDRCItem->GetErrorCode() == DRCE_CONNECTION_WIDTH
321 || aDRCItem->GetErrorCode() == DRCE_ASSERTION_FAILURE )
322 {
323 return menuDescription( PCB_ACTIONS::inspectConstraints );
324 }
325 else if( aDRCItem->GetErrorCode() == DRCE_LIB_FOOTPRINT_MISMATCH )
326 {
327 return menuDescription( PCB_ACTIONS::diffFootprint );
328 }
329 else if( aDRCItem->GetErrorCode() == DRCE_DANGLING_TRACK
330 || aDRCItem->GetErrorCode() == DRCE_DANGLING_VIA )
331 {
332 return menuDescription( PCB_ACTIONS::cleanupTracksAndVias );
333 }
334
335 return wxEmptyString;
336}
337
338
339void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr<RC_ITEM>& aDRCItem )
340{
341 wxCHECK( m_frame, /* void */ );
342
343 BOARD_ITEM* a = m_frame->GetBoard()->GetItem( aDRCItem->GetMainItemID() );
344 BOARD_ITEM* b = m_frame->GetBoard()->GetItem( aDRCItem->GetAuxItemID() );
345 BOARD_CONNECTED_ITEM* ac = dynamic_cast<BOARD_CONNECTED_ITEM*>( a );
346 BOARD_CONNECTED_ITEM* bc = dynamic_cast<BOARD_CONNECTED_ITEM*>( b );
348
349 if( aDRCItem->GetErrorCode() == DRCE_LIB_FOOTPRINT_MISMATCH )
350 {
351 if( FOOTPRINT* footprint = dynamic_cast<FOOTPRINT*>( a ) )
353
354 return;
355 }
356 else if( aDRCItem->GetErrorCode() == DRCE_DANGLING_TRACK
357 || aDRCItem->GetErrorCode() == DRCE_DANGLING_VIA )
358 {
360 return;
361 }
362
364 wxCHECK( dialog, /* void */ );
365
366 dialog->DeleteAllPages();
367
368 bool compileError = false;
369 bool courtyardError = false;
370 std::unique_ptr<DRC_ENGINE> drcEngine = makeDRCEngine( &compileError, &courtyardError );
371
372 WX_HTML_REPORT_BOX* r = nullptr;
373 DRC_CONSTRAINT constraint;
374 int clearance = 0;
375 wxString clearanceStr;
376
377 switch( aDRCItem->GetErrorCode() )
378 {
380 {
381 for( KIID id : aDRCItem->GetIDs() )
382 {
383 bc = dynamic_cast<BOARD_CONNECTED_ITEM*>( m_frame->GetBoard()->GetItem( id ) );
384
385 if( ac && bc && ac->GetNetCode() != bc->GetNetCode() )
386 break;
387 }
388
389 r = dialog->AddHTMLPage( _( "Uncoupled Length" ) );
390 reportHeader( _( "Diff pair uncoupled length resolution for:" ), ac, bc, r );
391
392 if( compileError )
394
395 constraint = drcEngine->EvalRules( MAX_UNCOUPLED_CONSTRAINT, a, b, layer, r );
396
397 r->Report( "" );
398 r->Report( wxString::Format( _( "Resolved max uncoupled length: %s." ),
399 reportMax( m_frame, constraint ) ) );
400 break;
401 }
402
403 case DRCE_TEXT_HEIGHT:
404 r = dialog->AddHTMLPage( _( "Text Height" ) );
405 reportHeader( _( "Text height resolution for:" ), a, r );
406
407 if( compileError )
409
410 constraint = drcEngine->EvalRules( TEXT_HEIGHT_CONSTRAINT, a, b, layer, r );
411
412 r->Report( "" );
413 r->Report( wxString::Format( _( "Resolved height constraints: min %s; max %s." ),
414 reportMin( m_frame, constraint ),
415 reportMax( m_frame, constraint ) ) );
416 break;
417
419 r = dialog->AddHTMLPage( _( "Text Thickness" ) );
420 reportHeader( _( "Text thickness resolution for:" ), a, r );
421
422 if( compileError )
424
425 constraint = drcEngine->EvalRules( TEXT_THICKNESS_CONSTRAINT, a, b, layer, r );
426
427 r->Report( "" );
428 r->Report( wxString::Format( _( "Resolved thickness constraints: min %s; max %s." ),
429 reportMin( m_frame, constraint ),
430 reportMax( m_frame, constraint ) ) );
431 break;
432
433 case DRCE_TRACK_WIDTH:
434 r = dialog->AddHTMLPage( _( "Track Width" ) );
435 reportHeader( _( "Track width resolution for:" ), a, r );
436
437 if( compileError )
439
440 constraint = drcEngine->EvalRules( TRACK_WIDTH_CONSTRAINT, a, b, layer, r );
441
442 r->Report( "" );
443 r->Report( wxString::Format( _( "Resolved width constraints: min %s; max %s." ),
444 reportMin( m_frame, constraint ),
445 reportMax( m_frame, constraint ) ) );
446 break;
447
448 case DRCE_TRACK_ANGLE:
449 r = dialog->AddHTMLPage( _( "Track Angle" ) );
450 reportHeader( _( "Track Angle resolution for:" ), a, r );
451
452 if( compileError )
454
455 constraint = drcEngine->EvalRules( TRACK_ANGLE_CONSTRAINT, a, b, layer, r );
456
457 r->Report( "" );
458 r->Report( wxString::Format( _( "Resolved angle constraints: min %s; max %s." ),
459 reportMin( m_frame, constraint ),
460 reportMax( m_frame, constraint ) ) );
461 break;
462
464 r = dialog->AddHTMLPage( _( "Track Segment Length" ) );
465 reportHeader( _( "Track segment length resolution for:" ), a, r );
466
467 if( compileError )
469
470 constraint = drcEngine->EvalRules( TRACK_SEGMENT_LENGTH_CONSTRAINT, a, b, layer, r );
471
472 r->Report( "" );
473 r->Report( wxString::Format( _( "Resolved segment length constraints: min %s; max %s." ),
474 reportMin( m_frame, constraint ),
475 reportMax( m_frame, constraint ) ) );
476 break;
477
479 r = dialog->AddHTMLPage( _( "Connection Width" ) );
480 reportHeader( _( "Connection width resolution for:" ), a, b, r );
481
482 if( compileError )
484
485 constraint = drcEngine->EvalRules( CONNECTION_WIDTH_CONSTRAINT, a, b, layer, r );
486
487 r->Report( "" );
488 r->Report( wxString::Format( _( "Resolved min connection width: %s." ),
489 reportMin( m_frame, constraint ) ) );
490 break;
491
493 r = dialog->AddHTMLPage( _( "Via Diameter" ) );
494 reportHeader( _( "Via diameter resolution for:" ), a, r );
495
496 if( compileError )
498
499 constraint = drcEngine->EvalRules( VIA_DIAMETER_CONSTRAINT, a, b, layer, r );
500
501 r->Report( "" );
502 r->Report( wxString::Format( _( "Resolved diameter constraints: min %s; max %s." ),
503 reportMin( m_frame, constraint ),
504 reportMax( m_frame, constraint ) ) );
505 break;
506
508 r = dialog->AddHTMLPage( _( "Via Annulus" ) );
509 reportHeader( _( "Via annular width resolution for:" ), a, r );
510
511 if( compileError )
513
514 constraint = drcEngine->EvalRules( ANNULAR_WIDTH_CONSTRAINT, a, b, layer, r );
515
516 r->Report( "" );
517 r->Report( wxString::Format( _( "Resolved annular width constraints: min %s; max %s." ),
518 reportMin( m_frame, constraint ),
519 reportMax( m_frame, constraint ) ) );
520 break;
521
524 r = dialog->AddHTMLPage( _( "Hole Size" ) );
525 reportHeader( _( "Hole size resolution for:" ), a, r );
526
527 if( compileError )
529
530 constraint = drcEngine->EvalRules( HOLE_SIZE_CONSTRAINT, a, b, layer, r );
531
532 r->Report( "" );
533 r->Report( wxString::Format( _( "Resolved hole size constraints: min %s; max %s." ),
534 reportMin( m_frame, constraint ),
535 reportMax( m_frame, constraint ) ) );
536 break;
537
539 r = dialog->AddHTMLPage( _( "Hole Clearance" ) );
540 reportHeader( _( "Hole clearance resolution for:" ), a, b, r );
541
542 if( compileError )
544
545 if( ac && bc && ac->GetNetCode() == bc->GetNetCode() )
546 {
547 r->Report( "" );
548 r->Report( _( "Items belong to the same net. Clearance is 0." ) );
549 }
550 else
551 {
552 constraint = drcEngine->EvalRules( HOLE_CLEARANCE_CONSTRAINT, a, b, layer, r );
553 clearance = constraint.m_Value.Min();
554 clearanceStr = m_frame->StringFromValue( clearance, true );
555
556 r->Report( "" );
557 r->Report( wxString::Format( _( "Resolved min clearance: %s." ), clearanceStr ) );
558 }
559
560 r->Report( "" );
561 r->Report( "" );
562 r->Report( "" );
563 reportHeader( _( "Physical hole clearance resolution for:" ), a, b, layer, r );
564
565 constraint = drcEngine->EvalRules( PHYSICAL_HOLE_CLEARANCE_CONSTRAINT, a, b, layer, r );
566 clearance = constraint.m_Value.Min();
567 clearanceStr = m_frame->StringFromValue( clearance, true );
568
569 if( !drcEngine->HasRulesForConstraintType( PHYSICAL_HOLE_CLEARANCE_CONSTRAINT ) )
570 {
571 r->Report( "" );
572 r->Report( _( "No 'physical_hole_clearance' constraints defined." ) );
573 }
574 else
575 {
576 r->Report( "" );
577 r->Report( wxString::Format( _( "Resolved min clearance: %s." ), clearanceStr ) );
578 }
579
580 break;
581
583 r = dialog->AddHTMLPage( _( "Hole to Hole" ) );
584 reportHeader( _( "Hole-to-hole clearance resolution for:" ), a, b, r );
585
586 if( compileError )
588
589 constraint = drcEngine->EvalRules( HOLE_TO_HOLE_CONSTRAINT, a, b, UNDEFINED_LAYER, r );
590 clearance = constraint.m_Value.Min();
591 clearanceStr = m_frame->StringFromValue( clearance, true );
592
593 r->Report( "" );
594 r->Report( wxString::Format( _( "Resolved min clearance: %s." ), clearanceStr ) );
595 break;
596
598 r = dialog->AddHTMLPage( _( "Edge Clearance" ) );
599 reportHeader( _( "Edge clearance resolution for:" ), a, b, r );
600
601 if( compileError )
603
604 constraint = drcEngine->EvalRules( EDGE_CLEARANCE_CONSTRAINT, a, b, layer, r );
605 clearance = constraint.m_Value.Min();
606 clearanceStr = m_frame->StringFromValue( clearance, true );
607
608 r->Report( "" );
609 r->Report( wxString::Format( _( "Resolved min clearance: %s." ), clearanceStr ) );
610 break;
611
612 case DRCE_CLEARANCE:
613 if( a->Type() == PCB_TRACE_T || a->Type() == PCB_ARC_T )
614 {
615 layer = a->GetLayer();
616 }
617 else if( b->Type() == PCB_TRACE_T || b->Type() == PCB_ARC_T )
618 {
619 layer = b->GetLayer();
620 }
621 else if( a->Type() == PCB_PAD_T
622 && static_cast<PAD*>( a )->GetAttribute() == PAD_ATTRIB::SMD )
623 {
624 PAD* pad = static_cast<PAD*>( a );
625
626 if( pad->IsOnLayer( F_Cu ) )
627 layer = F_Cu;
628 else
629 layer = B_Cu;
630 }
631 else if( b->Type() == PCB_PAD_T
632 && static_cast<PAD*>( a )->GetAttribute() == PAD_ATTRIB::SMD )
633 {
634 PAD* pad = static_cast<PAD*>( b );
635
636 if( pad->IsOnLayer( F_Cu ) )
637 layer = F_Cu;
638 else
639 layer = B_Cu;
640 }
641
642 r = dialog->AddHTMLPage( _( "Clearance" ) );
643 reportHeader( _( "Clearance resolution for:" ), a, b, layer, r );
644
645 if( compileError )
647
648 if( ac && bc && ac->GetNetCode() == bc->GetNetCode() )
649 {
650 r->Report( "" );
651 r->Report( _( "Items belong to the same net. Clearance is 0." ) );
652 }
653 else
654 {
655 constraint = drcEngine->EvalRules( CLEARANCE_CONSTRAINT, a, b, layer, r );
656 clearance = constraint.m_Value.Min();
657 clearanceStr = m_frame->StringFromValue( clearance, true );
658
659 r->Report( "" );
660 r->Report( wxString::Format( _( "Resolved min clearance: %s." ), clearanceStr ) );
661 }
662
663 r->Report( "" );
664 r->Report( "" );
665 r->Report( "" );
666 reportHeader( _( "Physical clearance resolution for:" ), a, b, layer, r );
667
668 constraint = drcEngine->EvalRules( PHYSICAL_CLEARANCE_CONSTRAINT, a, b, layer, r );
669 clearance = constraint.m_Value.Min();
670 clearanceStr = m_frame->StringFromValue( clearance, true );
671
672 if( !drcEngine->HasRulesForConstraintType( PHYSICAL_CLEARANCE_CONSTRAINT ) )
673 {
674 r->Report( "" );
675 r->Report( _( "No 'physical_clearance' constraints defined." ) );
676 }
677 else
678 {
679 r->Report( "" );
680 r->Report( wxString::Format( _( "Resolved min clearance: %s." ), clearanceStr ) );
681 }
682
683 break;
684
686 r = dialog->AddHTMLPage( _( "Assertions" ) );
687 reportHeader( _( "Assertions for:" ), a, r );
688
689 if( compileError )
691
692 drcEngine->ProcessAssertions( a, []( const DRC_CONSTRAINT* c ){}, r );
693 break;
694
695 default:
696 return;
697 }
698
699 r->Flush();
700
701 dialog->Raise();
702 dialog->Show( true );
703}
704
705
707{
708 wxCHECK( m_frame, 0 );
709
711
712 wxCHECK( selTool, 0 );
713
714 const PCB_SELECTION& selection = selTool->GetSelection();
715
716 if( selection.Size() != 2 )
717 {
718 m_frame->ShowInfoBarError( _( "Select two items for a clearance resolution report." ) );
719 return 0;
720 }
721
723 return 0;
724
725 BOARD_ITEM* a = static_cast<BOARD_ITEM*>( selection.GetItem( 0 ) );
726 BOARD_ITEM* b = static_cast<BOARD_ITEM*>( selection.GetItem( 1 ) );
727
728 if( a->Type() == PCB_GROUP_T )
729 {
730 PCB_GROUP* ag = static_cast<PCB_GROUP*>( a );
731
732 if( ag->GetItems().empty() )
733 {
734 m_frame->ShowInfoBarError( _( "Cannot generate clearance report on empty group." ) );
735 return 0;
736 }
737
738 a = *ag->GetItems().begin();
739 }
740
741 if( b->Type() == PCB_GROUP_T )
742 {
743 PCB_GROUP* bg = static_cast<PCB_GROUP*>( b );
744
745 if( bg->GetItems().empty() )
746 {
747 m_frame->ShowInfoBarError( _( "Cannot generate clearance report on empty group." ) );
748 return 0;
749 }
750
751 b = *bg->GetItems().begin();
752 }
753
754 // a or b could be null after group tests above.
755 if( !a || !b )
756 return 0;
757
758 auto checkFootprint =
759 [&]( FOOTPRINT* footprint ) -> BOARD_ITEM*
760 {
761 PAD* foundPad = nullptr;
762
763 for( PAD* pad : footprint->Pads() )
764 {
765 if( !foundPad || pad->SameLogicalPadAs( foundPad ) )
766 foundPad = pad;
767 else
768 return footprint;
769 }
770
771 if( !foundPad )
772 return footprint;
773
774 return foundPad;
775 };
776
777 if( a->Type() == PCB_FOOTPRINT_T )
778 a = checkFootprint( static_cast<FOOTPRINT*>( a ) );
779
780 if( b->Type() == PCB_FOOTPRINT_T )
781 b = checkFootprint( static_cast<FOOTPRINT*>( b ) );
782
783 // a or b could be null after footprint tests above.
784 if( !a || !b )
785 return 0;
786
788
789 wxCHECK( dialog, 0 );
790
791 dialog->DeleteAllPages();
792
793 if( a->Type() != PCB_ZONE_T && b->Type() == PCB_ZONE_T )
794 std::swap( a, b );
795 else if( !a->IsConnected() && b->IsConnected() )
796 std::swap( a, b );
797
798 WX_HTML_REPORT_BOX* r = nullptr;
800 LSET layerIntersection = a->GetLayerSet() & b->GetLayerSet();
801 LSET copperIntersection = layerIntersection & LSET::AllCuMask();
802 BOARD_CONNECTED_ITEM* ac = dynamic_cast<BOARD_CONNECTED_ITEM*>( a );
803 BOARD_CONNECTED_ITEM* bc = dynamic_cast<BOARD_CONNECTED_ITEM*>( b );
804 ZONE* zone = dynamic_cast<ZONE*>( a );
805 PAD* pad = dynamic_cast<PAD*>( b );
806 FOOTPRINT* aFP = dynamic_cast<FOOTPRINT*>( a );
807 FOOTPRINT* bFP = dynamic_cast<FOOTPRINT*>( b );
808 DRC_CONSTRAINT constraint;
809 int clearance = 0;
810
811 bool compileError = false;
812 bool courtyardError = false;
813 std::unique_ptr<DRC_ENGINE> drcEngine = makeDRCEngine( &compileError, &courtyardError );
814
815 if( copperIntersection.any() && zone && pad && zone->GetNetCode() == pad->GetNetCode() )
816 {
818
819 if( zone->IsOnLayer( active ) )
820 layer = active;
821 else if( zone->GetLayerSet().count() > 0 )
822 layer = zone->GetLayerSet().Seq().front();
823
824 r = dialog->AddHTMLPage( _( "Zone" ) );
825 reportHeader( _( "Zone connection resolution for:" ), a, b, layer, r );
826
827 constraint = drcEngine->EvalZoneConnection( pad, zone, layer, r );
828
829 if( constraint.m_ZoneConnection == ZONE_CONNECTION::THERMAL )
830 {
831 r->Report( "" );
832 r->Report( "" );
833 reportHeader( _( "Thermal-relief gap resolution for:" ), a, b, layer, r );
834
835 constraint = drcEngine->EvalRules( THERMAL_RELIEF_GAP_CONSTRAINT, pad, zone, layer, r );
836 int gap = constraint.m_Value.Min();
837
838 if( compileError )
840
841 r->Report( "" );
842 r->Report( wxString::Format( _( "Resolved thermal relief gap: %s." ),
843 m_frame->StringFromValue( gap, true ) ) );
844
845 r->Report( "" );
846 r->Report( "" );
847 reportHeader( _( "Thermal-relief spoke width resolution for:" ), a, b, layer, r );
848
849 constraint = drcEngine->EvalRules( THERMAL_SPOKE_WIDTH_CONSTRAINT, pad, zone, layer, r );
850 int width = constraint.m_Value.Opt();
851
852 if( compileError )
854
855 r->Report( "" );
856 r->Report( wxString::Format( _( "Resolved spoke width: %s." ),
857 m_frame->StringFromValue( width, true ) ) );
858
859 r->Report( "" );
860 r->Report( "" );
861 reportHeader( _( "Thermal-relief min spoke count resolution for:" ), a, b, layer, r );
862
863 constraint = drcEngine->EvalRules( MIN_RESOLVED_SPOKES_CONSTRAINT, pad, zone, layer, r );
864 int minSpokes = constraint.m_Value.Min();
865
866 if( compileError )
868
869 r->Report( "" );
870 r->Report( wxString::Format( _( "Resolved min spoke count: %d." ),
871 minSpokes ) );
872
873 std::shared_ptr<CONNECTIVITY_DATA> connectivity = pad->GetBoard()->GetConnectivity();
874 }
875 else if( constraint.m_ZoneConnection == ZONE_CONNECTION::NONE )
876 {
877 r->Report( "" );
878 r->Report( "" );
879 reportHeader( _( "Zone clearance resolution for:" ), a, b, layer, r );
880
881 clearance = zone->GetLocalClearance().value();
882 r->Report( "" );
883 r->Report( wxString::Format( _( "Zone clearance: %s." ),
884 m_frame->StringFromValue( clearance, true ) ) );
885
886 constraint = drcEngine->EvalRules( PHYSICAL_CLEARANCE_CONSTRAINT, pad, zone, layer, r );
887
888 if( constraint.m_Value.Min() > clearance )
889 {
890 clearance = constraint.m_Value.Min();
891
892 r->Report( "" );
893 r->Report( wxString::Format( _( "Overridden by larger physical clearance from %s;"
894 "clearance: %s." ),
895 EscapeHTML( constraint.GetName() ),
896 m_frame->StringFromValue( clearance, true ) ) );
897 }
898
899 if( !pad->FlashLayer( layer ) )
900 {
901 constraint = drcEngine->EvalRules( PHYSICAL_HOLE_CLEARANCE_CONSTRAINT, pad, zone,
902 layer, r );
903
904 if( constraint.m_Value.Min() > clearance )
905 {
906 clearance = constraint.m_Value.Min();
907
908 r->Report( "" );
909 r->Report( wxString::Format( _( "Overridden by larger physical hole clearance "
910 "from %s; clearance: %s." ),
911 EscapeHTML( constraint.GetName() ),
912 m_frame->StringFromValue( clearance, true ) ) );
913 }
914 }
915
916 if( compileError )
918
919 r->Report( "" );
920 r->Report( wxString::Format( _( "Resolved min clearance: %s." ),
921 m_frame->StringFromValue( clearance, true ) ) );
922 }
923 else
924 {
925 r->Report( "" );
926 r->Report( "" );
927 reportHeader( _( "Zone clearance resolution for:" ), a, b, layer, r );
928
929 if( compileError )
931
932 // Report a 0 clearance for solid connections
933 r->Report( "" );
934 r->Report( wxString::Format( _( "Resolved min clearance: %s." ),
935 m_frame->StringFromValue( 0, true ) ) );
936 }
937
938 r->Flush();
939 }
940 else if( copperIntersection.any() && !aFP && !bFP )
941 {
942 PCB_LAYER_ID layer = active;
943
944 if( !copperIntersection.test( layer ) )
945 layer = copperIntersection.Seq().front();
946
947 r = dialog->AddHTMLPage( m_frame->GetBoard()->GetLayerName( layer ) );
948 reportHeader( _( "Clearance resolution for:" ), a, b, layer, r );
949
950 if( ac && bc && ac->GetNetCode() > 0 && ac->GetNetCode() == bc->GetNetCode() )
951 {
952 // Same nets....
953 r->Report( _( "Items belong to the same net. Min clearance is 0." ) );
954 }
955 else
956 {
957 // Different nets (or one or both unconnected)....
958 constraint = drcEngine->EvalRules( CLEARANCE_CONSTRAINT, a, b, layer, r );
959 clearance = constraint.m_Value.Min();
960
961 if( compileError )
963
964 r->Report( "" );
965
966 if( constraint.IsNull() )
967 {
968 r->Report( _( "Min clearance is 0." ) );
969 }
970 else if( clearance < 0 )
971 {
972 r->Report( wxString::Format( _( "Resolved clearance: %s; clearance will not be "
973 "tested." ),
974 m_frame->StringFromValue( clearance, true ) ) );
975 }
976 else
977 {
978 r->Report( wxString::Format( _( "Resolved min clearance: %s." ),
979 m_frame->StringFromValue( clearance, true ) ) );
980 }
981 }
982
983 r->Flush();
984 }
985
986 if( ac && bc )
987 {
988 NETINFO_ITEM* refNet = ac->GetNet();
989 wxString coupledNet;
990 wxString dummy;
991
992 if( DRC_ENGINE::MatchDpSuffix( refNet->GetNetname(), coupledNet, dummy )
993 && bc->GetNetname() == coupledNet )
994 {
995 r = dialog->AddHTMLPage( _( "Diff Pair" ) );
996 reportHeader( _( "Diff-pair gap resolution for:" ), ac, bc, active, r );
997
998 constraint = drcEngine->EvalRules( DIFF_PAIR_GAP_CONSTRAINT, ac, bc, active, r );
999
1000 r->Report( "" );
1001 r->Report( wxString::Format( _( "Resolved gap constraints: min %s; opt %s; max %s." ),
1002 reportMin( m_frame, constraint ),
1003 reportOpt( m_frame, constraint ),
1004 reportMax( m_frame, constraint ) ) );
1005
1006 r->Report( "" );
1007 r->Report( "" );
1008 r->Report( "" );
1009 reportHeader( _( "Diff-pair max uncoupled length resolution for:" ), ac, bc,
1010 active, r );
1011
1012 if( !drcEngine->HasRulesForConstraintType( MAX_UNCOUPLED_CONSTRAINT ) )
1013 {
1014 r->Report( "" );
1015 r->Report( _( "No 'diff_pair_uncoupled' constraints defined." ) );
1016 }
1017 else
1018 {
1019 constraint = drcEngine->EvalRules( MAX_UNCOUPLED_CONSTRAINT, ac, bc, active, r );
1020
1021 r->Report( "" );
1022 r->Report( wxString::Format( _( "Resolved max uncoupled length: %s." ),
1023 reportMax( m_frame, constraint ) ) );
1024 }
1025 r->Flush();
1026 }
1027 }
1028
1029 auto isOnCorrespondingLayer=
1030 [&]( BOARD_ITEM* aItem, PCB_LAYER_ID aLayer, wxString* aWarning )
1031 {
1032 if( aItem->IsOnLayer( aLayer ) )
1033 return true;
1034
1035 PCB_LAYER_ID correspondingMask = IsFrontLayer( aLayer ) ? F_Mask : B_Mask;
1036 PCB_LAYER_ID correspondingCopper = IsFrontLayer( aLayer ) ? F_Cu : B_Cu;
1037
1038 if( aItem->IsOnLayer( aLayer ) )
1039 return true;
1040
1041 if( aItem->IsOnLayer( correspondingMask ) )
1042 return true;
1043
1044 if( aItem->IsTented( correspondingMask ) && aItem->IsOnLayer( correspondingCopper ) )
1045 {
1046 *aWarning = wxString::Format( _( "Note: %s is tented; clearance will only be "
1047 "applied to holes." ),
1048 getItemDescription( aItem ) );
1049 return true;
1050 }
1051
1052 return false;
1053 };
1054
1055 for( PCB_LAYER_ID layer : { F_SilkS, B_SilkS } )
1056 {
1057 wxString warning;
1058
1059 if( ( a->IsOnLayer( layer ) && isOnCorrespondingLayer( b, layer, &warning ) )
1060 || ( b->IsOnLayer( layer ) && isOnCorrespondingLayer( a, layer, &warning ) ) )
1061 {
1062 r = dialog->AddHTMLPage( m_frame->GetBoard()->GetLayerName( layer ) );
1063 reportHeader( _( "Silkscreen clearance resolution for:" ), a, b, layer, r );
1064
1065 constraint = drcEngine->EvalRules( SILK_CLEARANCE_CONSTRAINT, a, b, layer, r );
1066 clearance = constraint.m_Value.Min();
1067
1068 if( compileError )
1069 reportCompileError( r );
1070
1071 r->Report( "" );
1072
1073 if( !warning.IsEmpty() )
1074 r->Report( warning );
1075
1076 r->Report( wxString::Format( _( "Resolved min clearance: %s." ),
1077 m_frame->StringFromValue( clearance, true ) ) );
1078
1079 r->Flush();
1080 }
1081 }
1082
1083 for( PCB_LAYER_ID layer : { F_CrtYd, B_CrtYd } )
1084 {
1085 bool aCourtyard = aFP && !aFP->GetCourtyard( layer ).IsEmpty();
1086 bool bCourtyard = bFP && !bFP->GetCourtyard( layer ).IsEmpty();
1087
1088 if( aCourtyard && bCourtyard )
1089 {
1090 r = dialog->AddHTMLPage( m_frame->GetBoard()->GetLayerName( layer ) );
1091 reportHeader( _( "Courtyard clearance resolution for:" ), a, b, layer, r );
1092
1093 constraint = drcEngine->EvalRules( COURTYARD_CLEARANCE_CONSTRAINT, a, b, layer, r );
1094 clearance = constraint.m_Value.Min();
1095
1096 if( compileError )
1097 reportCompileError( r );
1098
1099 r->Report( "" );
1100 r->Report( wxString::Format( _( "Resolved min clearance: %s." ),
1101 m_frame->StringFromValue( clearance, true ) ) );
1102
1103 r->Flush();
1104 }
1105 }
1106
1107 if( a->HasHole() || b->HasHole() )
1108 {
1110 bool pageAdded = false;
1111
1112 if( a->HasHole() && b->IsOnLayer( active ) && IsCopperLayer( active ) )
1113 layer = active;
1114 else if( b->HasHole() && a->IsOnLayer( active ) && IsCopperLayer( active ) )
1115 layer = active;
1116 else if( a->HasHole() && b->IsOnCopperLayer() )
1117 layer = b->GetLayer();
1118 else if( b->HasHole() && b->IsOnCopperLayer() )
1119 layer = a->GetLayer();
1120
1121 if( layer >= 0 )
1122 {
1123 if( !pageAdded )
1124 {
1125 r = dialog->AddHTMLPage( _( "Hole" ) );
1126 pageAdded = true;
1127 }
1128 else
1129 {
1130 r->Report( "" );
1131 r->Report( "" );
1132 r->Report( "" );
1133 }
1134
1135 reportHeader( _( "Hole clearance resolution for:" ), a, b, layer, r );
1136
1137 constraint = drcEngine->EvalRules( HOLE_CLEARANCE_CONSTRAINT, a, b, layer, r );
1138 clearance = constraint.m_Value.Min();
1139
1140 if( compileError )
1141 reportCompileError( r );
1142
1143 r->Report( "" );
1144 r->Report( wxString::Format( _( "Resolved min clearance: %s." ),
1145 m_frame->StringFromValue( clearance, true ) ) );
1146
1147 r->Flush();
1148 }
1149
1150 if( a->HasDrilledHole() || b->HasDrilledHole() )
1151 {
1152 if( !pageAdded )
1153 {
1154 r = dialog->AddHTMLPage( _( "Hole" ) );
1155 pageAdded = true;
1156 }
1157 else
1158 {
1159 r->Report( "" );
1160 r->Report( "" );
1161 r->Report( "" );
1162 }
1163
1164 reportHeader( _( "Hole-to-hole clearance resolution for:" ), a, b, r );
1165
1166 constraint = drcEngine->EvalRules( HOLE_TO_HOLE_CONSTRAINT, a, b, UNDEFINED_LAYER, r );
1167 clearance = constraint.m_Value.Min();
1168
1169 if( compileError )
1170 reportCompileError( r );
1171
1172 r->Report( "" );
1173 r->Report( wxString::Format( _( "Resolved min clearance: %s." ),
1174 m_frame->StringFromValue( clearance, true ) ) );
1175
1176 r->Flush();
1177 }
1178 }
1179
1180 for( PCB_LAYER_ID edgeLayer : { Edge_Cuts, Margin } )
1181 {
1183
1184 if( a->IsOnLayer( edgeLayer ) && b->Type() != PCB_FOOTPRINT_T )
1185 {
1186 if( b->IsOnLayer( active ) && IsCopperLayer( active ) )
1187 layer = active;
1188 else if( IsCopperLayer( b->GetLayer() ) )
1189 layer = b->GetLayer();
1190 }
1191 else if( b->IsOnLayer( edgeLayer ) && a->Type() != PCB_FOOTPRINT_T )
1192 {
1193 if( a->IsOnLayer( active ) && IsCopperLayer( active ) )
1194 layer = active;
1195 else if( IsCopperLayer( a->GetLayer() ) )
1196 layer = a->GetLayer();
1197 }
1198
1199 if( layer >= 0 )
1200 {
1201 wxString layerName = m_frame->GetBoard()->GetLayerName( edgeLayer );
1202 r = dialog->AddHTMLPage( layerName + wxS( " " ) + _( "Clearance" ) );
1203 reportHeader( _( "Edge clearance resolution for:" ), a, b, layer, r );
1204
1205 constraint = drcEngine->EvalRules( EDGE_CLEARANCE_CONSTRAINT, a, b, layer, r );
1206 clearance = constraint.m_Value.Min();
1207
1208 if( compileError )
1209 reportCompileError( r );
1210
1211 r->Report( "" );
1212 r->Report( wxString::Format( _( "Resolved min clearance: %s." ),
1213 m_frame->StringFromValue( clearance, true ) ) );
1214
1215 r->Flush();
1216 }
1217 }
1218
1219 r = dialog->AddHTMLPage( _( "Physical Clearances" ) );
1220
1221 if( compileError )
1222 {
1223 reportCompileError( r );
1224 }
1225 else if( !drcEngine->HasRulesForConstraintType( PHYSICAL_CLEARANCE_CONSTRAINT ) )
1226 {
1227 r->Report( "" );
1228 r->Report( _( "No 'physical_clearance' constraints defined." ) );
1229 }
1230 else
1231 {
1232 LSET reportLayers = layerIntersection;
1233 bool reported = false;
1234
1235 if( a->IsOnLayer( Edge_Cuts ) )
1236 {
1237 LSET edgeInteractingLayers = bFP ? LSET( { F_CrtYd, B_CrtYd } )
1239 reportLayers |= edgeInteractingLayers;
1240 }
1241
1242 if( b->IsOnLayer( Edge_Cuts ) )
1243 {
1244 LSET edgeInteractingLayers = aFP ? LSET( { F_CrtYd, B_CrtYd } )
1246 reportLayers |= edgeInteractingLayers;
1247 }
1248
1249 for( PCB_LAYER_ID layer : reportLayers )
1250 {
1251 reported = true;
1252 reportHeader( _( "Physical clearance resolution for:" ), a, b, layer, r );
1253
1254 constraint = drcEngine->EvalRules( PHYSICAL_CLEARANCE_CONSTRAINT, a, b, layer, r );
1255 clearance = constraint.m_Value.Min();
1256
1257 if( constraint.IsNull() )
1258 {
1259 r->Report( "" );
1260 r->Report( wxString::Format( _( "No 'physical_clearance' constraints in effect on %s." ),
1261 m_frame->GetBoard()->GetLayerName( layer ) ) );
1262 }
1263 else
1264 {
1265 r->Report( "" );
1266 r->Report( wxString::Format( _( "Resolved min clearance: %s." ),
1267 m_frame->StringFromValue( clearance, true ) ) );
1268 }
1269
1270 r->Report( "" );
1271 r->Report( "" );
1272 r->Report( "" );
1273 }
1274
1275 if( !reported )
1276 {
1277 reportHeader( _( "Physical clearance resolution for:" ), a, b, r );
1278 r->Report( "" );
1279 r->Report( _( "Items share no relevant layers. No 'physical_clearance' constraints will "
1280 "be applied." ) );
1281 }
1282 }
1283
1284 if( a->HasHole() || b->HasHole() )
1285 {
1286 PCB_LAYER_ID layer;
1287
1288 if( a->HasHole() && b->IsOnLayer( active ) )
1289 layer = active;
1290 else if( b->HasHole() && a->IsOnLayer( active ) )
1291 layer = active;
1292 else if( a->HasHole() )
1293 layer = b->GetLayer();
1294 else
1295 layer = a->GetLayer();
1296
1297 reportHeader( _( "Physical hole clearance resolution for:" ), a, b, layer, r );
1298
1299 constraint = drcEngine->EvalRules( PHYSICAL_HOLE_CLEARANCE_CONSTRAINT, a, b, layer, r );
1300 clearance = constraint.m_Value.Min();
1301
1302 if( compileError )
1303 {
1304 reportCompileError( r );
1305 }
1306 else if( !drcEngine->HasRulesForConstraintType( PHYSICAL_HOLE_CLEARANCE_CONSTRAINT ) )
1307 {
1308 r->Report( "" );
1309 r->Report( _( "No 'physical_hole_clearance' constraints defined." ) );
1310 }
1311 else
1312 {
1313 r->Report( "" );
1314 r->Report( wxString::Format( _( "Resolved min clearance: %s." ),
1315 m_frame->StringFromValue( clearance, true ) ) );
1316 }
1317 }
1318
1319 r->Flush();
1320
1321 dialog->Raise();
1322 dialog->Show( true );
1323 return 0;
1324}
1325
1326
1328{
1329#define EVAL_RULES( constraint, a, b, layer, r ) drcEngine->EvalRules( constraint, a, b, layer, r )
1330
1331 wxCHECK( m_frame, 0 );
1332
1334
1335 wxCHECK( selTool, 0 );
1336
1337 const PCB_SELECTION& selection = selTool->GetSelection();
1338
1339 if( selection.Size() != 1 )
1340 {
1341 m_frame->ShowInfoBarError( _( "Select an item for a constraints resolution report." ) );
1342 return 0;
1343 }
1344
1346
1347 wxCHECK( dialog, 0 );
1348
1349 dialog->DeleteAllPages();
1350
1351 if( !selection.GetItem( 0 )->IsBOARD_ITEM() )
1352 return 0;
1353
1354 BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.GetItem( 0 ) );
1355 DRC_CONSTRAINT constraint;
1356
1357 bool compileError = false;
1358 bool courtyardError = false;
1359 std::unique_ptr<DRC_ENGINE> drcEngine = makeDRCEngine( &compileError, &courtyardError );
1360
1361 WX_HTML_REPORT_BOX* r = nullptr;
1362
1363 if( item->Type() == PCB_TRACE_T )
1364 {
1365 r = dialog->AddHTMLPage( _( "Track Width" ) );
1366 reportHeader( _( "Track width resolution for:" ), item, r );
1367
1368 constraint = EVAL_RULES( TRACK_WIDTH_CONSTRAINT, item, nullptr, item->GetLayer(), r );
1369
1370 if( compileError )
1371 reportCompileError( r );
1372
1373 r->Report( "" );
1374 r->Report( wxString::Format( _( "Resolved width constraints: min %s; opt %s; max %s." ),
1375 reportMin( m_frame, constraint ),
1376 reportOpt( m_frame, constraint ),
1377 reportMax( m_frame, constraint ) ) );
1378
1379 r->Flush();
1380 }
1381
1382 if( item->Type() == PCB_VIA_T )
1383 {
1384 r = dialog->AddHTMLPage( _( "Via Diameter" ) );
1385 reportHeader( _( "Via diameter resolution for:" ), item, r );
1386
1387 // PADSTACKS TODO: once we have padstacks we'll need to run this per-layer....
1388 constraint = EVAL_RULES( VIA_DIAMETER_CONSTRAINT, item, nullptr, UNDEFINED_LAYER, r );
1389
1390 if( compileError )
1391 reportCompileError( r );
1392
1393 r->Report( "" );
1394 r->Report( wxString::Format( _( "Resolved diameter constraints: min %s; opt %s; max %s." ),
1395 reportMin( m_frame, constraint ),
1396 reportOpt( m_frame, constraint ),
1397 reportMax( m_frame, constraint ) ) );
1398
1399 r->Flush();
1400
1401 r = dialog->AddHTMLPage( _( "Via Annular Width" ) );
1402 reportHeader( _( "Via annular width resolution for:" ), item, r );
1403
1404 // PADSTACKS TODO: once we have padstacks we'll need to run this per-layer....
1405 constraint = EVAL_RULES( ANNULAR_WIDTH_CONSTRAINT, item, nullptr, UNDEFINED_LAYER, r );
1406
1407 if( compileError )
1408 reportCompileError( r );
1409
1410 r->Report( "" );
1411 r->Report( wxString::Format( _( "Resolved annular width constraints: min %s; opt %s; max %s." ),
1412 reportMin( m_frame, constraint ),
1413 reportOpt( m_frame, constraint ),
1414 reportMax( m_frame, constraint ) ) );
1415
1416 r->Flush();
1417 }
1418
1419 if( ( item->Type() == PCB_PAD_T && static_cast<PAD*>( item )->GetDrillSize().x > 0 )
1420 || item->Type() == PCB_VIA_T )
1421 {
1422 r = dialog->AddHTMLPage( _( "Hole Size" ) );
1423 reportHeader( _( "Hole size resolution for:" ), item, r );
1424
1425 // PADSTACKS TODO: once we have padstacks we'll need to run this per-layer....
1426 constraint = EVAL_RULES( HOLE_SIZE_CONSTRAINT, item, nullptr, UNDEFINED_LAYER, r );
1427
1428 if( compileError )
1429 reportCompileError( r );
1430
1431 r->Report( "" );
1432 r->Report( wxString::Format( _( "Resolved hole size constraints: min %s; opt %s; max %s." ),
1433 reportMin( m_frame, constraint ),
1434 reportOpt( m_frame, constraint ),
1435 reportMax( m_frame, constraint ) ) );
1436
1437 r->Flush();
1438 }
1439
1440 if( item->Type() == PCB_FIELD_T || item->Type() == PCB_TEXT_T || item->Type() == PCB_TEXTBOX_T )
1441 {
1442 r = dialog->AddHTMLPage( _( "Text Size" ) );
1443 reportHeader( _( "Text height resolution for:" ), item, r );
1444
1445 constraint = EVAL_RULES( TEXT_HEIGHT_CONSTRAINT, item, nullptr, UNDEFINED_LAYER, r );
1446
1447 if( compileError )
1448 reportCompileError( r );
1449
1450 r->Report( "" );
1451 r->Report( wxString::Format( _( "Resolved height constraints: min %s; opt %s; max %s." ),
1452 reportMin( m_frame, constraint ),
1453 reportOpt( m_frame, constraint ),
1454 reportMax( m_frame, constraint ) ) );
1455
1456 r->Report( "" );
1457 r->Report( "" );
1458 r->Report( "" );
1459 reportHeader( _( "Text thickness resolution for:" ), item, r );
1460
1461 constraint = EVAL_RULES( TEXT_THICKNESS_CONSTRAINT, item, nullptr, UNDEFINED_LAYER, r );
1462
1463 if( compileError )
1464 reportCompileError( r );
1465
1466 r->Report( "" );
1467 r->Report( wxString::Format( _( "Resolved thickness constraints: min %s; opt %s; max %s." ),
1468 reportMin( m_frame, constraint ),
1469 reportOpt( m_frame, constraint ),
1470 reportMax( m_frame, constraint ) ) );
1471
1472 r->Flush();
1473 }
1474
1475 r = dialog->AddHTMLPage( _( "Keepouts" ) );
1476 reportHeader( _( "Keepout resolution for:" ), item, r );
1477
1478 constraint = EVAL_RULES( DISALLOW_CONSTRAINT, item, nullptr, item->GetLayer(), r );
1479
1480 if( compileError )
1481 reportCompileError( r );
1482
1483 if( courtyardError )
1484 {
1485 r->Report( "" );
1486 r->Report( _( "Report may be incomplete: some footprint courtyards are malformed." )
1487 + wxS( "&nbsp;&nbsp;" )
1488 + wxS( "<a href='$DRC'>" ) + _( "Run DRC for a full analysis." )
1489 + wxS( "</a>" ) );
1490 }
1491
1492 r->Report( "" );
1493
1494 if( constraint.m_DisallowFlags )
1495 r->Report( _( "Item <b>disallowed</b> at current location." ) );
1496 else
1497 r->Report( _( "Item allowed at current location." ) );
1498
1499 r->Flush();
1500
1501 r = dialog->AddHTMLPage( _( "Assertions" ) );
1502 reportHeader( _( "Assertions for:" ), item, r );
1503
1504 if( compileError )
1505 reportCompileError( r );
1506
1507 if( courtyardError )
1508 {
1509 r->Report( "" );
1510 r->Report( _( "Report may be incomplete: some footprint courtyards are malformed." )
1511 + wxS( "&nbsp;&nbsp;" )
1512 + wxS( "<a href='$DRC'>" ) + _( "Run DRC for a full analysis." )
1513 + wxS( "</a>" ) );
1514 }
1515
1516 drcEngine->ProcessAssertions( item, []( const DRC_CONSTRAINT* c ){}, r );
1517 r->Flush();
1518
1519 dialog->Raise();
1520 dialog->Show( true );
1521 return 0;
1522}
1523
1524
1526{
1527 wxCHECK( m_frame, 0 );
1528
1530
1531 wxCHECK( selTool, 0 );
1532
1533 const PCB_SELECTION& selection = selTool->RequestSelection(
1534 []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
1535 {
1536 // Iterate from the back so we don't have to worry about removals.
1537 for( int i = aCollector.GetCount() - 1; i >= 0; --i )
1538 {
1539 BOARD_ITEM* item = aCollector[ i ];
1540
1541 if( !dynamic_cast<FOOTPRINT*>( item ) )
1542 aCollector.Remove( item );
1543 }
1544 },
1545 false /* ignore locked flag */ );
1546
1547 if( selection.Size() == 1 )
1548 DiffFootprint( static_cast<FOOTPRINT*>( selection.GetItem( 0 ) ) );
1549 else
1550 m_frame->ShowInfoBarError( _( "Select a footprint to diff with its library equivalent." ) );
1551
1552 return 0;
1553}
1554
1555
1557{
1558 wxCHECK( m_frame, 0 );
1559
1561
1562 wxCHECK( selTool, 0 );
1563
1564 const PCB_SELECTION& selection = selTool->GetSelection();
1565
1566 if( selection.Size() != 1 || selection.Front()->Type() != PCB_FOOTPRINT_T )
1567 {
1568 m_frame->ShowInfoBarError( _( "Select a footprint for a footprint associations report." ) );
1569 return 0;
1570 }
1571
1573
1574 dlg.ShowModal();
1575
1576 return 0;
1577}
1578
1579
1581{
1583
1584 wxCHECK( dialog, /* void */ );
1585
1586 dialog->DeleteAllPages();
1587
1588 LIB_ID fpID = aFootprint->GetFPID();
1589 wxString libName = fpID.GetLibNickname();
1590 wxString fpName = fpID.GetLibItemName();
1591 WX_HTML_REPORT_BOX* r = nullptr;
1592
1593 r = dialog->AddHTMLPage( _( "Summary" ) );
1594
1595 r->Report( wxS( "<h7>" ) + _( "Board vs library diff for:" ) + wxS( "</h7>" ) );
1596 r->Report( wxS( "<ul><li>" ) + EscapeHTML( getItemDescription( aFootprint ) ) + wxS( "</li>" )
1597 + wxS( "<li>" ) + _( "Library: " ) + EscapeHTML( libName ) + wxS( "</li>" )
1598 + wxS( "<li>" ) + _( "Library item: " ) + EscapeHTML( fpName ) + wxS( "</li></ul>" ) );
1599
1600 r->Report( "" );
1601
1602 PROJECT* project = aFootprint->GetBoard()->GetProject();
1604 const LIB_TABLE_ROW* libTableRow = nullptr;
1605
1606 try
1607 {
1608 libTableRow = libTable->FindRow( libName );
1609 }
1610 catch( const IO_ERROR& )
1611 {
1612 }
1613
1614 if( !libTableRow )
1615 {
1616 r->Report( _( "The library is not included in the current configuration." )
1617 + wxS( "&nbsp;&nbsp;&nbsp" )
1618 + wxS( "<a href='$CONFIG'>" ) + _( "Manage Footprint Libraries" )
1619 + wxS( "</a>" ) );
1620
1621 }
1622 else if( !libTable->HasLibrary( libName, true ) )
1623 {
1624 r->Report( _( "The library is not enabled in the current configuration." )
1625 + wxS( "&nbsp;&nbsp;&nbsp" )
1626 + wxS( "<a href='$CONFIG'>" ) + _( "Manage Footprint Libraries" )
1627 + wxS( "</a>" ) );
1628
1629 }
1630 else
1631 {
1632 std::shared_ptr<FOOTPRINT> libFootprint;
1633
1634 try
1635 {
1636 libFootprint.reset( libTable->FootprintLoad( libName, fpName, true ) );
1637 }
1638 catch( const IO_ERROR& )
1639 {
1640 }
1641
1642 if( !libFootprint )
1643 {
1644 r->Report( wxString::Format( _( "The library no longer contains the item %s." ),
1645 fpName) );
1646 }
1647 else
1648 {
1649 if( !aFootprint->FootprintNeedsUpdate( libFootprint.get(), 0, r ) )
1650 r->Report( _( "No relevant differences detected." ) );
1651
1652 wxPanel* panel = dialog->AddBlankPage( _( "Visual" ) );
1654
1655 diff->DisplayDiff( aFootprint, libFootprint );
1656 }
1657 }
1658
1659 r->Flush();
1660
1661 dialog->Raise();
1662 dialog->Show( true );
1663}
1664
1665
1667{
1668 wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
1669
1670 FOOTPRINT_DIFF_WIDGET* diffWidget = new FOOTPRINT_DIFF_WIDGET( aParentPanel, m_frame->Kiway() );
1671
1672 sizer->Add( diffWidget, 1, wxEXPAND | wxALL, 5 );
1673 aParentPanel->SetSizer( sizer );
1674 aParentPanel->Layout();
1675
1676 return diffWidget;
1677}
1678
1679
1681{
1682 BOARD_ITEM* item = aEvent.Parameter<BOARD_ITEM*>();
1683
1684 m_frame->m_probingSchToPcb = true; // recursion guard
1685 {
1687
1688 if( item )
1690 }
1691 m_frame->m_probingSchToPcb = false;
1692
1693 bool request3DviewRedraw = frame()->GetPcbNewSettings()->m_Display.m_Live3DRefresh;
1694
1695 if( item && item->Type() != PCB_FOOTPRINT_T )
1696 request3DviewRedraw = false;
1697
1698 // Update 3D viewer highlighting
1699 if( request3DviewRedraw )
1700 m_frame->Update3DView( false, true );
1701
1702 return 0;
1703}
1704
1705
1706 bool BOARD_INSPECTION_TOOL::highlightNet( const VECTOR2D& aPosition, bool aUseSelection )
1707{
1708 BOARD* board = static_cast<BOARD*>( m_toolMgr->GetModel() );
1711
1712 int net = -1;
1713 bool enableHighlight = false;
1714
1715 if( aUseSelection )
1716 {
1717 const PCB_SELECTION& selection = selectionTool->GetSelection();
1718 std::set<int> netcodes;
1719
1720 for( EDA_ITEM* item : selection )
1721 {
1722 if( BOARD_CONNECTED_ITEM* ci = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
1723 netcodes.insert( ci->GetNetCode() );
1724 }
1725
1726 enableHighlight = !netcodes.empty();
1727
1728 if( enableHighlight && netcodes.size() > 1 )
1729 {
1730 // If we are doing a multi-highlight, cross-probing back and other stuff is not
1731 // yet supported
1732 settings->SetHighlight( netcodes );
1734
1735 for( int multiNet : netcodes )
1736 board->SetHighLightNet( multiNet, true );
1737
1738 board->HighLightON();
1740 m_currentlyHighlighted = netcodes;
1741 return true;
1742 }
1743 else if( enableHighlight )
1744 {
1745 net = *netcodes.begin();
1746 }
1747 }
1748
1749 // If we didn't get a net to highlight from the selection, use the cursor
1750 if( net < 0 )
1751 {
1753 guide.SetIgnoreZoneFills( false );
1754
1755 PCB_LAYER_ID activeLayer = static_cast<PCB_LAYER_ID>( view()->GetTopLayer() );
1756 guide.SetPreferredLayer( activeLayer );
1757
1758 GENERAL_COLLECTOR collector;
1759 collector.Collect( board, { PCB_PAD_T, PCB_VIA_T, PCB_TRACE_T, PCB_ARC_T, PCB_SHAPE_T }, aPosition,
1760 guide );
1761
1762 if( collector.GetCount() == 0 )
1763 collector.Collect( board, { PCB_ZONE_T }, aPosition, guide );
1764
1765 // Apply the active selection filter, except we want to allow picking locked items for
1766 // highlighting even if the user has disabled them for selection
1767 PCB_SELECTION_FILTER_OPTIONS& filter = selectionTool->GetFilter();
1768
1769 bool saved = filter.lockedItems;
1770 filter.lockedItems = true;
1771
1772 selectionTool->FilterCollectedItems( collector, true );
1773
1774 filter.lockedItems = saved;
1775
1776 // Clear the previous highlight
1777 //m_frame->SendMessageToEESCHEMA( nullptr );
1778
1779 bool highContrast = settings->GetHighContrast();
1780 PCB_LAYER_ID contrastLayer = settings->GetPrimaryHighContrastLayer();
1781
1782 for( int i = collector.GetCount() - 1; i >= 0; i-- )
1783 {
1784 LSET itemLayers = collector[i]->GetLayerSet();
1785
1786 if( ( itemLayers & LSET::AllCuMask() ).none() ||
1787 ( highContrast && !itemLayers.Contains( contrastLayer ) ) )
1788 {
1789 collector.Remove( i );
1790 continue;
1791 }
1792 }
1793
1794 enableHighlight = ( collector.GetCount() > 0 );
1795
1796 // Obtain net code for the clicked item
1797 if( enableHighlight )
1798 {
1799 BOARD_CONNECTED_ITEM* targetItem = static_cast<BOARD_CONNECTED_ITEM*>( collector[0] );
1800
1801 if( targetItem->Type() == PCB_PAD_T )
1802 m_frame->SendCrossProbeItem( targetItem );
1803
1804 net = targetItem->GetNetCode();
1805 }
1806 }
1807
1808 const std::set<int>& netcodes = settings->GetHighlightNetCodes();
1809
1810 // Toggle highlight when the same net was picked
1811 if( !aUseSelection && netcodes.size() == 1 && netcodes.contains( net ) )
1812 enableHighlight = !settings->IsHighlightEnabled();
1813
1814 if( enableHighlight != settings->IsHighlightEnabled() || !netcodes.count( net ) )
1815 {
1816 if( !netcodes.empty() )
1817 m_lastHighlighted = netcodes;
1818
1819 settings->SetHighlight( enableHighlight, net );
1820 m_toolMgr->GetView()->UpdateAllLayersColor();
1821 }
1822
1823 // Store the highlighted netcode in the current board (for dialogs for instance)
1824 if( enableHighlight && net >= 0 )
1825 {
1826 m_currentlyHighlighted = netcodes;
1827 board->SetHighLightNet( net );
1828 board->HighLightON();
1829
1830 NETINFO_ITEM* netinfo = board->FindNet( net );
1831
1832 if( netinfo )
1833 {
1834 std::vector<MSG_PANEL_ITEM> items;
1835 netinfo->GetMsgPanelInfo( m_frame, items );
1836 m_frame->SetMsgPanel( items );
1837 m_frame->SendCrossProbeNetName( netinfo->GetNetname() );
1838 }
1839 }
1840 else
1841 {
1842 m_currentlyHighlighted.clear();
1843 board->ResetNetHighLight();
1844 m_frame->SetMsgPanel( board );
1845 m_frame->SendCrossProbeNetName( "" );
1846 }
1847
1848 return true;
1849}
1850
1851
1853{
1854 int netcode = aEvent.Parameter<int>();
1856 const std::set<int>& highlighted = settings->GetHighlightNetCodes();
1857
1858 if( netcode > 0 )
1859 {
1860 m_lastHighlighted = highlighted;
1861 settings->SetHighlight( true, netcode );
1863 m_currentlyHighlighted.clear();
1864 m_currentlyHighlighted.insert( netcode );
1865 }
1866 else if( aEvent.IsAction( &PCB_ACTIONS::highlightNetSelection ) )
1867 {
1868 // Highlight selection (cursor position will be ignored)
1869 highlightNet( getViewControls()->GetMousePosition(), true );
1870 }
1871 else if( aEvent.IsAction( &PCB_ACTIONS::toggleLastNetHighlight ) )
1872 {
1873 std::set<int> temp = highlighted;
1874 settings->SetHighlight( m_lastHighlighted );
1877 m_lastHighlighted = std::move( temp );
1878 }
1879 else if( aEvent.IsAction( &PCB_ACTIONS::toggleNetHighlight ) )
1880 {
1881 bool turnOn = highlighted.empty() && !m_currentlyHighlighted.empty();
1882 settings->SetHighlight( m_currentlyHighlighted, turnOn );
1884 }
1885 else // Highlight the net belonging to the item under the cursor
1886 {
1887 highlightNet( getViewControls()->GetMousePosition(), false );
1888 }
1889
1890 return 0;
1891}
1892
1893
1895{
1896 BOARD* board = static_cast<BOARD*>( m_toolMgr->GetModel() );
1898
1899 m_currentlyHighlighted.clear();
1900 m_lastHighlighted.clear();
1901
1903 settings->SetHighlight( false );
1907 return 0;
1908}
1909
1910
1912{
1914 BOARD* board = getModel<BOARD>();
1915
1916 // Deactivate other tools; particularly important if another PICKER is currently running
1917 Activate();
1918
1919 picker->SetCursor( KICURSOR::BULLSEYE );
1920
1921 picker->SetClickHandler(
1922 [this, board]( const VECTOR2D& pt ) -> bool
1923 {
1925
1929
1930 PCB_SELECTION& selection = selectionTool->GetSelection();
1931
1932 if( selection.Empty() )
1933 {
1936 selection = selectionTool->GetSelection();
1937 }
1938
1939 if( selection.Empty() )
1940 {
1941 // Clear the previous local ratsnest if we click off all items
1942 for( FOOTPRINT* fp : board->Footprints() )
1943 {
1944 for( PAD* pad : fp->Pads() )
1945 pad->SetLocalRatsnestVisible( displayOptions().m_ShowGlobalRatsnest );
1946 }
1947 }
1948 else
1949 {
1950 for( EDA_ITEM* item : selection )
1951 {
1952 if( PAD* pad = dyn_cast<PAD*>( item) )
1953 {
1954 pad->SetLocalRatsnestVisible( !pad->GetLocalRatsnestVisible() );
1955 }
1956 else if( FOOTPRINT* fp = dyn_cast<FOOTPRINT*>( item) )
1957 {
1958 if( !fp->Pads().empty() )
1959 {
1960 bool enable = !fp->Pads()[0]->GetLocalRatsnestVisible();
1961
1962 for( PAD* childPad : fp->Pads() )
1963 childPad->SetLocalRatsnestVisible( enable );
1964 }
1965 }
1966 }
1967 }
1968
1970
1971 return true;
1972 } );
1973
1974 picker->SetFinalizeHandler(
1975 [this, board]( int aCondition )
1976 {
1977 if( aCondition != PCB_PICKER_TOOL::END_ACTIVATE )
1978 {
1979 for( FOOTPRINT* fp : board->Footprints() )
1980 {
1981 for( PAD* pad : fp->Pads() )
1982 pad->SetLocalRatsnestVisible( displayOptions().m_ShowGlobalRatsnest );
1983 }
1984 }
1985 } );
1986
1988
1989 return 0;
1990}
1991
1992
1994{
1995 VECTOR2I delta = aEvent.Parameter<VECTOR2I>();
1996
1997 if( delta == VECTOR2I() )
1998 {
1999 // We can delete the existing map to force a recalculation
2000 delete m_dynamicData;
2001 m_dynamicData = nullptr;
2002 }
2003
2004 auto selectionTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
2005 auto& selection = selectionTool->GetSelection();
2006 auto connectivity = getModel<BOARD>()->GetConnectivity();
2007
2008 if( selection.Empty() )
2009 {
2010 connectivity->ClearLocalRatsnest();
2011 delete m_dynamicData;
2012 m_dynamicData = nullptr;
2013 }
2014 else
2015 {
2017 }
2018
2019 return 0;
2020}
2021
2022
2024{
2025 getModel<BOARD>()->GetConnectivity()->ClearLocalRatsnest();
2026 delete m_dynamicData;
2027 m_dynamicData = nullptr;
2028
2029 return 0;
2030}
2031
2032
2034{
2036 SELECTION& selection = selectionTool->GetSelection();
2037 std::shared_ptr<CONNECTIVITY_DATA> connectivity = board()->GetConnectivity();
2038 std::vector<BOARD_ITEM*> items;
2039 std::deque<EDA_ITEM*> queued_items( selection.begin(), selection.end() );
2040
2041 for( std::size_t i = 0; i < queued_items.size(); ++i )
2042 {
2043 if( !queued_items[i]->IsBOARD_ITEM() )
2044 continue;
2045
2046 BOARD_ITEM* item = static_cast<BOARD_ITEM*>( queued_items[i] );
2047
2048 wxCHECK2( item, continue );
2049
2050 if( item->Type() == PCB_FOOTPRINT_T )
2051 {
2052 for( PAD* pad : static_cast<FOOTPRINT*>( item )->Pads() )
2053 {
2054 if( pad->GetLocalRatsnestVisible() || displayOptions().m_ShowModuleRatsnest )
2055 items.push_back( pad );
2056 }
2057 }
2058 else if( item->Type() == PCB_GROUP_T || item->Type() == PCB_GENERATOR_T )
2059 {
2060 item->RunOnChildren( [ &queued_items ]( BOARD_ITEM *aItem )
2061 {
2062 queued_items.push_back( aItem );
2063 },
2064 RECURSE_MODE::RECURSE );
2065 }
2066 else if( BOARD_CONNECTED_ITEM* boardItem = dyn_cast<BOARD_CONNECTED_ITEM*>( item ) )
2067 {
2068 if( boardItem->GetLocalRatsnestVisible() || displayOptions().m_ShowModuleRatsnest )
2069 items.push_back( boardItem );
2070 }
2071 }
2072
2073 if( items.empty() || std::none_of( items.begin(), items.end(),
2074 []( const BOARD_ITEM* aItem )
2075 {
2076 return( aItem->Type() == PCB_TRACE_T
2077 || aItem->Type() == PCB_PAD_T
2078 || aItem->Type() == PCB_ARC_T
2079 || aItem->Type() == PCB_ZONE_T
2080 || aItem->Type() == PCB_FOOTPRINT_T
2081 || aItem->Type() == PCB_VIA_T
2082 || aItem->Type() == PCB_SHAPE_T );
2083 } ) )
2084 {
2085 return;
2086 }
2087
2088 if( !m_dynamicData )
2089 {
2090 m_dynamicData = new CONNECTIVITY_DATA( board()->GetConnectivity(), items, true );
2091 connectivity->BlockRatsnestItems( items );
2092 }
2093 else
2094 {
2095 m_dynamicData->Move( aDelta );
2096 }
2097
2098 connectivity->ComputeLocalRatsnest( items, m_dynamicData );
2099}
2100
2101
2103{
2104 doHideRatsnestNet( aEvent.Parameter<int>(), true );
2105 return 0;
2106}
2107
2108
2110{
2111 doHideRatsnestNet( aEvent.Parameter<int>(), false );
2112 return 0;
2113}
2114
2115
2116void BOARD_INSPECTION_TOOL::doHideRatsnestNet( int aNetCode, bool aHide )
2117{
2120
2122 SELECTION& selection = selectionTool->GetSelection();
2123
2124 if( aNetCode <= 0 && !selection.Empty() )
2125 {
2126 for( EDA_ITEM* item : selection )
2127 {
2128 if( BOARD_CONNECTED_ITEM* bci = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
2129 {
2130 if( bci->GetNetCode() > 0 )
2131 doHideRatsnestNet( bci->GetNetCode(), aHide );
2132 }
2133 }
2134
2135 return;
2136 }
2137
2138 if( aHide )
2139 rs->GetHiddenNets().insert( aNetCode );
2140 else
2141 rs->GetHiddenNets().erase( aNetCode );
2142
2144 {
2147
2148 m_frame->GetAppearancePanel()->OnNetVisibilityChanged( aNetCode, !aHide );
2149 }
2150}
2151
2152
2154{
2158
2164
2171
2174}
#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:208
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:78
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:235
virtual bool IsConnected() const
Returns information if the object is derived from BOARD_CONNECTED_ITEM.
Definition: board_item.h:137
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Test to see if this object is on the given layer.
Definition: board_item.h:317
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:54
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:255
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:176
virtual void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction, RECURSE_MODE aMode) const
Invoke a function on all children.
Definition: board_item.h:211
virtual bool HasDrilledHole() const
Definition: board_item.h:164
virtual bool IsOnCopperLayer() const
Definition: board_item.h:154
virtual bool HasHole() const
Definition: board_item.h:159
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:297
void SetHighLightNet(int aNetCode, bool aMulti=false)
Select the netcode to be highlighted.
Definition: board.cpp:2772
BOARD_ITEM * GetItem(const KIID &aID) const
Definition: board.cpp:1501
const ZONES & Zones() const
Definition: board.h:342
void ResetNetHighLight()
Reset all high light data to the init state.
Definition: board.cpp:2763
const FOOTPRINTS & Footprints() const
Definition: board.h:338
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:614
PROJECT * GetProject() const
Definition: board.h:511
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:946
void HighLightON(bool aValue=true)
Enable or disable net highlighting.
Definition: board.cpp:2785
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:495
int GetCount() const
Return the number of objects in the list.
Definition: collector.h:82
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:95
virtual wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const
Return a user-visible description string of this item.
Definition: eda_item.cpp:115
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:107
EDA_ITEM_FLAGS GetFlags() const
Definition: eda_item.h:134
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:3121
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:3132
void DisplayDiff(FOOTPRINT *aBoardFootprint, std::shared_ptr< FOOTPRINT > &aLibFootprint)
Set the currently displayed symbol.
ZONES & Zones()
Definition: footprint.h:217
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:211
const LIB_ID & GetFPID() const
Definition: footprint.h:253
void BuildCourtyardCaches(OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr)
Build complex polygons of the courtyard areas from graphic items on the courtyard layers.
Definition: footprint.cpp:3010
const SHAPE_POLY_SET & GetCourtyard(PCB_LAYER_ID aLayer) const
Used in DRC to test the courtyard area (a complex polygon).
Definition: footprint.cpp:2987
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:79
std::set< int > & GetHiddenNets()
Definition: pcb_painter.h:139
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:572
static LSET PhysicalLayersMask()
Return a mask holding all layers which are physically realized.
Definition: lset.cpp:658
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:297
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:305
PAD_ATTRIB GetAttribute() const
Definition: pad.h:440
static TOOL_ACTION highlightItem
Definition: pcb_actions.h:582
static TOOL_ACTION toggleNetHighlight
Definition: pcb_actions.h:580
static TOOL_ACTION selectionCursor
Select a single item under the cursor position.
Definition: pcb_actions.h:66
static TOOL_ACTION highlightNet
Definition: pcb_actions.h:578
static TOOL_ACTION hideNetInRatsnest
Definition: pcb_actions.h:585
static TOOL_ACTION hideLocalRatsnest
Definition: pcb_actions.h:588
static TOOL_ACTION showNetInRatsnest
Definition: pcb_actions.h:586
static TOOL_ACTION cleanupTracksAndVias
Definition: pcb_actions.h:430
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:69
static TOOL_ACTION toggleLastNetHighlight
Definition: pcb_actions.h:579
static TOOL_ACTION inspectConstraints
Definition: pcb_actions.h:572
static TOOL_ACTION clearHighlight
Definition: pcb_actions.h:577
static TOOL_ACTION inspectClearance
Definition: pcb_actions.h:571
static TOOL_ACTION updateLocalRatsnest
Definition: pcb_actions.h:589
static TOOL_ACTION diffFootprint
Definition: pcb_actions.h:573
static TOOL_ACTION selectItem
Select an item (specified as the event parameter).
Definition: pcb_actions.h:72
static TOOL_ACTION showFootprintAssociations
Definition: pcb_actions.h:574
static TOOL_ACTION highlightNetSelection
Definition: pcb_actions.h:581
static TOOL_ACTION boardStatistics
Definition: pcb_actions.h:567
static TOOL_ACTION localRatsnestTool
Definition: pcb_actions.h:587
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:73
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:304
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:402
KIGFX::VIEW * GetView() const
Definition: tool_manager.h:395
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:74
std::optional< int > GetLocalClearance() const override
Definition: zone.cpp:795
virtual bool IsOnLayer(PCB_LAYER_ID) const override
Test to see if this object is on the given layer.
Definition: zone.cpp:642
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: zone.h:136
@ 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_STARVED_THERMAL
Definition: drc_item.h:49
@ 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:765
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition: layer_ids.h:663
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 ...
int clearance
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