KiCad PCB EDA Suite
direction45.h
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2013-2015 CERN
5  * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
6  * Copyright (C) 2017-2019 KiCad Developers, see AUTHORS.txt for contributors.
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.or/licenses/>.
20  */
21 
22 #ifndef DIRECTION45_H
23 #define DIRECTION45_H
24 
25 #include <geometry/seg.h>
27 #include <math/vector2d.h>
28 
29 // believe or not, X11 headers have a F****ING macro called Opposite...
30 #undef Opposite
31 
38 {
39 public:
40 
46  enum Directions : int
47  {
48  N = 0,
49  NE = 1,
50  E = 2,
51  SE = 3,
52  S = 4,
53  SW = 5,
54  W = 6,
55  NW = 7,
56  LAST = 8,
57  UNDEFINED = -1
58  };
59 
64  enum AngleType
65  {
66  ANG_OBTUSE = 0x01,
67  ANG_RIGHT = 0x02,
68  ANG_ACUTE = 0x04,
69  ANG_STRAIGHT = 0x08,
70  ANG_HALF_FULL = 0x10,
72  };
73 
74  DIRECTION_45( Directions aDir = UNDEFINED ) : m_dir( aDir ), m_90deg( false ) {}
75 
80  DIRECTION_45( const VECTOR2I &aVec, bool a90 = false ) :
81  m_90deg( a90 )
82  {
83  construct_( aVec );
84  }
85 
90  DIRECTION_45( const SEG& aSeg, bool a90 = false ) :
91  m_90deg( a90 )
92  {
93  construct_( aSeg.B - aSeg.A );
94  }
95 
101  const std::string Format() const
102  {
103  switch( m_dir )
104  {
105  case N:
106  return "north";
107 
108  case NE:
109  return "north-east";
110 
111  case E:
112  return "east";
113 
114  case SE:
115  return "south-east";
116 
117  case S:
118  return "south";
119 
120  case SW:
121  return "south-west";
122 
123  case W:
124  return "west";
125 
126  case NW:
127  return "north-west";
128 
129  case UNDEFINED:
130  return "undefined";
131 
132  default:
133  return "<Error>";
134  }
135  }
136 
143  {
144  const Directions OppositeMap[] = { S, SW, W, NW, N, NE, E, SE, UNDEFINED };
145  return OppositeMap[m_dir];
146  }
147 
153  AngleType Angle( const DIRECTION_45& aOther ) const
154  {
155  if( m_dir == UNDEFINED || aOther.m_dir == UNDEFINED )
156  return ANG_UNDEFINED;
157 
158  int d = std::abs( m_dir - aOther.m_dir );
159 
160  if( d == 1 || d == 7 )
161  return ANG_OBTUSE;
162  else if( d == 2 || d == 6 )
163  return ANG_RIGHT;
164  else if( d == 3 || d == 5 )
165  return ANG_ACUTE;
166  else if( d == 4 )
167  return ANG_HALF_FULL;
168  else
169  return ANG_STRAIGHT;
170  }
171 
176  bool IsObtuse( const DIRECTION_45& aOther ) const
177  {
178  return Angle( aOther ) == ANG_OBTUSE;
179  }
180 
186  bool IsDiagonal() const
187  {
188  return ( m_dir % 2 ) == 1;
189  }
190 
191  bool IsDefined() const
192  {
193  return m_dir != UNDEFINED;
194  }
195 
207  const SHAPE_LINE_CHAIN BuildInitialTrace( const VECTOR2I& aP0,
208  const VECTOR2I& aP1,
209  bool aStartDiagonal = false,
210  int aMaxRadius = 0 ) const;
211 
212  bool operator==( const DIRECTION_45& aOther ) const
213  {
214  return aOther.m_dir == m_dir;
215  }
216 
217  bool operator!=( const DIRECTION_45& aOther ) const
218  {
219  return aOther.m_dir != m_dir;
220  }
221 
228  const DIRECTION_45 Right() const
229  {
230  DIRECTION_45 r;
231 
232  if ( m_dir != UNDEFINED )
233  {
234  if( m_90deg )
235  r.m_dir = static_cast<Directions>( ( m_dir + 2 ) % LAST );
236  else
237  r.m_dir = static_cast<Directions>( ( m_dir + 1 ) % LAST );
238  }
239 
240  return r;
241  }
242 
249  const DIRECTION_45 Left() const
250  {
251  DIRECTION_45 l;
252 
253  if ( m_dir != UNDEFINED )
254  {
255  if( m_90deg )
256  l.m_dir = static_cast<Directions>( ( m_dir + LAST - 2 ) % LAST );
257  else
258  l.m_dir = static_cast<Directions>( ( m_dir + LAST - 1 ) % LAST );
259  }
260 
261  return l;
262  }
263 
269  const VECTOR2I ToVector() const
270  {
271  switch( m_dir )
272  {
273  case N: return VECTOR2I( 0, 1 );
274  case S: return VECTOR2I( 0, -1 );
275  case E: return VECTOR2I( 1, 0 );
276  case W: return VECTOR2I( -1, 0 );
277  case NE: return VECTOR2I( 1, 1 );
278  case NW: return VECTOR2I( -1, 1 );
279  case SE: return VECTOR2I( 1, -1 );
280  case SW: return VECTOR2I( -1, -1 );
281 
282  default:
283  return VECTOR2I( 0, 0 );
284  }
285  }
286 
287  int Mask() const
288  {
289  return 1 << ( (int) m_dir );
290  }
291 
292 private:
293 
300  void construct_( const VECTOR2I& aVec )
301  {
302  m_dir = UNDEFINED;
303 
304  if( aVec.x == 0 && aVec.y == 0 )
305  return;
306 
307  double mag = 360.0 - ( 180.0 / M_PI * atan2( (double) aVec.y, (double) aVec.x ) ) + 90.0;
308 
309  if( mag >= 360.0 )
310  mag -= 360.0;
311 
312  if( mag < 0.0 )
313  mag += 360.0;
314 
315  int dir = ( mag + 22.5 ) / 45.0;
316 
317  if( dir >= LAST )
318  dir -= LAST;
319 
320  if( dir < 0 )
321  dir += LAST;
322 
323  m_dir = (Directions) dir;
324 
325  return;
326  }
327 
330 
332  bool m_90deg;
333 };
334 
335 #endif // DIRECTION45_H
Directions
Enum Directions Represents available directions - there are 8 of them, as on a rectilinear map (north...
Definition: direction45.h:46
DIRECTION_45(const SEG &aSeg, bool a90=false)
Constructor.
Definition: direction45.h:90
int Mask() const
Definition: direction45.h:287
const std::string Format() const
Function Format() Formats the direction in a human readable word.
Definition: direction45.h:101
const VECTOR2I ToVector() const
Function ToVector()
Definition: direction45.h:269
const DIRECTION_45 Left() const
Function Left()
Definition: direction45.h:249
bool operator!=(const DIRECTION_45 &aOther) const
Definition: direction45.h:217
DIRECTION_45(const VECTOR2I &aVec, bool a90=false)
Constructor.
Definition: direction45.h:80
const DIRECTION_45 Right() const
Function Right()
Definition: direction45.h:228
VECTOR2< int > VECTOR2I
Definition: vector2d.h:594
DIRECTION_45(Directions aDir=UNDEFINED)
Definition: direction45.h:74
AngleType Angle(const DIRECTION_45 &aOther) const
Function Angle() Returns the type of angle between directions (this) and aOther.
Definition: direction45.h:153
DIRECTION_45.
Definition: direction45.h:37
bool IsDefined() const
Definition: direction45.h:191
DIRECTION_45 Opposite() const
Function Opposite() Returns a direction opposite (180 degree) to (this)
Definition: direction45.h:142
bool IsDiagonal() const
Function IsDiagonal() Returns true if the direction is diagonal (e.g.
Definition: direction45.h:186
bool operator==(const DIRECTION_45 &aOther) const
Definition: direction45.h:212
const SHAPE_LINE_CHAIN BuildInitialTrace(const VECTOR2I &aP0, const VECTOR2I &aP1, bool aStartDiagonal=false, int aMaxRadius=0) const
Function BuildInitialTrace()
Definition: seg.h:39
AngleType
Enum AngleType Represents kind of angle formed by vectors heading in two DIRECTION_45s.
Definition: direction45.h:64
SHAPE_LINE_CHAIN.
VECTOR2I A
Definition: seg.h:47
Directions m_dir
our actual direction
Definition: direction45.h:329
void construct_(const VECTOR2I &aVec)
Function construct() Calculates the direction from a vector.
Definition: direction45.h:300
bool IsObtuse(const DIRECTION_45 &aOther) const
Function IsObtuse()
Definition: direction45.h:176
bool m_90deg
Are we routing on 45 or 90 degree increments
Definition: direction45.h:332
VECTOR2I B
Definition: seg.h:48