Horizon
direction45.h
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>
26#include <geometry/shape_line_chain.h>
27
28// believe or not, X11 headers have a F****ING macro called Opposite...
29#undef Opposite
30
37{
38public:
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
63 {
64 ANG_OBTUSE = 0x01,
65 ANG_RIGHT = 0x02,
66 ANG_ACUTE = 0x04,
67 ANG_STRAIGHT = 0x08,
68 ANG_HALF_FULL = 0x10,
69 ANG_UNDEFINED = 0x20
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
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
321private:
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
358 Directions m_dir;
359};
360
361#endif // DIRECTION45_H
Class DIRECTION_45.
Definition: direction45.h:37
AngleType Angle(const DIRECTION_45 &aOther) const
Function Angle() Returns the type of angle between directions (this) and aOther.
Definition: direction45.h:149
DIRECTION_45(const SEG &aSeg)
Constructor.
Definition: direction45.h:87
const DIRECTION_45 Left() const
Function Left()
Definition: direction45.h:278
const VECTOR2I ToVector() const
Function ToVector()
Definition: direction45.h:298
AngleType
Enum AngleType Represents kind of angle formed by vectors heading in two DIRECTION_45s.
Definition: direction45.h:63
Directions
Enum Directions Represents available directions - there are 8 of them, as on a rectilinear map (north...
Definition: direction45.h:46
bool IsDiagonal() const
Function IsDiagonal() Returns true if the direction is diagonal (e.g.
Definition: direction45.h:182
const DIRECTION_45 Right() const
Function Right()
Definition: direction45.h:262
const SHAPE_LINE_CHAIN BuildInitialTrace(const VECTOR2I &aP0, const VECTOR2I &aP1, bool aStartDiagonal=false) const
Function BuildInitialTrace()
Definition: direction45.h:202
DIRECTION_45(const VECTOR2I &aVec)
Constructor.
Definition: direction45.h:78
const std::string Format() const
Function Format() Formats the direction in a human readable word.
Definition: direction45.h:97
bool IsObtuse(const DIRECTION_45 &aOther) const
Function IsObtuse()
Definition: direction45.h:172
DIRECTION_45 Opposite() const
Function Opposite() Returns a direction opposite (180 degree) to (this)
Definition: direction45.h:138
Definition: seg.h:37
Class SHAPE_LINE_CHAIN.
Definition: shape_line_chain.h:50
void Append(int aX, int aY, bool aAllowDuplication=false)
Function Append()
Definition: shape_line_chain.h:383
SHAPE_LINE_CHAIN & Simplify()
Function Simplify()
Definition: shape_line_chain.cpp:483