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 
28 // believe or not, X11 headers have a F****ING macro called Opposite...
29 #undef Opposite
30 
37 {
38 public:
39 
46  {
47  N = 0,
48  NE = 1,
49  E = 2,
50  SE = 3,
51  S = 4,
52  SW = 5,
53  W = 6,
54  NW = 7,
55  UNDEFINED = -1
56  };
57 
62  enum AngleType
63  {
64  ANG_OBTUSE = 0x01,
65  ANG_RIGHT = 0x02,
66  ANG_ACUTE = 0x04,
67  ANG_STRAIGHT = 0x08,
68  ANG_HALF_FULL = 0x10,
70  };
71 
72  DIRECTION_45( Directions aDir = UNDEFINED ) : m_dir( aDir ) {}
73 
78  DIRECTION_45( const VECTOR2I& aVec )
79  {
80  construct_( aVec );
81  }
82 
87  DIRECTION_45( const SEG& aSeg )
88  {
89  construct_( aSeg.B - aSeg.A );
90  }
91 
97  const std::string Format() const
98  {
99  switch( m_dir )
100  {
101  case N:
102  return "north";
103 
104  case NE:
105  return "north-east";
106 
107  case E:
108  return "east";
109 
110  case SE:
111  return "south-east";
112 
113  case S:
114  return "south";
115 
116  case SW:
117  return "south-west";
118 
119  case W:
120  return "west";
121 
122  case NW:
123  return "north-west";
124 
125  case UNDEFINED:
126  return "undefined";
127 
128  default:
129  return "<Error>";
130  }
131  }
132 
139  {
140  const Directions OppositeMap[] = { S, SW, W, NW, N, NE, E, SE, UNDEFINED };
141  return OppositeMap[m_dir];
142  }
143 
149  AngleType Angle( const DIRECTION_45& aOther ) const
150  {
151  if( m_dir == UNDEFINED || aOther.m_dir == UNDEFINED )
152  return ANG_UNDEFINED;
153 
154  int d = std::abs( m_dir - aOther.m_dir );
155 
156  if( d == 1 || d == 7 )
157  return ANG_OBTUSE;
158  else if( d == 2 || d == 6 )
159  return ANG_RIGHT;
160  else if( d == 3 || d == 5 )
161  return ANG_ACUTE;
162  else if( d == 4 )
163  return ANG_HALF_FULL;
164  else
165  return ANG_STRAIGHT;
166  }
167 
172  bool IsObtuse( const DIRECTION_45& aOther ) const
173  {
174  return Angle( aOther ) == ANG_OBTUSE;
175  }
176 
182  bool IsDiagonal() const
183  {
184  return ( m_dir % 2 ) == 1;
185  }
186 
187  bool IsDefined() const
188  {
189  return m_dir != UNDEFINED;
190  }
191 
203  const VECTOR2I& aP1,
204  bool aStartDiagonal = false ) const
205  {
206  int w = abs( aP1.x - aP0.x );
207  int h = abs( aP1.y - aP0.y );
208  int sw = sign( aP1.x - aP0.x );
209  int sh = sign( aP1.y - aP0.y );
210 
211  VECTOR2I mp0, mp1;
212 
213  // we are more horizontal than vertical?
214  if( w > h )
215  {
216  mp0 = VECTOR2I( ( w - h ) * sw, 0 ); // direction: E
217  mp1 = VECTOR2I( h * sw, h * sh ); // direction: NE
218  }
219  else
220  {
221  mp0 = VECTOR2I( 0, sh * ( h - w ) ); // direction: N
222  mp1 = VECTOR2I( sw * w, sh * w ); // direction: NE
223  }
224 
225  bool start_diagonal;
226 
227  if( m_dir == UNDEFINED )
228  start_diagonal = aStartDiagonal;
229  else
230  start_diagonal = IsDiagonal();
231 
232  SHAPE_LINE_CHAIN pl;
233 
234  pl.Append( aP0 );
235 
236  if( start_diagonal )
237  pl.Append( aP0 + mp1 );
238  else
239  pl.Append( aP0 + mp0 );
240 
241  pl.Append( aP1 );
242  pl.Simplify();
243  return pl;
244  }
245 
246  bool operator==( const DIRECTION_45& aOther ) const
247  {
248  return aOther.m_dir == m_dir;
249  }
250 
251  bool operator!=( const DIRECTION_45& aOther ) const
252  {
253  return aOther.m_dir != m_dir;
254  }
255 
262  const DIRECTION_45 Right() const
263  {
264  DIRECTION_45 r;
265 
266  if ( m_dir != UNDEFINED )
267  r.m_dir = static_cast<Directions>( ( m_dir + 1 ) % 8 );
268 
269  return r;
270  }
271 
278  const DIRECTION_45 Left() const
279  {
280  DIRECTION_45 l;
281 
282  if ( m_dir == UNDEFINED )
283  return l;
284 
285  if( m_dir == N )
286  l.m_dir = NW;
287  else
288  l.m_dir = static_cast<Directions>( m_dir - 1 );
289 
290  return l;
291  }
292 
298  const VECTOR2I ToVector() const
299  {
300  switch( m_dir )
301  {
302  case N: return VECTOR2I( 0, 1 );
303  case S: return VECTOR2I( 0, -1 );
304  case E: return VECTOR2I( 1, 0 );
305  case W: return VECTOR2I( -1, 0 );
306  case NE: return VECTOR2I( 1, 1 );
307  case NW: return VECTOR2I( -1, 1 );
308  case SE: return VECTOR2I( 1, -1 );
309  case SW: return VECTOR2I( -1, -1 );
310 
311  default:
312  return VECTOR2I( 0, 0 );
313  }
314  }
315 
316  int Mask() const
317  {
318  return 1 << ( (int) m_dir );
319  }
320 
321 private:
322 
329  void construct_( const VECTOR2I& aVec )
330  {
331  m_dir = UNDEFINED;
332 
333  if( aVec.x == 0 && aVec.y == 0 )
334  return;
335 
336  double mag = 360.0 - ( 180.0 / M_PI * atan2( (double) aVec.y, (double) aVec.x ) ) + 90.0;
337 
338  if( mag >= 360.0 )
339  mag -= 360.0;
340 
341  if( mag < 0.0 )
342  mag += 360.0;
343 
344  int dir = ( mag + 22.5 ) / 45.0;
345 
346  if( dir >= 8 )
347  dir = dir - 8;
348 
349  if( dir < 0 )
350  dir = dir + 8;
351 
352  m_dir = (Directions) dir;
353 
354  return;
355  }
356 
359 };
360 
361 #endif // DIRECTION45_H
int Mask() const
Definition: direction45.h:316
const VECTOR2I ToVector() const
Function ToVector()
Definition: direction45.h:298
DIRECTION_45 Opposite() const
Function Opposite() Returns a direction opposite (180 degree) to (this)
Definition: direction45.h:138
const DIRECTION_45 Left() const
Function Left()
Definition: direction45.h:278
VECTOR2< int > VECTOR2I
Definition: vector2d.h:587
#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:72
SHAPE_LINE_CHAIN & Simplify()
Function Simplify()
bool operator==(const DIRECTION_45 &aOther) const
Definition: direction45.h:246
bool IsDefined() const
Definition: direction45.h:187
DIRECTION_45(const VECTOR2I &aVec)
Constructor.
Definition: direction45.h:78
Class DIRECTION_45.
Definition: direction45.h:36
bool IsObtuse(const DIRECTION_45 &aOther) const
Function IsObtuse()
Definition: direction45.h:172
bool operator!=(const DIRECTION_45 &aOther) const
Definition: direction45.h:251
DIRECTION_45(const SEG &aSeg)
Constructor.
Definition: direction45.h:87
bool IsDiagonal() const
Function IsDiagonal() Returns true if the direction is diagonal (e.g.
Definition: direction45.h:182
Definition: seg.h:36
AngleType
Enum AngleType Represents kind of angle formed by vectors heading in two DIRECTION_45s.
Definition: direction45.h:62
const std::string Format() const
Function Format() Formats the direction in a human readable word.
Definition: direction45.h:97
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:149
const DIRECTION_45 Right() const
Function Right()
Definition: direction45.h:262
Directions m_dir
our actual direction
Definition: direction45.h:358
const SHAPE_LINE_CHAIN BuildInitialTrace(const VECTOR2I &aP0, const VECTOR2I &aP1, bool aStartDiagonal=false) const
Function BuildInitialTrace()
Definition: direction45.h:202
void construct_(const VECTOR2I &aVec)
Function construct() Calculates the direction from a vector.
Definition: direction45.h:329
Directions
Enum Directions Represents available directions - there are 8 of them, as on a rectilinear map (north...
Definition: direction45.h:45
int sign(T val)
Definition: math_util.h:44
VECTOR2I B
Definition: seg.h:47