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