pns_line_placer.h 7.58 KB
Newer Older
1 2 3 4 5
/*
 * KiRouter - a push-and-(sometimes-)shove PCB router
 *
 * Copyright (C) 2013  CERN
 * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
6
 *
7 8 9 10
 * 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.
11
 *
12 13 14 15
 * 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.
16
 *
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.or/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_node.h"
#include "pns_via.h"
#include "pns_line.h"
#include "pns_routing_settings.h"
33

34 35 36 37 38 39 40 41
class PNS_ROUTER;
class PNS_SHOVE;
class PNS_OPTIMIZER;
class PNS_ROUTER_BASE;

/**
 * Class PNS_LINE_PLACER
 *
42
 * Interactively routes a single track. Runs shove and walkaround
43
 * algorithms when needed.
44 45 46 47
 */

class PNS_LINE_PLACER
{
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
public:
    PNS_LINE_PLACER( PNS_NODE* aWorld );
    ~PNS_LINE_PLACER();

    ///> Appends a via at the end of currently placed line.
    void AddVia( bool aEnabled, int aDiameter, int aDrill )
    {
        m_viaDiameter = aDiameter;
        m_viaDrill = aDrill;
        m_placingVia = aEnabled;
    }

    ///> Starts placement of a line at point aStart.
    void StartPlacement( const VECTOR2I& aStart, int aNet, int aWidth, int aLayer );

    /**
     * Function Route()
     *
66 67 68
     * 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()
69 70 71 72 73 74 75 76 77 78 79 80 81 82
     * repetitively due to mouse smoothing.
     * @param aP ending point of current route.
     * @return true, if the routing is complete.
     */
    bool Route( const VECTOR2I& aP );

    ///> Sets initial routing direction/posture
    void SetInitialDirection( const DIRECTION_45& aDirection );

    void ApplySettings( const PNS_ROUTING_SETTINGS& aSettings );

    ///> Returns the "head" of the line being placed, that is the volatile part
    ///> that has not been settled yet
    const PNS_LINE& GetHead() const { return m_head; }
83
    ///> Returns the "tail" of the line being placed the part that has been
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
    ///> fixed already (follow mouse mode only)
    const PNS_LINE& GetTail() const { return m_tail; }

    ///> Returns the whole routed line
    const PNS_LINE GetTrace() const;

    ///> 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
    {
        if( m_head.GetCLine().PointCount() > 0 )
            return m_head.GetCLine().CPoint( -1 );
        else if( m_tail.GetCLine().PointCount() > 0 )
            return m_tail.GetCLine().CPoint( -1 );
        else
            return m_p_start;
    }

102
    ///> Returns all items in the world that have been affected by the routing
103
    ///> operation. Used to update data structures of the host application
104
    void GetUpdatedItems( PNS_NODE::ItemVector& aRemoved,
105 106 107 108 109 110 111 112 113 114 115 116
                          PNS_NODE::ItemVector& aAdded );

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

    ///> Returns the most recent world state
    PNS_NODE* GetCurrentNode() const;

private:
    static const double m_shoveLengthThreshold = 1.7;

    bool handleViaPlacement( PNS_LINE& aHead );
117

118 119 120
    /**
     * Function checkObtusity()
     *
121
     * Helper that checks if segments a and b form an obtuse angle
122 123 124 125
     * (in 45-degree regime).
     * @return true, if angle (a, b) is obtuse
     */
    bool checkObtusity( const SEG& a, const SEG& b ) const;
126

127 128 129
    /**
     * Function handleSelfIntersections()
     *
130
     * Checks if the head of the track intersects its tail. If so, cuts the
131 132 133 134 135
     * 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();
136

137 138 139
    /**
     * Function handlePullback()
     *
140
     * Deals with pull-back: reduces the tail if head trace is moved backwards
141 142 143 144 145 146 147 148
     * wrs to the current tail direction.
     * @return true if the line has been changed.
     */
    bool handlePullback();

    /**
     * Function mergeHead()
     *
149
     * Moves "estabished" segments from the head to the tail if certain
150 151 152 153 154 155 156 157
     * conditions are met.
     * @return true, if the line has been changed.
     */
    bool mergeHead();

    /**
     * Function reduceTail()
     *
158 159
     * 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
160 161 162 163 164
     * 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 );
165

166
    void fixHeadPosture();
167

168 169 170
    /**
     * Function optimizeTailHeadTransition()
     *
171
     * Tries to reduce the corner count of the most recent part of tail/head by
172 173 174 175 176 177 178 179
     * merging obtuse/collinear segments.
     * @return true, if the line has been changed.
     */
    bool optimizeTailHeadTransition();

    /**
     * Function routeHead()
     *
180 181 182
     * 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
183 184
     * ignored, as they'll be handled later by the shove algorithm.
     */
185
    bool routeHead( const VECTOR2I& aP, PNS_LINE& aNewHead,
186 187 188 189 190 191 192 193 194 195 196 197 198 199
                    bool aCwWalkaround = true );

    /**
     * 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 );

    ///> routing mode (walkaround, shove, etc.)
    PNS_MODE m_mode;

200
    ///> follow mouse trail by attaching new segments to the head
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
    ///> as the cursor moves
    bool m_follow_mouse;

    ///> mouse smoothing active
    bool m_smooth_mouse;

    ///> mouse smoothing step (in world units)
    int m_smoothing_step;

    ///> 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;

    ///> current algorithm iteration
    int m_iteration;

    ///> 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;

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

    ///> current via diameter
    int m_viaDiameter;

    ///> current via drill
    int m_viaDrill;

    ///> walkaround algorithm iteration limit
    int m_walkaroundIterationLimit;

    ///> smart pads optimizer enabled.
    bool m_smartPads;
252
};
253 254

#endif    // __PNS_LINE_PLACER_H