KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pns_helpers.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 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20#include <board.h>
22#include <math/vector2d.h>
23#include <netinfo.h>
24#include <pcb_track.h>
25#include <router/pns_helpers.h>
26#include <router/pns_arc.h>
27
28
29PNS::LINKED_ITEM* PNS::HELPERS::PickSegment( PNS::ROUTER* aRouter, const VECTOR2I& aWhere, int aLayer,
30 VECTOR2I& aPointOut, const SHAPE_LINE_CHAIN& aBaseline )
31{
32 int maxSlopRadius = aRouter->Sizes().Clearance() + aRouter->Sizes().TrackWidth() / 2;
33
34 static const int candidateCount = 2;
35 PNS::LINKED_ITEM* prioritized[candidateCount];
36 SEG::ecoord dist[candidateCount];
37 SEG::ecoord distBaseline[candidateCount];
38 VECTOR2I point[candidateCount];
39
40 for( int i = 0; i < candidateCount; i++ )
41 {
42 prioritized[i] = nullptr;
43 dist[i] = VECTOR2I::ECOORD_MAX;
44 distBaseline[i] = VECTOR2I::ECOORD_MAX;
45 }
46
47 for( int slopRadius : { 0, maxSlopRadius } )
48 {
49 PNS::ITEM_SET candidates = aRouter->QueryHoverItems( aWhere, slopRadius );
50
51 for( PNS::ITEM* item : candidates.Items() )
52 {
53 if( !item->OfKind( PNS::ITEM::SEGMENT_T | PNS::ITEM::ARC_T ) )
54 continue;
55
56 if( !item->IsRoutable() )
57 continue;
58
59 if( !item->Layers().Overlaps( aLayer ) )
60 continue;
61
62 PNS::LINKED_ITEM* linked = static_cast<PNS::LINKED_ITEM*>( item );
63
64 if( item->Kind() & PNS::ITEM::ARC_T )
65 {
66 PNS::ARC* pnsArc = static_cast<PNS::ARC*>( item );
67
68 VECTOR2I nearest = pnsArc->Arc().NearestPoint( aWhere );
69 SEG::ecoord d0 = ( nearest - aWhere ).SquaredEuclideanNorm();
70
71 if( d0 > dist[1] )
72 continue;
73
74 if( aBaseline.PointCount() > 0 )
75 {
76 SEG::ecoord dcBaseline;
77 VECTOR2I target = pnsArc->Arc().GetArcMid();
78
79 if( aBaseline.SegmentCount() > 0 )
80 dcBaseline = aBaseline.SquaredDistance( target );
81 else
82 dcBaseline = ( aBaseline.CPoint( 0 ) - target ).SquaredEuclideanNorm();
83
84 if( dcBaseline > distBaseline[1] )
85 continue;
86
87 distBaseline[1] = dcBaseline;
88 }
89
90 prioritized[1] = linked;
91 dist[1] = d0;
92 point[1] = nearest;
93 }
94 else if( item->Kind() & PNS::ITEM::SEGMENT_T )
95 {
96 PNS::SEGMENT* segm = static_cast<PNS::SEGMENT*>( item );
97
98 VECTOR2I nearest = segm->CLine().NearestPoint( aWhere, false );
99 SEG::ecoord dd = ( aWhere - nearest ).SquaredEuclideanNorm();
100
101 if( dd > dist[1] )
102 continue;
103
104 if( aBaseline.PointCount() > 0 )
105 {
106 SEG::ecoord dcBaseline;
107 VECTOR2I target = segm->Shape( -1 )->Centre();
108
109 if( aBaseline.SegmentCount() > 0 )
110 dcBaseline = aBaseline.SquaredDistance( target );
111 else
112 dcBaseline = ( aBaseline.CPoint( 0 ) - target ).SquaredEuclideanNorm();
113
114 if( dcBaseline > distBaseline[1] )
115 continue;
116
117 distBaseline[1] = dcBaseline;
118 }
119
120 prioritized[1] = segm;
121 dist[1] = dd;
122 point[1] = nearest;
123 }
124 }
125 }
126
127 PNS::LINKED_ITEM* rv = nullptr;
128
129 for( int i = 0; i < candidateCount; i++ )
130 {
131 PNS::LINKED_ITEM* item = prioritized[i];
132
133 if( item && ( aLayer < 0 || item->Layers().Overlaps( aLayer ) ) )
134 {
135 rv = item;
136 aPointOut = point[i];
137 break;
138 }
139 }
140
141 return rv;
142}
143
144
146 PCB_TRACK** aNearestTrack )
147{
149 VECTOR2I closestPt = aP;
150
151 for( PCB_TRACK* track : aBoard->Tracks() )
152 {
153 if( aNet && track->GetNet() != aNet )
154 continue;
155
156 VECTOR2I nearest;
157
158 if( track->Type() == PCB_ARC_T )
159 {
160 PCB_ARC* pcbArc = static_cast<PCB_ARC*>( track );
161 SHAPE_ARC arc( pcbArc->GetStart(), pcbArc->GetMid(), pcbArc->GetEnd(), pcbArc->GetWidth() );
162
163 nearest = arc.NearestPoint( aP );
164 }
165 else
166 {
167 SEG seg( track->GetStart(), track->GetEnd() );
168 nearest = seg.NearestPoint( aP );
169 }
170
171 SEG::ecoord dist_sq = ( nearest - aP ).SquaredEuclideanNorm();
172
173 if( dist_sq < minDist_sq )
174 {
175 minDist_sq = dist_sq;
176 closestPt = nearest;
177
178 if( aNearestTrack )
179 *aNearestTrack = track;
180 }
181 }
182
183 return closestPt;
184}
185
186
188{
189 if( aStartItem->Kind() == ITEM::SEGMENT_T )
190 {
191 return static_cast<SEGMENT*>( aStartItem )->Seg().NearestPoint( aStartPoint );
192 }
193 else
194 {
195 wxASSERT( aStartItem->Kind() == ITEM::ARC_T );
196 ARC* arc = static_cast<ARC*>( aStartItem );
197
198 if( ( VECTOR2I( arc->Anchor( 0 ) - aStartPoint ) ).SquaredEuclideanNorm()
199 <= ( VECTOR2I( arc->Anchor( 1 ) - aStartPoint ) ).SquaredEuclideanNorm() )
200 {
201 return arc->Anchor( 0 );
202 }
203 else
204 {
205 return arc->Anchor( 1 );
206 }
207 }
208}
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:372
const TRACKS & Tracks() const
Definition board.h:418
Handle the data for a net.
Definition netinfo.h:46
const VECTOR2I & GetMid() const
Definition pcb_track.h:286
const VECTOR2I & GetStart() const
Definition pcb_track.h:93
const VECTOR2I & GetEnd() const
Definition pcb_track.h:90
virtual int GetWidth() const
Definition pcb_track.h:87
virtual VECTOR2I Anchor(int n) const override
Definition pns_arc.h:100
SHAPE_ARC & Arc()
Definition pns_arc.h:115
std::vector< ITEM * > & Items()
Definition pns_itemset.h:95
Base class for PNS router board items.
Definition pns_item.h:98
PnsKind Kind() const
Return the type (kind) of the item.
Definition pns_item.h:173
const ITEM_SET QueryHoverItems(const VECTOR2I &aP, int aSlopRadius=0)
SIZES_SETTINGS & Sizes()
Definition pns_router.h:233
const SHAPE_LINE_CHAIN CLine() const
const SHAPE * Shape(int aLayer) const override
Return the geometrical shape of the item.
Definition pns_segment.h:86
Definition seg.h:38
VECTOR2I::extended_type ecoord
Definition seg.h:40
const VECTOR2I NearestPoint(const VECTOR2I &aP) const
Compute a point on the segment (this) that is closest to point aP.
Definition seg.cpp:629
const VECTOR2I & GetArcMid() const
Definition shape_arc.h:116
VECTOR2I NearestPoint(const VECTOR2I &aP) const
SEG::ecoord SquaredDistance(const VECTOR2I &aP, bool aOutlineOnly=false) const override
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
int PointCount() const
Return the number of points (vertices) in this line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
const VECTOR2I NearestPoint(const VECTOR2I &aP, bool aAllowInternalShapePoints=true) const
Find a point on the line chain that is closest to point aP.
int SegmentCount() const
Return the number of segments in this line chain.
virtual VECTOR2I Centre() const
Compute a center-of-mass of the shape.
Definition shape.h:230
static constexpr extended_type ECOORD_MAX
Definition vector2d.h:72
static VECTOR2I GetSnappedStartPoint(LINKED_ITEM *aStartItem, VECTOR2I aStartPoint)
static VECTOR2I SnapToNearestTrack(const VECTOR2I &aP, BOARD *aBoard, NETINFO_ITEM *aNet, PCB_TRACK **aNearestTrack)
static LINKED_ITEM * PickSegment(ROUTER *aRouter, const VECTOR2I &aWhere, int aLayer, VECTOR2I &aPointOut, const SHAPE_LINE_CHAIN &aBaseline=SHAPE_LINE_CHAIN())
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition typeinfo.h:91
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683