KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pns_via.cpp
Go to the documentation of this file.
1/*
2 * KiRouter - a push-and-(sometimes-)shove PCB router
3 *
4 * Copyright (C) 2013-2014 CERN
5 * Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors.
6 * Author: Tomasz Wlostowski <[email protected]>
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include "pns_via.h"
23#include "pns_node.h"
24#include "pns_utils.h"
25#include "pns_router.h"
26#include "pns_debug_decorator.h"
27
28#include <geometry/shape_rect.h>
29#include <math/box2.h>
30
31namespace PNS {
32
33bool VIA::PushoutForce( NODE* aNode, const ITEM* aOther, VECTOR2I& aForce )
34{
35 int clearance = aNode->GetClearance( this, aOther, false );
36 VECTOR2I elementForces[4], force;
37 size_t nf = 0;
38
39 aOther->Shape()->Collide( Shape(), clearance, &elementForces[nf++] );
40
41 for( size_t i = 0; i < nf; i++ )
42 {
43 if( elementForces[i].SquaredEuclideanNorm() > force.SquaredEuclideanNorm() )
44 force = elementForces[i];
45 }
46
47 aForce = force;
48
49 return ( force != VECTOR2I( 0, 0 ) );
50}
51
52bool VIA::PushoutForce( NODE* aNode, const VECTOR2I& aDirection, VECTOR2I& aForce,
53 int aCollisionMask, int aMaxIterations )
54{
55 int iter = 0;
56 VIA mv( *this );
57 VECTOR2I totalForce;
58
60 PNS_DBG( dbg, AddPoint, Pos(), YELLOW, 100000, wxString::Format( "via-force-init-pos, iter %d", aMaxIterations ) );
61
62 while( iter < aMaxIterations )
63 {
65 opt.m_limitCount = 1;
66 opt.m_kindMask = aCollisionMask;
67 opt.m_useClearanceEpsilon = false;
68
69 NODE::OPT_OBSTACLE obs = aNode->CheckColliding( &mv, opt );
70
71 if( !obs )
72 break;
73
74 VECTOR2I force;
75 bool collFound = mv.PushoutForce( aNode, obs->m_item, force );
76
77 if( !collFound )
78 {
79 if( obs )
80 {
81 // might happen (although rarely) that we see a collision, but the MTV
82 // is zero... Assume force propagation has failed in such case.
83 return false;
84 }
85 PNS_DBG( dbg, Message, wxString::Format( "no-coll %d", iter ) );
86 break;
87 }
88
89 const int threshold = Diameter() / 4; // another stupid heuristic.
90 const int forceMag = force.EuclideanNorm();
91
92 // We've been through a lot of iterations already and our pushout force is still too big?
93 // Perhaps the barycentric force goes in the wrong direction, let's try to move along
94 // the 'lead' vector instead (usually backwards to the cursor)
95 if( iter > aMaxIterations / 2 && forceMag > threshold )
96 {
97 VECTOR2I l = aDirection.Resize( threshold );
98 totalForce += l;
99
101 ff.Append( mv.Pos() );
102 ff.Append( mv.Pos() + l );
103
104 mv.SetPos( mv.Pos() + l );
105
106 PNS_DBG( dbg, AddShape, &ff, YELLOW, 100000, "via-force-lead" );
107 }
108 else if( collFound ) // push along the minmum translation vector
109 {
110 // Limit the force magnitude to, say, 25% of the via diameter
111 // This adds a few iterations for large areas (e.g. keepouts)
112 // But makes the algorithm more predictable and less 'jumpy'
113 if( forceMag > threshold )
114 {
115 force.Resize( threshold );
116 }
117
118 totalForce += force;
119
121 ff.Append( mv.Pos() );
122 ff.Append( mv.Pos() + force );
123
124 mv.SetPos( mv.Pos() + force );
125
126 PNS_DBG( dbg, AddShape, &ff, WHITE, 100000, "via-force-coll" );
127 }
128
129 iter++;
130 }
131
132 if( iter == aMaxIterations )
133 return false;
134
135 PNS_DBG( dbg, AddPoint, ( Pos() + totalForce ), WHITE, 1000000, "via-force-new" );
136
137 aForce = totalForce;
138
139 return true;
140}
141
142
143const SHAPE_LINE_CHAIN VIA::Hull( int aClearance, int aWalkaroundThickness, int aLayer ) const
144{
145 int cl = ( aClearance + aWalkaroundThickness / 2 );
146 int width = m_diameter;
147
148 if( m_hole && !ROUTER::GetInstance()->GetInterface()->IsFlashedOnLayer( this, aLayer ) )
149 width = m_hole->Radius() * 2;
150
151 // Chamfer = width * ( 1 - sqrt(2)/2 ) for equilateral octagon
152 return OctagonalHull( m_pos - VECTOR2I( width / 2, width / 2 ),
153 VECTOR2I( width, width ),
154 cl, ( 2 * cl + width ) * ( 1.0 - M_SQRT1_2 ) );
155}
156
157
159{
160 VIA* v = new VIA();
161
162 v->SetNet( Net() );
163 v->SetLayers( Layers() );
164 v->m_pos = m_pos;
166 v->m_drill = m_drill;
169 v->m_rank = m_rank;
170 v->m_marker = m_marker;
171 v->m_viaType = m_viaType;
172 v->m_parent = m_parent;
173 v->m_isFree = m_isFree;
175
176 return v;
177}
178
179
180OPT_BOX2I VIA::ChangedArea( const VIA* aOther ) const
181{
182 if( aOther->Pos() != Pos() )
183 {
184 BOX2I tmp = Shape()->BBox();
185 tmp.Merge( aOther->Shape()->BBox() );
186 return tmp;
187 }
188
189 return OPT_BOX2I();
190}
191
192
194{
195 VIA_HANDLE h;
196 h.pos = Pos();
197 h.layers = Layers();
198 h.net = Net();
199 h.valid = true;
200 return h;
201}
202
203
204const std::string VIA::Format( ) const
205{
206 std::stringstream ss;
207 ss << ITEM::Format() << " drill " << m_drill << " ";
208 ss << m_shape.Format( false );
209 return ss.str();
210}
211
212}
std::optional< BOX2I > OPT_BOX2I
Definition: box2.h:926
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
int Radius() const
Definition: pns_hole.cpp:103
static HOLE * MakeCircularHole(const VECTOR2I &pos, int radius)
Definition: pns_hole.cpp:131
Base class for PNS router board items.
Definition: pns_item.h:97
void SetLayers(const PNS_LAYER_RANGE &aLayers)
Definition: pns_item.h:197
virtual const std::string Format() const
Definition: pns_item.cpp:305
bool m_isVirtual
Definition: pns_item.h:295
const PNS_LAYER_RANGE & Layers() const
Definition: pns_item.h:196
virtual NET_HANDLE Net() const
Definition: pns_item.h:194
void SetNet(NET_HANDLE aNet)
Definition: pns_item.h:193
virtual const SHAPE * Shape() const
Return the geometrical shape of the item.
Definition: pns_item.h:225
int m_marker
Definition: pns_item.h:292
BOARD_ITEM * m_parent
Definition: pns_item.h:287
int m_rank
Definition: pns_item.h:293
Keep the router "world" - i.e.
Definition: pns_node.h:207
int GetClearance(const ITEM *aA, const ITEM *aB, bool aUseClearanceEpsilon=true) const
Return the pre-set worst case clearance between any pair of items.
Definition: pns_node.cpp:129
OPT_OBSTACLE CheckColliding(const ITEM *aItem, int aKindMask=ITEM::ANY_T)
Check if the item collides with anything else in the world, and if found, returns the obstacle.
Definition: pns_node.cpp:410
std::optional< OBSTACLE > OPT_OBSTACLE
Definition: pns_node.h:217
virtual DEBUG_DECORATOR * GetDebugDecorator()=0
virtual bool IsFlashedOnLayer(const PNS::ITEM *aItem, int aLayer) const =0
ROUTER_IFACE * GetInterface() const
Definition: pns_router.h:223
static ROUTER * GetInstance()
Definition: pns_router.cpp:80
VIA()
Definition: pns_via.h:53
OPT_BOX2I ChangedArea(const VIA *aOther) const
Definition: pns_via.cpp:180
int m_drill
Definition: pns_via.h:208
const VECTOR2I & Pos() const
Definition: pns_via.h:128
const SHAPE * Shape() const override
Return the geometrical shape of the item.
Definition: pns_via.h:168
virtual void SetHole(HOLE *aHole) override
Definition: pns_via.h:189
int Diameter() const
Definition: pns_via.h:142
const VIA_HANDLE MakeHandle() const
Definition: pns_via.cpp:193
virtual const std::string Format() const override
Definition: pns_via.cpp:204
bool PushoutForce(NODE *aNode, const VECTOR2I &aDirection, VECTOR2I &aForce, int aCollisionMask=ITEM::ANY_T, int aMaxIterations=10)
Definition: pns_via.cpp:52
void SetPos(const VECTOR2I &aPos)
Definition: pns_via.h:130
int m_diameter
Definition: pns_via.h:207
VIATYPE m_viaType
Definition: pns_via.h:211
HOLE * m_hole
Definition: pns_via.h:213
VECTOR2I m_pos
Definition: pns_via.h:209
const SHAPE_LINE_CHAIN Hull(int aClearance=0, int aWalkaroundThickness=0, int aLayer=-1) const override
Definition: pns_via.cpp:143
bool m_isFree
Definition: pns_via.h:212
SHAPE_CIRCLE m_shape
Definition: pns_via.h:210
VIA * Clone() const override
Return a deep copy of the item.
Definition: pns_via.cpp:158
virtual const std::string Format(bool aCplusPlus=true) const override
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
virtual bool Collide(const VECTOR2I &aP, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const
Check if the boundary of shape (this) lies closer to the point aP than aClearance,...
Definition: shape.h:181
virtual const BOX2I BBox(int aClearance=0) const =0
Compute a bounding box of the shape, with a margin of aClearance a collision.
constexpr extended_type SquaredEuclideanNorm() const
Compute the squared euclidean norm of the vector, which is defined as (x ** 2 + y ** 2).
Definition: vector2d.h:307
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:283
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
Definition: vector2d.h:385
@ WHITE
Definition: color4d.h:48
@ YELLOW
Definition: color4d.h:67
Push and Shove diff pair dimensions (gap) settings dialog.
const SHAPE_LINE_CHAIN OctagonalHull(const VECTOR2I &aP0, const VECTOR2I &aSize, int aClearance, int aChamfer)
Definition: pns_utils.cpp:36
#define PNS_DBG(dbg, method,...)
VECTOR2I pos
Definition: pns_via.h:45
NET_HANDLE net
Definition: pns_via.h:47
PNS_LAYER_RANGE layers
Definition: pns_via.h:46
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:691