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