1 /*
2  * KiRouter - a push-and-(sometimes-)shove PCB router
3  *
4  * Copyright (C) 2013-2014 CERN
5  * Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors.
6  * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
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 #ifndef __PNS_ROUTER_H
23 #define __PNS_ROUTER_H
24 
25 #include <list>
26 #include <memory>
27 #include <core/optional.h>
28 #include <math/box2.h>
29 
30 #include "pns_routing_settings.h"
31 #include "pns_sizes_settings.h"
32 #include "pns_node.h"
33 
34 namespace KIGFX
35 {
36 
37 class VIEW;
38 class VIEW_GROUP;
39 
40 }
41 
42 namespace PNS {
43 
44 class DEBUG_DECORATOR;
45 class NODE;
46 class DIFF_PAIR_PLACER;
47 class PLACEMENT_ALGO;
48 class LINE_PLACER;
49 class ITEM;
50 class ARC;
51 class LINE;
52 class SOLID;
53 class SEGMENT;
54 class JOINT;
55 class VIA;
56 class RULE_RESOLVER;
57 class SHOVE;
58 class DRAGGER;
59 class DRAG_ALGO;
60 class LOGGER;
61 
62 enum ROUTER_MODE {
63     PNS_MODE_ROUTE_SINGLE = 1,
64     PNS_MODE_ROUTE_DIFF_PAIR,
65     PNS_MODE_TUNE_SINGLE,
66     PNS_MODE_TUNE_DIFF_PAIR,
67     PNS_MODE_TUNE_DIFF_PAIR_SKEW
68 };
69 
70 enum DRAG_MODE
71 {
72     DM_CORNER = 0x1,
73     DM_SEGMENT = 0x2,
74     DM_VIA = 0x4,
75     DM_FREE_ANGLE = 0x8,
76     DM_ARC = 0x10,
77     DM_ANY = 0x17,
78     DM_COMPONENT = 0x20
79 };
80 /**
81  * ROUTER
82  *
83  * Main router class.
84  */
85 
86  class ROUTER_IFACE
87  {
88  public:
ROUTER_IFACE()89     ROUTER_IFACE() {};
~ROUTER_IFACE()90     virtual ~ROUTER_IFACE() {};
91 
92     virtual void SyncWorld( NODE* aNode ) = 0;
93     virtual void AddItem( ITEM* aItem ) = 0;
94     virtual void UpdateItem( ITEM* aItem ) = 0;
95     virtual void RemoveItem( ITEM* aItem ) = 0;
96     virtual bool IsAnyLayerVisible( const LAYER_RANGE& aLayer ) const = 0;
97     virtual bool IsItemVisible( const PNS::ITEM* aItem ) const = 0;
98     virtual bool IsFlashedOnLayer( const PNS::ITEM* aItem, int aLayer ) const = 0;
99     virtual void DisplayItem( const ITEM* aItem, int aClearance, bool aEdit = false ) = 0;
100     virtual void DisplayRatline( const SHAPE_LINE_CHAIN& aRatline, int aColor = -1 ) = 0;
101     virtual void HideItem( ITEM* aItem ) = 0;
102     virtual void Commit() = 0;
103     virtual bool ImportSizes( SIZES_SETTINGS& aSizes, ITEM* aStartItem, int aNet ) = 0;
104     virtual int  StackupHeight( int aFirstLayer, int aSecondLayer ) const = 0;
105 
106     virtual void EraseView() = 0;
107     virtual void UpdateNet( int aNetCode ) = 0;
108 
109     virtual PNS::NODE* GetWorld() const = 0;
110 
111     virtual RULE_RESOLVER* GetRuleResolver() = 0;
112     virtual DEBUG_DECORATOR* GetDebugDecorator() = 0;
113 };
114 
115 class ROUTER
116 {
117 public:
118     enum RouterState
119     {
120         IDLE,
121         DRAG_SEGMENT,
122         DRAG_COMPONENT,
123         ROUTE_TRACK
124     };
125 
126 public:
127     ROUTER();
128     ~ROUTER();
129 
130     void SetInterface( ROUTER_IFACE* aIface );
131     void SetMode ( ROUTER_MODE aMode );
Mode()132     ROUTER_MODE Mode() const { return m_mode; }
133 
GetState()134     RouterState GetState() const { return m_state; }
135 
GetDragger()136     DRAG_ALGO* GetDragger() { return m_dragger.get(); }
137 
138     static ROUTER* GetInstance();
139 
140     void ClearWorld();
141     void SyncWorld();
142 
143     bool RoutingInProgress() const;
144     bool StartRouting( const VECTOR2I& aP, ITEM* aItem, int aLayer );
145     void Move( const VECTOR2I& aP, ITEM* aItem );
146     bool FixRoute( const VECTOR2I& aP, ITEM* aItem, bool aForceFinish = false );
147     void BreakSegment( ITEM *aItem, const VECTOR2I& aP );
148 
149     void UndoLastSegment();
150     void CommitRouting();
151     void StopRouting();
152     void ClearViewDecorations();
153 
GetWorld()154     NODE* GetWorld() const { return m_world.get(); }
155 
156     void FlipPosture();
157 
158     bool SwitchLayer( int layer );
159 
160     void ToggleViaPlacement();
161     void SetOrthoMode( bool aEnable );
162 
163     void ToggleCornerMode();
164 
165     int GetCurrentLayer() const;
166     const std::vector<int> GetCurrentNets() const;
167 
168     LOGGER* Logger();
169 
GetRuleResolver()170     RULE_RESOLVER* GetRuleResolver() const { return m_iface->GetRuleResolver(); }
171 
172     bool IsPlacingVia() const;
173 
174     const ITEM_SET QueryHoverItems( const VECTOR2I& aP, bool aUseClearance = false );
175 
176     bool StartDragging( const VECTOR2I& aP, ITEM* aItem, int aDragMode = DM_ANY );
177     bool StartDragging( const VECTOR2I& aP, ITEM_SET aItems, int aDragMode = DM_COMPONENT );
178 
SetIterLimit(int aX)179     void SetIterLimit( int aX ) { m_iterLimit = aX; }
GetIterLimit()180     int GetIterLimit() const { return m_iterLimit; };
181 
Settings()182     ROUTING_SETTINGS& Settings() { return *m_settings; }
183 
184     void CommitRouting( NODE* aNode );
185 
186     /**
187      * Applies stored settings.
188      * @see Settings()
189      */
190     void UpdateSizes( const SIZES_SETTINGS& aSizes );
191 
192     /**
193      * Changes routing settings to ones passed in the parameter.
194      * @param aSettings are the new settings.
195      */
LoadSettings(ROUTING_SETTINGS * aSettings)196     void LoadSettings( ROUTING_SETTINGS* aSettings )
197     {
198         m_settings = aSettings;
199     }
200 
Sizes()201     SIZES_SETTINGS& Sizes() { return m_sizes; }
202 
SetFailureReason(const wxString & aReason)203     void SetFailureReason( const wxString& aReason ) { m_failureReason = aReason; }
FailureReason()204     const wxString& FailureReason() const { return m_failureReason; }
205 
Placer()206     PLACEMENT_ALGO* Placer() { return m_placer.get(); }
207 
GetInterface()208     ROUTER_IFACE* GetInterface() const { return m_iface; }
209 
SetVisibleViewArea(const BOX2I & aExtents)210     void SetVisibleViewArea( const BOX2I& aExtents ) { m_visibleViewArea = aExtents; }
VisibleViewArea()211     const BOX2I& VisibleViewArea() const { return m_visibleViewArea; }
212 
213 private:
214     void movePlacing( const VECTOR2I& aP, ITEM* aItem );
215     void moveDragging( const VECTOR2I& aP, ITEM* aItem );
216 
217     void updateView( NODE* aNode, ITEM_SET& aCurrent, bool aDragging = false );
218 
219     // optHoverItem queryHoverItemEx(const VECTOR2I& aP);
220 
221     void markViolations( NODE* aNode, ITEM_SET& aCurrent, NODE::ITEM_VECTOR& aRemoved );
222     bool isStartingPointRoutable( const VECTOR2I& aWhere, ITEM* aItem, int aLayer );
223 
224 private:
225     BOX2I                           m_visibleViewArea;
226     RouterState                     m_state;
227 
228     std::unique_ptr<NODE>           m_world;
229     NODE*                           m_lastNode;
230 
231     std::unique_ptr<PLACEMENT_ALGO> m_placer;
232     std::unique_ptr<DRAG_ALGO>      m_dragger;
233     std::unique_ptr<SHOVE>          m_shove;
234 
235     ROUTER_IFACE*     m_iface;
236 
237     int               m_iterLimit;
238     bool              m_forceMarkObstaclesMode = false;
239 
240     ROUTING_SETTINGS* m_settings;
241     SIZES_SETTINGS    m_sizes;
242     ROUTER_MODE       m_mode;
243     LOGGER*           m_logger;
244 
245     wxString          m_toolStatusbarName;
246     wxString          m_failureReason;
247 };
248 
249 }
250 
251 #endif
252