1 /***************************************************************************
2 * Copyright (C) 2007 by Daniel Brody *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 3 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
21 #include "Coordinate.h"
24 Path::Path(const Coordinate
& from
, const Coordinate
& to
) :
33 //assign the component values in the transform
34 m_xcomponent
= m_to
.getXCoordinate() - m_from
.getXCoordinate();
35 m_ycomponent
= m_to
.getYCoordinate() - m_from
.getYCoordinate();
36 m_zcomponent
= m_to
.getZCoordinate() - m_from
.getZCoordinate();
39 void Path::setFrom(const Coordinate
& from
)
45 void Path::setTo(const Coordinate
& to
)
51 const Coordinate
& Path::getFrom() const
56 const Coordinate
& Path::getTo() const
61 long Path::length() const
63 long x_length
= abs(m_xcomponent
);
64 long y_length
= abs(m_ycomponent
);
65 long z_length
= abs(m_zcomponent
);
67 if (x_length
>= y_length
&& x_length
>= z_length
)
69 else if (y_length
>= z_length
)
75 const Coordinate
& Path::direction() const
80 long x
= m_xcomponent
;
81 long y
= m_ycomponent
;
82 long z
= m_zcomponent
;
84 long x_length
= abs(x
);
85 long y_length
= abs(y
);
86 long z_length
= abs(z
);
89 //********* x is largest component **********//
91 if (x_length
>= y_length
&& x_length
>= z_length
)
93 if (x
>0) //x is +ve (east)
95 if (y
>0 && (x_length
*ratio
)/y_length
<=threshold
) //y is +ve and a decent ratio of x
97 if (z
==0) //z will be 0 in most situations
98 return Coordinate::NE
;
99 else if (z
>0 && (x_length
*ratio
)/z_length
<=threshold
) //z has to be a decent ratio too
100 return Coordinate::NEUP
;
101 else if (z
<0 && (x_length
*ratio
)/z_length
<=threshold
)
102 return Coordinate::NEDOWN
;
104 return Coordinate::NE
; //in case z isn't 0, but irrelevant
106 else if (y
<0 && (x_length
*ratio
)/y_length
<=threshold
) //y is -ve and a decent ratio of x
109 return Coordinate::SE
;
110 else if (z
>0 && (x_length
*ratio
)/z_length
<=threshold
)
111 return Coordinate::SEUP
;
112 else if (z
<0 && (x_length
*ratio
)/z_length
<=threshold
)
113 return Coordinate::SEDOWN
;
115 return Coordinate::SE
;
117 else //catch the irrelevant and 0 cases of y
120 return Coordinate::EAST
;
121 else if (z
>0 && (x_length
*ratio
)/z_length
<=threshold
)
122 return Coordinate::EUP
;
123 else if (z
<0 && (x_length
*ratio
)/z_length
<=threshold
)
124 return Coordinate::EDOWN
;
126 return Coordinate::EAST
;
130 else if (x
<0) //x is -ve (west)
132 if (y
>0 && (x_length
*ratio
)/y_length
<=threshold
) //same stuff as x +ve
135 return Coordinate::NW
; //west this time
136 else if (z
>0 && (x_length
*ratio
)/z_length
<=threshold
)
137 return Coordinate::NWUP
;
138 else if (z
<0 && (x_length
*ratio
)/z_length
<=threshold
)
139 return Coordinate::NWDOWN
;
141 return Coordinate::NW
;
143 else if (y
<0 && (x_length
*ratio
)/y_length
<=threshold
)
146 return Coordinate::SW
;
147 else if (z
>0 && (x_length
*ratio
)/z_length
<=threshold
)
148 return Coordinate::SWUP
;
149 else if (z
<0 && (x_length
*ratio
)/z_length
<=threshold
)
150 return Coordinate::SWDOWN
;
152 return Coordinate::SW
;
157 return Coordinate::WEST
;
158 else if (z
>0 && (x_length
*ratio
)/z_length
<=threshold
)
159 return Coordinate::WUP
;
160 else if (z
<0 && (x_length
*ratio
)/z_length
<=threshold
)
161 return Coordinate::WDOWN
;
163 return Coordinate::WEST
;
168 //********* y is largest component **********//
170 else if (y_length
>= z_length
) //x has been checked already
172 if (y
>0) //y is +ve (north)
174 if (x
>0 && (y_length
*ratio
)/x_length
<=threshold
) //x is +ve (east)
176 if (z
==0) //the rest is very similar to before
177 return Coordinate::NE
;
178 else if (z
>0 && (y_length
*ratio
)/z_length
<=threshold
)
179 return Coordinate::NEUP
;
180 else if (z
<0 && (y_length
*ratio
)/z_length
<=threshold
)
181 return Coordinate::NEDOWN
;
183 return Coordinate::NE
; //in case z isn't 0, but irrelevant
185 else if (x
<0 && (y_length
*ratio
)/x_length
<=threshold
) //x is -ve (west)
188 return Coordinate::NW
;
189 else if (z
>0 && (y_length
*ratio
)/z_length
<=threshold
)
190 return Coordinate::NWUP
;
191 else if (z
<0 && (y_length
*ratio
)/z_length
<=threshold
)
192 return Coordinate::NWDOWN
;
194 return Coordinate::NW
;
196 else //x is irrelevant or 0
199 return Coordinate::NORTH
;
200 else if (z
>0 && (y_length
*ratio
)/z_length
<=threshold
)
201 return Coordinate::NUP
;
202 else if (z
<0 && (y_length
*ratio
)/z_length
<=threshold
)
203 return Coordinate::NDOWN
;
205 return Coordinate::NORTH
;
209 else if (y
<0) //y is -ve (south)
211 if (x
>0 && (y_length
*ratio
)/x_length
<=threshold
) //x is +ve (east)
214 return Coordinate::SE
;
215 else if (z
>0 && (y_length
*ratio
)/z_length
<=threshold
)
216 return Coordinate::SEUP
;
217 else if (z
<0 && (y_length
*ratio
)/z_length
<=threshold
)
218 return Coordinate::SEDOWN
;
220 return Coordinate::SE
;
222 else if (x
<0 && (y_length
*ratio
)/x_length
<=threshold
) //x is -ve (west)
225 return Coordinate::SW
;
226 else if (z
>0 && (y_length
*ratio
)/z_length
<=threshold
)
227 return Coordinate::SWUP
;
228 else if (z
<0 && (y_length
*ratio
)/z_length
<=threshold
)
229 return Coordinate::SWDOWN
;
231 return Coordinate::SW
;
233 else //if x is irrelevant
236 return Coordinate::SOUTH
;
237 else if (z
>0 && (y_length
*ratio
)/z_length
<=threshold
)
238 return Coordinate::SUP
;
239 else if (z
<0 && (y_length
*ratio
)/z_length
<=threshold
)
240 return Coordinate::SDOWN
;
242 return Coordinate::SOUTH
;
247 //********* z is largest component **********//
249 else //z has to be largest
251 if (z
>0) //z is +ve (up)
253 if (x
>0 && (z_length
*ratio
)/x_length
<=threshold
) //using a bigger ratio to narrow
254 { //the 'cone' of pure UP
255 if (y
>0 && (z_length
*ratio
)/y_length
<=threshold
)
256 return Coordinate::NEUP
;
257 else if (y
<0 && (z_length
*ratio
)/y_length
<=threshold
)
258 return Coordinate::SEUP
;
260 return Coordinate::EUP
; //in case y is irrelevant
262 else if (x
<0 && (z_length
*ratio
)/x_length
<=threshold
) //x is -ve (west)
264 if (y
>0 && (z_length
*ratio
)/y_length
<=threshold
) //y is +ve (north)
265 return Coordinate::NWUP
;
266 else if (y
<0 && (z_length
*ratio
)/y_length
<=threshold
) //y is -ve (south)
267 return Coordinate::SWUP
;
269 return Coordinate::WUP
;
271 else //x is irrelevant or 0
273 if (y
>0 && (z_length
*ratio
)/y_length
<=threshold
) //if y is +ve and decent ratio
274 return Coordinate::NUP
;
275 else if (y
<0 && (z_length
*ratio
)/y_length
<=threshold
) //y is -ve
276 return Coordinate::SUP
;
278 return Coordinate::UP
; //y AND x are irrelevant or 0
282 else if (z
<0) //z is -ve (down)
284 if (x
>0 && (z_length
*ratio
)/x_length
<=threshold
) //x is +ve (east)
286 if (y
>0 && (z_length
*ratio
)/y_length
<=threshold
)
287 return Coordinate::NEDOWN
;
288 else if (y
<0 && (z_length
*ratio
)/y_length
<=threshold
)
289 return Coordinate::SEDOWN
;
291 return Coordinate::EDOWN
;
293 else if (x
<0 && (z_length
*ratio
)/x_length
<=threshold
) //x is -ve (west)
295 if (y
>0 && (z_length
*ratio
)/y_length
<=threshold
)
296 return Coordinate::NWDOWN
;
297 else if (y
<0 && (z_length
*ratio
)/y_length
<=threshold
)
298 return Coordinate::SWDOWN
;
300 return Coordinate::WDOWN
;
302 else //if x is irrelevant
304 if (y
>0 && (z_length
*ratio
)/y_length
<=threshold
)
305 return Coordinate::NDOWN
;
306 else if (y
<0 && (z_length
*ratio
)/y_length
<=threshold
)
307 return Coordinate::SDOWN
;
309 return Coordinate::DOWN
; //x AND y are irrelevant or 0
315 std::vector
<Coordinate
> Path::route() const
317 std::vector
<Coordinate
> route
;
318 long distance
= length();
319 Path
thePath(m_from
, m_to
);
321 for(long i
= 0; i
< distance
; i
++)
323 route
.push_back(thePath
.getTo()); //push destination to route
324 thePath
.setTo(thePath
.getTo() - thePath
.direction()); //increment destination closer