summaryrefslogtreecommitdiff
path: root/pcbnew/router/pns_line_placer.h
blob: 8a1f263910e4dce96bd6daa4903ff585acb8950e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
/*
 * KiRouter - a push-and-(sometimes-)shove PCB router
 *
 * Copyright (C) 2013-2014 CERN
 * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
 *
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or (at your
 * option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef __PNS_LINE_PLACER_H
#define __PNS_LINE_PLACER_H

#include <math/vector2d.h>

#include <geometry/shape.h>
#include <geometry/shape_line_chain.h>

#include "pns_sizes_settings.h"
#include "pns_node.h"
#include "pns_via.h"
#include "pns_line.h"
#include "pns_placement_algo.h"

class PNS_ROUTER;
class PNS_SHOVE;
class PNS_OPTIMIZER;
class PNS_ROUTER_BASE;
class PNS_VIA;
class PNS_SIZES_SETTINGS;


/**
 * Class PNS_LINE_PLACER
 *
 * Single track placement algorithm. Interactively routes a track.
 * Applies shove and walkaround algorithms when needed.
 */

class PNS_LINE_PLACER : public PNS_PLACEMENT_ALGO
{
public:
    PNS_LINE_PLACER( PNS_ROUTER* aRouter );
    ~PNS_LINE_PLACER();

    /**
     * Function Start()
     *
     * Starts routing a single track at point aP, taking item aStartItem as anchor
     * (unless NULL).
     */
    bool Start( const VECTOR2I& aP, PNS_ITEM* aStartItem );

    /**
     * Function Move()
     *
     * Moves the end of the currently routed trace to the point aP, taking
     * aEndItem as anchor (if not NULL).
     * (unless NULL).
     */
    bool Move( const VECTOR2I& aP, PNS_ITEM* aEndItem );

    /**
     * Function FixRoute()
     *
     * Commits the currently routed track to the parent node, taking
     * aP as the final end point and aEndItem as the final anchor (if provided).
     * @return true, if route has been commited. May return false if the routing
     * result is violating design rules - in such case, the track is only committed
     * if Settings.CanViolateDRC() is on.
     */
    bool FixRoute( const VECTOR2I& aP, PNS_ITEM* aEndItem );

    /**
     * Function ToggleVia()
     *
     * Enables/disables a via at the end of currently routed trace.
     */
    bool ToggleVia( bool aEnabled );

    /**
     * Function SetLayer()
     *
     * Sets the current routing layer.
     */
    bool SetLayer( int aLayer );

    /**
     * Function Head()
     *
     * Returns the "head" of the line being placed, that is the volatile part
     * that has not "settled" yet.
     */
    const PNS_LINE& Head() const { return m_head; }

    /**
     * Function Tail()
     *
     * Returns the "tail" of the line being placed, the part which has already wrapped around
     * and shoved some obstacles.
     */
    const PNS_LINE& Tail() const { return m_tail; }

    /**
     * Function Trace()
     *
     * Returns the complete routed line.
     */
    const PNS_LINE Trace() const;

    /**
     * Function Traces()
     *
     * Returns the complete routed line, as a single-member PNS_ITEMSET.
     */
    const PNS_ITEMSET Traces();

    /**
     * Function CurrentEnd()
     *
     * Returns the current end of the line being placed. It may not be equal
     * to the cursor position due to collisions.
     */
    const VECTOR2I& CurrentEnd() const
    {
        return m_currentEnd;
    }

    /**
     * Function CurrentNet()
     *
     * Returns the net code of currently routed track.
     */
    const std::vector<int> CurrentNets() const
    {
        return std::vector<int>( 1, m_currentNet );
    }

    /**
     * Function CurrentLayer()
     *
     * Returns the layer of currently routed track.
     */
    int CurrentLayer() const
    {
        return m_currentLayer;
    }

    /**
     * Function CurrentNode()
     *
     * Returns the most recent world state.
     */
    PNS_NODE* CurrentNode( bool aLoopsRemoved = false ) const;

    /**
     * Function FlipPosture()
     *
     * Toggles the current posture (straight/diagonal) of the trace head.
     */
    void FlipPosture();

    /**
     * Function UpdateSizes()
     *
     * Performs on-the-fly update of the width, via diameter & drill size from
     * a settings class. Used to dynamically change these parameters as
     * the track is routed.
     */
    void UpdateSizes( const PNS_SIZES_SETTINGS& aSizes );

    void SetOrthoMode( bool aOrthoMode );

    bool IsPlacingVia() const { return m_placingVia; }

    void GetModifiedNets( std::vector<int>& aNets ) const;

    PNS_LOGGER* Logger();


private:
    /**
     * Function route()
     *
     * Re-routes the current track to point aP. Returns true, when routing has
     * completed successfully (i.e. the trace end has reached point aP), and false
     * if the trace was stuck somewhere on the way. May call routeStep()
     * repetitively due to mouse smoothing.
     * @param aP ending point of current route.
     * @return true, if the routing is complete.
     */
    bool route( const VECTOR2I& aP );

    /**
     * Function updateLeadingRatLine()
     *
     * Draws the "leading" ratsnest line, which connects the end of currently
     * routed track and the nearest yet unrouted item. If the routing for
     * current net is complete, draws nothing.
     */
    void updateLeadingRatLine();

    /**
     * Function setWorld()
     *
     * Sets the board to route.
     */
    void setWorld( PNS_NODE* aWorld );

    /**
     * Function startPlacement()
     *
     * Initializes placement of a new line with given parameters.
     */
    void initPlacement( bool aSplitSeg = false );

    /**
     * Function setInitialDirection()
     *
     * Sets preferred direction of the very first track segment to be laid.
     * Used by posture switching mechanism.
     */
    void setInitialDirection( const DIRECTION_45& aDirection );

    /**
     * Function splitAdjacentSegments()
     *
     * Checks if point aP lies on segment aSeg. If so, splits the segment in two,
     * forming a joint at aP and stores updated topology in node aNode.
     */
    void splitAdjacentSegments( PNS_NODE* aNode, PNS_ITEM* aSeg, const VECTOR2I& aP );

    /**
     * Function removeLoops()
     *
     * Searches aNode for traces concurrent to aLatest and removes them. Updated
     * topology is stored in aNode.
     */
    void removeLoops( PNS_NODE* aNode, PNS_LINE& aLatest );

    /**
     * Function simplifyNewLine()
     *
     * Assembles a line starting from segment aLatest, removes collinear segments
     * and redundant vertexes. If a simplification bhas been found, replaces the
     * old line with the simplified one in aNode.
     */
    void simplifyNewLine( PNS_NODE* aNode, PNS_SEGMENT* aLatest );

    /**
     * Function checkObtusity()
     *
     * Helper function, checking if segments a and b form an obtuse angle
     * (in 45-degree regime).
     * @return true, if angle (aA, aB) is obtuse
     */
    bool checkObtusity( const SEG& aA, const SEG& aB ) const;

    /**
     * Function handleSelfIntersections()
     *
     * Checks if the head of the track intersects its tail. If so, cuts the
     * tail up to the intersecting segment and fixes the head direction to match
     * the last segment before the cut.
     * @return true if the line has been changed.
     */
    bool handleSelfIntersections();

    /**
     * Function handlePullback()
     *
     * Deals with pull-back: reduces the tail if head trace is moved backwards
     * wrs to the current tail direction.
     * @return true if the line has been changed.
     */
    bool handlePullback();

    /**
     * Function mergeHead()
     *
     * Moves "estabished" segments from the head to the tail if certain
     * conditions are met.
     * @return true, if the line has been changed.
     */
    bool mergeHead();

    /**
     * Function reduceTail()
     *
     * Attempts to reduce the numer of segments in the tail by trying to replace a
     * certain number of latest tail segments with a direct trace leading to aEnd
     * that does not collide with anything.
     * @param aEnd: current routing destination point.
     * @return true if the line has been changed.
     */
    bool reduceTail( const VECTOR2I& aEnd );

    /**
     * Function optimizeTailHeadTransition()
     *
     * Tries to reduce the corner count of the most recent part of tail/head by
     * merging obtuse/collinear segments.
     * @return true, if the line has been changed.
     */
    bool optimizeTailHeadTransition();

    /**
     * Function routeHead()
     *
     * Computes the head trace between the current start point (m_p_start) and
     * point aP, starting with direction defined in m_direction. The trace walks
     * around all colliding solid or non-movable items. Movable segments are
     * ignored, as they'll be handled later by the shove algorithm.
     */
    bool routeHead( const VECTOR2I& aP, PNS_LINE& aNewHead);

    /**
     * Function routeStep()
     *
     * Performs a single routing alorithm step, for the end point aP.
     * @param aP ending point of current route
     * @return true, if the line has been changed.
     */
    void routeStep( const VECTOR2I& aP );

    ///> route step, walkaround mode
    bool rhWalkOnly( const VECTOR2I& aP, PNS_LINE& aNewHead);

    ///> route step, shove mode
    bool rhShoveOnly( const VECTOR2I& aP, PNS_LINE& aNewHead);

    ///> route step, mark obstacles mode
    bool rhMarkObstacles( const VECTOR2I& aP, PNS_LINE& aNewHead );

    const PNS_VIA makeVia ( const VECTOR2I& aP );

    bool buildInitialLine( const VECTOR2I& aP, PNS_LINE& aHead );

    ///> current routing direction
    DIRECTION_45 m_direction;

    ///> routing direction for new traces
    DIRECTION_45 m_initial_direction;

    ///> routing "head": volatile part of the track from the previously
    ///  analyzed point to the current routing destination
    PNS_LINE m_head;

    ///> routing "tail": part of the track that has been already fixed due to collisions with obstacles
    PNS_LINE m_tail;

    ///> pointer to world to search colliding items
    PNS_NODE* m_world;

    ///> current routing start point (end of tail, beginning of head)
    VECTOR2I m_p_start;

    ///> The shove engine
    PNS_SHOVE* m_shove;

    ///> Current world state
    PNS_NODE* m_currentNode;

    ///> Postprocessed world state (including marked collisions & removed loops)
    PNS_NODE* m_lastNode;

    PNS_SIZES_SETTINGS m_sizes;

    ///> Are we placing a via?
    bool m_placingVia;

    int m_currentNet;
    int m_currentLayer;

    VECTOR2I m_currentEnd, m_currentStart;
    PNS_LINE m_currentTrace;

    PNS_MODE m_currentMode;
    PNS_ITEM* m_startItem;

    bool m_idle;
    bool m_chainedPlacement;
    bool m_splitSeg;
    bool m_orthoMode;
};

#endif    // __PNS_LINE_PLACER_H