UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
SegmentTypes.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3// ported from geometry3Sharp Segment2
4
5#pragma once
6
7#include "Math/UnrealMath.h"
8#include "VectorTypes.h"
9#include "BoxTypes.h"
10
11namespace UE
12{
13namespace Geometry
14{
15
16using namespace UE::Math;
17
18/*
19 * 2D Line Segment stored as Center point, normalized Direction vector, and scalar Extent
20 */
21template<typename T>
23{
24public:
30 T Extent = (T)0;
31
32 TSegment2() = default;
33
37 TSegment2(const TVector2<T>& Point0, const TVector2<T>& Point1)
38 {
39 // set from endpoints
40 Center = T(.5) * (Point0 + Point1);
41 Direction = Point1 - Point0;
42 Extent = T(.5) * Normalize(Direction);
43 }
44
54
55
56
58 inline void SetStartPoint(const TVector2<T>& Point)
59 {
61 }
62
64 inline void SetEndPoint(const TVector2<T>& Point)
65 {
67 }
68
74
75
76
77
79 inline TVector2<T> StartPoint() const
80 {
81 return Center - Extent * Direction;
82 }
83
85 inline TVector2<T> EndPoint() const
86 {
87 return Center + Extent * Direction;
88 }
89
90
92 inline T Length() const
93 {
94 return (T)2 * Extent;
95 }
96
98 inline TVector2<T> GetPointFromIndex(int i) const
99 {
100 return (i == 0) ? (Center - Extent * Direction) : (Center + Extent * Direction);
101 }
102
107 {
109 }
110
116 {
117 return Center + ((T)2 * UnitParameter - (T)1) * Extent * Direction;
118 }
119
125 {
126 return T(0.5) * (T(1) + DistanceParameter / Extent);
127 }
128
132 inline T DistanceSquared(const TVector2<T>& Point) const
133 {
136 }
137
138
139
161
162
167 {
168 T t = (QueryPoint - Center).Dot(Direction);
169 if (t >= Extent)
170 {
171 return EndPoint();
172 }
173 if (t <= -Extent)
174 {
175 return StartPoint();
176 }
177 return Center + t * Direction;
178 }
179
180
184 inline T Project(const TVector2<T>& QueryPoint) const
185 {
186 return (QueryPoint - Center).Dot(Direction);
187 }
188
189
194 {
196 T Alpha = ((ProjT / Extent) + (T)1) * (T)0.5;
197 return TMathUtil<T>::Clamp(Alpha, (T)0, (T)1);
198 }
199
206 int GetSide(const TVector2<T>& QueryPoint, T Tolerance = 0)
207 {
210
211 // Note that we don't have to adjust tolerance because direction is already normalized
212 double Dist = DotPerp(AQ, Direction);
213 return (Dist > Tolerance ? -1 : (Dist < -Tolerance ? 1 : 0));
214 }
215
223 UE_DEPRECATED(5.5, "Use GetSide instead.")
224 int WhichSide(const TVector2<T>& QueryPoint, T Tolerance = 0)
225 {
226 // [TODO] subtract Center from test?
230 return (det > Tolerance ? +1 : (det < -Tolerance ? -1 : 0));
231 }
232
233
242 {
243 // see IntrLine2Line2 and IntrSegment2Segment2 for details on this code
244
245 // Special handling of degenerate segments; by convention if Direction was too small to normalize, Extent and Direction will be zero
246 bool bIsPoint = Extent == 0;
247 bool bIsPointOther = OtherSegment.Extent == 0;
248 int IsPointCount = (int)bIsPoint + (int)bIsPointOther;
249 if (IsPointCount == 2)
250 {
252 }
253 else if (IsPointCount == 1)
254 {
255 T DistSq;
256 if (bIsPoint)
257 {
258 DistSq = OtherSegment.DistanceSquared(Center);
259 }
260 else
261 {
263 }
265 }
266
269 if (TMathUtil<T>::Abs(D0DotPerpD1) > DotThresh) // Lines intersect in a single point.
270 {
271 T invD0DotPerpD1 = ((T)1) / D0DotPerpD1;
273 T diffDotPerpD1 = DotPerp(diff, OtherSegment.Direction);
278 }
279
280 // Lines are parallel.
282 T diffNDotPerpD1 = DotPerp(diff, OtherSegment.Direction);
284 {
285 // Compute the location of OtherSegment endpoints relative to our Segment
286 diff = OtherSegment.Center - Center;
287 T t1 = Direction.Dot(diff);
288 // Note: IntervalThresh not used here; this is a bit inconsistent but simplifies the code
289 // If you add it, make sure that segments that intersect without it don't end up with too-wide intersection intervals
290 T tmin = t1 - OtherSegment.Extent;
291 T tmax = t1 + OtherSegment.Extent;
293 if (extents.Overlaps(TInterval1<T>(tmin, tmax)))
294 {
295 return true;
296 }
297 return false;
298 }
299
300 // lines are parallel but not collinear
301 return false;
302 }
303
304
305
306
307
308 // 2D segment utility functions
309
310
315 {
316 T vx = EndPt.X - StartPt.X, vy = EndPt.Y - StartPt.Y;
317 T len2 = vx * vx + vy * vy;
318 T dx = QueryPt.X - StartPt.X, dy = QueryPt.Y - StartPt.Y;
319 //if (len2 < 1e-13)
320 if (len2 < Tolerance)
321 {
322 return dx * dx + dy * dy;
323 }
324 T t = (dx*vx + dy * vy);
325 if (t <= 0)
326 {
327 return dx * dx + dy * dy;
328 }
329 else if (t >= len2)
330 {
331 dx = QueryPt.X - EndPt.X;
332 dy = QueryPt.Y - EndPt.Y;
333 return dx * dx + dy * dy;
334 }
335 dx = QueryPt.X - (StartPt.X + ((t * vx) / len2));
336 dy = QueryPt.Y - (StartPt.Y + ((t * vy) / len2));
337 return dx * dx + dy * dy;
338 }
339
349 static int GetSide(const TVector2<T>& StartPt, const TVector2<T>& EndPt, const TVector2<T>& QueryPt, T Tolerance = (T)0)
350 {
353 if (Tolerance == 0)
354 {
355 return (DotPerpResult > 0 ? -1 : (DotPerpResult < 0 ? 1 : 0));
356 }
357
358 // If tolerance is nonzero, we have to use segment length to adjust it, since we use unnormalized
359 // direction in DotPerp.
360 T LengthSquared = AB.SizeSquared();
361 if (LengthSquared == 0)
362 {
363 // It's possible to get here without DotPerp underflowing, so we early out to avoid incorrectly
364 // zeroing out the tolerance below while comparing against a nonzero DotPerpResult.
365 // We could scale AB to deal with this case to try to better match behavior with the tolerance
366 // 0 case (which blindly uses DotPerp result), but it's fair to expect tolerance to affect the
367 // treatment of near-degenerate segments, so we don't bother.
368 return 0;
369 }
370 T ToleranceToUse = Tolerance * FMath::Sqrt(LengthSquared);
371
372 return (DotPerpResult > ToleranceToUse ? -1 : (DotPerpResult < -ToleranceToUse ? 1 : 0));
373 }
374
384 UE_DEPRECATED(5.5, "Use GetSide instead.")
385 static int WhichSide(const TVector2<T>& StartPt, const TVector2<T>& EndPt, const TVector2<T>& QueryPt, T Tolerance = (T)0)
386 {
388 return (det > Tolerance ? +1 : (det < -Tolerance ? -1 : 0));
389 }
390
394 static bool IsOnSegment(const TVector2<T>& A, const TVector2<T>& B, const TVector2<T>& QueryPt, T Tolerance = (T)0)
395 {
396 const TVector2<T> AB = B - A;
397
399 if (SquaredLength == 0)
400 {
401 // It's possible to underflow here (i.e. A and B are not coincident), but the distance between
402 // A and B is negligible in that case, and we'll still correctly identify B as on the segment
403 // (since we'll underflow the same way). The fact that we're slighly more tolerant near A at
404 // these scales seems ok.
405 return TVector2<T>::DistSquared(A, QueryPt) <= Tolerance * Tolerance;
406 }
407 // We can either normalize AB so that the values we get from dot products are distances,
408 // or just multiply the other side by length.
409 T DotTolerance = FMath::Sqrt(SquaredLength) * Tolerance;
410 const TVector2<T> AQ = QueryPt - A;
411 if (FMath::Abs(DotPerp(AB, AQ)) > DotTolerance)
412 {
413 // Must not be on the line
414 return false;
415 }
416
417 // Make sure it's between the endpoints
418 return (AB.Dot(AQ) >= -DotTolerance && AB.Dot(QueryPt - B) <= DotTolerance);
419 }
420
421protected:
422
423 // update segment based on new endpoints
424 inline void update_from_endpoints(const TVector2<T>& p0, const TVector2<T>& p1)
425 {
426 Center = 0.5 * (p0 + p1);
427 Direction = p1 - p0;
428 Extent = 0.5 * Normalize(Direction);
429 }
430
431};
434
435
436
437
438
439
440
441
442/*
443 * 3D Line Segment stored as Center point, normalized Direction vector, and scalar Extent
444 */
445template<typename T>
447{
448public:
454 T Extent = (T)0;
455
456 TSegment3() = default;
457
461 TSegment3(const TVector<T>& Point0, const TVector<T>& Point1)
462 {
463 // set from endpoints
464 Center = T(.5) * (Point0 + Point1);
465 Direction = Point1 - Point0;
466 Extent = T(.5) * Normalize(Direction);
467 }
468
478
479
480
482 inline void SetStartPoint(const TVector<T>& Point)
483 {
485 }
486
488 inline void SetEndPoint(const TVector<T>& Point)
489 {
491 }
492
494 void Reverse()
495 {
497 }
498
499
500
501
503 inline TVector<T> StartPoint() const
504 {
505 return Center - Extent * Direction;
506 }
507
509 inline TVector<T> EndPoint() const
510 {
511 return Center + Extent * Direction;
512 }
513
514
516 inline T Length() const
517 {
518 return (T)2 * Extent;
519 }
520
522 inline TVector<T> GetPointFromIndex(int i) const
523 {
524 return (i == 0) ? (Center - Extent * Direction) : (Center + Extent * Direction);
525 }
526
531 {
533 }
534
540 {
541 return Center + ((T)2 * UnitParameter - (T)1) * Extent * Direction;
542 }
543
549 {
550 return T(0.5) * (T(1) + DistanceParameter / Extent);
551 }
552
556 inline T DistanceSquared(const TVector<T>& Point) const
557 {
560 }
561
562
563
585
586
591 {
592 T t = (QueryPoint - Center).Dot(Direction);
593 if (t >= Extent)
594 {
595 return EndPoint();
596 }
597 if (t <= -Extent)
598 {
599 return StartPoint();
600 }
601 return Center + t * Direction;
602 }
603
604
608 inline T Project(const TVector<T>& QueryPoint) const
609 {
610 return (QueryPoint - Center).Dot(Direction);
611 }
612
613
618 {
620 T Alpha = ((ProjT / Extent) + (T)1) * (T)0.5;
621 return TMathUtil<T>::Clamp(Alpha, (T)0, (T)1);
622 }
623
628 {
629 TAxisAlignedBox3<T> Result;
630
631 for (int32 j = 0; j < 3; ++j)
632 {
633 T LowValue = Center[j] - Extent * Direction[j];
634 T HighValue = Center[j] + Extent * Direction[j];
635 Result.Min[j] = TMathUtil<T>::Min(LowValue, HighValue);
636 Result.Max[j] = TMathUtil<T>::Max(LowValue, HighValue);
637 }
638 return Result;
639 }
640
645 {
647 Result.Expand(SegmentRadius);
648 return Result;
649 }
650
651protected:
652
653 // update segment based on new endpoints
654 inline void update_from_endpoints(const TVector<T>& p0, const TVector<T>& p1)
655 {
656 Center = 0.5 * (p0 + p1);
657 Direction = p1 - p0;
658 Extent = 0.5 * Normalize(Direction);
659 }
660
661};
664
665} // end namespace UE::Geometry
666} // end namespace UE
667
#define UE_DEPRECATED(Version, Message)
Definition CoreMiscDefines.h:302
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
Definition MathUtil.h:150
static RealType Clamp(const RealType Value, const RealType ClampMin, const RealType ClampMax)
Definition MathUtil.h:222
static RealType Max(const RealType A, const RealType B)
Definition MathUtil.h:246
static RealType Abs(const RealType Value)
Definition MathUtil.h:215
static RealType Min(const RealType A, const RealType B)
Definition MathUtil.h:271
TSegment2< float > FSegment2f
Definition SegmentTypes.h:432
TSegment3< float > FSegment3f
Definition SegmentTypes.h:662
constexpr T DotPerp(const UE::Math::TVector2< T > &V1, const UE::Math::TVector2< T > &V2)
Definition VectorTypes.h:19
T DistanceSquared(const UE::Math::TVector2< T > &V1, const UE::Math::TVector2< T > &V2)
Definition VectorTypes.h:82
T SquaredLength(const UE::Math::TVector< T > &V)
Definition VectorTypes.h:154
TSegment2< double > FSegment2d
Definition SegmentTypes.h:433
T Orient(const UE::Math::TVector2< T > &A, const UE::Math::TVector2< T > &B, const UE::Math::TVector2< T > &C)
Definition VectorTypes.h:33
TSegment3< double > FSegment3d
Definition SegmentTypes.h:663
T Normalize(UE::Math::TVector2< T > &Vector, const T Epsilon=0)
Definition VectorTypes.h:46
Definition Sphere.cpp:10
Definition AdvancedWidgetsModule.cpp:13
Definition BoxTypes.h:247
Definition BoxTypes.h:19
Definition SegmentTypes.h:23
TVector2< T > EndPoint() const
Definition SegmentTypes.h:85
T ConvertToUnitRange(T DistanceParameter) const
Definition SegmentTypes.h:124
TVector2< T > PointBetween(T UnitParameter) const
Definition SegmentTypes.h:115
T Project(const TVector2< T > &QueryPoint) const
Definition SegmentTypes.h:184
static bool IsOnSegment(const TVector2< T > &A, const TVector2< T > &B, const TVector2< T > &QueryPt, T Tolerance=(T) 0)
Definition SegmentTypes.h:394
T Extent
Definition SegmentTypes.h:30
TVector2< T > StartPoint() const
Definition SegmentTypes.h:79
bool Intersects(const TSegment2< T > &OtherSegment, T DotThresh=TMathUtil< T >::Epsilon, T IntervalThresh=0) const
Definition SegmentTypes.h:241
TVector2< T > Direction
Definition SegmentTypes.h:28
static T FastDistanceSquared(const TVector2< T > &StartPt, const TVector2< T > &EndPt, const TVector2< T > &QueryPt, T Tolerance=TMathUtil< T >::Epsilon)
Definition SegmentTypes.h:314
void Reverse()
Definition SegmentTypes.h:70
int GetSide(const TVector2< T > &QueryPoint, T Tolerance=0)
Definition SegmentTypes.h:206
void update_from_endpoints(const TVector2< T > &p0, const TVector2< T > &p1)
Definition SegmentTypes.h:424
static int GetSide(const TVector2< T > &StartPt, const TVector2< T > &EndPt, const TVector2< T > &QueryPt, T Tolerance=(T) 0)
Definition SegmentTypes.h:349
int WhichSide(const TVector2< T > &QueryPoint, T Tolerance=0)
Definition SegmentTypes.h:224
TVector2< T > NearestPoint(const TVector2< T > &QueryPoint) const
Definition SegmentTypes.h:166
T DistanceSquared(const TVector2< T > &Point, T &DistParameterOut) const
Definition SegmentTypes.h:145
TVector2< T > Center
Definition SegmentTypes.h:26
T DistanceSquared(const TVector2< T > &Point) const
Definition SegmentTypes.h:132
TVector2< T > PointAt(T DistanceParameter) const
Definition SegmentTypes.h:106
TSegment2(const TVector2< T > &CenterIn, const TVector2< T > &DirectionIn, T ExtentIn)
Definition SegmentTypes.h:48
void SetStartPoint(const TVector2< T > &Point)
Definition SegmentTypes.h:58
T ProjectUnitRange(const TVector2< T > &QueryPoint) const
Definition SegmentTypes.h:193
TVector2< T > GetPointFromIndex(int i) const
Definition SegmentTypes.h:98
TSegment2(const TVector2< T > &Point0, const TVector2< T > &Point1)
Definition SegmentTypes.h:37
void SetEndPoint(const TVector2< T > &Point)
Definition SegmentTypes.h:64
T Length() const
Definition SegmentTypes.h:92
Definition SegmentTypes.h:447
TVector< T > PointAt(T DistanceParameter) const
Definition SegmentTypes.h:530
void SetStartPoint(const TVector< T > &Point)
Definition SegmentTypes.h:482
TSegment3(const TVector< T > &CenterIn, const TVector< T > &DirectionIn, T ExtentIn)
Definition SegmentTypes.h:472
TSegment3(const TVector< T > &Point0, const TVector< T > &Point1)
Definition SegmentTypes.h:461
TAxisAlignedBox3< T > GetBounds(T SegmentRadius) const
Definition SegmentTypes.h:644
TVector< T > PointBetween(T UnitParameter) const
Definition SegmentTypes.h:539
T ProjectUnitRange(const TVector< T > &QueryPoint) const
Definition SegmentTypes.h:617
TVector< T > GetPointFromIndex(int i) const
Definition SegmentTypes.h:522
void Reverse()
Definition SegmentTypes.h:494
void SetEndPoint(const TVector< T > &Point)
Definition SegmentTypes.h:488
T Extent
Definition SegmentTypes.h:454
T ConvertToUnitRange(T DistanceParameter) const
Definition SegmentTypes.h:548
TVector< T > EndPoint() const
Definition SegmentTypes.h:509
void update_from_endpoints(const TVector< T > &p0, const TVector< T > &p1)
Definition SegmentTypes.h:654
T Length() const
Definition SegmentTypes.h:516
T Project(const TVector< T > &QueryPoint) const
Definition SegmentTypes.h:608
T DistanceSquared(const TVector< T > &Point) const
Definition SegmentTypes.h:556
TAxisAlignedBox3< T > GetBounds() const
Definition SegmentTypes.h:627
TVector< T > StartPoint() const
Definition SegmentTypes.h:503
TVector< T > NearestPoint(const TVector< T > &QueryPoint) const
Definition SegmentTypes.h:590
T DistanceSquared(const TVector< T > &Point, T &DistParameterOut) const
Definition SegmentTypes.h:569
TVector< T > Center
Definition SegmentTypes.h:450
TVector< T > Direction
Definition SegmentTypes.h:452
Definition Vector2D.h:38
static TVector2< T > UnitX()
Definition Vector2D.h:81
UE_FORCEINLINE_HINT T SquaredLength() const
Definition Vector2D.h:516
static UE_FORCEINLINE_HINT T DistSquared(const TVector2< T > &V1, const TVector2< T > &V2)
Definition Vector2D.h:935
T Dot(const TVector2< T > &V2) const
Definition Vector2D.h:1123
static TVector2< T > Zero()
Definition Vector2D.h:79
T SizeSquared() const
Definition Vector2D.h:1117
Definition Vector.h:51
static TVector< T > UnitX()
Definition Vector.h:118
static TVector< T > Zero()
Definition Vector.h:112