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  * Copyright (C) 2017-2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * @author Tomasz Wlostowski <[email protected]>
8  *
9  * This program is free software: you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License as published by the
11  * Free Software Foundation, either version 3 of the License, or (at your
12  * option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program. If not, see <http://www.gnu.or/licenses/>.
21  */
22 
23 #ifndef DIRECTION45_H
24 #define DIRECTION45_H
25 
26 #include <geometry/seg.h>
28 #include <math/vector2d.h>
29 
30 // believe or not, X11 headers have a F****ING macro called Opposite...
31 #undef Opposite
32 
37 {
38 public:
39 
48  enum Directions : int
49  {
50  N = 0,
51  NE = 1,
52  E = 2,
53  SE = 3,
54  S = 4,
55  SW = 5,
56  W = 6,
57  NW = 7,
58  LAST = 8,
59  UNDEFINED = -1
60  };
61 
67  {
68  MITERED_45 = 0,
69  ROUNDED_45 = 1,
70  MITERED_90 = 2,
71  ROUNDED_90 = 3,
72  };
73 
77  enum AngleType
78  {
79  ANG_OBTUSE = 0x01,
80  ANG_RIGHT = 0x02,
81  ANG_ACUTE = 0x04,
82  ANG_STRAIGHT = 0x08,
83  ANG_HALF_FULL = 0x10,
85  };
86 
87  DIRECTION_45( Directions aDir = UNDEFINED ) : m_dir( aDir ), m_90deg( false ) {}
88 
92  DIRECTION_45( const VECTOR2I &aVec, bool a90 = false ) :
93  m_90deg( a90 )
94  {
95  VECTOR2I vec( aVec );
96  vec.y = -vec.y;
97  construct_( vec );
98  }
99 
103  DIRECTION_45( const SEG& aSeg, bool a90 = false ) :
104  m_90deg( a90 )
105  {
106  VECTOR2I vec( aSeg.B - aSeg.A );
107  vec.y = -vec.y;
108  construct_( vec );
109  }
110 
116  DIRECTION_45( const SHAPE_ARC& aArc, bool a90 = false ) :
117  m_90deg( a90 )
118  {
119  VECTOR2I vec( aArc.GetP1() - aArc.GetP0() );
120  vec.y = -vec.y;
121  construct_( vec );
122  }
123 
129  const std::string Format() const
130  {
131  switch( m_dir )
132  {
133  case N:
134  return "north";
135 
136  case NE:
137  return "north-east";
138 
139  case E:
140  return "east";
141 
142  case SE:
143  return "south-east";
144 
145  case S:
146  return "south";
147 
148  case SW:
149  return "south-west";
150 
151  case W:
152  return "west";
153 
154  case NW:
155  return "north-west";
156 
157  case UNDEFINED:
158  return "undefined";
159 
160  default:
161  return "<Error>";
162  }
163  }
164 
171  {
172  const Directions OppositeMap[] = { S, SW, W, NW, N, NE, E, SE, UNDEFINED };
173  return OppositeMap[m_dir];
174  }
175 
181  AngleType Angle( const DIRECTION_45& aOther ) const
182  {
183  if( m_dir == UNDEFINED || aOther.m_dir == UNDEFINED )
184  return ANG_UNDEFINED;
185 
186  int d = std::abs( m_dir - aOther.m_dir );
187 
188  if( d == 1 || d == 7 )
189  return ANG_OBTUSE;
190  else if( d == 2 || d == 6 )
191  return ANG_RIGHT;
192  else if( d == 3 || d == 5 )
193  return ANG_ACUTE;
194  else if( d == 4 )
195  return ANG_HALF_FULL;
196  else
197  return ANG_STRAIGHT;
198  }
199 
203  bool IsObtuse( const DIRECTION_45& aOther ) const
204  {
205  return Angle( aOther ) == ANG_OBTUSE;
206  }
207 
213  bool IsDiagonal() const
214  {
215  return ( m_dir % 2 ) == 1;
216  }
217 
218  bool IsDefined() const
219  {
220  return m_dir != UNDEFINED;
221  }
222 
234  const SHAPE_LINE_CHAIN BuildInitialTrace( const VECTOR2I& aP0, const VECTOR2I& aP1,
235  bool aStartDiagonal = false,
236  CORNER_MODE aMode = CORNER_MODE::MITERED_45 ) const;
237 
238  bool operator==( const DIRECTION_45& aOther ) const
239  {
240  return aOther.m_dir == m_dir;
241  }
242 
243  bool operator!=( const DIRECTION_45& aOther ) const
244  {
245  return aOther.m_dir != m_dir;
246  }
247 
251  const DIRECTION_45 Right() const
252  {
253  DIRECTION_45 r;
254 
255  if ( m_dir != UNDEFINED )
256  {
257  if( m_90deg )
258  r.m_dir = static_cast<Directions>( ( m_dir + 2 ) % LAST );
259  else
260  r.m_dir = static_cast<Directions>( ( m_dir + 1 ) % LAST );
261  }
262 
263  return r;
264  }
265 
269  const DIRECTION_45 Left() const
270  {
271  DIRECTION_45 l;
272 
273  if ( m_dir != UNDEFINED )
274  {
275  if( m_90deg )
276  l.m_dir = static_cast<Directions>( ( m_dir + LAST - 2 ) % LAST );
277  else
278  l.m_dir = static_cast<Directions>( ( m_dir + LAST - 1 ) % LAST );
279  }
280 
281  return l;
282  }
283 
287  const VECTOR2I ToVector() const
288  {
289  switch( m_dir )
290  {
291  case N: return VECTOR2I( 0, -1 );
292  case S: return VECTOR2I( 0, 1 );
293  case E: return VECTOR2I( 1, 0 );
294  case W: return VECTOR2I( -1, 0 );
295  case NE: return VECTOR2I( 1, -1 );
296  case NW: return VECTOR2I( -1, -1 );
297  case SE: return VECTOR2I( 1, 1 );
298  case SW: return VECTOR2I( -1, 1 );
299 
300  default:
301  return VECTOR2I( 0, 0 );
302  }
303  }
304 
305  int Mask() const
306  {
307  return 1 << ( (int) m_dir );
308  }
309 
310 private:
317  void construct_( const VECTOR2I& aVec )
318  {
319  m_dir = UNDEFINED;
320 
321  if( aVec.x == 0 && aVec.y == 0 )
322  return;
323 
324  double mag = 360.0 - ( 180.0 / M_PI * atan2( (double) aVec.y, (double) aVec.x ) ) + 90.0;
325 
326  if( mag >= 360.0 )
327  mag -= 360.0;
328 
329  if( mag < 0.0 )
330  mag += 360.0;
331 
332  int dir = ( mag + 22.5 ) / 45.0;
333 
334  if( dir >= LAST )
335  dir -= LAST;
336 
337  if( dir < 0 )
338  dir += LAST;
339 
340  m_dir = (Directions) dir;
341 
342  return;
343  }
344 
347 
349  bool m_90deg;
350 };
351 
352 #endif // DIRECTION45_H
Directions
Available directions, there are 8 of them, as on a rectilinear map (north = up) + an extra undefined ...
Definition: direction45.h:48
DIRECTION_45(const SEG &aSeg, bool a90=false)
Definition: direction45.h:103
int Mask() const
Definition: direction45.h:305
const std::string Format() const
Format the direction in a human readable word.
Definition: direction45.h:129
const VECTOR2I ToVector() const
Definition: direction45.h:287
const SHAPE_LINE_CHAIN BuildInitialTrace(const VECTOR2I &aP0, const VECTOR2I &aP1, bool aStartDiagonal=false, CORNER_MODE aMode=CORNER_MODE::MITERED_45) const
Build a 2-segment line chain between points aP0 and aP1 and following 45-degree routing regime.
const DIRECTION_45 Left() const
Return the direction on the left side of this (i.e.
Definition: direction45.h:269
bool operator!=(const DIRECTION_45 &aOther) const
Definition: direction45.h:243
DIRECTION_45(const VECTOR2I &aVec, bool a90=false)
Definition: direction45.h:92
const DIRECTION_45 Right() const
Return the direction on the right side of this (i.e.
Definition: direction45.h:251
VECTOR2< int > VECTOR2I
Definition: vector2d.h:622
DIRECTION_45(const SHAPE_ARC &aArc, bool a90=false)
Create a DIRECTION_45 from the endpoints of a given arc.
Definition: direction45.h:116
DIRECTION_45(Directions aDir=UNDEFINED)
Definition: direction45.h:87
AngleType Angle(const DIRECTION_45 &aOther) const
Return the type of angle between directions (this) and aOther.
Definition: direction45.h:181
Represent route directions & corner angles in a 45-degree metric.
Definition: direction45.h:36
bool IsDefined() const
Definition: direction45.h:218
const VECTOR2I & GetP0() const
Definition: shape_arc.h:111
CORNER_MODE
Corner modes.
Definition: direction45.h:66
H/V with filleted corners.
Definition: direction45.h:71
DIRECTION_45 Opposite() const
Return a direction opposite (180 degree) to (this).
Definition: direction45.h:170
bool IsDiagonal() const
Returns true if the direction is diagonal (e.g.
Definition: direction45.h:213
E_SERIE r
Definition: eserie.cpp:41
bool operator==(const DIRECTION_45 &aOther) const
Definition: direction45.h:238
H/V/45 with mitered corners (default)
Definition: direction45.h:68
H/V/45 with filleted corners.
Definition: direction45.h:69
Definition: seg.h:40
AngleType
Represent kind of angle formed by vectors heading in two DIRECTION_45s.
Definition: direction45.h:77
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
H/V only (90-degree corners)
Definition: direction45.h:70
VECTOR2I A
Definition: seg.h:48
Directions m_dir
Are we routing on 45 or 90 degree increments.
Definition: direction45.h:346
void construct_(const VECTOR2I &aVec)
Calculate the direction from a vector.
Definition: direction45.h:317
const VECTOR2I & GetP1() const
Definition: shape_arc.h:112
bool IsObtuse(const DIRECTION_45 &aOther) const
Definition: direction45.h:203
VECTOR2I B
Definition: seg.h:49