KiCad PCB EDA Suite
Loading...
Searching...
No Matches
bus-wire-junction.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) 2004 Jean-Pierre Charras, [email protected]
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
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 2
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, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#include <core/kicad_algo.h>
26#include <general.h>
27#include <sch_bus_entry.h>
28#include <sch_edit_frame.h>
29#include <sch_junction.h>
30#include <sch_line.h>
31#include <sch_no_connect.h>
32#include <sch_commit.h>
33#include <tool/tool_manager.h>
35#include <trigo.h>
36
37
39{
40 std::function<void( SCH_ITEM* )> changeHandler =
41 [&]( SCH_ITEM* aChangedItem ) -> void
42 {
43 GetCanvas()->GetView()->Update( aChangedItem, KIGFX::REPAINT );
44 };
45
46 GetScreen()->TestDanglingEnds( nullptr, &changeHandler );
47}
48
49
50bool SCH_EDIT_FRAME::TrimWire( SCH_COMMIT* aCommit, const VECTOR2I& aStart, const VECTOR2I& aEnd )
51{
52 if( aStart == aEnd )
53 return false;
54
55 SCH_SCREEN* screen = GetScreen();
56 std::vector<SCH_LINE*> wires;
57 BOX2I bb( aStart );
58
59 bb.Merge( aEnd );
60
61 // We cannot modify the RTree while iterating, so push the possible
62 // wires into a separate structure.
63 for( EDA_ITEM* item : screen->Items().Overlapping( bb ) )
64 {
65 SCH_LINE* line = static_cast<SCH_LINE*>( item );
66
67 if( item->Type() == SCH_LINE_T && line->GetLayer() == LAYER_WIRE )
68 wires.push_back( line );
69 }
70
71 for( SCH_LINE* line : wires )
72 {
73 // Don't remove wires that are already deleted or are currently being dragged
74 if( line->GetEditFlags() & ( STRUCT_DELETED | IS_MOVING | SKIP_STRUCT ) )
75 continue;
76
77 if( !IsPointOnSegment( line->GetStartPoint(), line->GetEndPoint(), aStart ) ||
78 !IsPointOnSegment( line->GetStartPoint(), line->GetEndPoint(), aEnd ) )
79 {
80 continue;
81 }
82
83 // Don't remove entire wires
84 if( ( line->GetStartPoint() == aStart && line->GetEndPoint() == aEnd )
85 || ( line->GetStartPoint() == aEnd && line->GetEndPoint() == aStart ) )
86 {
87 continue;
88 }
89
90 // Step 1: break the segment on one end.
91 // Ensure that *line points to the segment containing aEnd
92 SCH_LINE* new_line;
93 Schematic().BreakSegment( aCommit, line, aStart, &new_line, screen );
94
95 if( IsPointOnSegment( new_line->GetStartPoint(), new_line->GetEndPoint(), aEnd ) )
96 line = new_line;
97
98 // Step 2: break the remaining segment.
99 // Ensure that *line _also_ contains aStart. This is our overlapping segment
100 Schematic().BreakSegment( aCommit, line, aEnd, &new_line, screen );
101
102 if( IsPointOnSegment( new_line->GetStartPoint(), new_line->GetEndPoint(), aStart ) )
103 line = new_line;
104
105 RemoveFromScreen( line, screen );
106 aCommit->Removed( line, screen );
107
108 return true;
109 }
110
111 return false;
112}
113
114
116{
117 SCH_SCREEN* screen = GetScreen();
118 PICKED_ITEMS_LIST undoList;
120
121 aJunction->SetFlags( STRUCT_DELETED );
122 RemoveFromScreen( aJunction, screen );
123 aCommit->Removed( aJunction, screen );
124
127 std::list<SCH_LINE*> lines;
128
129 for( SCH_ITEM* item : screen->Items().Overlapping( SCH_LINE_T, aJunction->GetPosition() ) )
130 {
131 SCH_LINE* line = static_cast<SCH_LINE*>( item );
132
133 if( ( line->IsWire() || line->IsBus() )
134 && line->IsEndPoint( aJunction->GetPosition() )
135 && !( line->GetEditFlags() & STRUCT_DELETED ) )
136 {
137 lines.push_back( line );
138 }
139 }
140
141 alg::for_all_pairs( lines.begin(), lines.end(),
142 [&]( SCH_LINE* firstLine, SCH_LINE* secondLine )
143 {
144 if( ( firstLine->GetEditFlags() & STRUCT_DELETED )
145 || ( secondLine->GetEditFlags() & STRUCT_DELETED )
146 || !secondLine->IsParallel( firstLine ) )
147 {
148 return;
149 }
150
151 // Remove identical lines
152 if( firstLine->IsEndPoint( secondLine->GetStartPoint() )
153 && firstLine->IsEndPoint( secondLine->GetEndPoint() ) )
154 {
155 firstLine->SetFlags( STRUCT_DELETED );
156 return;
157 }
158
159 // Try to merge the remaining lines
160 if( SCH_LINE* new_line = secondLine->MergeOverlap( screen, firstLine, false ) )
161 {
162 firstLine->SetFlags( STRUCT_DELETED );
163 secondLine->SetFlags( STRUCT_DELETED );
164 AddToScreen( new_line, screen );
165 aCommit->Added( new_line, screen );
166
167 if( new_line->IsSelected() )
168 selectionTool->AddItemToSel( new_line, true /*quiet mode*/ );
169
170 lines.push_back( new_line );
171 }
172 } );
173
174 for( SCH_LINE* line : lines )
175 {
176 if( line->GetEditFlags() & STRUCT_DELETED )
177 {
178 if( line->IsSelected() )
179 selectionTool->RemoveItemFromSel( line, true /*quiet mode*/ );
180
181 RemoveFromScreen( line, screen );
182 aCommit->Removed( line, screen );
183 }
184 }
185}
186
187
189 const VECTOR2I& aPos )
190{
191 SCH_JUNCTION* junction = new SCH_JUNCTION( aPos );
192
193 AddToScreen( junction, aScreen );
194 aCommit->Added( junction, aScreen );
195
196 Schematic().BreakSegments( aCommit, aPos, aScreen );
197
198 return junction;
199}
200
202{
203 std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> items;
204
205 GetCanvas()->GetView()->Query( aItem->GetBoundingBox(), items );
206
207 for( const auto& it : items )
208 {
209 if( !it.first->IsSCH_ITEM() )
210 continue;
211
212 SCH_ITEM* item = static_cast<SCH_ITEM*>( it.first );
213
214 if( item == aItem )
215 continue;
216
217 if( item->IsType( { SCH_ITEM_LOCATE_WIRE_T } ) )
218 {
219 GetCanvas()->GetView()->Update( item );
220 }
221 }
222}
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: box2.h:658
COMMIT & Added(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Notify observers that aItem has been added.
Definition: commit.h:85
COMMIT & Removed(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Definition: commit.h:97
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:98
virtual VECTOR2I GetPosition() const
Definition: eda_item.h:272
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:110
EDA_ITEM_FLAGS GetEditFlags() const
Definition: eda_item.h:148
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:142
EE_TYPE Overlapping(const BOX2I &aRect) const
Definition: sch_rtree.h:246
void Update(const KIGFX::VIEW_ITEM *aItem, int aUpdateFlags) const override
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition: sch_view.cpp:60
int Query(const BOX2I &aRect, std::vector< LAYER_ITEM_PAIR > &aResult) const
Find all visible items that touch or are within the rectangle aRect.
Definition: view.cpp:420
A holder to handle information on schematic or board items.
void BreakSegment(SCH_COMMIT *aCommit, SCH_LINE *aSegment, const VECTOR2I &aPoint, SCH_LINE **aNewSegment, SCH_SCREEN *aScreen)
Break a single segment into two at the specified point.
Definition: schematic.cpp:1056
bool BreakSegments(SCH_COMMIT *aCommit, const VECTOR2I &aPoint, SCH_SCREEN *aScreen)
Check every wire and bus for a intersection at aPoint and break into two segments at aPoint if an int...
Definition: schematic.cpp:1076
void RemoveFromScreen(EDA_ITEM *aItem, SCH_SCREEN *aScreen) override
Remove an item from the screen (and view) aScreen is the screen the item is located on,...
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
void AddToScreen(EDA_ITEM *aItem, SCH_SCREEN *aScreen=nullptr) override
Add an item to the screen (and view) aScreen is the screen the item is located on,...
KIGFX::SCH_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
SCHEMATIC & Schematic() const
bool TrimWire(SCH_COMMIT *aCommit, const VECTOR2I &aStart, const VECTOR2I &aEnd)
If any single wire passes through both points, remove the portion between the two points,...
void TestDanglingEnds()
Test all of the connectable objects in the schematic for unused connection points.
void DeleteJunction(SCH_COMMIT *aCommit, SCH_ITEM *aItem)
Remove a given junction and heals any wire segments under the junction.
void UpdateHopOveredWires(SCH_ITEM *aItem)
SCH_JUNCTION * AddJunction(SCH_COMMIT *aCommit, SCH_SCREEN *aScreen, const VECTOR2I &aPos)
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:168
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition: sch_item.h:313
bool IsType(const std::vector< KICAD_T > &aScanTypes) const override
Check whether the item is one of the listed types.
Definition: sch_item.h:183
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:42
bool IsWire() const
Return true if the line is a wire.
Definition: sch_line.cpp:949
VECTOR2I GetEndPoint() const
Definition: sch_line.h:144
VECTOR2I GetStartPoint() const
Definition: sch_line.h:139
SCH_LINE * MergeOverlap(SCH_SCREEN *aScreen, SCH_LINE *aLine, bool aCheckJunctions)
Check line against aLine to see if it overlaps and merge if it does.
Definition: sch_line.cpp:425
bool IsBus() const
Return true if the line is a bus.
Definition: sch_line.cpp:955
bool IsEndPoint(const VECTOR2I &aPoint) const override
Test if aPt is an end point of this schematic object.
Definition: sch_line.h:91
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.
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition: sch_screen.h:117
TOOL_MANAGER * m_toolManager
Definition: tools_holder.h:171
#define STRUCT_DELETED
flag indication structures to be erased
#define SKIP_STRUCT
flag indicating that the structure should be ignored
#define IS_MOVING
Item being moved.
@ LAYER_WIRE
Definition: layer_ids.h:442
@ REPAINT
Item needs to be redrawn.
Definition: view_item.h:58
void for_all_pairs(_InputIterator __first, _InputIterator __last, _Function __f)
Apply a function to every possible pair of elements of a sequence.
Definition: kicad_algo.h:84
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
@ SCH_LINE_T
Definition: typeinfo.h:164