KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_drag_net_collision.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 * Copyright (C) 2025 VUT Brno, Faculty of Electrical Engineering and Communication
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 3
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
22
23#include <trace_helpers.h>
24
25#include <algorithm>
26#include <limits>
27#include <unordered_set>
28
29#include <eda_item.h>
30#include <sch_connection.h>
31#include <sch_edit_frame.h>
32#include <sch_item.h>
33#include <sch_junction.h>
34#include <sch_screen.h>
35#include <sch_selection.h>
36#include <sch_sheet_path.h>
37#include <view/view.h>
38#include <view/view_overlay.h>
39#include <gal/color4d.h>
40#include <layer_ids.h>
42#include <eeschema_settings.h>
43
55
56
61
62
64{
65 wxLogTrace( traceSchDragNetCollision, "Initialize: Starting initialization" );
66
67 m_itemNetCodes.clear();
69 m_sheetPath = m_frame->GetCurrentSheet();
70 m_hasCollision = false;
71
72 EE_RTREE& items = m_frame->GetScreen()->Items();
73
74 wxLogTrace( traceSchDragNetCollision, "Initialize: Recording nets for %zu screen items",
75 items.size() );
76
77 for( SCH_ITEM* item : items )
78 recordItemNet( item );
79
80 wxLogTrace( traceSchDragNetCollision, "Initialize: Recording nets for %d selected items",
81 aSelection.GetSize() );
82
83 for( EDA_ITEM* edaItem : aSelection )
84 recordItemNet( static_cast<SCH_ITEM*>( edaItem ) );
85
86 recordOriginalConnections( aSelection );
87
88 wxLogTrace( traceSchDragNetCollision, "Initialize: Complete. Tracked %zu items with net codes",
89 m_itemNetCodes.size() );
90}
91
92
93bool SCH_DRAG_NET_COLLISION_MONITOR::Update( const std::vector<SCH_JUNCTION*>& aJunctions,
94 const SCH_SELECTION& aSelection,
95 std::span<const PREVIEW_NET_ASSIGNMENT> aPreviewAssignments )
96{
97 wxLogTrace( traceSchDragNetCollision, "Update: Called with %zu junctions, %d selected items, %zu preview assignments",
98 aJunctions.size(), aSelection.GetSize(), aPreviewAssignments.size() );
99
100 std::unordered_map<const SCH_ITEM*, std::optional<int>> previewNetCodes;
101
102 previewNetCodes.reserve( aPreviewAssignments.size() );
103
104 for( const PREVIEW_NET_ASSIGNMENT& assignment : aPreviewAssignments )
105 {
106 if( !assignment.item )
107 continue;
108
109 wxLogTrace( traceSchDragNetCollision, "Update: Preview assignment - item %p, netCode %s",
110 assignment.item,
111 assignment.netCode.has_value() ? std::to_string( *assignment.netCode ).c_str() : "none" );
112
113 previewNetCodes[ assignment.item ] = assignment.netCode;
114 }
115
116 std::vector<COLLISION_MARKER> markers;
117
118 if( aJunctions.empty() )
119 {
120 wxLogTrace( traceSchDragNetCollision, "Update: No junctions to analyze" );
121 }
122 else
123 {
124 wxLogTrace( traceSchDragNetCollision, "Update: Analyzing %zu junctions", aJunctions.size() );
125
126 for( SCH_JUNCTION* junction : aJunctions )
127 {
128 if( auto marker = analyzeJunction( junction, aSelection, previewNetCodes ) )
129 {
130 wxLogTrace( traceSchDragNetCollision, "Update: Junction at (%d, %d) has collision",
131 marker->position.x, marker->position.y );
132 markers.push_back( *marker );
133 }
134 }
135 }
136
137 std::vector<DISCONNECTION_MARKER> disconnections = collectDisconnectedMarkers( aSelection );
138
139 if( markers.empty() && disconnections.empty() )
140 {
141 wxLogTrace( traceSchDragNetCollision, "Update: No collisions or disconnections detected" );
142 clearOverlay();
143 m_hasCollision = false;
144 return false;
145 }
146
147 wxLogTrace( traceSchDragNetCollision, "Update: Drawing %zu collision markers and %zu disconnection markers",
148 markers.size(), disconnections.size() );
149
151 m_overlay->Clear();
152
153 COLOR4D baseColor( 1.0, 0.0, 0.0, 0.8 );
154
155 if( COLOR_SETTINGS* colorSettings = m_frame->GetColorSettings() )
156 {
157 COLOR4D themeColor = colorSettings->GetColor( LAYER_DRAG_NET_COLLISION );
158
159 if( themeColor != COLOR4D::UNSPECIFIED )
160 baseColor = themeColor;
161 }
162
163 double baseAlpha = baseColor.a;
164
165 if( baseAlpha <= 0.0 )
166 baseAlpha = 1.0;
167
168 double fillAlpha = std::clamp( baseAlpha * 0.35, 0.05, 1.0 );
169 double strokeAlpha = std::clamp( baseAlpha, 0.05, 1.0 );
170
171 m_overlay->SetIsFill( true );
172 m_overlay->SetFillColor( baseColor.WithAlpha( fillAlpha ) );
173 m_overlay->SetIsStroke( true );
174 m_overlay->SetStrokeColor( baseColor.WithAlpha( strokeAlpha ) );
175
176 int lineWidthPixels = 4;
177
178 if( EESCHEMA_SETTINGS* cfg = m_frame->eeconfig() )
179 lineWidthPixels = std::max( cfg->m_Selection.drag_net_collision_width, 1 );
180
181 double lineWidth = m_view->ToWorld( lineWidthPixels );
182
183 if( lineWidth <= 0.0 )
184 lineWidth = 1.0;
185
186 m_overlay->SetLineWidth( lineWidth );
187
188 for( const COLLISION_MARKER& marker : markers )
189 m_overlay->Circle( marker.position, marker.radius );
190
191 for( const DISCONNECTION_MARKER& marker : disconnections )
192 {
193 m_overlay->Circle( marker.pointA, marker.radius );
194 m_overlay->Circle( marker.pointB, marker.radius );
195 m_overlay->Line( VECTOR2D( marker.pointA ), VECTOR2D( marker.pointB ) );
196 }
197
198 m_view->Update( m_overlay.get() );
199 m_hasCollision = true;
200 return true;
201}
202
203
205{
206 clearOverlay();
207 m_itemNetCodes.clear();
208 m_originalConnections.clear();
209 m_hasCollision = false;
210}
211
212
214{
215 if( m_hasCollision )
216 return KICURSOR::WARNING;
217
218 return aBaseCursor;
219}
220
221
222std::optional<int> SCH_DRAG_NET_COLLISION_MONITOR::GetNetCode( const SCH_ITEM* aItem ) const
223{
224 if( !aItem )
225 return std::nullopt;
226
227 auto it = m_itemNetCodes.find( aItem );
228
229 if( it != m_itemNetCodes.end() )
230 return it->second;
231
232 if( SCH_CONNECTION* connection = aItem->Connection( &m_sheetPath ) )
233 {
234 if( connection->IsNet() && !connection->IsUnconnected() )
235 {
236 int netCode = connection->NetCode();
237
238 if( netCode > 0 )
239 return netCode;
240 }
241 }
242
243 return std::nullopt;
244}
245
246
247std::optional<SCH_DRAG_NET_COLLISION_MONITOR::COLLISION_MARKER> SCH_DRAG_NET_COLLISION_MONITOR::analyzeJunction(
248 SCH_JUNCTION* aJunction, const SCH_SELECTION& aSelection,
249 const std::unordered_map<const SCH_ITEM*, std::optional<int>>& aPreviewNetCodes ) const
250{
251 if( !aJunction )
252 return std::nullopt;
253
254 VECTOR2I position = aJunction->GetPosition();
255 EE_RTREE& items = m_frame->GetScreen()->Items();
256
257 wxLogTrace( traceSchDragNetCollision, "analyzeJunction: Checking junction at (%d, %d)",
258 position.x, position.y );
259
260 std::unordered_set<int> allNetCodes;
261 std::unordered_set<int> movedNetCodes;
262 std::unordered_set<int> originalNetCodes;
263 std::unordered_set<int> movedOriginalNetCodes;
264 std::unordered_set<int> stationaryOriginalNetCodes;
265
266 auto accumulateNet = [&]( SCH_ITEM* item )
267 {
268 if( !item )
269 {
270 wxLogTrace( traceSchDragNetCollision, " accumulateNet: null item" );
271 return;
272 }
273
274 if( !item->IsConnectable() )
275 {
276 wxLogTrace( traceSchDragNetCollision, " accumulateNet: item %p (%s) not connectable",
277 item, item->GetClass().c_str() );
278 return;
279 }
280
281 if( !item->IsConnected( position ) && !( item->IsType( { SCH_LINE_T } ) && item->HitTest( position ) ) )
282 {
283 wxLogTrace( traceSchDragNetCollision, " accumulateNet: item %p (%s) not connected at (%d, %d)",
284 item, item->GetClass().c_str(), position.x, position.y );
285 return;
286 }
287
288 auto previewIt = aPreviewNetCodes.find( item );
289 auto originalIt = m_itemNetCodes.find( item );
290 std::optional<int> netCodeOpt;
291 std::optional<int> originalNetOpt;
292
293 if( originalIt != m_itemNetCodes.end() )
294 originalNetOpt = originalIt->second;
295
296 if( previewIt != aPreviewNetCodes.end() )
297 {
298 netCodeOpt = previewIt->second;
299 wxLogTrace( traceSchDragNetCollision, " accumulateNet: item %p (%s) using preview net %s",
300 item, item->GetClass().c_str(),
301 netCodeOpt.has_value() ? std::to_string( *netCodeOpt ).c_str() : "none" );
302 }
303 else if( originalIt != m_itemNetCodes.end() )
304 {
305 netCodeOpt = originalIt->second;
306 wxLogTrace( traceSchDragNetCollision, " accumulateNet: item %p (%s) using cached net %s",
307 item, item->GetClass().c_str(),
308 netCodeOpt.has_value() ? std::to_string( *netCodeOpt ).c_str() : "none" );
309 }
310 else
311 {
312 wxLogTrace( traceSchDragNetCollision, " accumulateNet: item %p (%s) has no net code",
313 item, item->GetClass().c_str() );
314 }
315
316 bool isSelectionItem = item->IsSelected() || aSelection.Contains( item );
317 bool isMoved = ( previewIt != aPreviewNetCodes.end() ) || isSelectionItem;
318
319 if( !netCodeOpt )
320 {
321 if( originalNetOpt )
322 {
323 originalNetCodes.insert( *originalNetOpt );
324
325 if( isSelectionItem )
326 movedOriginalNetCodes.insert( *originalNetOpt );
327 else
328 stationaryOriginalNetCodes.insert( *originalNetOpt );
329 }
330
331 wxLogTrace( traceSchDragNetCollision, " accumulateNet: item %p (%s) netCode is nullopt",
332 item, item->GetClass().c_str() );
333 return;
334 }
335
336 int netCode = *netCodeOpt;
337 allNetCodes.insert( netCode );
338
339 wxLogTrace( traceSchDragNetCollision, " accumulateNet: item %p (%s) net %d, moved=%s",
340 item, item->GetClass().c_str(), netCode, isMoved ? "yes" : "no" );
341
342 if( isMoved )
343 movedNetCodes.insert( netCode );
344
345 if( originalNetOpt )
346 {
347 originalNetCodes.insert( *originalNetOpt );
348
349 if( isSelectionItem )
350 movedOriginalNetCodes.insert( *originalNetOpt );
351 else
352 stationaryOriginalNetCodes.insert( *originalNetOpt );
353 }
354 };
355
356 wxLogTrace( traceSchDragNetCollision, "analyzeJunction: Checking items overlapping position" );
357
358 int candidateCount = 0;
359
360 for( SCH_ITEM* candidate : items.Overlapping( position ) )
361 {
362 candidateCount++;
363 accumulateNet( candidate );
364 }
365
366 wxLogTrace( traceSchDragNetCollision, "analyzeJunction: Checked %d overlapping items", candidateCount );
367 wxLogTrace( traceSchDragNetCollision, "analyzeJunction: Checking %d selected items", aSelection.GetSize() );
368
369 for( EDA_ITEM* selected : aSelection )
370 accumulateNet( static_cast<SCH_ITEM*>( selected ) );
371
372 wxLogTrace( traceSchDragNetCollision, "analyzeJunction: Found %zu unique nets, %zu moved nets",
373 allNetCodes.size(), movedNetCodes.size() );
374
375 if( !movedNetCodes.empty() )
376 {
377 wxLogTrace( traceSchDragNetCollision, "analyzeJunction: Moved nets:" );
378
379 for( int netCode : movedNetCodes )
380 wxLogTrace( traceSchDragNetCollision, " - Net %d", netCode );
381 }
382
383 wxLogTrace( traceSchDragNetCollision,
384 "analyzeJunction: Original nets=%zu, moved originals=%zu, stationary originals=%zu",
385 originalNetCodes.size(), movedOriginalNetCodes.size(), stationaryOriginalNetCodes.size() );
386
387 if( !movedOriginalNetCodes.empty() )
388 {
389 wxLogTrace( traceSchDragNetCollision, "analyzeJunction: Moved original nets:" );
390
391 for( int netCode : movedOriginalNetCodes )
392 wxLogTrace( traceSchDragNetCollision, " - Net %d", netCode );
393 }
394
395 if( !stationaryOriginalNetCodes.empty() )
396 {
397 wxLogTrace( traceSchDragNetCollision, "analyzeJunction: Stationary original nets:" );
398
399 for( int netCode : stationaryOriginalNetCodes )
400 wxLogTrace( traceSchDragNetCollision, " - Net %d", netCode );
401 }
402
403 if( allNetCodes.size() >= 2 )
404 {
405 wxLogTrace( traceSchDragNetCollision, "analyzeJunction: All nets at junction:" );
406
407 for( int netCode : allNetCodes )
408 wxLogTrace( traceSchDragNetCollision, " - Net %d", netCode );
409 }
410
411 bool previewCollision = !movedNetCodes.empty() && allNetCodes.size() >= 2;
412
413 bool originalCollision = false;
414
415 if( !movedOriginalNetCodes.empty() && !stationaryOriginalNetCodes.empty() )
416 {
417 for( int movedNet : movedOriginalNetCodes )
418 {
419 for( int stationaryNet : stationaryOriginalNetCodes )
420 {
421 if( movedNet != stationaryNet )
422 {
423 originalCollision = true;
424 break;
425 }
426 }
427
428 if( originalCollision )
429 break;
430 }
431 }
432
433 if( !previewCollision && !originalCollision )
434 {
435 wxLogTrace( traceSchDragNetCollision, "analyzeJunction: No collision (movedNets=%zu, allNets=%zu)",
436 movedNetCodes.size(), allNetCodes.size() );
437 return std::nullopt;
438 }
439
440 if( originalCollision && !previewCollision )
441 {
442 wxLogTrace( traceSchDragNetCollision,
443 "analyzeJunction: Original net mismatch detected under moved endpoints" );
444 }
445
446 COLLISION_MARKER marker;
447 marker.position = position;
448 double base = static_cast<double>( aJunction->GetEffectiveDiameter() );
449 marker.radius = std::max( base * 1.5, 800.0 );
450
451 wxLogTrace( traceSchDragNetCollision, "analyzeJunction: COLLISION DETECTED at (%d, %d) with radius %.1f",
452 position.x, position.y, marker.radius );
453
454 return marker;
455}
456
457
459{
460 if( !aItem )
461 return;
462
463 if( !aItem->IsConnectable() )
464 return;
465
466 if( m_itemNetCodes.find( aItem ) != m_itemNetCodes.end() )
467 return;
468
469 if( SCH_CONNECTION* connection = aItem->Connection( &m_sheetPath ) )
470 {
471 if( connection->IsNet() && !connection->IsUnconnected() )
472 {
473 int netCode = connection->NetCode();
474
475 if( netCode > 0 )
476 {
477 wxLogTrace( traceSchDragNetCollision, "recordItemNet: Item %p (%s) at (%d, %d) -> net %d (%s)",
478 aItem, aItem->GetClass().c_str(),
479 aItem->GetPosition().x, aItem->GetPosition().y,
480 netCode, connection->Name().c_str() );
481 m_itemNetCodes.emplace( aItem, netCode );
482 }
483 else
484 {
485 wxLogTrace( traceSchDragNetCollision, "recordItemNet: Item %p (%s) has invalid netCode %d",
486 aItem, aItem->GetClass().c_str(), netCode );
487 m_itemNetCodes.emplace( aItem, std::nullopt );
488 }
489 }
490 else
491 {
492 wxLogTrace( traceSchDragNetCollision, "recordItemNet: Item %p (%s) connection not a net or unconnected",
493 aItem, aItem->GetClass().c_str() );
494 m_itemNetCodes.emplace( aItem, std::nullopt );
495 }
496 }
497 else
498 {
499 wxLogTrace( traceSchDragNetCollision, "recordItemNet: Item %p (%s) has no connection",
500 aItem, aItem->GetClass().c_str() );
501 m_itemNetCodes.emplace( aItem, std::nullopt );
502 }
503}
504
505
507{
508 wxLogTrace( traceSchDragNetCollision, "recordOriginalConnections: Recording connections for %d items",
509 aSelection.GetSize() );
510
511 // Don't record original connections for new or pasted items (duplicates, pastes)
512 // as they weren't previously connected to anything
513 bool hasNewOrPastedItems = false;
514
515 for( EDA_ITEM* edaItem : aSelection )
516 {
517 if( edaItem->IsNew() || ( edaItem->GetFlags() & IS_PASTED ) )
518 {
519 hasNewOrPastedItems = true;
520 break;
521 }
522 }
523
524 if( hasNewOrPastedItems )
525 {
526 wxLogTrace( traceSchDragNetCollision,
527 "recordOriginalConnections: Skipping - selection contains new or pasted items" );
528 return;
529 }
530
531 EE_RTREE& items = m_frame->GetScreen()->Items();
532
533 for( EDA_ITEM* edaItem : aSelection )
534 {
535 SCH_ITEM* item = static_cast<SCH_ITEM*>( edaItem );
536
537 if( !item || !item->IsConnectable() )
538 continue;
539
540 std::vector<VECTOR2I> points = item->GetConnectionPoints();
541
542 for( size_t index = 0; index < points.size(); ++index )
543 {
544 const VECTOR2I& point = points[index];
545
546 for( SCH_ITEM* candidate : items.Overlapping( point ) )
547 {
548 if( candidate == item || !candidate->IsConnectable() )
549 continue;
550
551 if( !candidate->CanConnect( item ) )
552 continue;
553
554 if( !candidate->IsConnected( point )
555 && !( candidate->IsType( { SCH_LINE_T } ) && candidate->HitTest( point ) ) )
556 {
557 continue;
558 }
559
560 std::vector<VECTOR2I> candidatePoints = candidate->GetConnectionPoints();
561 size_t candidateIndex = std::numeric_limits<size_t>::max();
562
563 for( size_t candidatePos = 0; candidatePos < candidatePoints.size(); ++candidatePos )
564 {
565 if( candidatePoints[candidatePos] == point )
566 {
567 candidateIndex = candidatePos;
568 break;
569 }
570 }
571
572 if( candidateIndex == std::numeric_limits<size_t>::max() )
573 continue;
574
575 SCH_ITEM* firstItem = item;
576 size_t firstIndex = index;
577 SCH_ITEM* secondItem = candidate;
578 size_t secondIndex = candidateIndex;
579
580 if( secondItem < firstItem || ( secondItem == firstItem && secondIndex < firstIndex ) )
581 {
582 std::swap( firstItem, secondItem );
583 std::swap( firstIndex, secondIndex );
584 }
585
586 if( firstItem == secondItem )
587 continue;
588
589 bool firstSelected = firstItem->IsSelected() || aSelection.Contains( firstItem );
590 bool secondSelected = secondItem->IsSelected() || aSelection.Contains( secondItem );
591
592 if( !firstSelected && !secondSelected )
593 continue;
594
595 auto existing = std::find_if( m_originalConnections.begin(), m_originalConnections.end(),
596 [&]( const ORIGINAL_CONNECTION& connection )
597 {
598 return connection.itemA == firstItem && connection.indexA == firstIndex
599 && connection.itemB == secondItem && connection.indexB == secondIndex;
600 } );
601
602 if( existing != m_originalConnections.end() )
603 continue;
604
605 m_originalConnections.push_back( { firstItem, firstIndex, secondItem, secondIndex } );
606 }
607 }
608 }
609
610 wxLogTrace( traceSchDragNetCollision, "recordOriginalConnections: Tracked %zu connections",
611 m_originalConnections.size() );
612}
613
614
615std::vector<SCH_DRAG_NET_COLLISION_MONITOR::DISCONNECTION_MARKER>
617{
618 std::vector<DISCONNECTION_MARKER> markers;
619
620 for( const ORIGINAL_CONNECTION& connection : m_originalConnections )
621 {
622 SCH_ITEM* itemA = connection.itemA;
623 SCH_ITEM* itemB = connection.itemB;
624
625 if( !itemA || !itemB )
626 continue;
627
628 if( !itemA->IsConnectable() || !itemB->IsConnectable() )
629 continue;
630
631 std::vector<VECTOR2I> pointsA = itemA->GetConnectionPoints();
632 std::vector<VECTOR2I> pointsB = itemB->GetConnectionPoints();
633
634 if( connection.indexA >= pointsA.size() || connection.indexB >= pointsB.size() )
635 continue;
636
637 VECTOR2I pointA = pointsA[ connection.indexA ];
638 VECTOR2I pointB = pointsB[ connection.indexB ];
639
640 // Check if the connection is still valid. Points match exactly.
641 bool stillConnected = ( pointA == pointB );
642
643 // For lines, connection is valid if the point is anywhere on the line
644 if( !stillConnected && itemB->IsType( { SCH_LINE_T } ) && itemB->HitTest( pointA, 0 ) )
645 stillConnected = true;
646
647 if( !stillConnected && itemA->IsType( { SCH_LINE_T } ) && itemA->HitTest( pointB, 0 ) )
648 stillConnected = true;
649
650 if( stillConnected )
651 continue;
652
653 bool relevant = itemA->IsSelected() || aSelection.Contains( itemA )
654 || itemB->IsSelected() || aSelection.Contains( itemB );
655
656 if( !relevant )
657 continue;
658
659 double radius = std::max( { 800.0,
660 static_cast<double>( itemA->GetPenWidth() ),
661 static_cast<double>( itemB->GetPenWidth() ) } );
662
664 marker.pointA = pointA;
665 marker.pointB = pointB;
666 marker.radius = radius;
667 markers.push_back( marker );
668 }
669
670 if( !markers.empty() )
671 {
672 wxLogTrace( traceSchDragNetCollision,
673 "collectDisconnectedMarkers: Identified %zu disconnections", markers.size() );
674 }
675
676 return markers;
677}
678
679
681{
682 if( !m_overlay )
683 m_overlay = m_view->MakeOverlay();
684}
685
686
688{
689 if( m_overlay )
690 {
691 m_overlay->Clear();
692 m_view->Update( m_overlay.get() );
693 }
694}
int index
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition color4d.h:398
Color settings are a bit different than most of the settings objects in that there can be more than o...
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:96
virtual VECTOR2I GetPosition() const
Definition eda_item.h:282
bool IsSelected() const
Definition eda_item.h:132
virtual bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const
Test if aPosition is inside or on the boundary of this item.
Definition eda_item.h:243
Implement an R-tree for fast spatial and type indexing of schematic items.
Definition sch_rtree.h:34
size_t size() const
Return the number of items in the tree.
Definition sch_rtree.h:150
EE_TYPE Overlapping(const BOX2I &aRect) const
Definition sch_rtree.h:226
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
COLOR4D WithAlpha(double aAlpha) const
Return a color with the same color, but the given alpha.
Definition color4d.h:308
double a
Alpha component.
Definition color4d.h:392
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition view.h:63
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
std::optional< COLLISION_MARKER > analyzeJunction(SCH_JUNCTION *aJunction, const SCH_SELECTION &aSelection, const std::unordered_map< const SCH_ITEM *, std::optional< int > > &aPreviewNetCodes) const
std::vector< ORIGINAL_CONNECTION > m_originalConnections
std::vector< DISCONNECTION_MARKER > collectDisconnectedMarkers(const SCH_SELECTION &aSelection) const
std::unordered_map< const SCH_ITEM *, std::optional< int > > m_itemNetCodes
void recordOriginalConnections(const SCH_SELECTION &aSelection)
KICURSOR AdjustCursor(KICURSOR aBaseCursor) const
std::shared_ptr< KIGFX::VIEW_OVERLAY > m_overlay
SCH_DRAG_NET_COLLISION_MONITOR(SCH_EDIT_FRAME *aFrame, KIGFX::VIEW *aView)
std::optional< int > GetNetCode(const SCH_ITEM *aItem) const
bool Update(const std::vector< SCH_JUNCTION * > &aJunctions, const SCH_SELECTION &aSelection, std::span< const PREVIEW_NET_ASSIGNMENT > aPreviewAssignments={})
void Initialize(const SCH_SELECTION &aSelection)
Schematic editor (Eeschema) main window.
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:162
virtual bool IsConnectable() const
Definition sch_item.h:524
virtual int GetPenWidth() const
Definition sch_item.h:351
SCH_CONNECTION * Connection(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieve the connection associated with this object in the given sheet.
Definition sch_item.cpp:487
wxString GetClass() const override
Return the class name.
Definition sch_item.h:172
virtual std::vector< VECTOR2I > GetConnectionPoints() const
Add all the connection points for this item to aPoints.
Definition sch_item.h:539
bool IsType(const std::vector< KICAD_T > &aScanTypes) const override
Check whether the item is one of the listed types.
Definition sch_item.h:177
int GetEffectiveDiameter() const
VECTOR2I GetPosition() const override
virtual unsigned int GetSize() const override
Return the number of stored items.
Definition selection.h:101
bool Contains(EDA_ITEM *aItem) const
Definition selection.cpp:80
KICURSOR
Definition cursors.h:40
@ WARNING
Definition cursors.h:46
#define IS_PASTED
Modifier on IS_NEW which indicates it came from clipboard.
const wxChar *const traceSchDragNetCollision
Flag to enable debug output of schematic drag net collision detection.
@ LAYER_DRAG_NET_COLLISION
Definition layer_ids.h:492
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
int radius
wxLogTrace helper definitions.
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683
VECTOR2< double > VECTOR2D
Definition vector2d.h:682