28#include <unordered_set>
33 bool aBreakCrossings )
42 info.hasBusEntry =
false;
43 info.hasExplicitJunctionDot =
false;
44 info.isJunction =
false;
45 info.hasBusEntryToMultipleWires =
false;
46 info.hasBusAtPoint =
false;
48 bool breakLines[2] = {
false };
49 std::unordered_set<int> exitAngles[2];
50 std::vector<const SCH_LINE*> midPointLines[2];
53 std::list<std::unique_ptr<SCH_LINE>> mergedLines;
62 switch( item->Type() )
69 mergedLines.emplace_back(
new SCH_LINE( *line ) );
75 if( item->HitTest( aPosition, -1 ) )
76 info.hasExplicitJunctionDot =
true;
82 info.hasBusEntry =
true;
99 if( mergedLines.size() + filtered.
size() < 2 )
106 std::unordered_set<int> preMergeWireExits;
107 std::unordered_set<int> preMergeBusExits;
109 for(
const auto& line : mergedLines )
111 if( line->GetStartPoint() == line->GetEndPoint() )
114 if( !line->IsConnected( aPosition ) )
118 preMergeWireExits.insert( line->GetAngleFrom( aPosition ) );
120 preMergeBusExits.insert( line->GetAngleFrom( aPosition ) );
123 const bool keepStubJunction = preMergeWireExits.size() >= 3 || preMergeBusExits.size() >= 3;
130 if(
info.hasExplicitJunctionDot || aBreakCrossings || keepStubJunction )
135 for(
auto it_i = mergedLines.begin(); it_i != mergedLines.end() && !merged; ++it_i )
137 for(
auto it_j = std::next( it_i ); it_j != mergedLines.end(); ++it_j )
139 if(
auto* line = ( *it_i )->MergeOverlap(
nullptr, it_j->get(),
false ) )
142 mergedLines.erase( it_j );
150 for(
const auto& line : mergedLines )
151 filtered.
insert( line.get() );
155 int uniqueAngle = 10000;
157 for(
const SCH_ITEM* item : filtered )
162 switch( item->Type() )
165 if( item->HitTest( aPosition, -1 ) )
166 info.hasExplicitJunctionDot =
true;
186 breakLines[layer] =
true;
187 exitAngles[layer].insert( line->
GetAngleFrom( aPosition ) );
189 else if( line->
HitTest( aPosition, -1 ) )
191 if( aBreakCrossings )
192 breakLines[layer] =
true;
195 midPointLines[layer].push_back( line );
198 if( layer == BUSES && line->
HitTest( aPosition, -1 ) )
199 info.hasBusAtPoint =
true;
204 if( item->IsConnected( aPosition ) )
206 breakLines[BUSES] =
true;
207 exitAngles[BUSES].insert( uniqueAngle++ );
208 breakLines[WIRES] =
true;
209 exitAngles[WIRES].insert( uniqueAngle++ );
210 info.hasBusEntry =
true;
217 if( item->IsConnected( aPosition ) )
219 breakLines[WIRES] =
true;
220 exitAngles[WIRES].insert( uniqueAngle++ );
226 if( item->IsConnected( aPosition ) )
229 breakLines[BUSES] =
true;
231 breakLines[WIRES] =
true;
238 if( item->IsConnected( aPosition ) )
239 breakLines[WIRES] =
true;
248 for(
int layer : { WIRES, BUSES } )
250 if( breakLines[layer] )
252 for(
const SCH_LINE* line : midPointLines[layer] )
254 exitAngles[layer].insert( line->GetAngleFrom( aPosition ) );
255 exitAngles[layer].insert( line->GetReverseAngleFrom( aPosition ) );
260 if(
info.hasBusEntry )
265 info.hasBusEntryToMultipleWires = exitAngles[WIRES].size() > 2 && exitAngles[BUSES].size() == 1;
269 info.isJunction = exitAngles[WIRES].size() >= 3 || exitAngles[BUSES].size() >= 3;
276 const std::vector<SCH_ITEM*>& aItems )
279 std::unordered_set<const SCH_ITEM*> previewSet( aItems.begin(), aItems.end() );
284 if( !item->IsConnectable() )
287 if( previewSet.count( item ) )
296 if( !item || !item->IsConnectable() )
303 std::vector<VECTOR2I> pts;
307 if( !item || !item->IsConnectable() )
310 std::vector<VECTOR2I> new_pts = item->GetConnectionPoints();
311 pts.insert( pts.end(), new_pts.begin(), new_pts.end() );
317 for(
const VECTOR2I& pt : connections )
325 std::sort( pts.begin(), pts.end(),
328 return a.x < b.x || ( a.x == b.x && a.y < b.y );
331 pts.erase( std::unique( pts.begin(), pts.end() ), pts.end() );
333 std::vector<SCH_JUNCTION*> jcts;
339 if(
info.isJunction && ( !
info.hasBusEntry ||
info.hasBusEntryToMultipleWires ) )
343 if(
info.hasBusAtPoint )
346 jcts.push_back( junction );
Implement an R-tree for fast spatial and type indexing of schematic items.
size_t size() const
Return the number of items in the tree.
EE_TYPE Overlapping(const BOX2I &aRect) const
void insert(SCH_ITEM *aItem)
Insert an item into the tree.
static bool IsBusLabel(const wxString &aLabel)
Test if aLabel has a bus notation.
Base class for any item which can be embedded within the SCHEMATIC container class,...
void SetLayer(SCH_LAYER_ID aLayer)
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
bool IsConnected(const VECTOR2I &aPoint) const
Test the item to see if it is connected to aPoint.
Segment description base class to describe items which have 2 end points (track, wire,...
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
int GetAngleFrom(const VECTOR2I &aPoint) const
VECTOR2I GetEndPoint() const
VECTOR2I GetStartPoint() const
bool IsConnectable() const override
EE_RTREE & Items()
Get the full RTree, usually for iterating.
std::vector< VECTOR2I > GetConnections() const
Collect a unique list of all possible connection points in the schematic.
#define STRUCT_DELETED
flag indication structures to be erased
#define SKIP_STRUCT
flag indicating that the structure should be ignored
std::vector< SCH_JUNCTION * > PreviewJunctions(const class SCH_SCREEN *aScreen, const std::vector< class SCH_ITEM * > &aItems)
Determine the points where explicit junctions would be required if the given temporary items were com...
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,...
A selection of information about a point in the schematic that might be eligible for turning into a j...
bool IsPointOnSegment(const VECTOR2I &aSegStart, const VECTOR2I &aSegEnd, const VECTOR2I &aTestPoint)
Test if aTestPoint is on line defined by aSegStart and aSegEnd.
VECTOR2< int32_t > VECTOR2I