KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_screen.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) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
6 * Copyright (C) 2008 Wayne Stambaugh <[email protected]>
7 * Copyright (C) 1992-2024 KiCad Developers, see AUTHORS.txt for contributors.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, you may find one here:
21 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22 * or you may search the http://www.gnu.org website for the version 2 license,
23 * or you may write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
27#include <stack>
28#include <wx/filefn.h>
29#include <wx/log.h>
30
31#include <eda_item.h>
32#include <id.h>
33#include <string_utils.h>
34#include <kiway.h>
35#include <plotters/plotter.h>
36#include <sch_plotter.h>
37#include <project.h>
38#include <project_sch.h>
39#include <reporter.h>
40#include <trace_helpers.h>
41#include <sch_edit_frame.h>
42#include <sch_item.h>
43
44#include <symbol_library.h>
45#include <connection_graph.h>
46#include <junction_helpers.h>
47#include <sch_pin.h>
48#include <sch_symbol.h>
49#include <sch_junction.h>
50#include <sch_line.h>
51#include <sch_marker.h>
52#include <sch_sheet.h>
53#include <sch_sheet_pin.h>
54#include <sch_text.h>
55#include <schematic.h>
56#include <symbol_lib_table.h>
57#include <tool/common_tools.h>
58#include <sim/sim_model.h> // For V6 to V7 simulation model migration.
59#include <locale_io.h>
60
61#include <algorithm>
62
63// TODO(JE) Debugging only
64#include <core/profile.h>
65#include "sch_bus_entry.h"
66
67/*
68 * Flag to enable profiling of the TestDanglingEnds() function.
69 * @ingroup trace_env_vars
70 */
71static const wxChar DanglingProfileMask[] = wxT( "DANGLING_PROFILE" );
72
74 BASE_SCREEN( aParent, SCH_SCREEN_T ),
75 m_fileFormatVersionAtLoad( 0 ),
76 m_paper( wxT( "A4" ) ),
77 m_isReadOnly( false ),
78 m_fileExists( false )
79{
81 m_refCount = 0;
82 m_zoomInitialized = false;
83 m_LastZoomLevel = 1.0;
84
85 // Suitable for schematic only. For symbol_editor and viewlib, must be set to true
86 m_Center = false;
87
89}
90
91
93{
96}
97
98
100{
101 wxCHECK_MSG( GetParent() && GetParent()->Type() == SCHEMATIC_T, nullptr,
102 wxT( "SCH_SCREEN must have a SCHEMATIC parent!" ) );
103
104 return static_cast<SCHEMATIC*>( GetParent() );
105}
106
107
109{
110 for( const std::pair<const wxString, LIB_SYMBOL*>& libSymbol : m_libSymbols )
111 delete libSymbol.second;
112
113 m_libSymbols.clear();
114}
115
116
117void SCH_SCREEN::SetFileName( const wxString& aFileName )
118{
119 wxASSERT( aFileName.IsEmpty() || wxIsAbsolutePath( aFileName ) );
120
121 m_fileName = aFileName;
122}
123
124
126{
127 m_refCount++;
128}
129
130
132{
133 wxCHECK_RET( m_refCount != 0, wxT( "Screen reference count already zero. Bad programmer!" ) );
134 m_refCount--;
135}
136
137
138bool SCH_SCREEN::HasItems( KICAD_T aItemType ) const
139{
140 EE_RTREE::EE_TYPE sheets = m_rtree.OfType( aItemType );
141
142 return sheets.begin() != sheets.end();
143}
144
145
146bool SCH_SCREEN::ClassOf( const EDA_ITEM* aItem )
147{
148 return aItem && SCH_SCREEN_T == aItem->Type();
149}
150
151
152void SCH_SCREEN::Append( SCH_ITEM* aItem, bool aUpdateLibSymbol )
153{
154 if( aItem->Type() != SCH_SHEET_PIN_T && aItem->Type() != SCH_FIELD_T )
155 {
156 // Ensure the item can reach the SCHEMATIC through this screen
157 aItem->SetParent( this );
158
159 if( aItem->Type() == SCH_SYMBOL_T && aUpdateLibSymbol )
160 {
161 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( aItem );
162
163 if( symbol->GetLibSymbolRef() )
164 {
165 symbol->GetLibSymbolRef()->GetDrawItems().sort();
166
167 auto it = m_libSymbols.find( symbol->GetSchSymbolLibraryName() );
168
169 if( it == m_libSymbols.end() || !it->second )
170 {
172 new LIB_SYMBOL( *symbol->GetLibSymbolRef() );
173 }
174 else
175 {
176 // The original library symbol may have changed since the last time
177 // it was added to the schematic. If it has changed, then a new name
178 // must be created for the library symbol list to prevent all of the
179 // other schematic symbols referencing that library symbol from changing.
180 LIB_SYMBOL* foundSymbol = it->second;
181
182 foundSymbol->GetDrawItems().sort();
183
184 if( *foundSymbol != *symbol->GetLibSymbolRef() )
185 {
186 wxString newName;
187 std::vector<wxString> matches;
188
189 getLibSymbolNameMatches( *symbol, matches );
190 foundSymbol = nullptr;
191
192 for( const wxString& libSymbolName : matches )
193 {
194 it = m_libSymbols.find( libSymbolName );
195
196 if( it == m_libSymbols.end() )
197 continue;
198
199 foundSymbol = it->second;
200
201 wxCHECK2( foundSymbol, continue );
202
203 wxString tmp = symbol->GetLibSymbolRef()->GetName();
204
205 // Temporarily update the new symbol library symbol name so it
206 // doesn't fail on the name comparison below.
207 symbol->GetLibSymbolRef()->SetName( foundSymbol->GetName() );
208
209 if( *foundSymbol == *symbol->GetLibSymbolRef() )
210 {
211 newName = libSymbolName;
212 symbol->GetLibSymbolRef()->SetName( tmp );
213 break;
214 }
215
216 symbol->GetLibSymbolRef()->SetName( tmp );
217 foundSymbol = nullptr;
218 }
219
220 if( !foundSymbol )
221 {
222 int cnt = 1;
223
224 newName.Printf( wxT( "%s_%d" ),
226 cnt );
227
228 while( m_libSymbols.find( newName ) != m_libSymbols.end() )
229 {
230 cnt += 1;
231 newName.Printf( wxT( "%s_%d" ),
233 cnt );
234 }
235 }
236
237 // Update the schematic symbol library link as this symbol only exists
238 // in the schematic.
239 symbol->SetSchSymbolLibraryName( newName );
240
241 if( !foundSymbol )
242 {
243 // Update the schematic symbol library link as this symbol does not
244 // exist in any symbol library.
245 LIB_ID newLibId( wxEmptyString, newName );
246 LIB_SYMBOL* newLibSymbol = new LIB_SYMBOL( *symbol->GetLibSymbolRef() );
247
248 newLibSymbol->SetLibId( newLibId );
249 newLibSymbol->SetName( newName );
250 symbol->SetLibSymbol( newLibSymbol->Flatten().release() );
251 m_libSymbols[newName] = newLibSymbol;
252 }
253 }
254 }
255 }
256 }
257
258 m_rtree.insert( aItem );
260 }
261}
262
263
265{
266 wxCHECK_RET( aScreen, "Invalid screen object." );
267
268 // No need to descend the hierarchy. Once the top level screen is copied, all of its
269 // children are copied as well.
270 for( SCH_ITEM* aItem : aScreen->m_rtree )
271 Append( aItem );
272
273 aScreen->Clear( false );
274}
275
276
277void SCH_SCREEN::Clear( bool aFree )
278{
279 if( aFree )
280 {
281 FreeDrawList();
283 }
284 else
285 {
286 m_rtree.clear();
287 }
288
289 // Clear the project settings
291
292 m_titles.Clear();
293}
294
295
297{
298 // We don't know which order we will encounter dependent items (e.g. pins or fields), so
299 // we store the items to be deleted until we've fully cleared the tree before deleting
300 std::vector<SCH_ITEM*> delete_list;
301
302 std::copy_if( m_rtree.begin(), m_rtree.end(), std::back_inserter( delete_list ),
303 []( SCH_ITEM* aItem )
304 {
305 return ( aItem->Type() != SCH_SHEET_PIN_T && aItem->Type() != SCH_FIELD_T );
306 } );
307
308 m_rtree.clear();
309
310 for( SCH_ITEM* item : delete_list )
311 delete item;
312}
313
314
315void SCH_SCREEN::Update( SCH_ITEM* aItem, bool aUpdateLibSymbol )
316{
317 if( Remove( aItem, aUpdateLibSymbol ) )
318 Append( aItem, aUpdateLibSymbol );
319}
320
321
322bool SCH_SCREEN::Remove( SCH_ITEM* aItem, bool aUpdateLibSymbol )
323{
324 bool retv = m_rtree.remove( aItem );
325
326 // Check if the library symbol for the removed schematic symbol is still required.
327 if( retv && aItem->Type() == SCH_SYMBOL_T && aUpdateLibSymbol )
328 {
329 SCH_SYMBOL* removedSymbol = static_cast<SCH_SYMBOL*>( aItem );
330
331 bool removeUnusedLibSymbol = true;
332
333 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
334 {
335 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
336
337 if( removedSymbol->GetSchSymbolLibraryName() == symbol->GetSchSymbolLibraryName() )
338 {
339 removeUnusedLibSymbol = false;
340 break;
341 }
342 }
343
344 if( removeUnusedLibSymbol )
345 {
346 auto it = m_libSymbols.find( removedSymbol->GetSchSymbolLibraryName() );
347
348 if( it != m_libSymbols.end() )
349 {
350 delete it->second;
351 m_libSymbols.erase( it );
352 }
353 }
354 }
355
356 return retv;
357}
358
359
361{
362 wxCHECK_RET( aItem, wxT( "Cannot delete invalid item from screen." ) );
363
364 // Markers are not saved in the file, no need to flag as modified.
365 // TODO: Maybe we should have a listing somewhere of items that aren't saved?
366 if( aItem->Type() != SCH_MARKER_T )
368
369 Remove( aItem );
370
371 if( aItem->Type() == SCH_SHEET_PIN_T )
372 {
373 // This structure is attached to a sheet, get the parent sheet object.
374 SCH_SHEET_PIN* sheetPin = (SCH_SHEET_PIN*) aItem;
375 SCH_SHEET* sheet = sheetPin->GetParent();
376 wxCHECK_RET( sheet, wxT( "Sheet pin parent not properly set, bad programmer!" ) );
377 sheet->RemovePin( sheetPin );
378 return;
379 }
380
381 delete aItem;
382}
383
384
385bool SCH_SCREEN::CheckIfOnDrawList( const SCH_ITEM* aItem ) const
386{
387 return m_rtree.contains( aItem, true );
388}
389
390
391SCH_ITEM* SCH_SCREEN::GetItem( const VECTOR2I& aPosition, int aAccuracy, KICAD_T aType ) const
392{
393 BOX2I bbox;
394 bbox.SetOrigin( aPosition );
395 bbox.Inflate( aAccuracy );
396
397 for( SCH_ITEM* item : Items().Overlapping( aType, bbox ) )
398 {
399 if( item->HitTest( aPosition, aAccuracy ) )
400 return item;
401 }
402
403 return nullptr;
404}
405
406
407std::set<SCH_ITEM*> SCH_SCREEN::MarkConnections( SCH_LINE* aSegment, bool aSecondPass )
408{
409#define PROCESSED CANDIDATE // Don't use SKIP_STRUCT; IsConnected() returns false if it's set.
410
411 std::set<SCH_ITEM*> retval;
412 std::stack<SCH_LINE*> to_search;
413
414 wxCHECK_MSG( aSegment && aSegment->Type() == SCH_LINE_T, retval, wxT( "Invalid pointer." ) );
415
416 to_search.push( aSegment );
417
418 while( !to_search.empty() )
419 {
420 SCH_ITEM* item = to_search.top();
421 to_search.pop();
422
423 if( item->HasFlag( PROCESSED ) )
424 continue;
425
426 item->SetFlags( PROCESSED );
427
428 for( SCH_ITEM* candidate : Items().Overlapping( SCH_LINE_T, item->GetBoundingBox() ) )
429 {
430 SCH_LINE* line = static_cast<SCH_LINE*>( candidate );
431
432 if( line->HasFlag( PROCESSED ) )
433 continue;
434
435 // Skip connecting lines on different layers (e.g. buses)
436 if( item->GetLayer() != line->GetLayer() )
437 continue;
438
439 for( VECTOR2I pt : { line->GetStartPoint(), line->GetEndPoint() } )
440 {
441 if( item->IsConnected( pt ) )
442 {
443 SCH_ITEM* junction = GetItem( pt, 0, SCH_JUNCTION_T );
444 SCH_ITEM* pin = GetItem( pt, 0, SCH_PIN_T );
445
446 if( item->IsSelected() && aSecondPass )
447 {
448 if( junction )
449 retval.insert( junction );
450
451 retval.insert( line );
452 to_search.push( line );
453 }
454 else if( !junction && !pin )
455 {
456 retval.insert( line );
457 to_search.push( line );
458 }
459
460 break;
461 }
462 else if( line->GetLayer() == LAYER_NOTES && item->GetLayer() == LAYER_NOTES )
463 {
464 retval.insert( line );
465 to_search.push( line );
466 }
467 }
468 }
469 }
470
471 for( SCH_ITEM* item : Items() )
472 item->ClearTempFlags();
473
474 return retval;
475}
476
477
478bool SCH_SCREEN::IsJunction( const VECTOR2I& aPosition ) const
479{
481 JUNCTION_HELPERS::AnalyzePoint( Items(), aPosition, false );
482 return info.isJunction;
483}
484
485
486bool SCH_SCREEN::IsExplicitJunction( const VECTOR2I& aPosition ) const
487{
489 JUNCTION_HELPERS::AnalyzePoint( Items(), aPosition, false );
490
491 return info.isJunction && ( !info.hasBusEntry || info.hasBusEntryToMultipleWires );
492}
493
494
495bool SCH_SCREEN::IsExplicitJunctionNeeded( const VECTOR2I& aPosition ) const
496{
498 JUNCTION_HELPERS::AnalyzePoint( Items(), aPosition, false );
499
500 return info.isJunction && ( !info.hasBusEntry || info.hasBusEntryToMultipleWires )
501 && !info.hasExplicitJunctionDot;
502}
503
504
506{
508 JUNCTION_HELPERS::AnalyzePoint( Items(), aPosition, true );
509
510 return info.isJunction && (!info.hasBusEntry || info.hasBusEntryToMultipleWires );
511}
512
513
515 SPIN_STYLE aDefaultOrientation,
516 const SCH_SHEET_PATH* aSheet ) const
517{
518 auto ret = aDefaultOrientation;
519 for( SCH_ITEM* item : Items().Overlapping( aPosition ) )
520 {
521 if( item->GetEditFlags() & STRUCT_DELETED )
522 continue;
523
524 switch( item->Type() )
525 {
527 {
528 auto busEntry = static_cast<const SCH_BUS_WIRE_ENTRY*>( item );
529 if( busEntry->m_connected_bus_item )
530 {
531 // bus connected, take the bus direction into consideration ony if it is
532 // vertical or horizontal
533 auto bus = static_cast<const SCH_LINE*>( busEntry->m_connected_bus_item );
534 if( bus->Angle().AsDegrees() == 90.0 )
535 {
536 // bus is vertical -> label shall be horizontal and
537 // shall be placed to the side where the bus entry is
538 if( aPosition.x < bus->GetPosition().x )
539 ret = SPIN_STYLE::LEFT;
540 else if( aPosition.x > bus->GetPosition().x )
541 ret = SPIN_STYLE::RIGHT;
542 }
543 else if( bus->Angle().AsDegrees() == 0.0 )
544 {
545 // bus is horizontal -> label shall be vertical and
546 // shall be placed to the side where the bus entry is
547 if( aPosition.y < bus->GetPosition().y )
548 ret = SPIN_STYLE::UP;
549 else if( aPosition.y > bus->GetPosition().y )
550 ret = SPIN_STYLE::BOTTOM;
551 }
552 }
553 }
554 break;
555
556 case SCH_LINE_T:
557 {
558 auto line = static_cast<const SCH_LINE*>( item );
559 // line angles goes between -90 and 90 degrees, but normalize
560 auto angle = line->Angle().Normalize90().AsDegrees();
561
562 if( -45 < angle && angle <= 45 )
563 {
564 if( line->GetStartPoint().x <= line->GetEndPoint().x )
565 ret = line->GetEndPoint() == aPosition ? SPIN_STYLE::RIGHT : SPIN_STYLE::LEFT;
566 else
567 ret = line->GetEndPoint() == aPosition ? SPIN_STYLE::LEFT : SPIN_STYLE::RIGHT;
568 }
569 else
570 {
571 if( line->GetStartPoint().y <= line->GetEndPoint().y )
572 ret = line->GetEndPoint() == aPosition ? SPIN_STYLE::BOTTOM : SPIN_STYLE::UP;
573 else
574 ret = line->GetEndPoint() == aPosition ? SPIN_STYLE::UP : SPIN_STYLE::BOTTOM;
575 }
576 }
577 break;
578
579 case SCH_SYMBOL_T:
580 {
581 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
582
583 for( SCH_PIN* pin : symbol->GetPins( aSheet ) )
584 {
585 if( pin->GetPosition() == aPosition )
586 {
587 if( pin->GetOrientation() == PIN_ORIENTATION::PIN_RIGHT )
588 ret = SPIN_STYLE::LEFT;
589 else if( pin->GetOrientation() == PIN_ORIENTATION::PIN_LEFT )
590 ret = SPIN_STYLE::RIGHT;
591 else if( pin->GetOrientation() == PIN_ORIENTATION::PIN_UP )
592 ret = SPIN_STYLE::BOTTOM;
593 else if( pin->GetOrientation() == PIN_ORIENTATION::PIN_DOWN )
594 ret = SPIN_STYLE::UP;
595
596 switch( static_cast<SYMBOL_ORIENTATION_T>(
597 symbol->GetOrientation() & ( ~( SYM_MIRROR_X | SYM_MIRROR_Y ) ) ) )
598 {
600 case SYM_ORIENT_90:
601 if( ret == SPIN_STYLE::UP )
602 ret = SPIN_STYLE::LEFT;
603 else if( ret == SPIN_STYLE::BOTTOM )
604 ret = SPIN_STYLE::RIGHT;
605 else if( ret == SPIN_STYLE::LEFT )
606 ret = SPIN_STYLE::BOTTOM;
607 else if( ret == SPIN_STYLE::RIGHT )
608 ret = SPIN_STYLE::UP;
609
610 if( symbol->GetOrientation() & SYM_MIRROR_X )
611 {
612 if( ret == SPIN_STYLE::UP )
613 ret = SPIN_STYLE::BOTTOM;
614 else if( ret == SPIN_STYLE::BOTTOM )
615 ret = SPIN_STYLE::UP;
616 }
617
618 if( symbol->GetOrientation() & SYM_MIRROR_Y )
619 {
620 if( ret == SPIN_STYLE::LEFT )
621 ret = SPIN_STYLE::RIGHT;
622 else if( ret == SPIN_STYLE::RIGHT )
623 ret = SPIN_STYLE::LEFT;
624 }
625 break;
627 case SYM_ORIENT_270:
628 if( ret == SPIN_STYLE::UP )
629 ret = SPIN_STYLE::RIGHT;
630 else if( ret == SPIN_STYLE::BOTTOM )
631 ret = SPIN_STYLE::LEFT;
632 else if( ret == SPIN_STYLE::LEFT )
633 ret = SPIN_STYLE::UP;
634 else if( ret == SPIN_STYLE::RIGHT )
635 ret = SPIN_STYLE::BOTTOM;
636
637 if( symbol->GetOrientation() & SYM_MIRROR_X )
638 {
639 if( ret == SPIN_STYLE::UP )
640 ret = SPIN_STYLE::BOTTOM;
641 else if( ret == SPIN_STYLE::BOTTOM )
642 ret = SPIN_STYLE::UP;
643 }
644
645 if( symbol->GetOrientation() & SYM_MIRROR_Y )
646 {
647 if( ret == SPIN_STYLE::LEFT )
648 ret = SPIN_STYLE::RIGHT;
649 else if( ret == SPIN_STYLE::RIGHT )
650 ret = SPIN_STYLE::LEFT;
651 }
652 break;
653 case SYM_ORIENT_180:
654 if( ret == SPIN_STYLE::UP )
655 ret = SPIN_STYLE::BOTTOM;
656 else if( ret == SPIN_STYLE::BOTTOM )
657 ret = SPIN_STYLE::UP;
658 else if( ret == SPIN_STYLE::LEFT )
659 ret = SPIN_STYLE::RIGHT;
660 else if( ret == SPIN_STYLE::RIGHT )
661 ret = SPIN_STYLE::LEFT;
662
663 if( symbol->GetOrientation() & SYM_MIRROR_X )
664 {
665 if( ret == SPIN_STYLE::UP )
666 ret = SPIN_STYLE::BOTTOM;
667 else if( ret == SPIN_STYLE::BOTTOM )
668 ret = SPIN_STYLE::UP;
669 }
670
671 if( symbol->GetOrientation() & SYM_MIRROR_Y )
672 {
673 if( ret == SPIN_STYLE::LEFT )
674 ret = SPIN_STYLE::RIGHT;
675 else if( ret == SPIN_STYLE::RIGHT )
676 ret = SPIN_STYLE::LEFT;
677 }
678 break;
679 case SYM_ORIENT_0:
680 case SYM_NORMAL:
681 default:
682 if( symbol->GetOrientation() & SYM_MIRROR_X )
683 {
684 if( ret == SPIN_STYLE::UP )
685 ret = SPIN_STYLE::BOTTOM;
686 else if( ret == SPIN_STYLE::BOTTOM )
687 ret = SPIN_STYLE::UP;
688 }
689
690 if( symbol->GetOrientation() & SYM_MIRROR_Y )
691 {
692 if( ret == SPIN_STYLE::LEFT )
693 ret = SPIN_STYLE::RIGHT;
694 else if( ret == SPIN_STYLE::RIGHT )
695 ret = SPIN_STYLE::LEFT;
696 }
697 break;
698 }
699
700 break;
701 }
702 }
703 }
704 break;
705 default: break;
706 }
707 }
708 return ret;
709}
710
711
712bool SCH_SCREEN::IsTerminalPoint( const VECTOR2I& aPosition, int aLayer ) const
713{
714 wxCHECK_MSG( aLayer == LAYER_NOTES || aLayer == LAYER_BUS || aLayer == LAYER_WIRE, false,
715 wxT( "Invalid layer type passed to SCH_SCREEN::IsTerminalPoint()." ) );
716
717 SCH_SHEET_PIN* sheetPin;
718 SCH_LABEL_BASE* label;
719
720 switch( aLayer )
721 {
722 case LAYER_BUS:
723 if( GetBus( aPosition ) )
724 return true;
725
726 sheetPin = GetSheetPin( aPosition );
727
728 if( sheetPin && sheetPin->IsConnected( aPosition ) )
729 return true;
730
731 label = GetLabel( aPosition );
732
733 if( label && !label->IsNew() && label->IsConnected( aPosition ) )
734 return true;
735
736 break;
737
738 case LAYER_NOTES:
739 if( GetLine( aPosition ) )
740 return true;
741
742 break;
743
744 case LAYER_WIRE:
745 if( GetItem( aPosition, 1, SCH_BUS_WIRE_ENTRY_T ) )
746 return true;
747
748 if( GetItem( aPosition, 1, SCH_JUNCTION_T ) )
749 return true;
750
751 if( GetPin( aPosition, nullptr, true ) )
752 return true;
753
754 if( GetWire( aPosition ) )
755 return true;
756
757 label = GetLabel( aPosition, 1 );
758
759 if( label && !label->IsNew() && label->IsConnected( aPosition ) )
760 return true;
761
762 sheetPin = GetSheetPin( aPosition );
763
764 if( sheetPin && sheetPin->IsConnected( aPosition ) )
765 return true;
766
767 break;
768
769 default:
770 break;
771 }
772
773 return false;
774}
775
776
778{
779 wxCHECK_RET( Schematic(), "Cannot call SCH_SCREEN::UpdateSymbolLinks with no SCHEMATIC" );
780
781 wxString msg;
782 std::unique_ptr< LIB_SYMBOL > libSymbol;
783 std::vector<SCH_SYMBOL*> symbols;
785
786 // This will be a nullptr if an s-expression schematic is loaded.
787 SYMBOL_LIBS* legacyLibs = PROJECT_SCH::SchLibs( &Schematic()->Prj() );
788
789 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
790 symbols.push_back( static_cast<SCH_SYMBOL*>( item ) );
791
792 // Remove them from the R tree. There bounding box size may change.
793 for( SCH_SYMBOL* symbol : symbols )
794 Remove( symbol );
795
796 // Clear all existing symbol links.
798
799 for( SCH_SYMBOL* symbol : symbols )
800 {
801 LIB_SYMBOL* tmp = nullptr;
802 libSymbol.reset();
803
804 // If the symbol is already in the internal library, map the symbol to it.
805 auto it = m_libSymbols.find( symbol->GetSchSymbolLibraryName() );
806
807 if( ( it != m_libSymbols.end() ) )
808 {
809 if( aReporter )
810 {
811 msg.Printf( _( "Setting schematic symbol '%s %s' library identifier to '%s'." ),
812 symbol->GetField( REFERENCE_FIELD )->GetText(),
813 symbol->GetField( VALUE_FIELD )->GetText(),
814 UnescapeString( symbol->GetLibId().Format() ) );
815 aReporter->ReportTail( msg, RPT_SEVERITY_INFO );
816 }
817
818 // Internal library symbols are already flattened so just make a copy.
819 symbol->SetLibSymbol( new LIB_SYMBOL( *it->second ) );
820 continue;
821 }
822
823 if( !symbol->GetLibId().IsValid() )
824 {
825 if( aReporter )
826 {
827 msg.Printf( _( "Schematic symbol reference '%s' library identifier is not valid. "
828 "Unable to link library symbol." ),
829 UnescapeString( symbol->GetLibId().Format() ) );
830 aReporter->ReportTail( msg, RPT_SEVERITY_WARNING );
831 }
832
833 continue;
834 }
835
836 // LIB_TABLE_BASE::LoadSymbol() throws an IO_ERROR if the library nickname
837 // is not found in the table so check if the library still exists in the table
838 // before attempting to load the symbol.
839 if( !libs->HasLibrary( symbol->GetLibId().GetLibNickname() ) && !legacyLibs )
840 {
841 if( aReporter )
842 {
843 msg.Printf( _( "Symbol library '%s' not found and no fallback cache library "
844 "available. Unable to link library symbol." ),
845 symbol->GetLibId().GetLibNickname().wx_str() );
846 aReporter->ReportTail( msg, RPT_SEVERITY_WARNING );
847 }
848
849 continue;
850 }
851
852 if( libs->HasLibrary( symbol->GetLibId().GetLibNickname() ) )
853 {
854 try
855 {
856 tmp = libs->LoadSymbol( symbol->GetLibId() );
857 }
858 catch( const IO_ERROR& ioe )
859 {
860 if( aReporter )
861 {
862 msg.Printf( _( "I/O error %s resolving library symbol %s" ), ioe.What(),
863 UnescapeString( symbol->GetLibId().Format() ) );
864 aReporter->ReportTail( msg, RPT_SEVERITY_ERROR );
865 }
866 }
867 }
868
869 if( !tmp && legacyLibs && legacyLibs->GetLibraryCount() )
870 {
871 SYMBOL_LIB& legacyCacheLib = legacyLibs->back();
872
873 // It better be the cache library.
874 wxCHECK2( legacyCacheLib.IsCache(), continue );
875
876 wxString id = symbol->GetLibId().Format();
877
878 id.Replace( ':', '_' );
879
880 if( aReporter )
881 {
882 msg.Printf( _( "Falling back to cache to set symbol '%s:%s' link '%s'." ),
883 symbol->GetField( REFERENCE_FIELD )->GetText(),
884 symbol->GetField( VALUE_FIELD )->GetText(),
885 UnescapeString( id ) );
886 aReporter->ReportTail( msg, RPT_SEVERITY_WARNING );
887 }
888
889 tmp = legacyCacheLib.FindSymbol( id );
890 }
891
892 if( tmp )
893 {
894 // We want a full symbol not just the top level child symbol.
895 libSymbol = tmp->Flatten();
896 libSymbol->SetParent();
897
898 m_libSymbols.insert( { symbol->GetSchSymbolLibraryName(),
899 new LIB_SYMBOL( *libSymbol.get() ) } );
900
901 if( aReporter )
902 {
903 msg.Printf( _( "Setting schematic symbol '%s %s' library identifier to '%s'." ),
904 symbol->GetField( REFERENCE_FIELD )->GetText(),
905 symbol->GetField( VALUE_FIELD )->GetText(),
906 UnescapeString( symbol->GetLibId().Format() ) );
907 aReporter->ReportTail( msg, RPT_SEVERITY_INFO );
908 }
909 }
910 else
911 {
912 if( aReporter )
913 {
914 msg.Printf( _( "No library symbol found for schematic symbol '%s %s'." ),
915 symbol->GetField( REFERENCE_FIELD )->GetText(),
916 symbol->GetField( VALUE_FIELD )->GetText() );
917 aReporter->ReportTail( msg, RPT_SEVERITY_ERROR );
918 }
919 }
920
921 if( libSymbol.get() ) // Only change the old link if the new link exists
922 symbol->SetLibSymbol( libSymbol.release() );
923 }
924
925 // Changing the symbol may adjust the bbox of the symbol. This re-inserts the
926 // item with the new bbox
927 for( SCH_SYMBOL* symbol : symbols )
928 Append( symbol );
929}
930
931
933{
934 std::vector<SCH_SYMBOL*> symbols;
935
936 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
937 symbols.push_back( static_cast<SCH_SYMBOL*>( item ) );
938
939 for( SCH_SYMBOL* symbol : symbols )
940 {
941 // Changing the symbol may adjust the bbox of the symbol; remove and reinsert it afterwards.
942 m_rtree.remove( symbol );
943
944 auto it = m_libSymbols.find( symbol->GetSchSymbolLibraryName() );
945
946 LIB_SYMBOL* libSymbol = nullptr;
947
948 if( it != m_libSymbols.end() )
949 libSymbol = new LIB_SYMBOL( *it->second );
950
951 symbol->SetLibSymbol( libSymbol );
952
953 m_rtree.insert( symbol );
954 }
955}
956
957
959{
960 for( SCH_ITEM* item : Items() )
961 item->SetConnectivityDirty( true );
962}
963
964
966{
967 // Ensure links are up to date, even if a library was reloaded for some reason:
968 std::vector<SCH_ITEM*> junctions;
969 std::vector<SCH_ITEM*> bitmaps;
970 std::vector<SCH_ITEM*> other;
971
972 for( SCH_ITEM* item : Items() )
973 {
974 if( item->IsMoving() )
975 continue;
976
977 if( item->Type() == SCH_JUNCTION_T )
978 junctions.push_back( item );
979 else if( item->Type() == SCH_BITMAP_T )
980 bitmaps.push_back( item );
981 else
982 other.push_back( item );
983 }
984
986 std::stable_sort( other.begin(), other.end(),
987 []( const SCH_ITEM* a, const SCH_ITEM* b )
988 {
989 if( a->Type() == b->Type() )
990 return a->GetLayer() > b->GetLayer();
991
992 return a->Type() < b->Type();
993 } );
994
995 for( SCH_ITEM* item : bitmaps )
996 item->Print( aSettings, 0, 0, VECTOR2I( 0, 0 ), false, false );
997
998 for( SCH_ITEM* item : other )
999 item->PrintBackground( aSettings, 0, 0, VECTOR2I( 0, 0 ), false );
1000
1001 for( SCH_ITEM* item : other )
1002 item->Print( aSettings, 0, 0, VECTOR2I( 0, 0 ), false, false );
1003
1004 for( SCH_ITEM* item : junctions )
1005 item->Print( aSettings, 0, 0, VECTOR2I( 0, 0 ), false, false );
1006}
1007
1008
1009void SCH_SCREEN::Plot( PLOTTER* aPlotter, const SCH_PLOT_OPTS& aPlotOpts ) const
1010{
1011 // Ensure links are up to date, even if a library was reloaded for some reason:
1012 std::vector<SCH_ITEM*> junctions;
1013 std::vector<SCH_ITEM*> bitmaps;
1014 std::vector<SCH_SYMBOL*> symbols;
1015 std::vector<SCH_ITEM*> other;
1016
1017 for( SCH_ITEM* item : Items() )
1018 {
1019 if( item->IsMoving() )
1020 continue;
1021
1022 if( item->Type() == SCH_JUNCTION_T )
1023 junctions.push_back( item );
1024 else if( item->Type() == SCH_BITMAP_T )
1025 bitmaps.push_back( item );
1026 else
1027 other.push_back( item );
1028
1029 // Where the symbols overlap each other, we need to plot the text items a second
1030 // time to get them on top of the overlapping element. This collection is in addition
1031 // to the symbols already collected in `other`
1032 if( item->Type() == SCH_SYMBOL_T )
1033 {
1034 for( SCH_ITEM* sym : m_rtree.Overlapping( SCH_SYMBOL_T, item->GetBoundingBox() ) )
1035 {
1036 if( sym != item )
1037 {
1038 symbols.push_back( static_cast<SCH_SYMBOL*>( item ) );
1039 break;
1040 }
1041 }
1042 }
1043 }
1044
1046 std::sort( other.begin(), other.end(),
1047 []( const SCH_ITEM* a, const SCH_ITEM* b )
1048 {
1049 if( a->Type() == b->Type() )
1050 return a->GetLayer() > b->GetLayer();
1051
1052 return a->Type() > b->Type();
1053 } );
1054
1055 auto* renderSettings = static_cast<SCH_RENDER_SETTINGS*>( aPlotter->RenderSettings() );
1056 constexpr bool background = true;
1057
1058 // Bitmaps are drawn first to ensure they are in the background
1059 // This is particularly important for the wxPostscriptDC (used in *nix printers) as
1060 // the bitmap PS command clears the screen
1061 for( SCH_ITEM* item : bitmaps )
1062 {
1063 aPlotter->SetCurrentLineWidth( item->GetEffectivePenWidth( renderSettings ) );
1064 item->Plot( aPlotter, background, aPlotOpts, 0, 0, { 0, 0 }, false );
1065 }
1066
1067 // Plot the background items
1068 for( SCH_ITEM* item : other )
1069 {
1070 aPlotter->SetCurrentLineWidth( item->GetEffectivePenWidth( renderSettings ) );
1071 item->Plot( aPlotter, background, aPlotOpts, 0, 0, { 0, 0 }, false );
1072 }
1073
1074 // Plot the foreground items
1075 for( SCH_ITEM* item : other )
1076 {
1077 aPlotter->SetCurrentLineWidth( item->GetEffectivePenWidth( renderSettings ) );
1078 item->Plot( aPlotter, !background, aPlotOpts, 0, 0, { 0, 0 }, false );
1079 }
1080
1081 // After plotting the symbols as a group above (in `other`), we need to overplot the pins
1082 // and symbols to ensure that they are always visible
1083 TRANSFORM savedTransform = renderSettings->m_Transform;
1084
1085 for( const SCH_SYMBOL* sym :symbols )
1086 {
1087 renderSettings->m_Transform = sym->GetTransform();
1088 aPlotter->SetCurrentLineWidth( sym->GetEffectivePenWidth( renderSettings ) );
1089
1090 for( SCH_FIELD field : sym->GetFields() )
1091 {
1092 field.ClearRenderCache();
1093 field.Plot( aPlotter, false, aPlotOpts, sym->GetUnit(), sym->GetBodyStyle(), { 0, 0 },
1094 sym->GetDNP() );
1095 }
1096
1097 sym->PlotPins( aPlotter );
1098
1099 if( sym->GetDNP() )
1100 sym->PlotDNP( aPlotter );
1101 }
1102
1103 renderSettings->m_Transform = savedTransform;
1104
1105 for( SCH_ITEM* item : junctions )
1106 {
1107 aPlotter->SetCurrentLineWidth( item->GetEffectivePenWidth( renderSettings ) );
1108 item->Plot( aPlotter, !background, aPlotOpts, 0, 0, { 0, 0 }, false );
1109 }
1110}
1111
1112
1114{
1115 for( SCH_ITEM* item : Items() )
1116 item->ClearTempFlags();
1117}
1118
1119
1120SCH_PIN* SCH_SCREEN::GetPin( const VECTOR2I& aPosition, SCH_SYMBOL** aSymbol,
1121 bool aEndPointOnly ) const
1122{
1123 SCH_SYMBOL* candidate = nullptr;
1124 SCH_PIN* pin = nullptr;
1125
1126 for( SCH_ITEM* item : Items().Overlapping( SCH_SYMBOL_T, aPosition ) )
1127 {
1128 candidate = static_cast<SCH_SYMBOL*>( item );
1129
1130 if( aEndPointOnly )
1131 {
1132 pin = nullptr;
1133
1134 if( !candidate->GetLibSymbolRef() )
1135 continue;
1136
1137 for( SCH_PIN* test_pin : candidate->GetLibPins() )
1138 {
1139 if( candidate->GetPinPhysicalPosition( test_pin ) == aPosition )
1140 {
1141 pin = test_pin;
1142 break;
1143 }
1144 }
1145
1146 if( pin )
1147 break;
1148 }
1149 else
1150 {
1151 pin = static_cast<SCH_PIN*>( candidate->GetDrawItem( aPosition, SCH_PIN_T ) );
1152
1153 if( pin )
1154 break;
1155 }
1156 }
1157
1158 if( pin && aSymbol )
1159 *aSymbol = candidate;
1160
1161 return pin;
1162}
1163
1164
1166{
1167 SCH_SHEET_PIN* sheetPin = nullptr;
1168
1169 for( SCH_ITEM* item : Items().Overlapping( SCH_SHEET_T, aPosition ) )
1170 {
1171 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1172
1173 sheetPin = sheet->GetPin( aPosition );
1174
1175 if( sheetPin )
1176 break;
1177 }
1178
1179 return sheetPin;
1180}
1181
1182
1183size_t SCH_SCREEN::CountConnectedItems( const VECTOR2I& aPos, bool aTestJunctions ) const
1184{
1185 size_t count = 0;
1186
1187 for( const SCH_ITEM* item : Items().Overlapping( aPos ) )
1188 {
1189 if( ( item->Type() != SCH_JUNCTION_T || aTestJunctions ) && item->IsConnected( aPos ) )
1190 count++;
1191 }
1192
1193 return count;
1194}
1195
1196
1197void SCH_SCREEN::ClearAnnotation( SCH_SHEET_PATH* aSheetPath, bool aResetPrefix )
1198{
1199
1200 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1201 {
1202 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1203
1204 symbol->ClearAnnotation( aSheetPath, aResetPrefix );
1205 }
1206}
1207
1208
1210{
1211 if( GetClientSheetPaths().size() <= 1 ) // No need for alternate reference
1212 return;
1213
1214 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1215 {
1216 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1217
1218 // Add (when not existing) all sheet path entries
1219 for( const SCH_SHEET_PATH& sheet : GetClientSheetPaths() )
1220 symbol->AddSheetPathReferenceEntryIfMissing( sheet.Path() );
1221 }
1222}
1223
1224
1225void SCH_SCREEN::GetHierarchicalItems( std::vector<SCH_ITEM*>* aItems ) const
1226{
1227 static const std::vector<KICAD_T> hierarchicalTypes = { SCH_SYMBOL_T,
1230
1231 for( SCH_ITEM* item : Items() )
1232 {
1233 if( item->IsType( hierarchicalTypes ) )
1234 aItems->push_back( item );
1235 }
1236}
1237
1238
1239void SCH_SCREEN::GetSheets( std::vector<SCH_ITEM*>* aItems ) const
1240{
1241 for( SCH_ITEM* item : Items().OfType( SCH_SHEET_T ) )
1242 aItems->push_back( item );
1243
1244 std::sort( aItems->begin(), aItems->end(),
1245 []( EDA_ITEM* a, EDA_ITEM* b ) -> bool
1246 {
1247 if( a->GetPosition().x == b->GetPosition().x )
1248 {
1249 // Ensure deterministic sort
1250 if( a->GetPosition().y == b->GetPosition().y )
1251 return a->m_Uuid < b->m_Uuid;
1252
1253 return a->GetPosition().y < b->GetPosition().y;
1254 }
1255 else
1256 {
1257 return a->GetPosition().x < b->GetPosition().x;
1258 }
1259 } );
1260}
1261
1262
1264 std::function<void( SCH_ITEM* )>* aChangedHandler ) const
1265{
1266 PROF_TIMER timer( __FUNCTION__ );
1267
1268 std::vector<DANGLING_END_ITEM> endPointsByPos;
1269 std::vector<DANGLING_END_ITEM> endPointsByType;
1270
1271 auto get_ends =
1272 [&]( SCH_ITEM* item )
1273 {
1274 if( item->IsConnectable() )
1275 item->GetEndPoints( endPointsByType );
1276 };
1277
1278 auto update_state =
1279 [&]( SCH_ITEM* item )
1280 {
1281 if( item->UpdateDanglingState( endPointsByType, endPointsByPos, aPath ) )
1282 {
1283 if( aChangedHandler )
1284 ( *aChangedHandler )( item );
1285 }
1286 };
1287
1288 for( SCH_ITEM* item : Items() )
1289 {
1290 get_ends( item );
1291 item->RunOnChildren( get_ends );
1292 }
1293
1294 PROF_TIMER sortTimer( "SCH_SCREEN::TestDanglingEnds pre-sort" );
1295 endPointsByPos = endPointsByType;
1296 DANGLING_END_ITEM_HELPER::sort_dangling_end_items( endPointsByType, endPointsByPos );
1297 sortTimer.Stop();
1298
1299 if( wxLog::IsAllowedTraceMask( DanglingProfileMask ) )
1300 sortTimer.Show();
1301
1302 for( SCH_ITEM* item : Items() )
1303 {
1304 update_state( item );
1305 item->RunOnChildren( update_state );
1306 }
1307
1308 if( wxLog::IsAllowedTraceMask( DanglingProfileMask ) )
1309 timer.Show();
1310}
1311
1312
1313SCH_LINE* SCH_SCREEN::GetLine( const VECTOR2I& aPosition, int aAccuracy, int aLayer,
1314 SCH_LINE_TEST_T aSearchType ) const
1315{
1316 // an accuracy of 0 had problems with rounding errors; use at least 1
1317 aAccuracy = std::max( aAccuracy, 1 );
1318
1319 for( SCH_ITEM* item : Items().Overlapping( aPosition, aAccuracy ) )
1320 {
1321 if( item->Type() != SCH_LINE_T )
1322 continue;
1323
1324 if( item->GetLayer() != aLayer )
1325 continue;
1326
1327 if( !item->HitTest( aPosition, aAccuracy ) )
1328 continue;
1329
1330 switch( aSearchType )
1331 {
1332 case ENTIRE_LENGTH_T:
1333 return (SCH_LINE*) item;
1334
1336 if( !( (SCH_LINE*) item )->IsEndPoint( aPosition ) )
1337 return (SCH_LINE*) item;
1338 break;
1339
1340 case END_POINTS_ONLY_T:
1341 if( ( (SCH_LINE*) item )->IsEndPoint( aPosition ) )
1342 return (SCH_LINE*) item;
1343 }
1344 }
1345
1346 return nullptr;
1347}
1348
1349
1350std::vector<SCH_LINE*> SCH_SCREEN::GetBusesAndWires( const VECTOR2I& aPosition,
1351 bool aIgnoreEndpoints ) const
1352{
1353 std::vector<SCH_LINE*> retVal;
1354
1355 for( SCH_ITEM* item : Items().Overlapping( SCH_LINE_T, aPosition ) )
1356 {
1357 if( item->IsType( { SCH_ITEM_LOCATE_WIRE_T, SCH_ITEM_LOCATE_BUS_T } ) )
1358 {
1359 SCH_LINE* wire = static_cast<SCH_LINE*>( item );
1360
1361 if( aIgnoreEndpoints && wire->IsEndPoint( aPosition ) )
1362 continue;
1363
1364 if( IsPointOnSegment( wire->GetStartPoint(), wire->GetEndPoint(), aPosition ) )
1365 retVal.push_back( wire );
1366 }
1367 }
1368
1369 return retVal;
1370}
1371
1372
1373std::vector<VECTOR2I> SCH_SCREEN::GetConnections() const
1374{
1375 std::vector<VECTOR2I> retval;
1376
1377 for( SCH_ITEM* item : Items() )
1378 {
1379 // Avoid items that are changing
1380 if( !( item->GetEditFlags() & ( IS_MOVING | IS_DELETED ) ) )
1381 {
1382 std::vector<VECTOR2I> pts = item->GetConnectionPoints();
1383 retval.insert( retval.end(), pts.begin(), pts.end() );
1384 }
1385 }
1386
1387 // We always have some overlapping connection points. Drop duplicates here
1388 std::sort( retval.begin(), retval.end(),
1389 []( const VECTOR2I& a, const VECTOR2I& b ) -> bool
1390 {
1391 return a.x < b.x || ( a.x == b.x && a.y < b.y );
1392 } );
1393 retval.erase( std::unique( retval.begin(), retval.end() ), retval.end() );
1394
1395 return retval;
1396}
1397
1398
1399std::vector<VECTOR2I> SCH_SCREEN::GetNeededJunctions( const std::deque<EDA_ITEM*>& aItems ) const
1400{
1401 std::vector<VECTOR2I> pts;
1402 std::vector<VECTOR2I> connections = GetConnections();
1403
1404 for( const EDA_ITEM* edaItem : aItems )
1405 {
1406 const SCH_ITEM* item = dynamic_cast<const SCH_ITEM*>( edaItem );
1407
1408 if( !item || !item->IsConnectable() )
1409 continue;
1410
1411 std::vector<VECTOR2I> new_pts = item->GetConnectionPoints();
1412 pts.insert( pts.end(), new_pts.begin(), new_pts.end() );
1413
1414 // If the item is a line, we also add any connection points from the rest of the schematic
1415 // that terminate on the line after it is moved.
1416 if( item->Type() == SCH_LINE_T )
1417 {
1418 SCH_LINE* line = (SCH_LINE*) item;
1419
1420 for( const VECTOR2I& pt : connections )
1421 {
1422 if( IsPointOnSegment( line->GetStartPoint(), line->GetEndPoint(), pt ) )
1423 pts.push_back( pt );
1424 }
1425 }
1426 }
1427
1428 // We always have some overlapping connection points. Drop duplicates here
1429 std::sort( pts.begin(), pts.end(),
1430 []( const VECTOR2I& a, const VECTOR2I& b ) -> bool
1431 {
1432 return a.x < b.x || ( a.x == b.x && a.y < b.y );
1433 } );
1434
1435 pts.erase( unique( pts.begin(), pts.end() ), pts.end() );
1436
1437 // We only want the needed junction points, remove all the others
1438 pts.erase( std::remove_if( pts.begin(), pts.end(),
1439 [this]( const VECTOR2I& a ) -> bool
1440 {
1441 return !IsExplicitJunctionNeeded( a );
1442 } ),
1443 pts.end() );
1444
1445 return pts;
1446}
1447
1448
1449SCH_LABEL_BASE* SCH_SCREEN::GetLabel( const VECTOR2I& aPosition, int aAccuracy ) const
1450{
1451 for( SCH_ITEM* item : Items().Overlapping( aPosition, aAccuracy ) )
1452 {
1453 switch( item->Type() )
1454 {
1455 case SCH_LABEL_T:
1456 case SCH_GLOBAL_LABEL_T:
1457 case SCH_HIER_LABEL_T:
1459 if( item->HitTest( aPosition, aAccuracy ) )
1460 return static_cast<SCH_LABEL_BASE*>( item );
1461
1462 break;
1463
1464 default:
1465 ;
1466 }
1467 }
1468
1469 return nullptr;
1470}
1471
1472
1474{
1475 wxCHECK( aLibSymbol, /* void */ );
1476
1477 wxString libSymbolName = aLibSymbol->GetLibId().Format().wx_str();
1478
1479 auto it = m_libSymbols.find( libSymbolName );
1480
1481 if( it != m_libSymbols.end() )
1482 {
1483 delete it->second;
1484 m_libSymbols.erase( it );
1485 }
1486
1487 m_libSymbols[libSymbolName] = aLibSymbol;
1488}
1489
1490
1492{
1493 SCHEMATIC* schematic = Schematic();
1494
1495 for( auto& [name, libSym] : m_libSymbols )
1496 {
1497 for( auto& [filename, embeddedFile] : libSym->EmbeddedFileMap() )
1498 {
1499 EMBEDDED_FILES::EMBEDDED_FILE* file = schematic->GetEmbeddedFile( filename );
1500
1501 if( file )
1502 {
1503 embeddedFile->compressedEncodedData = file->compressedEncodedData;
1504 embeddedFile->decompressedData = file->decompressedData;
1505 embeddedFile->data_sha = file->data_sha;
1506 embeddedFile->is_valid = file->is_valid;
1507 }
1508 }
1509 }
1510}
1511
1512
1513void SCH_SCREEN::AddBusAlias( std::shared_ptr<BUS_ALIAS> aAlias )
1514{
1515 m_aliases.insert( aAlias );
1516}
1517
1518
1520{
1521 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1522 {
1523 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1524
1525 // Add missing value and footprint instance data for legacy schematics.
1526 for( const SCH_SYMBOL_INSTANCE& instance : symbol->GetInstances() )
1527 {
1528 symbol->AddHierarchicalReference( instance.m_Path, instance.m_Reference,
1529 instance.m_Unit );
1530 }
1531 }
1532}
1533
1534
1536{
1537 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1538 {
1539 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1540
1541 // Fix pre-8.0 legacy power symbols with invisible pins
1542 // that have mismatched pin names and value fields
1543 if( symbol->GetLibSymbolRef()
1544 && symbol->GetLibSymbolRef()->IsPower()
1545 && symbol->GetAllLibPins().size() > 0
1546 && symbol->GetAllLibPins()[0]->IsGlobalPower()
1547 && !symbol->GetAllLibPins()[0]->IsVisible() )
1548 {
1549 symbol->SetValueFieldText( symbol->GetAllLibPins()[0]->GetName() );
1550 }
1551 }
1552}
1553
1554
1556 std::vector<wxString>& aMatches )
1557{
1558 wxString searchName = aSymbol.GetLibId().GetUniStringLibId();
1559
1560 if( m_libSymbols.find( searchName ) != m_libSymbols.end() )
1561 aMatches.emplace_back( searchName );
1562
1563 searchName = aSymbol.GetLibId().GetUniStringLibItemName() + wxS( "_" );
1564
1565 long tmp;
1566 wxString suffix;
1567
1568 for( auto& pair : m_libSymbols )
1569 {
1570 if( pair.first.StartsWith( searchName, &suffix ) && suffix.ToLong( &tmp ) )
1571 aMatches.emplace_back( pair.first );
1572 }
1573
1574 return aMatches.size();
1575}
1576
1577
1578void SCH_SCREEN::PruneOrphanedSymbolInstances( const wxString& aProjectName,
1579 const SCH_SHEET_LIST& aValidSheetPaths )
1580{
1581 // The project name cannot be empty. Projects older than 7.0 did not save project names
1582 // when saving instance data. Running this algorithm with an empty project name would
1583 // clobber all instance data for projects other than the current one when a schematic
1584 // file is shared across multiple projects. Because running the schematic editor in
1585 // stand alone mode can result in an empty project name, do not assert here.
1586 if( aProjectName.IsEmpty() )
1587 return;
1588
1589 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1590 {
1591 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1592
1593 wxCHECK2( symbol, continue );
1594
1595 std::set<KIID_PATH> pathsToPrune;
1596 const std::vector<SCH_SYMBOL_INSTANCE> instances = symbol->GetInstances();
1597
1598 for( const SCH_SYMBOL_INSTANCE& instance : instances )
1599 {
1600 // Ignore instance paths from other projects.
1601 if( aProjectName != instance.m_ProjectName )
1602 continue;
1603
1604 std::optional<SCH_SHEET_PATH> pathFound =
1605 aValidSheetPaths.GetSheetPathByKIIDPath( instance.m_Path );
1606
1607 // Check for paths that do not exist in the current project and paths that do
1608 // not contain the current symbol.
1609 if( !pathFound )
1610 pathsToPrune.emplace( instance.m_Path );
1611 else if( pathFound.value().LastScreen() != this )
1612 pathsToPrune.emplace( pathFound.value().Path() );
1613 }
1614
1615 for( const KIID_PATH& sheetPath : pathsToPrune )
1616 {
1617 wxLogTrace( traceSchSheetPaths, wxS( "Pruning project '%s' symbol instance %s." ),
1618 aProjectName, sheetPath.AsString() );
1619 symbol->RemoveInstance( sheetPath );
1620 }
1621 }
1622}
1623
1624
1625void SCH_SCREEN::PruneOrphanedSheetInstances( const wxString& aProjectName,
1626 const SCH_SHEET_LIST& aValidSheetPaths )
1627{
1628 // The project name cannot be empty. Projects older than 7.0 did not save project names
1629 // when saving instance data. Running this algorithm with an empty project name would
1630 // clobber all instance data for projects other than the current one when a schematic
1631 // file is shared across multiple projects. Because running the schematic editor in
1632 // stand alone mode can result in an empty project name, do not assert here.
1633 if( aProjectName.IsEmpty() )
1634 return;
1635
1636 for( SCH_ITEM* item : Items().OfType( SCH_SHEET_T ) )
1637 {
1638 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1639
1640 wxCHECK2( sheet, continue );
1641
1642 std::set<KIID_PATH> pathsToPrune;
1643 const std::vector<SCH_SHEET_INSTANCE> instances = sheet->GetInstances();
1644
1645 for( const SCH_SHEET_INSTANCE& instance : instances )
1646 {
1647 // Ignore instance paths from other projects.
1648 if( aProjectName != instance.m_ProjectName )
1649 continue;
1650
1651 std::optional<SCH_SHEET_PATH> pathFound =
1652 aValidSheetPaths.GetSheetPathByKIIDPath( instance.m_Path );
1653
1654 // Check for paths that do not exist in the current project and paths that do
1655 // not contain the current symbol.
1656 if( !pathFound )
1657 pathsToPrune.emplace( instance.m_Path );
1658 else if( pathFound.value().LastScreen() != this )
1659 pathsToPrune.emplace( pathFound.value().Path() );
1660 }
1661
1662 for( const KIID_PATH& sheetPath : pathsToPrune )
1663 {
1664 wxLogTrace( traceSchSheetPaths, wxS( "Pruning project '%s' sheet instance %s." ),
1665 aProjectName, sheetPath.AsString() );
1666 sheet->RemoveInstance( sheetPath );
1667 }
1668 }
1669}
1670
1671
1672#if defined(DEBUG)
1673void SCH_SCREEN::Show( int nestLevel, std::ostream& os ) const
1674{
1675 // for now, make it look like XML, expand on this later.
1676 NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() << ">\n";
1677
1678 for( const SCH_ITEM* item : Items() )
1679 item->Show( nestLevel + 1, os );
1680
1681 NestedSpace( nestLevel, os ) << "</" << GetClass().Lower().mb_str() << ">\n";
1682}
1683#endif
1684
1685
1687{
1688 m_index = 0;
1689 buildScreenList( aSheet );
1690}
1691
1692
1694{
1695}
1696
1697
1699{
1700 m_index = 0;
1701
1702 if( m_screens.size() > 0 )
1703 return m_screens[0];
1704
1705 return nullptr;
1706}
1707
1708
1710{
1711 if( m_index < m_screens.size() )
1712 m_index++;
1713
1714 return GetScreen( m_index );
1715}
1716
1717
1718SCH_SCREEN* SCH_SCREENS::GetScreen( unsigned int aIndex ) const
1719{
1720 if( aIndex < m_screens.size() )
1721 return m_screens[ aIndex ];
1722
1723 return nullptr;
1724}
1725
1726
1727SCH_SHEET* SCH_SCREENS::GetSheet( unsigned int aIndex ) const
1728{
1729 if( aIndex < m_sheets.size() )
1730 return m_sheets[ aIndex ];
1731
1732 return nullptr;
1733}
1734
1735
1737{
1738 if( aScreen == nullptr )
1739 return;
1740
1741 for( const SCH_SCREEN* screen : m_screens )
1742 {
1743 if( screen == aScreen )
1744 return;
1745 }
1746
1747 m_screens.push_back( aScreen );
1748 m_sheets.push_back( aSheet );
1749}
1750
1751
1753{
1754 if( aSheet && aSheet->Type() == SCH_SHEET_T )
1755 {
1756 SCH_SCREEN* screen = aSheet->GetScreen();
1757
1758 wxCHECK_RET( screen, "No screen for aSheet" );
1759
1760 addScreenToList( screen, aSheet );
1761
1762 for( SCH_ITEM* item : screen->Items().OfType( SCH_SHEET_T ) )
1763 buildScreenList( static_cast<SCH_SHEET*>( item ) );
1764 }
1765}
1766
1767
1769{
1770 SCH_SCREEN* first = GetFirst();
1771
1772 if( !first )
1773 return;
1774
1775 SCHEMATIC* sch = first->Schematic();
1776
1777 wxCHECK_RET( sch, "Null schematic in SCH_SCREENS::ClearAnnotationOfNewSheetPaths" );
1778
1779 // Clear the annotation for symbols inside new sheetpaths not already in aInitialSheetList
1780 SCH_SCREENS screensList( sch->Root() ); // The list of screens, shared by sheet paths
1781 screensList.BuildClientSheetPathList(); // build the shared by sheet paths, by screen
1782
1783 // Search for new sheet paths, not existing in aInitialSheetPathList
1784 // and existing in sheetpathList
1785 for( SCH_SHEET_PATH& sheetpath : sch->BuildSheetListSortedByPageNumbers() )
1786 {
1787 bool path_exists = false;
1788
1789 for( const SCH_SHEET_PATH& existing_sheetpath: aInitialSheetPathList )
1790 {
1791 if( existing_sheetpath.Path() == sheetpath.Path() )
1792 {
1793 path_exists = true;
1794 break;
1795 }
1796 }
1797
1798 if( !path_exists )
1799 {
1800 // A new sheet path is found: clear the annotation corresponding to this new path:
1801 SCH_SCREEN* curr_screen = sheetpath.LastScreen();
1802
1803 // Clear annotation and create the AR for this path, if not exists,
1804 // when the screen is shared by sheet paths.
1805 // Otherwise ClearAnnotation do nothing, because the F1 field is used as
1806 // reference default value and takes the latest displayed value
1807 curr_screen->EnsureAlternateReferencesExist();
1808 curr_screen->ClearAnnotation( &sheetpath, false );
1809 }
1810 }
1811}
1812
1813
1815{
1816 std::vector<SCH_ITEM*> items;
1817 int count = 0;
1818
1819 auto timestamp_cmp = []( const EDA_ITEM* a, const EDA_ITEM* b ) -> bool
1820 {
1821 return a->m_Uuid < b->m_Uuid;
1822 };
1823
1824 std::set<EDA_ITEM*, decltype( timestamp_cmp )> unique_stamps( timestamp_cmp );
1825
1826 for( SCH_SCREEN* screen : m_screens )
1827 screen->GetHierarchicalItems( &items );
1828
1829 if( items.size() < 2 )
1830 return 0;
1831
1832 for( EDA_ITEM* item : items )
1833 {
1834 if( !unique_stamps.insert( item ).second )
1835 {
1836 // Reset to fully random UUID. This may lose reference, but better to be
1837 // deterministic about it rather than to have duplicate UUIDs with random
1838 // side-effects.
1839 const_cast<KIID&>( item->m_Uuid ) = KIID();
1840 count++;
1841
1842 // @todo If the item is a sheet, we need to decend the heirarchy from the sheet
1843 // and repace all instances of the changed UUID in sheet paths. Otherwise,
1844 // all instance paths with the sheet's UUID will get clobbered.
1845 }
1846 }
1847
1848 return count;
1849}
1850
1851
1853{
1854 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1855 {
1856 for( SCH_ITEM* item : screen->Items() )
1857 item->ClearEditFlags();
1858 }
1859}
1860
1861
1863{
1864 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1865 {
1866 for( SCH_ITEM* item : screen->Items().OfType( SCH_MARKER_T ) )
1867 {
1868 if( item == aMarker )
1869 {
1870 screen->DeleteItem( item );
1871 return;
1872 }
1873 }
1874 }
1875}
1876
1877
1878void SCH_SCREENS::DeleteMarkers( enum MARKER_BASE::MARKER_T aMarkerType, int aErrorCode,
1879 bool aIncludeExclusions )
1880{
1881 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1882 {
1883 std::vector<SCH_ITEM*> markers;
1884
1885 for( SCH_ITEM* item : screen->Items().OfType( SCH_MARKER_T ) )
1886 {
1887 SCH_MARKER* marker = static_cast<SCH_MARKER*>( item );
1888 std::shared_ptr<RC_ITEM>rcItem = marker->GetRCItem();
1889
1890 if( marker->GetMarkerType() == aMarkerType
1891 && ( aErrorCode == ERCE_UNSPECIFIED || rcItem->GetErrorCode() == aErrorCode )
1892 && ( !marker->IsExcluded() || aIncludeExclusions ) )
1893 {
1894 markers.push_back( item );
1895 }
1896 }
1897
1898 for( SCH_ITEM* marker : markers )
1899 screen->DeleteItem( marker );
1900 }
1901}
1902
1903
1905 bool aIncludeExclusions )
1906{
1907 DeleteMarkers( aMarkerType, ERCE_UNSPECIFIED, aIncludeExclusions );
1908}
1909
1910
1912{
1913 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1914 screen->UpdateSymbolLinks( aReporter );
1915
1916 SCH_SCREEN* first = GetFirst();
1917
1918 if( !first )
1919 return;
1920
1921 SCHEMATIC* sch = first->Schematic();
1922
1923 wxCHECK_RET( sch, "Null schematic in SCH_SCREENS::UpdateSymbolLinks" );
1924
1926
1927 // All of the library symbols have been replaced with copies so the connection graph
1928 // pointers are stale.
1929 if( sch->ConnectionGraph() )
1930 sch->ConnectionGraph()->Recalculate( sheets, true );
1931}
1932
1933
1935{
1936 bool has_symbols = false;
1937
1938 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1939 {
1940 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
1941 {
1942 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1943 has_symbols = true;
1944
1945 if( !symbol->GetLibId().GetLibNickname().empty() )
1946 return false;
1947 }
1948 }
1949
1950 // return true (i.e. has no fully defined symbol) only if at least one symbol is found
1951 return has_symbols ? true : false;
1952}
1953
1954
1955size_t SCH_SCREENS::GetLibNicknames( wxArrayString& aLibNicknames )
1956{
1957 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1958 {
1959 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
1960 {
1961 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1962 const UTF8& nickname = symbol->GetLibId().GetLibNickname();
1963
1964 if( !nickname.empty() && ( aLibNicknames.Index( nickname ) == wxNOT_FOUND ) )
1965 aLibNicknames.Add( nickname );
1966 }
1967 }
1968
1969 return aLibNicknames.GetCount();
1970}
1971
1972
1973int SCH_SCREENS::ChangeSymbolLibNickname( const wxString& aFrom, const wxString& aTo )
1974{
1975 SCH_SCREEN* screen;
1976 int cnt = 0;
1977
1978 for( screen = GetFirst(); screen; screen = GetNext() )
1979 {
1980 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
1981 {
1982 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1983
1984 if( symbol->GetLibId().GetLibNickname().wx_str() != aFrom )
1985 continue;
1986
1987 LIB_ID id = symbol->GetLibId();
1988 id.SetLibNickname( aTo );
1989 symbol->SetLibId( id );
1990 cnt++;
1991 }
1992 }
1993
1994 return cnt;
1995}
1996
1997
1998bool SCH_SCREENS::HasSchematic( const wxString& aSchematicFileName )
1999{
2000 for( const SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2001 {
2002 if( screen->GetFileName() == aSchematicFileName )
2003 return true;
2004 }
2005
2006 return false;
2007}
2008
2009
2011{
2012 SCH_SCREEN* first = GetFirst();
2013
2014 if( !first )
2015 return;
2016
2017 SCHEMATIC* sch = first->Schematic();
2018
2019 wxCHECK_RET( sch, "Null schematic in SCH_SCREENS::BuildClientSheetPathList" );
2020
2021 for( SCH_SCREEN* curr_screen = GetFirst(); curr_screen; curr_screen = GetNext() )
2022 curr_screen->GetClientSheetPaths().clear();
2023
2024 for( SCH_SHEET_PATH& sheetpath : sch->BuildSheetListSortedByPageNumbers() )
2025 {
2026 SCH_SCREEN* used_screen = sheetpath.LastScreen();
2027
2028 // Search for the used_screen in list and add this unique sheet path:
2029 for( SCH_SCREEN* curr_screen = GetFirst(); curr_screen; curr_screen = GetNext() )
2030 {
2031 if( used_screen == curr_screen )
2032 {
2033 curr_screen->GetClientSheetPaths().push_back( sheetpath );
2034 break;
2035 }
2036 }
2037 }
2038}
2039
2040
2042{
2043 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2044 screen->SetLegacySymbolInstanceData();
2045}
2046
2047
2049{
2050 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2051 screen->FixLegacyPowerSymbolMismatches();
2052}
2053
2054
2056{
2057 LOCALE_IO toggle;
2058
2059 // V6 schematics may specify model names in Value fields, which we don't do in V7.
2060 // Migrate by adding an equivalent model for these symbols.
2061
2062 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
2063 {
2064 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
2065 SIM_MODEL::MigrateSimModel<SCH_SYMBOL>( *symbol, &Schematic()->Prj() );
2066 }
2067}
2068
2069
2070void SCH_SCREENS::PruneOrphanedSymbolInstances( const wxString& aProjectName,
2071 const SCH_SHEET_LIST& aValidSheetPaths )
2072{
2073 if( aProjectName.IsEmpty() )
2074 return;
2075
2076 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2077 screen->PruneOrphanedSymbolInstances( aProjectName, aValidSheetPaths );
2078}
2079
2080
2081void SCH_SCREENS::PruneOrphanedSheetInstances( const wxString& aProjectName,
2082 const SCH_SHEET_LIST& aValidSheetPaths )
2083{
2084 if( aProjectName.IsEmpty() )
2085 return;
2086
2087 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2088 screen->PruneOrphanedSheetInstances( aProjectName, aValidSheetPaths );
2089}
const char * name
Definition: DXF_plotter.cpp:57
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:110
Handles how to draw a screen (a board, a schematic ...)
Definition: base_screen.h:41
int m_virtualPageNumber
An integer based page number used for printing a range of pages.
Definition: base_screen.h:119
bool m_Center
Center on screen.
Definition: base_screen.h:96
int m_pageCount
The number of BASE_SCREEN objects in this design.
Definition: base_screen.h:111
void SetContentModified(bool aModified=true)
Definition: base_screen.h:59
void InitDataPoints(const VECTOR2I &aPageSizeInternalUnits)
Definition: base_screen.cpp:46
void SetOrigin(const Vec &pos)
Definition: box2.h:227
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:541
void Recalculate(const SCH_SHEET_LIST &aSheetList, bool aUnconditional=false, std::function< void(SCH_ITEM *)> *aChangedItemHandler=nullptr)
Update the connection graph for the given list of sheets.
static void sort_dangling_end_items(std::vector< DANGLING_END_ITEM > &aItemListByType, std::vector< DANGLING_END_ITEM > &aItemListByPos)
Both contain the same information.
Definition: sch_item.cpp:615
EDA_ANGLE Normalize90()
Definition: eda_angle.h:249
double AsDegrees() const
Definition: eda_angle.h:113
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:89
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:74
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:127
const KIID m_Uuid
Definition: eda_item.h:489
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:101
bool IsSelected() const
Definition: eda_item.h:110
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:104
EDA_ITEM * GetParent() const
Definition: eda_item.h:103
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition: eda_item.h:131
bool IsNew() const
Definition: eda_item.h:107
EE_TYPE Overlapping(const BOX2I &aRect) const
Definition: sch_rtree.h:243
bool remove(SCH_ITEM *aItem)
Remove an item from the tree.
Definition: sch_rtree.h:78
void insert(SCH_ITEM *aItem)
Insert an item into the tree.
Definition: sch_rtree.h:59
bool contains(const SCH_ITEM *aItem, bool aRobust=false) const
Determine if a given item exists in the tree.
Definition: sch_rtree.h:125
iterator end()
Returns a read/write iterator that points to one past the last element in the EE_RTREE.
Definition: sch_rtree.h:285
iterator begin()
Returns a read/write iterator that points to the first element in the EE_RTREE N.B.
Definition: sch_rtree.h:276
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:238
void clear()
Remove all items from the RTree.
Definition: sch_rtree.h:111
EMBEDDED_FILE * GetEmbeddedFile(const wxString &aName) const
Returns the embedded file with the given name or nullptr if it does not exist.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:77
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
Definition: kiid.h:49
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:49
int SetLibNickname(const UTF8 &aLibNickname)
Override the logical library name portion of the LIB_ID to aLibNickname.
Definition: lib_id.cpp:99
wxString GetUniStringLibId() const
Definition: lib_id.h:148
UTF8 Format() const
Definition: lib_id.cpp:118
const wxString GetUniStringLibItemName() const
Get strings for display messages in dialogs.
Definition: lib_id.h:112
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:87
Define a library symbol object.
Definition: lib_symbol.h:78
const LIB_ID & GetLibId() const override
Definition: lib_symbol.h:143
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
Definition: lib_symbol.h:499
wxString GetName() const override
Definition: lib_symbol.h:137
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
Definition: lib_symbol.cpp:304
void SetLibId(const LIB_ID &aLibId)
Definition: lib_symbol.h:144
virtual void SetName(const wxString &aName)
Definition: lib_symbol.cpp:288
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library table.
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition: locale_io.h:49
bool IsExcluded() const
Definition: marker_base.h:98
std::shared_ptr< RC_ITEM > GetRCItem() const
Definition: marker_base.h:112
enum MARKER_T GetMarkerType() const
Definition: marker_base.h:96
void sort()
Definition: multivector.h:248
const VECTOR2D GetSizeIU(double aIUScale) const
Gets the page size in internal units.
Definition: page_info.h:171
Base plotter engine class.
Definition: plotter.h:105
RENDER_SETTINGS * RenderSettings()
Definition: plotter.h:136
virtual void SetCurrentLineWidth(int width, void *aData=nullptr)=0
Set the line width for the next drawing.
A small class to help profiling.
Definition: profile.h:49
void Show(std::ostream &aStream=std::cerr)
Print the elapsed time (in a suitable unit) to a stream.
Definition: profile.h:105
void Stop()
Save the time when this function was called, and set the counter stane to stop.
Definition: profile.h:88
static SYMBOL_LIB_TABLE * SchSymbolLibTable(PROJECT *aProject)
Accessor for project symbol library table.
static SYMBOL_LIBS * SchLibs(PROJECT *aProject)
Definition: project_sch.cpp:90
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:71
virtual REPORTER & ReportTail(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Places the report at the end of the list, for objects that support report ordering.
Definition: reporter.h:99
Holds all the data relating to one schematic.
Definition: schematic.h:76
CONNECTION_GRAPH * ConnectionGraph() const override
Definition: schematic.h:154
SCH_SHEET & Root() const
Definition: schematic.h:113
SCH_SHEET_LIST BuildSheetListSortedByPageNumbers() const override
Definition: schematic.h:96
Class for a wire to bus entry.
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:51
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:166
virtual bool IsConnectable() const
Definition: sch_item.h:449
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition: sch_item.h:281
bool IsConnected(const VECTOR2I &aPoint) const
Test the item to see if it is connected to aPoint.
Definition: sch_item.cpp:212
virtual std::vector< VECTOR2I > GetConnectionPoints() const
Add all the connection points for this item to aPoints.
Definition: sch_item.h:464
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:41
EDA_ANGLE Angle() const
Gets the angle between the start and end lines.
Definition: sch_line.h:103
VECTOR2I GetEndPoint() const
Definition: sch_line.h:141
VECTOR2I GetStartPoint() const
Definition: sch_line.h:136
bool IsEndPoint(const VECTOR2I &aPoint) const
Definition: sch_line.h:90
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:710
SCH_SCREEN * GetNext()
unsigned int m_index
Definition: sch_screen.h:844
std::vector< SCH_SHEET * > m_sheets
Definition: sch_screen.h:843
SCH_SCREEN * GetScreen(unsigned int aIndex) const
void UpdateSymbolLinks(REPORTER *aReporter=nullptr)
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in the full schematic.
void DeleteMarker(SCH_MARKER *aMarker)
Delete a specific marker.
void DeleteMarkers(enum MARKER_BASE::MARKER_T aMarkerTyp, int aErrorCode, bool aIncludeExclusions=true)
Delete all markers of a particular type and error code.
void buildScreenList(SCH_SHEET *aSheet)
void FixLegacyPowerSymbolMismatches()
Fix legacy power symbols that have mismatched value text fields and invisible power pin names.
SCH_SCREEN * GetFirst()
void DeleteAllMarkers(enum MARKER_BASE::MARKER_T aMarkerType, bool aIncludeExclusions)
Delete all electronic rules check markers of aMarkerType from all the screens in the list.
void PruneOrphanedSheetInstances(const wxString &aProjectName, const SCH_SHEET_LIST &aValidSheetPaths)
int ChangeSymbolLibNickname(const wxString &aFrom, const wxString &aTo)
Change all of the symbol library nicknames.
SCH_SCREENS(SCH_SHEET *aSheet)
void BuildClientSheetPathList()
built the list of sheet paths sharing a screen for each screen in use
void ClearAnnotationOfNewSheetPaths(SCH_SHEET_LIST &aInitialSheetPathList)
Clear the annotation for the symbols inside new sheetpaths when a complex hierarchy is modified and n...
void PruneOrphanedSymbolInstances(const wxString &aProjectName, const SCH_SHEET_LIST &aValidSheetPaths)
bool HasNoFullyDefinedLibIds()
Test all of the schematic symbols to see if all LIB_ID objects library nickname is not set.
void ClearEditFlags()
SCH_SHEET * GetSheet(unsigned int aIndex) const
int ReplaceDuplicateTimeStamps()
Test all sheet and symbol objects in the schematic for duplicate time stamps and replaces them as nec...
std::vector< SCH_SCREEN * > m_screens
Definition: sch_screen.h:842
bool HasSchematic(const wxString &aSchematicFileName)
Check if one of the schematics in the list of screens is aSchematicFileName.
size_t GetLibNicknames(wxArrayString &aLibNicknames)
Fetch all of the symbol library nicknames into aLibNicknames.
void SetLegacySymbolInstanceData()
Update the symbol value and footprint instance data for legacy designs.
void addScreenToList(SCH_SCREEN *aScreen, SCH_SHEET *aSheet)
std::map< wxString, LIB_SYMBOL * > m_libSymbols
Library symbols required for this schematic.
Definition: sch_screen.h:671
SCH_PIN * GetPin(const VECTOR2I &aPosition, SCH_SYMBOL **aSymbol=nullptr, bool aEndPointOnly=false) const
Test the screen for a symbol pin item at aPosition.
void ClearDrawingState()
Clear the state flags of all the items in the screen.
SCH_LINE * GetLine(const VECTOR2I &aPosition, int aAccuracy=0, int aLayer=LAYER_NOTES, SCH_LINE_TEST_T aSearchType=ENTIRE_LENGTH_T) const
Return a line item located at aPosition.
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Definition: sch_screen.cpp:152
void AddLibSymbol(LIB_SYMBOL *aLibSymbol)
Add aLibSymbol to the library symbol map.
void AddBusAlias(std::shared_ptr< BUS_ALIAS > aAlias)
Add a bus alias definition (and transfers ownership of the pointer).
void FixLegacyPowerSymbolMismatches()
Fix legacy power symbols that have mismatched value text fields and invisible power pin names.
bool HasItems(KICAD_T aItemType) const
Definition: sch_screen.cpp:138
void Clear(bool aFree=true)
Delete all draw items and clears the project settings.
Definition: sch_screen.cpp:277
void PruneOrphanedSymbolInstances(const wxString &aProjectName, const SCH_SHEET_LIST &aValidSheetPaths)
Remove all invalid symbol instance data in this screen object for the project defined by aProjectName...
std::vector< SCH_SHEET_PATH > & GetClientSheetPaths()
Return the number of times this screen is used.
Definition: sch_screen.h:177
void UpdateSymbolLinks(REPORTER *aReporter=nullptr)
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in this schematic from the project SYMB...
Definition: sch_screen.cpp:777
SCH_LINE * GetWire(const VECTOR2I &aPosition, int aAccuracy=0, SCH_LINE_TEST_T aSearchType=ENTIRE_LENGTH_T) const
Definition: sch_screen.h:428
int m_refCount
Definition: sch_screen.h:639
TITLE_BLOCK m_titles
Definition: sch_screen.h:652
void TestDanglingEnds(const SCH_SHEET_PATH *aPath=nullptr, std::function< void(SCH_ITEM *)> *aChangedHandler=nullptr) const
Test all of the connectable objects in the schematic for unused connection points.
void EnsureAlternateReferencesExist()
For screens shared by many sheetpaths (complex hierarchies): to be able to clear or modify any refere...
void PruneOrphanedSheetInstances(const wxString &aProjectName, const SCH_SHEET_LIST &aValidSheetPaths)
Remove all invalid sheet instance data in this screen object for the project defined by aProjectName ...
std::vector< SCH_LINE * > GetBusesAndWires(const VECTOR2I &aPosition, bool aIgnoreEndpoints=false) const
Return buses and wires passing through aPosition.
int m_modification_sync
Definition: sch_screen.h:656
double m_LastZoomLevel
last value for the zoom level, useful in Eeschema when changing the current displayed sheet to reuse ...
Definition: sch_screen.h:634
bool IsExplicitJunction(const VECTOR2I &aPosition) const
Indicates that a junction dot is necessary at the given location.
Definition: sch_screen.cpp:486
EE_RTREE & Items()
Gets the full RTree, usually for iterating.
Definition: sch_screen.h:108
void DecRefCount()
Definition: sch_screen.cpp:131
std::set< SCH_ITEM * > MarkConnections(SCH_LINE *aSegment, bool aSecondPass)
Return all wires and junctions connected to aSegment which are not connected any symbol pin.
Definition: sch_screen.cpp:407
void Print(const SCH_RENDER_SETTINGS *aSettings)
Print all the items in the screen to aDC.
Definition: sch_screen.cpp:965
SCH_ITEM * GetItem(const VECTOR2I &aPosition, int aAccuracy=0, KICAD_T aType=SCH_LOCATE_ANY_T) const
Check aPosition within a distance of aAccuracy for items of type aFilter.
Definition: sch_screen.cpp:391
bool IsExplicitJunctionAllowed(const VECTOR2I &aPosition) const
Indicates that a juction dot may be placed at the given location.
Definition: sch_screen.cpp:505
void clearLibSymbols()
Definition: sch_screen.cpp:108
wxString m_fileName
Definition: sch_screen.h:637
bool IsTerminalPoint(const VECTOR2I &aPosition, int aLayer) const
Test if aPosition is a connection point on aLayer.
Definition: sch_screen.cpp:712
void UpdateLocalLibSymbolLinks()
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in this schematic with the local projec...
Definition: sch_screen.cpp:932
void IncRefCount()
Definition: sch_screen.cpp:125
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
Definition: sch_screen.cpp:117
static bool ClassOf(const EDA_ITEM *aItem)
Definition: sch_screen.cpp:146
void SetLegacySymbolInstanceData()
Update the symbol value and footprint instance data for legacy designs.
SCH_LINE * GetBus(const VECTOR2I &aPosition, int aAccuracy=0, SCH_LINE_TEST_T aSearchType=ENTIRE_LENGTH_T) const
Definition: sch_screen.h:434
bool Remove(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Remove aItem from the schematic associated with this screen.
Definition: sch_screen.cpp:322
SCH_SCREEN(EDA_ITEM *aParent=nullptr)
Definition: sch_screen.cpp:73
SCHEMATIC * Schematic() const
Definition: sch_screen.cpp:99
EE_RTREE m_rtree
Definition: sch_screen.h:654
void FixupEmbeddedData()
After loading a file from disk, the library symbols do not yet contain the full data for their embedd...
void GetHierarchicalItems(std::vector< SCH_ITEM * > *aItems) const
Add all schematic sheet and symbol objects in the screen to aItems.
bool IsExplicitJunctionNeeded(const VECTOR2I &aPosition) const
Indicates that a junction dot is necessary at the given location, and does not yet exist.
Definition: sch_screen.cpp:495
SCH_SHEET_PIN * GetSheetPin(const VECTOR2I &aPosition) const
Test the screen if aPosition is a sheet label object.
void FreeDrawList()
Free all the items from the schematic associated with the screen.
Definition: sch_screen.cpp:296
void Plot(PLOTTER *aPlotter, const SCH_PLOT_OPTS &aPlotOpts) const
Plot all the schematic objects to aPlotter.
virtual wxString GetClass() const override
Return the class name.
Definition: sch_screen.h:122
void Update(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Update aItem's bounding box in the tree.
Definition: sch_screen.cpp:315
void SetConnectivityDirty()
Definition: sch_screen.cpp:958
bool m_zoomInitialized
Definition: sch_screen.h:659
std::vector< VECTOR2I > GetNeededJunctions(const std::deque< EDA_ITEM * > &aItems) const
Return the unique set of points belonging to aItems where a junction is needed.
PAGE_INFO m_paper
Definition: sch_screen.h:651
bool IsJunction(const VECTOR2I &aPosition) const
Test if a junction is required for the items at aPosition on the screen.
Definition: sch_screen.cpp:478
void GetSheets(std::vector< SCH_ITEM * > *aItems) const
Similar to Items().OfType( SCH_SHEET_T ), but return the sheets in a deterministic order (L-R,...
bool CheckIfOnDrawList(const SCH_ITEM *aItem) const
Definition: sch_screen.cpp:385
std::vector< VECTOR2I > GetConnections() const
Collect a unique list of all possible connection points in the schematic.
SPIN_STYLE GetLabelOrientationForPoint(const VECTOR2I &aPosition, SPIN_STYLE aDefaultOrientation, const SCH_SHEET_PATH *aSheet) const
Definition: sch_screen.cpp:514
void ClearAnnotation(SCH_SHEET_PATH *aSheetPath, bool aResetPrefix)
Clear the annotation for the symbols in aSheetPath on the screen.
size_t CountConnectedItems(const VECTOR2I &aPos, bool aTestJunctions) const
void MigrateSimModels()
Migrate any symbols having V6 simulation models to their V7 equivalents.
void DeleteItem(SCH_ITEM *aItem)
Removes aItem from the linked list and deletes the object.
Definition: sch_screen.cpp:360
std::set< std::shared_ptr< BUS_ALIAS >, BusAliasCmp > m_aliases
List of bus aliases stored in this screen.
Definition: sch_screen.h:668
size_t getLibSymbolNameMatches(const SCH_SYMBOL &aSymbol, std::vector< wxString > &aMatches)
Return a list of potential library symbol matches for aSymbol.
SCH_LABEL_BASE * GetLabel(const VECTOR2I &aPosition, int aAccuracy=0) const
Return a label item located at aPosition.
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
std::optional< SCH_SHEET_PATH > GetSheetPathByKIIDPath(const KIID_PATH &aPath, bool aIncludeLastSheet=true) const
Finds a SCH_SHEET_PATH that matches the provided KIID_PATH.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet_pin.h:66
SCH_SHEET * GetParent() const
Get the parent sheet object of this sheet pin.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:57
void RemoveInstance(const KIID_PATH &aInstancePath)
Definition: sch_sheet.cpp:1397
SCH_SHEET_PIN * GetPin(const VECTOR2I &aPosition)
Return the sheet pin item found at aPosition in the sheet.
Definition: sch_sheet.cpp:639
void RemovePin(const SCH_SHEET_PIN *aSheetPin)
Remove aSheetPin from the sheet.
Definition: sch_sheet.cpp:437
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:110
const std::vector< SCH_SHEET_INSTANCE > & GetInstances() const
Definition: sch_sheet.h:417
Schematic symbol object.
Definition: sch_symbol.h:105
void SetLibId(const LIB_ID &aName)
Definition: sch_symbol.cpp:260
SCH_ITEM * GetDrawItem(const VECTOR2I &aPosition, KICAD_T aType=TYPE_NOT_INIT)
Return the symbol library item at aPosition that is part of this symbol.
const std::vector< SCH_SYMBOL_INSTANCE > & GetInstances() const
Definition: sch_symbol.h:164
void RemoveInstance(const SCH_SHEET_PATH &aInstancePath)
Definition: sch_symbol.cpp:592
void SetValueFieldText(const wxString &aValue)
Definition: sch_symbol.cpp:897
wxString GetSchSymbolLibraryName() const
Definition: sch_symbol.cpp:266
bool AddSheetPathReferenceEntryIfMissing(const KIID_PATH &aSheetPath)
Add an instance to the alternate references list (m_instanceReferences), if this entry does not alrea...
void ClearAnnotation(const SCH_SHEET_PATH *aSheetPath, bool aResetPrefix)
Clear exiting symbol annotation.
std::vector< SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieve a list of the SCH_PINs for the given sheet path.
std::vector< SCH_PIN * > GetAllLibPins() const
void AddHierarchicalReference(const KIID_PATH &aPath, const wxString &aRef, int aUnit)
Add a full hierarchical reference to this symbol.
Definition: sch_symbol.cpp:620
const LIB_ID & GetLibId() const override
Definition: sch_symbol.h:194
void SetSchSymbolLibraryName(const wxString &aName)
The name of the symbol in the schematic library symbol list.
Definition: sch_symbol.h:209
std::vector< SCH_PIN * > GetLibPins() const
Populate a vector with all the pins from the library object that match the current unit and bodyStyle...
int GetOrientation() const
Get the display symbol orientation.
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition: sch_symbol.h:213
void SetLibSymbol(LIB_SYMBOL *aLibSymbol)
Set this schematic symbol library symbol reference to aLibSymbol.
Definition: sch_symbol.cpp:275
VECTOR2I GetPinPhysicalPosition(const SCH_PIN *Pin) const
A collection of SYMBOL_LIB objects.
int GetLibraryCount()
LIB_SYMBOL * LoadSymbol(const wxString &aNickname, const wxString &aName)
Load a LIB_SYMBOL having aName from the library given by aNickname.
Object used to load, save, search, and otherwise manipulate symbol library files.
bool IsCache() const
LIB_SYMBOL * FindSymbol(const wxString &aName) const
Find LIB_SYMBOL by aName.
void Clear()
Definition: title_block.h:113
for transforming drawing coordinates for a wxDC device context.
Definition: transform.h:46
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
Definition: utf8.h:72
bool empty() const
Definition: utf8.h:104
wxString wx_str() const
Definition: utf8.cpp:45
#define _(s)
#define IS_DELETED
#define STRUCT_DELETED
flag indication structures to be erased
#define IS_MOVING
Item being moved.
@ ERCE_UNSPECIFIED
Definition: erc_settings.h:38
static const wxChar DanglingProfileMask[]
Flag to enable connectivity profiling.
const wxChar *const traceSchSheetPaths
Flag to enable debug output of schematic symbol sheet path manipulation code.
PROJECT & Prj()
Definition: kicad.cpp:595
@ LAYER_WIRE
Definition: layer_ids.h:357
@ LAYER_NOTES
Definition: layer_ids.h:372
@ LAYER_BUS
Definition: layer_ids.h:358
POINT_INFO AnalyzePoint(const EE_RTREE &aItem, const VECTOR2I &aPosition, bool aBreakCrossings)
Check a tree of items for a confluence at a given point and work out what kind of junction it is,...
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_INFO
static const wxChar DanglingProfileMask[]
Definition: sch_screen.cpp:71
#define PROCESSED
SCH_LINE_TEST_T
Definition: sch_screen.h:70
@ ENTIRE_LENGTH_T
Definition: sch_screen.h:71
@ EXCLUDE_END_POINTS_T
Definition: sch_screen.h:73
@ END_POINTS_ONLY_T
Definition: sch_screen.h:72
SYMBOL_ORIENTATION_T
enum used in RotationMiroir()
Definition: sch_symbol.h:77
@ SYM_ORIENT_270
Definition: sch_symbol.h:84
@ SYM_ROTATE_CLOCKWISE
Definition: sch_symbol.h:79
@ SYM_ROTATE_COUNTERCLOCKWISE
Definition: sch_symbol.h:80
@ SYM_MIRROR_Y
Definition: sch_symbol.h:86
@ SYM_ORIENT_180
Definition: sch_symbol.h:83
@ SYM_MIRROR_X
Definition: sch_symbol.h:85
@ SYM_NORMAL
Definition: sch_symbol.h:78
@ SYM_ORIENT_90
Definition: sch_symbol.h:82
@ SYM_ORIENT_0
Definition: sch_symbol.h:81
wxString UnescapeString(const wxString &aSource)
const double IU_PER_MILS
Definition: base_units.h:77
The EE_TYPE struct provides a type-specific auto-range iterator to the RTree.
Definition: sch_rtree.h:192
iterator begin()
Definition: sch_rtree.h:222
iterator end()
Definition: sch_rtree.h:227
std::vector< char > decompressedData
A selection of information about a point in the schematic that might be eligible for turning into a j...
A simple container for sheet instance information.
A simple container for schematic symbol instance information.
Definition for symbol library class.
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
@ REFERENCE_FIELD
Field Reference of part, i.e. "IC21".
wxLogTrace helper definitions.
bool IsPointOnSegment(const VECTOR2I &aSegStart, const VECTOR2I &aSegEnd, const VECTOR2I &aTestPoint)
Test if aTestPoint is on line defined by aSegStart and aSegEnd.
Definition: trigo.cpp:88
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:78
@ SCH_LINE_T
Definition: typeinfo.h:163
@ SCH_SYMBOL_T
Definition: typeinfo.h:172
@ SCH_FIELD_T
Definition: typeinfo.h:150
@ SCH_DIRECTIVE_LABEL_T
Definition: typeinfo.h:171
@ SCH_LABEL_T
Definition: typeinfo.h:167
@ SCH_SHEET_T
Definition: typeinfo.h:174
@ SCH_MARKER_T
Definition: typeinfo.h:158
@ SCH_HIER_LABEL_T
Definition: typeinfo.h:169
@ SCH_SCREEN_T
Definition: typeinfo.h:201
@ SCH_LABEL_LOCATE_ANY_T
Definition: typeinfo.h:190
@ SCHEMATIC_T
Definition: typeinfo.h:203
@ SCH_SHEET_PIN_T
Definition: typeinfo.h:173
@ SCH_BUS_WIRE_ENTRY_T
Definition: typeinfo.h:161
@ SCH_BITMAP_T
Definition: typeinfo.h:164
@ SCH_GLOBAL_LABEL_T
Definition: typeinfo.h:168
@ SCH_JUNCTION_T
Definition: typeinfo.h:159
@ SCH_PIN_T
Definition: typeinfo.h:153
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:673