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