KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pns_meander_placer.cpp
Go to the documentation of this file.
1/*
2 * KiRouter - a push-and-(sometimes-)shove PCB router
3 *
4 * Copyright (C) 2013-2015 CERN
5 * Copyright (C) 2016-2021 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_debug_decorator.h"
23#include "pns_itemset.h"
24#include "pns_meander_placer.h"
25#include "pns_node.h"
26#include "pns_router.h"
27#include "pns_solid.h"
28#include "pns_topology.h"
29
30namespace PNS {
31
33 MEANDER_PLACER_BASE( aRouter )
34{
35 m_currentNode = nullptr;
36
37 // Init temporary variables (do not leave uninitialized members)
38 m_initialSegment = nullptr;
39 m_lastLength = 0;
42}
43
44
46{
47}
48
49
50NODE* MEANDER_PLACER::CurrentNode( bool aLoopsRemoved ) const
51{
52 if( !m_currentNode )
53 return m_world;
54
55 return m_currentNode;
56}
57
58
59bool MEANDER_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem )
60{
61 if( !aStartItem || !aStartItem->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T ) )
62 {
63 Router()->SetFailureReason( _( "Please select a track whose length you want to tune." ) );
64 return false;
65 }
66
67 m_initialSegment = static_cast<LINKED_ITEM*>( aStartItem );
68 m_currentNode = nullptr;
70
71 m_world = Router()->GetWorld()->Branch();
73
74 TOPOLOGY topo( m_world );
76
78
79 if( m_startPad_n )
81
82 if( m_endPad_n )
84
86
88 m_currentEnd = VECTOR2I( 0, 0 );
89
90 return true;
91}
92
93
94long long int MEANDER_PLACER::origPathLength() const
95{
97}
98
99
100bool MEANDER_PLACER::Move( const VECTOR2I& aP, ITEM* aEndItem )
101{
104}
105
106
107bool MEANDER_PLACER::doMove( const VECTOR2I& aP, ITEM* aEndItem, long long int aTargetLength,
108 long long int aTargetMin, long long int aTargetMax )
109{
110 if( m_currentStart == aP )
111 return false;
112
113 if( m_currentNode )
114 delete m_currentNode;
115
117
118 SHAPE_LINE_CHAIN pre, tuned, post;
119
120 m_originLine.CLine().Split( m_currentStart, aP, pre, tuned, post );
121
122 m_result = MEANDERED_LINE( this, false );
125
126 for( int i = 0; i < tuned.SegmentCount(); i++ )
127 {
128 if( tuned.IsArcSegment( i ) )
129 {
130 ssize_t arcIndex = tuned.ArcIndex( i );
131 m_result.AddArc( tuned.Arc( arcIndex ) );
132 i = tuned.NextShape( i );
133
134 // NextShape will return -1 if last shape
135 if( i < 0 )
136 i = tuned.SegmentCount();
137
138 continue;
139 }
140
141 bool side = false;
142 const SEG s = tuned.CSegment( i );
143
144 if( m_settings.m_initialSide == 0 )
145 side = s.Side( aP ) < 0;
146 else
147 side = m_settings.m_initialSide < 0;
148
149 m_result.AddCorner( s.A );
150 m_result.MeanderSegment( s, side );
151 m_result.AddCorner( s.B );
152 }
153
154 long long int lineLen = origPathLength();
155
156 m_lastLength = lineLen;
158
159 if( lineLen > m_settings.m_targetLength.Max() )
160 {
162 }
163 else
164 {
165 m_lastLength = lineLen - tuned.Length();
166 tuneLineLength( m_result, aTargetLength - lineLen );
167 }
168
169 for( const ITEM* item : m_tunedPath.CItems() )
170 {
171 if( const LINE* l = dyn_cast<const LINE*>( item ) )
172 {
173 PNS_DBG( Dbg(), AddItem, l, BLUE, 30000, wxT( "tuned-line" ) );
174
175 m_router->GetInterface()->DisplayPathLine( l->CLine(), 1 );
176 }
177 }
178
179 if( m_lastStatus != TOO_LONG )
180 {
181 tuned.Clear();
182
183 for( MEANDER_SHAPE* m : m_result.Meanders() )
184 {
185 if( m->Type() != MT_EMPTY )
186 {
187 tuned.Append ( m->CLine( 0 ) );
188 }
189 }
190
191 m_lastLength += tuned.Length();
192
193 if( m_lastLength > aTargetMax )
195 else if( m_lastLength < aTargetMin )
197 else
199 }
200
202
204 {
205 pre.Simplify();
206 tuned.Simplify();
207 post.Simplify();
208
209 m_finalShape.Append( pre );
210 m_finalShape.Append( tuned );
211 m_finalShape.Append( post );
212 }
213 else
214 {
215 m_finalShape.Append( pre );
216 m_finalShape.Append( tuned );
217 m_finalShape.Append( post );
219 }
220
221 return true;
222}
223
224
225bool MEANDER_PLACER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinish )
226{
227 if( !m_currentNode )
228 return false;
229
233
234 return true;
235}
236
237
239{
241 return true;
242}
243
244
246{
247 return m_currentTrace.SegmentCount() > 0;
248}
249
250
252{
253 if( m_currentNode )
255
256 m_currentNode = nullptr;
257 return true;
258}
259
260
262{
263 LINE l( m_originLine, aShape->CLine( 0 ) );
264
265 if( m_currentNode->CheckColliding( &l ) )
266 return false;
267
268 int w = aShape->Width();
269 int clearance = w + m_settings.m_spacing;
270
271 return m_result.CheckSelfIntersections( aShape, clearance );
272}
273
274
276{
278 return ITEM_SET( &m_currentTrace );
279}
280
282{
283 return m_tunedPath;
284}
285
287{
288 return m_currentStart;
289}
290
292{
293 return m_currentEnd;
294}
295
297{
298 return m_initialSegment->Layers().Start();
299}
300
301
302long long int MEANDER_PLACER::TuningResult() const
303{
304 if( m_lastLength )
305 return m_lastLength;
306 else
307 return origPathLength();
308}
309
310
312{
313 return m_lastStatus;
314}
315
316}
T Min() const
Definition: minoptmax.h:33
T Max() const
Definition: minoptmax.h:34
T Opt() const
Definition: minoptmax.h:35
ROUTER * Router() const
Return current router settings.
Definition: pns_algo_base.h:54
ROUTER * m_router
Definition: pns_algo_base.h:87
DEBUG_DECORATOR * Dbg() const
Definition: pns_algo_base.h:78
const std::vector< ITEM * > & CItems() const
Definition: pns_itemset.h:88
Base class for PNS router board items.
Definition: pns_item.h:97
const PNS_LAYER_RANGE & Layers() const
Definition: pns_item.h:199
@ SEGMENT_T
Definition: pns_item.h:106
bool OfKind(int aKindMask) const
Definition: pns_item.h:178
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
Definition: pns_line.h:62
const SHAPE_LINE_CHAIN & CLine() const
Definition: pns_line.h:138
int SegmentCount() const
Definition: pns_line.h:140
int Width() const
Return true if the line is geometrically identical as line aOther.
Definition: pns_line.h:157
Represent a set of meanders fitted over a single or two lines.
Definition: pns_meander.h:425
void SetBaselineOffset(int aOffset)
Set the parallel offset between the base segment and the meandered line.
Definition: pns_meander.h:520
void SetWidth(int aWidth)
Set the line width.
Definition: pns_meander.h:505
void AddCorner(const VECTOR2I &aA, const VECTOR2I &aB=VECTOR2I(0, 0))
Create a dummy meander shape representing a line corner.
void MeanderSegment(const SEG &aSeg, bool aSide, int aBaseIndex=0)
Fit maximum amplitude meanders on a given segment and adds to the current line.
void AddArc(const SHAPE_ARC &aArc1, const SHAPE_ARC &aArc2=SHAPE_ARC())
Create a dummy meander shape representing an arc corner.
bool CheckSelfIntersections(MEANDER_SHAPE *aShape, int aClearance)
Check if the given shape is intersecting with any other meander in the current line.
std::vector< MEANDER_SHAPE * > & Meanders()
Definition: pns_meander.h:528
Base class for Single trace & Differential pair meandering tools, as both of them share a lot of code...
void tuneLineLength(MEANDERED_LINE &aTuned, long long int aElongation)
Take a set of meanders in aTuned and tunes their length to extend the original line length by aElonga...
TUNING_STATUS
< Result of the length tuning operation
int m_currentWidth
Meander settings.
MEANDER_SETTINGS m_settings
The current end point.
NODE * m_world
Width of the meandered trace(s).
VECTOR2I getSnappedStartPoint(LINKED_ITEM *aStartItem, VECTOR2I aStartPoint)
long long int lineLength(const ITEM_SET &aLine, const SOLID *aStartPad, const SOLID *aEndPad) const
Calculate the total length of the line represented by an item set (tracks and vias)
virtual bool FixRoute(const VECTOR2I &aP, ITEM *aEndItem, bool aForceFinish=false) override
Function FixRoute()
bool doMove(const VECTOR2I &aP, ITEM *aEndItem, long long int aTargetLength, long long int aTargetMin, long long int aTargetMax)
TUNING_STATUS m_lastStatus
virtual bool Move(const VECTOR2I &aP, ITEM *aEndItem) override
Function Move()
virtual long long int origPathLength() const
current routing start point (end of tail, beginning of head)
int CurrentLayer() const override
Function CurrentLayer()
const VECTOR2I & CurrentEnd() const override
Function CurrentEnd()
const VECTOR2I & CurrentStart() const override
Function CurrentStart()
bool AbortPlacement() override
bool HasPlacedAnything() const override
NODE * CurrentNode(bool aLoopsRemoved=false) const override
Function CurrentNode()
LINKED_ITEM * m_initialSegment
Total length added by pad to die size.
SHAPE_LINE_CHAIN m_finalShape
const ITEM_SET TunedPath() override
const ITEM_SET Traces() override
Function Traces()
MEANDER_PLACER(ROUTER *aRouter)
bool CheckFit(MEANDER_SHAPE *aShape) override
Checks if it's OK to place the shape aShape (i.e.
VECTOR2I m_currentStart
Current world state.
TUNING_STATUS TuningStatus() const override
Return the tuning status (too short, too long, etc.) of the trace(s) being tuned.
virtual bool Start(const VECTOR2I &aP, ITEM *aStartItem) override
Function Start()
long long int TuningResult() const override
Return the resultant length or skew of the tuned traces.
bool CommitPlacement() override
long long int m_lastLength
MEANDER_SIDE m_initialSide
Allowable tuning error.
Definition: pns_meander.h:115
MINOPTMAX< long long int > m_targetLength
Target skew value for diff pair de-skewing.
Definition: pns_meander.h:98
int m_spacing
Amplitude/spacing adjustment step.
Definition: pns_meander.h:89
The geometry of a single meander.
Definition: pns_meander.h:128
int Width() const
Definition: pns_meander.h:310
const SHAPE_LINE_CHAIN & CLine(int aShape) const
Definition: pns_meander.h:250
Keep the router "world" - i.e.
Definition: pns_node.h:231
NODE * Branch()
Create a lightweight copy (called branch) of self that tracks the changes (added/removed items) wrs t...
Definition: pns_node.cpp:143
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
bool Add(std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant=false)
Add an item to the current node.
Definition: pns_node.cpp:665
void KillChildren()
Definition: pns_node.cpp:1523
void Remove(ARC *aArc)
Remove an item from this branch.
Definition: pns_node.cpp:906
const LINE AssembleLine(LINKED_ITEM *aSeg, int *aOriginSegmentIndex=nullptr, bool aStopAtLockedJoints=false, bool aFollowLockedSegments=false)
Follow the joint map to assemble a line connecting two non-trivial joints starting from segment aSeg.
Definition: pns_node.cpp:1044
virtual void DisplayPathLine(const SHAPE_LINE_CHAIN &aLine, int aImportance)=0
ROUTER_IFACE * GetInterface() const
Definition: pns_router.h:223
void SetFailureReason(const wxString &aReason)
Definition: pns_router.h:218
void CommitRouting()
Definition: pns_router.cpp:921
NODE * GetWorld() const
Definition: pns_router.h:169
int GetPadToDie() const
Definition: pns_solid.h:107
const ITEM_SET AssembleTuningPath(ITEM *aStart, SOLID **aStartPad=nullptr, SOLID **aEndPad=nullptr)
Like AssembleTrivialPath, but follows the track length algorithm, which discards segments that are fu...
int Start() const
Definition: pns_layerset.h:86
Definition: seg.h:42
VECTOR2I A
Definition: seg.h:49
VECTOR2I B
Definition: seg.h:50
int Side(const VECTOR2I &aP) const
Determine on which side of directed line passing via segment ends point aP lies.
Definition: seg.h:143
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
const SHAPE_ARC & Arc(size_t aArc) const
int Split(const VECTOR2I &aP, bool aExact=false)
Insert the point aP belonging to one of the our segments, splitting the adjacent segment in two.
void Simplify(int aMaxError=0)
Simplify the line chain by removing colinear adjacent segments and duplicate vertices.
ssize_t ArcIndex(size_t aSegment) const
Return the arc index for the given segment index.
void Clear()
Remove all points from the line chain.
int NextShape(int aPointIndex) const
Return the vertex index of the next shape in the chain, or -1 if aPointIndex is the last shape.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
int SegmentCount() const
Return the number of segments in this line chain.
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.
bool IsArcSegment(size_t aSegment) const
long long int Length() const
Return length of the line chain in Euclidean metric.
@ BLUE
Definition: color4d.h:56
#define _(s)
Push and Shove diff pair dimensions (gap) settings dialog.
@ MT_EMPTY
Definition: pns_meander.h:47
#define PNS_DBG(dbg, method,...)
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:691