Duckcpp 2.1.0
Duckcpp 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 duckcpp/duckcpp.hpp
4
5#ifndef DCPP_LINE_2D_HPP_INCLUDED
6#define DCPP_LINE_2D_HPP_INCLUDED
7
8#include <duckcpp/core/engine/dcpp_types.hpp>
9#include <duckcpp/core/engine/vector2d.hpp>
10
11namespace dcpp
12{
13namespace nub
14{
15template <class T>
16class line2d;
17
22
24template <class T>
25class line2d
26{
27 public:
29 line2d() : start(0,0), end(1,1) {}
31 line2d(T xa, T ya, T xb, T yb) : start(xa, ya), end(xb, yb) {}
34
35 // operators
36
37 line2d<T> operator+(const vector2d<T>& point) const { return line2d<T>(start + point, end + point); }
38 line2d<T>& operator+=(const vector2d<T>& point) { start += point; end += point; return *this; }
39
40 line2d<T> operator-(const vector2d<T>& point) const { return line2d<T>(start - point, end - point); }
41 line2d<T>& operator-=(const vector2d<T>& point) { start -= point; end -= point; return *this; }
42
43 bool operator==(const line2d<T>& other) const
44 { return (start==other.start && end==other.end) || (end==other.start && start==other.end);}
45 bool operator!=(const line2d<T>& other) const
46 { return !(start==other.start && end==other.end) || (end==other.start && start==other.end);}
47
48 // functions
50 void setLine(const T& xa, const T& ya, const T& xb, const T& yb){start.set(xa, ya); end.set(xb, yb);}
52 void setLine(const vector2d<T>& nstart, const vector2d<T>& nend){start.set(nstart); end.set(nend);}
54 void setLine(const line2d<T>& line){start.set(line.start); end.set(line.end);}
55
57
58 T getLength() const { return start.getDistanceFrom(end); }
59
61
62 T getLengthSQ() const { return start.getDistanceFromSQ(end); }
63
65
67 {
68 return (start + end)/(T)2;
69 }
70
72
73 vector2d<T> getVector() const { return vector2d<T>( end.X - start.X, end.Y - start.Y); }
74
78 {
79 // Taken from:
80 // http://www.geeksforgeeks.org/check-if-two-given-line-segments-intersect/
81
82 // Find the four orientations needed for general and
83 // special cases
84 dcpp::int32_kt o1 = start.checkOrientation( end, other.start);
85 dcpp::int32_kt o2 = start.checkOrientation( end, other.end);
86 dcpp::int32_kt o3 = other.start.checkOrientation( other.end, start);
87 dcpp::int32_kt o4 = other.start.checkOrientation( other.end, end);
88
89 // General case
90 if (o1 != o2 && o3 != o4)
91 return true;
92
93 // Special Cases to check if segments are coolinear
94 if (o1 == 0 && other.start.isBetweenPoints( start, end)) return true;
95 if (o2 == 0 && other.end.isBetweenPoints( start, end)) return true;
96 if (o3 == 0 && start.isBetweenPoints( other.start, other.end)) return true;
97 if (o4 == 0 && end.isBetweenPoints( other.start, other.end)) return true;
98
99 return false; // Doesn't fall in any of the above cases
100 }
101
103 bool incidentSegments( const line2d<T>& other) const
104 {
105 return
106 start.checkOrientation( end, other.start) != start.checkOrientation( end, other.end)
107 && other.start.checkOrientation( other.end, start) != other.start.checkOrientation( other.end, end);
108 }
109
112 {
113 const vector2d<T> a = getVector();
114 const vector2d<T> b = line.getVector();
115
116 return a.nearlyParallel( b, factor);
117 }
118
124 {
125 const dcpp::float32_kt commonDenominator = (dcpp::float32_kt)((l.end.Y - l.start.Y)*(end.X - start.X) -
126 (l.end.X - l.start.X)*(end.Y - start.Y));
127
128 if ( commonDenominator != 0.f )
129 {
130 const dcpp::float32_kt numeratorA = (dcpp::float32_kt)((l.end.X - l.start.X)*(start.Y - l.start.Y) -
131 (l.end.Y - l.start.Y)*(start.X - l.start.X));
132
134
135 // Calculate the intersection point.
136 return vector2d<T> (
137 (T)(start.X + uA * (end.X - start.X)),
138 (T)(start.Y + uA * (end.Y - start.Y))
139 );
140 }
141 else
142 return l.start;
143 }
144
147 {
149 return false;
150
152
153 return out.isBetweenPoints( segment.start, segment.end);
154 }
155
157
166 {
167 // Uses the method given at:
168 // http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
169 const dcpp::float64_kt commonDenominator = (dcpp::float64_kt)((l.end.Y - l.start.Y)*(end.X - start.X) -
170 (l.end.X - l.start.X)*(end.Y - start.Y));
171
172 const dcpp::float64_kt numeratorA = (dcpp::float64_kt)((l.end.X - l.start.X)*(start.Y - l.start.Y) -
173 (l.end.Y - l.start.Y)*(start.X -l.start.X));
174
175 const dcpp::float64_kt numeratorB = (dcpp::float64_kt)((end.X - start.X)*(start.Y - l.start.Y) -
176 (end.Y - start.Y)*(start.X -l.start.X));
177
178 if(equals(commonDenominator, 0.0))
179 {
180 // The lines are either coincident or parallel
181 // if both numerators are 0, the lines are coincident
183 {
184 // Try and find a common endpoint
185 if(l.start == start || l.end == start)
186 out = start;
187 else if(l.end == end || l.start == end)
188 out = end;
189 // now check if the two segments are disjunct
190 else if (l.start.X>start.X && l.end.X>start.X && l.start.X>end.X && l.end.X>end.X)
191 return false;
192 else if (l.start.Y>start.Y && l.end.Y>start.Y && l.start.Y>end.Y && l.end.Y>end.Y)
193 return false;
194 else if (l.start.X<start.X && l.end.X<start.X && l.start.X<end.X && l.end.X<end.X)
195 return false;
196 else if (l.start.Y<start.Y && l.end.Y<start.Y && l.start.Y<end.Y && l.end.Y<end.Y)
197 return false;
198 // else the lines are overlapping to some extent
199 else
200 {
201 // find the points which are not contributing to the
202 // common part
205 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))
206 maxp=start;
207 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))
208 maxp=end;
209 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))
210 maxp=l.start;
211 else
212 maxp=l.end;
213 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)))
214 minp=start;
215 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)))
216 minp=end;
217 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)))
218 minp=l.start;
219 else
220 minp=l.end;
221
222 // one line is contained in the other. Pick the center
223 // of the remaining points, which overlap for sure
225 if (start != maxp && start != minp)
226 out += start;
227 if (end != maxp && end != minp)
228 out += end;
229 if (l.start != maxp && l.start != minp)
230 out += l.start;
231 if (l.end != maxp && l.end != minp)
232 out += l.end;
233 out.X = (T)(out.X/2);
234 out.Y = (T)(out.Y/2);
235 }
236
237 return true; // coincident
238 }
239
240 return false; // parallel
241 }
242
243 // Get the point of intersection on this line, checking that
244 // it is within the line segment.
247 {
248 if(uA < 0.0 || uA > 1.0)
249 return false; // Outside the line segment
250
252 if(uB < 0.0 || uB > 1.0)
253 return false; // Outside the line segment
254 }
255
256 // Calculate the intersection point.
257 out.X = (T)(start.X + uA * (end.X - start.X));
258 out.Y = (T)(start.Y + uA * (end.Y - start.Y));
259 return true;
260 }
261
263
265 {
266 T len = (T)(1.0 / getLength());
267 return vector2d<T>((end.X - start.X) * len, (end.Y - start.Y) * len);
268 }
269
271
274 {
276 vector2d<T> vect2 = l.getVector();
277 return vect.getAngleWith(vect2);
278 }
279
281
284 {
285 return ( (end.X - start.X) * (point.Y - start.Y) -
286 (point.X - start.X) * (end.Y - start.Y) );
287 }
288
290
291 bool isPointOnLine(const vector2d<T>& point) const
292 {
294 return (d == 0 && point.isBetweenPoints(start, end));
295 }
296
298
300 {
301 return point.isBetweenPoints(start, end);
302 }
303
305
309 {
312 dcpp::float64_kt d = v.getLength();
313 if ( d == 0 ) // can't tell much when the line is just a single point
314 return start;
315 v /= d;
316 dcpp::float64_kt t = v.dotProduct(c);
317
318 if ( checkOnlySegments )
319 {
320 if (t < 0) return vector2d<T>((T)start.X, (T)start.Y);
321 if (t > d) return vector2d<T>((T)end.X, (T)end.Y);
322 }
323
324 v *= t;
325 return vector2d<T>((T)(start.X + v.X), (T)(start.Y + v.Y));
326 }
327
332};
333
334// partial specialization to optimize <dcpp::float32_kt> lines (avoiding casts)
335template <>
337{
338 const vector2df c = point - start;
339 vector2df v = end - start;
341 if ( d == 0 ) // can't tell much when the line is just a single point
342 return start;
343 v /= d;
344 const dcpp::float32_kt t = v.dotProduct(c);
345
346 if ( checkOnlySegments )
347 {
348 if (t < 0) return start;
349 if (t > d) return end;
350 }
351
352 v *= t;
353 return start + v;
354}
355
356} // end namespace nub
357} // end namespace dcpp
358
359#endif
360
Axis aligned bounding box in 3d dimensional space.
Definition aabbox3d.hpp:22
2D line between two points with intersection methods.
Definition line2d.hpp:26
bool lineIntersectSegment(const line2d< T > &segment, vector2d< T > &out) const
Definition line2d.hpp:146
line2d(T xa, T ya, T xb, T yb)
Constructor for line between the two points.
Definition line2d.hpp:31
T getLength() const
Get length of line.
Definition line2d.hpp:58
bool incidentSegments(const line2d< T > &other) const
Definition line2d.hpp:103
vector2d< T > getClosestPoint(const vector2d< T > &point, bool checkOnlySegments=true) const
Get the closest point on this line to a point.
Definition line2d.hpp:308
vector2d< T > getMiddle() const
Get middle of the line.
Definition line2d.hpp:66
void setLine(const line2d< T > &line)
Set this line to new line given as parameter.
Definition line2d.hpp:54
vector2d< T > getVector() const
Get the vector of the line.
Definition line2d.hpp:73
bool nearlyParallel(const line2d< T > &line, const T factor=relativeErrorFactor< T >()) const
Definition line2d.hpp:111
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:283
T getLengthSQ() const
Get squared length of the line.
Definition line2d.hpp:62
bool isPointOnLine(const vector2d< T > &point) const
Check if the given point is a member of the line.
Definition line2d.hpp:291
vector2d< T > start
Start point of the line.
Definition line2d.hpp:329
dcpp::float64_kt getAngleWith(const line2d< T > &l) const
Get angle between this line and given line.
Definition line2d.hpp:273
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:165
void setLine(const vector2d< T > &nstart, const vector2d< T > &nend)
Set this line to new line going through the two points.
Definition line2d.hpp:52
vector2d< T > getUnitVector() const
Get unit vector of the line.
Definition line2d.hpp:264
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:50
vector2d< T > end
End point of the line.
Definition line2d.hpp:331
vector2d< T > fastLinesIntersection(const line2d< T > &l) const
Definition line2d.hpp:123
line2d()
Default constructor for line going from (0,0) to (1,1).
Definition line2d.hpp:29
bool intersectAsSegments(const line2d< T > &other) const
Definition line2d.hpp:77
bool isPointBetweenStartAndEnd(const vector2d< T > &point) const
Check if the given point is between start and end of the line.
Definition line2d.hpp:299
line2d(const vector2d< T > &start, const vector2d< T > &end)
Constructor for line between the two points given as vectors.
Definition line2d.hpp:33
2d vector template class with lots of operators and methods.
Definition vector2d.hpp:22
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 Duckcpp 1.6, position2d is a synonym for vector2d.
Definition shared_device.hpp:34
double float64_kt
64 bit floating point variable.
Definition irrTypes.hpp:112
float float32_kt
32 bit floating point variable.
Definition irrTypes.hpp:108
signed int int32_kt
32 bit signed variable.
Definition irrTypes.hpp:72

Duckcpp    @cppfx.xyz