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