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