Nirtcpp 2.1.0
Nirtcpp is a high-performance c++ graphics engine.
Loading...
Searching...
No Matches
line2d.hpp
1// Copyright (C) 2002-2012 Nikolaus Gebhardt
2// This file is part of the "Irrlicht Engine".
3// For conditions of distribution and use, see copyright notice in nirtcpp/nirtcpp.hpp
4
5#ifndef NIRT_LINE_2D_HPP_INCLUDED
6#define NIRT_LINE_2D_HPP_INCLUDED
7
8#include <nirtcpp/core/engine/nirt_types.hpp>
9#include <nirtcpp/core/engine/vector2d.hpp>
10
11namespace nirt
12{
13namespace core
14{
15
17template <class T>
18class line2d
19{
20 public:
22 line2d() : start(0,0), end(1,1) {}
24 line2d(T xa, T ya, T xb, T yb) : start(xa, ya), end(xb, yb) {}
27
28 // operators
29
30 line2d<T> operator+(const vector2d<T>& point) const { return line2d<T>(start + point, end + point); }
31 line2d<T>& operator+=(const vector2d<T>& point) { start += point; end += point; return *this; }
32
33 line2d<T> operator-(const vector2d<T>& point) const { return line2d<T>(start - point, end - point); }
34 line2d<T>& operator-=(const vector2d<T>& point) { start -= point; end -= point; return *this; }
35
36 bool operator==(const line2d<T>& other) const
37 { return (start==other.start && end==other.end) || (end==other.start && start==other.end);}
38 bool operator!=(const line2d<T>& other) const
39 { return !(start==other.start && end==other.end) || (end==other.start && start==other.end);}
40
41 // functions
43 void setLine(const T& xa, const T& ya, const T& xb, const T& yb){start.set(xa, ya); end.set(xb, yb);}
45 void setLine(const vector2d<T>& nstart, const vector2d<T>& nend){start.set(nstart); end.set(nend);}
47 void setLine(const line2d<T>& line){start.set(line.start); end.set(line.end);}
48
50
51 T getLength() const { return start.getDistanceFrom(end); }
52
54
55 T getLengthSQ() const { return start.getDistanceFromSQ(end); }
56
58
60 {
61 return (start + end)/(T)2;
62 }
63
65
66 vector2d<T> getVector() const { return vector2d<T>( end.X - start.X, end.Y - start.Y); }
67
71 {
72 // Taken from:
73 // http://www.geeksforgeeks.org/check-if-two-given-line-segments-intersect/
74
75 // Find the four orientations needed for general and
76 // special cases
77 s32 o1 = start.checkOrientation( end, other.start);
78 s32 o2 = start.checkOrientation( end, other.end);
79 s32 o3 = other.start.checkOrientation( other.end, start);
80 s32 o4 = other.start.checkOrientation( other.end, end);
81
82 // General case
83 if (o1 != o2 && o3 != o4)
84 return true;
85
86 // Special Cases to check if segments are coolinear
87 if (o1 == 0 && other.start.isBetweenPoints( start, end)) return true;
88 if (o2 == 0 && other.end.isBetweenPoints( start, end)) return true;
89 if (o3 == 0 && start.isBetweenPoints( other.start, other.end)) return true;
90 if (o4 == 0 && end.isBetweenPoints( other.start, other.end)) return true;
91
92 return false; // Doesn't fall in any of the above cases
93 }
94
96 bool incidentSegments( const line2d<T>& other) const
97 {
98 return
99 start.checkOrientation( end, other.start) != start.checkOrientation( end, other.end)
100 && other.start.checkOrientation( other.end, start) != other.start.checkOrientation( other.end, end);
101 }
102
105 {
106 const vector2d<T> a = getVector();
107 const vector2d<T> b = line.getVector();
108
109 return a.nearlyParallel( b, factor);
110 }
111
117 {
118 const f32 commonDenominator = (f32)((l.end.Y - l.start.Y)*(end.X - start.X) -
119 (l.end.X - l.start.X)*(end.Y - start.Y));
120
121 if ( commonDenominator != 0.f )
122 {
123 const f32 numeratorA = (f32)((l.end.X - l.start.X)*(start.Y - l.start.Y) -
124 (l.end.Y - l.start.Y)*(start.X - l.start.X));
125
127
128 // Calculate the intersection point.
129 return vector2d<T> (
130 (T)(start.X + uA * (end.X - start.X)),
131 (T)(start.Y + uA * (end.Y - start.Y))
132 );
133 }
134 else
135 return l.start;
136 }
137
140 {
142 return false;
143
145
146 return out.isBetweenPoints( segment.start, segment.end);
147 }
148
150
159 {
160 // Uses the method given at:
161 // http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
162 const f64 commonDenominator = (f64)((l.end.Y - l.start.Y)*(end.X - start.X) -
163 (l.end.X - l.start.X)*(end.Y - start.Y));
164
165 const f64 numeratorA = (f64)((l.end.X - l.start.X)*(start.Y - l.start.Y) -
166 (l.end.Y - l.start.Y)*(start.X -l.start.X));
167
168 const f64 numeratorB = (f64)((end.X - start.X)*(start.Y - l.start.Y) -
169 (end.Y - start.Y)*(start.X -l.start.X));
170
171 if(equals(commonDenominator, 0.0))
172 {
173 // The lines are either coincident or parallel
174 // if both numerators are 0, the lines are coincident
176 {
177 // Try and find a common endpoint
178 if(l.start == start || l.end == start)
179 out = start;
180 else if(l.end == end || l.start == end)
181 out = end;
182 // now check if the two segments are disjunct
183 else if (l.start.X>start.X && l.end.X>start.X && l.start.X>end.X && l.end.X>end.X)
184 return false;
185 else if (l.start.Y>start.Y && l.end.Y>start.Y && l.start.Y>end.Y && l.end.Y>end.Y)
186 return false;
187 else if (l.start.X<start.X && l.end.X<start.X && l.start.X<end.X && l.end.X<end.X)
188 return false;
189 else if (l.start.Y<start.Y && l.end.Y<start.Y && l.start.Y<end.Y && l.end.Y<end.Y)
190 return false;
191 // else the lines are overlapping to some extent
192 else
193 {
194 // find the points which are not contributing to the
195 // common part
198 if ((start.X>l.start.X && start.X>l.end.X && start.X>end.X) || (start.Y>l.start.Y && start.Y>l.end.Y && start.Y>end.Y))
199 maxp=start;
200 else if ((end.X>l.start.X && end.X>l.end.X && end.X>start.X) || (end.Y>l.start.Y && end.Y>l.end.Y && end.Y>start.Y))
201 maxp=end;
202 else if ((l.start.X>start.X && l.start.X>l.end.X && l.start.X>end.X) || (l.start.Y>start.Y && l.start.Y>l.end.Y && l.start.Y>end.Y))
203 maxp=l.start;
204 else
205 maxp=l.end;
206 if (maxp != start && ((start.X<l.start.X && start.X<l.end.X && start.X<end.X) || (start.Y<l.start.Y && start.Y<l.end.Y && start.Y<end.Y)))
207 minp=start;
208 else if (maxp != end && ((end.X<l.start.X && end.X<l.end.X && end.X<start.X) || (end.Y<l.start.Y && end.Y<l.end.Y && end.Y<start.Y)))
209 minp=end;
210 else if (maxp != l.start && ((l.start.X<start.X && l.start.X<l.end.X && l.start.X<end.X) || (l.start.Y<start.Y && l.start.Y<l.end.Y && l.start.Y<end.Y)))
211 minp=l.start;
212 else
213 minp=l.end;
214
215 // one line is contained in the other. Pick the center
216 // of the remaining points, which overlap for sure
218 if (start != maxp && start != minp)
219 out += start;
220 if (end != maxp && end != minp)
221 out += end;
222 if (l.start != maxp && l.start != minp)
223 out += l.start;
224 if (l.end != maxp && l.end != minp)
225 out += l.end;
226 out.X = (T)(out.X/2);
227 out.Y = (T)(out.Y/2);
228 }
229
230 return true; // coincident
231 }
232
233 return false; // parallel
234 }
235
236 // Get the point of intersection on this line, checking that
237 // it is within the line segment.
240 {
241 if(uA < 0.0 || uA > 1.0)
242 return false; // Outside the line segment
243
245 if(uB < 0.0 || uB > 1.0)
246 return false; // Outside the line segment
247 }
248
249 // Calculate the intersection point.
250 out.X = (T)(start.X + uA * (end.X - start.X));
251 out.Y = (T)(start.Y + uA * (end.Y - start.Y));
252 return true;
253 }
254
256
258 {
259 T len = (T)(1.0 / getLength());
260 return vector2d<T>((end.X - start.X) * len, (end.Y - start.Y) * len);
261 }
262
264
267 {
269 vector2d<T> vect2 = l.getVector();
270 return vect.getAngleWith(vect2);
271 }
272
274
277 {
278 return ( (end.X - start.X) * (point.Y - start.Y) -
279 (point.X - start.X) * (end.Y - start.Y) );
280 }
281
283
284 bool isPointOnLine(const vector2d<T>& point) const
285 {
287 return (d == 0 && point.isBetweenPoints(start, end));
288 }
289
291
293 {
294 return point.isBetweenPoints(start, end);
295 }
296
298
302 {
303 vector2d<f64> c((f64)(point.X-start.X), (f64)(point.Y- start.Y));
304 vector2d<f64> v((f64)(end.X-start.X), (f64)(end.Y-start.Y));
305 f64 d = v.getLength();
306 if ( d == 0 ) // can't tell much when the line is just a single point
307 return start;
308 v /= d;
309 f64 t = v.dotProduct(c);
310
311 if ( checkOnlySegments )
312 {
313 if (t < 0) return vector2d<T>((T)start.X, (T)start.Y);
314 if (t > d) return vector2d<T>((T)end.X, (T)end.Y);
315 }
316
317 v *= t;
318 return vector2d<T>((T)(start.X + v.X), (T)(start.Y + v.Y));
319 }
320
325};
326
327 // partial specialization to optimize <f32> lines (avoiding casts)
328 template <>
330 {
331 const vector2df c = point - start;
332 vector2df v = end - start;
333 const f32 d = (f32)v.getLength();
334 if ( d == 0 ) // can't tell much when the line is just a single point
335 return start;
336 v /= d;
337 const f32 t = v.dotProduct(c);
338
339 if ( checkOnlySegments )
340 {
341 if (t < 0) return start;
342 if (t > d) return end;
343 }
344
345 v *= t;
346 return start + v;
347 }
348
349
354
355} // end namespace core
356} // end namespace nirt
357
358#endif
359
Axis aligned bounding box in 3d dimensional space.
Definition aabbox3d.hpp:22
aabbox3d()
Default Constructor.
Definition aabbox3d.hpp:26
2D line between two points with intersection methods.
Definition line2d.hpp:19
vector2d< T > end
End point of the line.
Definition line2d.hpp:324
vector2d< T > start
Start point of the line.
Definition line2d.hpp:322
vector2d< T > getVector() const
Get the vector of the line.
Definition line2d.hpp:66
bool intersectAsSegments(const line2d< T > &other) const
Definition line2d.hpp:70
line2d()
Default constructor for line going from (0,0) to (1,1).
Definition line2d.hpp:22
f64 getAngleWith(const line2d< T > &l) const
Get angle between this line and given line.
Definition line2d.hpp:266
void setLine(const T &xa, const T &ya, const T &xb, const T &yb)
Set this line to new line going through the two points.
Definition line2d.hpp:43
T getPointOrientation(const vector2d< T > &point) const
Tells us if the given point lies to the left, right, or on the line.
Definition line2d.hpp:276
T getLengthSQ() const
Get squared length of the line.
Definition line2d.hpp:55
T getLength() const
Get length of line.
Definition line2d.hpp:51
vector2d< T > getClosestPoint(const vector2d< T > &point, bool checkOnlySegments=true) const
Get the closest point on this line to a point.
Definition line2d.hpp:301
line2d(T xa, T ya, T xb, T yb)
Constructor for line between the two points.
Definition line2d.hpp:24
bool lineIntersectSegment(const line2d< T > &segment, vector2d< T > &out) const
Definition line2d.hpp:139
vector2d< T > fastLinesIntersection(const line2d< T > &l) const
Definition line2d.hpp:116
bool nearlyParallel(const line2d< T > &line, const T factor=relativeErrorFactor< T >()) const
Definition line2d.hpp:104
bool incidentSegments(const line2d< T > &other) const
Definition line2d.hpp:96
bool intersectWith(const line2d< T > &l, vector2d< T > &out, bool checkOnlySegments=true, bool ignoreCoincidentLines=false) const
Tests if this line intersects with another line.
Definition line2d.hpp:158
vector2d< T > getMiddle() const
Get middle of the line.
Definition line2d.hpp:59
void setLine(const line2d< T > &line)
Set this line to new line given as parameter.
Definition line2d.hpp:47
line2d(const vector2d< T > &start, const vector2d< T > &end)
Constructor for line between the two points given as vectors.
Definition line2d.hpp:26
vector2d< T > getUnitVector() const
Get unit vector of the line.
Definition line2d.hpp:257
bool isPointBetweenStartAndEnd(const vector2d< T > &point) const
Check if the given point is between start and end of the line.
Definition line2d.hpp:292
void setLine(const vector2d< T > &nstart, const vector2d< T > &nend)
Set this line to new line going through the two points.
Definition line2d.hpp:45
bool isPointOnLine(const vector2d< T > &point) const
Check if the given point is a member of the line.
Definition line2d.hpp:284
T getLength() const
Gets the length of the vector.
Definition vector2d.hpp:125
T dotProduct(const vector2d< T > &other) const
Get the dot product of this vector with another.
Definition vector2d.hpp:135
bool equals(const T a, const T b, const T tolerance=roundingError< T >())
returns if a equals b, taking possible rounding errors into account
Definition irrMath.hpp:243
As of Nirtcpp 1.6, position2d is a synonym for vector2d.
Definition vector3d.hpp:11
signed int s32
32 bit signed variable.
Definition irrTypes.hpp:72
double f64
64 bit floating point variable.
Definition irrTypes.hpp:114
float f32
32 bit floating point variable.
Definition irrTypes.hpp:110

Nirtcpp    @cppfx.xyz

Esvcpp    esv::print