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 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 
34 {
35 public:
36 
43  {
44  N = 0,
45  NE = 1,
46  E = 2,
47  SE = 3,
48  S = 4,
49  SW = 5,
50  W = 6,
51  NW = 7,
52  UNDEFINED = -1
53  };
54 
59  enum AngleType
60  {
61  ANG_OBTUSE = 0x01,
62  ANG_RIGHT = 0x02,
63  ANG_ACUTE = 0x04,
64  ANG_STRAIGHT = 0x08,
65  ANG_HALF_FULL = 0x10,
67  };
68 
69  DIRECTION_45( Directions aDir = UNDEFINED ) : m_dir( aDir ) {}
70 
75  DIRECTION_45( const VECTOR2I& aVec )
76  {
77  construct_( aVec );
78  }
79 
84  DIRECTION_45( const SEG& aSeg )
85  {
86  construct_( aSeg.B - aSeg.A );
87  }
88 
94  const std::string Format() const
95  {
96  switch( m_dir )
97  {
98  case N:
99  return "north";
100 
101  case NE:
102  return "north-east";
103 
104  case E:
105  return "east";
106 
107  case SE:
108  return "south-east";
109 
110  case S:
111  return "south";
112 
113  case SW:
114  return "south-west";
115 
116  case W:
117  return "west";
118 
119  case NW:
120  return "north-west";
121 
122  case UNDEFINED:
123  return "undefined";
124 
125  default:
126  return "<Error>";
127  }
128  }
129 
136  {
137  const Directions OppositeMap[] = { S, SW, W, NW, N, NE, E, SE, UNDEFINED };
138  return OppositeMap[m_dir];
139  }
140 
146  AngleType Angle( const DIRECTION_45& aOther ) const
147  {
148  if( m_dir == UNDEFINED || aOther.m_dir == UNDEFINED )
149  return ANG_UNDEFINED;
150 
151  int d = std::abs( m_dir - aOther.m_dir );
152 
153  if( d == 1 || d == 7 )
154  return ANG_OBTUSE;
155  else if( d == 2 || d == 6 )
156  return ANG_RIGHT;
157  else if( d == 3 || d == 5 )
158  return ANG_ACUTE;
159  else if( d == 4 )
160  return ANG_HALF_FULL;
161  else
162  return ANG_STRAIGHT;
163  }
164 
169  bool IsObtuse( const DIRECTION_45& aOther ) const
170  {
171  return Angle( aOther ) == ANG_OBTUSE;
172  }
173 
179  bool IsDiagonal() const
180  {
181  return ( m_dir % 2 ) == 1;
182  }
183 
184  bool IsDefined() const
185  {
186  return m_dir != UNDEFINED;
187  }
188 
200  const VECTOR2I& aP1,
201  bool aStartDiagonal = false ) const
202  {
203  int w = abs( aP1.x - aP0.x );
204  int h = abs( aP1.y - aP0.y );
205  int sw = sign( aP1.x - aP0.x );
206  int sh = sign( aP1.y - aP0.y );
207 
208  VECTOR2I mp0, mp1;
209 
210  // we are more horizontal than vertical?
211  if( w > h )
212  {
213  mp0 = VECTOR2I( ( w - h ) * sw, 0 ); // direction: E
214  mp1 = VECTOR2I( h * sw, h * sh ); // direction: NE
215  }
216  else
217  {
218  mp0 = VECTOR2I( 0, sh * ( h - w ) ); // direction: N
219  mp1 = VECTOR2I( sw * w, sh * w ); // direction: NE
220  }
221 
222  bool start_diagonal;
223 
224  if( m_dir == UNDEFINED )
225  start_diagonal = aStartDiagonal;
226  else
227  start_diagonal = IsDiagonal();
228 
229  SHAPE_LINE_CHAIN pl;
230 
231  pl.Append( aP0 );
232 
233  if( start_diagonal )
234  pl.Append( aP0 + mp1 );
235  else
236  pl.Append( aP0 + mp0 );
237 
238  pl.Append( aP1 );
239  pl.Simplify();
240  return pl;
241  }
242 
243  bool operator==( const DIRECTION_45& aOther ) const
244  {
245  return aOther.m_dir == m_dir;
246  }
247 
248  bool operator!=( const DIRECTION_45& aOther ) const
249  {
250  return aOther.m_dir != m_dir;
251  }
252 
259  const DIRECTION_45 Right() const
260  {
261  DIRECTION_45 r;
262 
263  if ( m_dir != UNDEFINED )
264  r.m_dir = static_cast<Directions>( ( m_dir + 1 ) % 8 );
265 
266  return r;
267  }
268 
275  const DIRECTION_45 Left() const
276  {
277  DIRECTION_45 l;
278 
279  if ( m_dir == UNDEFINED )
280  return l;
281 
282  if( m_dir == N )
283  l.m_dir = NW;
284  else
285  l.m_dir = static_cast<Directions>( m_dir - 1 );
286 
287  return l;
288  }
289 
295  const VECTOR2I ToVector() const
296  {
297  switch( m_dir )
298  {
299  case N: return VECTOR2I( 0, 1 );
300  case S: return VECTOR2I( 0, -1 );
301  case E: return VECTOR2I( 1, 0 );
302  case W: return VECTOR2I( -1, 0 );
303  case NE: return VECTOR2I( 1, 1 );
304  case NW: return VECTOR2I( -1, 1 );
305  case SE: return VECTOR2I( 1, -1 );
306  case SW: return VECTOR2I( -1, -1 );
307 
308  default:
309  return VECTOR2I( 0, 0 );
310  }
311  }
312 
313  int Mask() const
314  {
315  return 1 << ( (int) m_dir );
316  }
317 
318 private:
319 
326  void construct_( const VECTOR2I& aVec )
327  {
328  m_dir = UNDEFINED;
329 
330  if( aVec.x == 0 && aVec.y == 0 )
331  return;
332 
333  double mag = 360.0 - ( 180.0 / M_PI * atan2( (double) aVec.y, (double) aVec.x ) ) + 90.0;
334 
335  if( mag >= 360.0 )
336  mag -= 360.0;
337 
338  if( mag < 0.0 )
339  mag += 360.0;
340 
341  int dir = ( mag + 22.5 ) / 45.0;
342 
343  if( dir >= 8 )
344  dir = dir - 8;
345 
346  if( dir < 0 )
347  dir = dir + 8;
348 
349  m_dir = (Directions) dir;
350 
351  return;
352  }
353 
356 };
357 
358 #endif // DIRECTION45_H
int Mask() const
Definition: direction45.h:313
const VECTOR2I ToVector() const
Function ToVector()
Definition: direction45.h:295
DIRECTION_45 Opposite() const
Function Opposite() Returns a direction opposite (180 degree) to (this)
Definition: direction45.h:135
const DIRECTION_45 Left() const
Function Left()
Definition: direction45.h:275
VECTOR2< int > VECTOR2I
Definition: vector2d.h:589
#define abs(a)
Definition: auxiliary.h:84
void Append(int aX, int aY, bool aAllowDuplication=false)
Function Append()
DIRECTION_45(Directions aDir=UNDEFINED)
Definition: direction45.h:69
SHAPE_LINE_CHAIN & Simplify()
Function Simplify()
bool operator==(const DIRECTION_45 &aOther) const
Definition: direction45.h:243
bool IsDefined() const
Definition: direction45.h:184
DIRECTION_45(const VECTOR2I &aVec)
Constructor.
Definition: direction45.h:75
Class DIRECTION_45.
Definition: direction45.h:33
bool IsObtuse(const DIRECTION_45 &aOther) const
Function IsObtuse()
Definition: direction45.h:169
bool operator!=(const DIRECTION_45 &aOther) const
Definition: direction45.h:248
DIRECTION_45(const SEG &aSeg)
Constructor.
Definition: direction45.h:84
bool IsDiagonal() const
Function IsDiagonal() Returns true if the direction is diagonal (e.g.
Definition: direction45.h:179
Definition: seg.h:36
AngleType
Enum AngleType Represents kind of angle formed by vectors heading in two DIRECTION_45s.
Definition: direction45.h:59
const std::string Format() const
Function Format() Formats the direction in a human readable word.
Definition: direction45.h:94
Class SHAPE_LINE_CHAIN.
VECTOR2I A
Definition: seg.h:46
AngleType Angle(const DIRECTION_45 &aOther) const
Function Angle() Returns the type of angle between directions (this) and aOther.
Definition: direction45.h:146
const DIRECTION_45 Right() const
Function Right()
Definition: direction45.h:259
Directions m_dir
our actual direction
Definition: direction45.h:355
const SHAPE_LINE_CHAIN BuildInitialTrace(const VECTOR2I &aP0, const VECTOR2I &aP1, bool aStartDiagonal=false) const
Function BuildInitialTrace()
Definition: direction45.h:199
void construct_(const VECTOR2I &aVec)
Function construct() Calculates the direction from a vector.
Definition: direction45.h:326
Directions
Enum Directions Represents available directions - there are 8 of them, as on a rectilinear map (north...
Definition: direction45.h:42
int sign(T val)
Definition: math_util.h:44
VECTOR2I B
Definition: seg.h:47