UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
MeshDijkstra.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "VectorTypes.h"
6#include "MatrixTypes.h"
7#include "BoxTypes.h"
8#include "FrameTypes.h"
10#include "Util/DynamicVector.h"
11
12namespace UE
13{
14namespace Geometry
15{
16
23template<class PointSetType>
25{
26public:
29
36
42
49
50
56 {
58
59 int32 MaxID = PointSet->MaxVertexID();
60 Queue.Initialize(MaxID);
61
62 MaxGraphDistance = 0.0;
63 MaxGraphDistancePointID = -1;
64
65 GetPositionFunc = [this](int32 PointID) { return PointSet->GetVertex(PointID); };
67 GetWeightedDistanceFunc = [](int32, int32, int32, double Distance) { return Distance; };
68 }
69
71 static double InvalidDistance() { return TNumericLimits<double>::Max(); };
72
76 void Reset()
77 {
78 IDToNodeIndexMap.Reset();
79 AllocatedNodes.Clear();
80 Queue.Clear(false);
81 MaxGraphDistance = 0.0;
82 MaxGraphDistancePointID = -1;
83 }
84
85
90 {
96 double StartDistance = 0;
97 };
98
99
106 {
107 MaxGraphDistance = 0.0f;
108 MaxGraphDistancePointID = -1;
109
110 SeedPoints.Reset();
111 for (const FSeedPoint& SeedPoint : SeedPointsIn)
112 {
113 int32 NewIndex = SeedPoints.Num();
114 SeedPoints.Add(SeedPoint);
115
116 int32 PointID = SeedPoint.PointID;
117 if (ensure(Queue.Contains(PointID) == false))
118 {
119 FGraphNode* Node = GetNodeForPointSetID(PointID, true);
120 Node->GraphDistance = SeedPoint.StartDistance;
121 Node->bFrozen = true;
122 Node->SeedPointID = NewIndex;
123 Queue.Insert(PointID, float(Node->GraphDistance));
124 }
125 }
126
127 while (Queue.GetCount() > 0)
128 {
129 int32 NextID = Queue.Dequeue();
130 FGraphNode* Node = GetNodeForPointSetID(NextID, false);
131 check(Node != nullptr);
132
133 MaxGraphDistance = TMathUtil<double>::Max(Node->GraphDistance, MaxGraphDistance);
134 if (MaxGraphDistance > ComputeToMaxDistanceIn)
135 {
136 return;
137 }
138
139 Node->bFrozen = true;
140 MaxGraphDistancePointID = Node->PointID;
141 UpdateNeighboursSparse(Node);
142 }
143 }
144
145
146
163
164
165
174 {
175 MaxGraphDistance = 0.0f;
176 MaxGraphDistancePointID = -1;
177
178 SeedPoints.Reset();
179 for (const FSeedPoint& SeedPoint : SeedPointsIn)
180 {
181 int32 NewIndex = SeedPoints.Num();
182 SeedPoints.Add(SeedPoint);
183
184 int32 PointID = SeedPoint.PointID;
185 if (ensure(Queue.Contains(PointID) == false))
186 {
187 FGraphNode* Node = GetNodeForPointSetID(PointID, true);
188 Node->GraphDistance = SeedPoint.StartDistance;
189 Node->bFrozen = true;
190 Node->SeedPointID = NewIndex;
191 Queue.Insert(PointID, (float)Node->GraphDistance);
192 }
193 }
194
195 while (Queue.GetCount() > 0)
196 {
197 int32 NextID = Queue.Dequeue();
198 FGraphNode* Node = GetNodeForPointSetID(NextID, false);
199 check(Node != nullptr);
200
201 MaxGraphDistance = TMathUtil<double>::Max(Node->GraphDistance, MaxGraphDistance);
202 if (MaxGraphDistance > ComputeToMaxDistanceIn)
203 {
204 return false;
205 }
206
207 Node->bFrozen = true;
208 MaxGraphDistancePointID = Node->PointID;
209
210 if (Node->PointID == TargetPointID)
211 {
212 return true;
213 }
214
215 UpdateNeighboursSparse(Node);
216 }
217
218 return false;
219 }
220
221
222
223
227 double GetMaxGraphDistance() const
228 {
229 return MaxGraphDistance;
230 }
231
232
237 {
238 return MaxGraphDistancePointID;
239 }
240
241
246 {
247 const FGraphNode* Node = GetNodeForPointSetID(PointID);
248 if (Node == nullptr || Node->bFrozen == false)
249 {
250 return -1;
251 }
252 int32 SeedIndex = Node->SeedPointID;
253 return SeedPoints[SeedIndex].ExternalID;
254 }
255
256
260 bool HasDistance(int32 PointID) const
261 {
262 const FGraphNode* Node = GetNodeForPointSetID(PointID);
263 return (Node != nullptr && Node->bFrozen);
264 }
265
266
270 double GetDistance(int32 PointID) const
271 {
272 const FGraphNode* Node = GetNodeForPointSetID(PointID);
273 return (Node != nullptr && Node->bFrozen) ? Node->GraphDistance : InvalidDistance();
274 }
275
283 bool FindPathToNearestSeed(int32 PointID, TArray<int32>& PathToSeedOut, int32 MaxLength = 100000)
284 {
285 const FGraphNode* CurNode = GetNodeForPointSetID(PointID);
286 if (CurNode == nullptr || CurNode->bFrozen == false)
287 {
288 return false;
289 }
290
291 PathToSeedOut.Reset();
292 PathToSeedOut.Add(PointID);
293
294 int32 IterCount = 0;
295 while (IterCount++ < MaxLength)
296 {
297 if (CurNode->ParentPointID == -1)
298 {
299 return true;
300 }
301
302 PathToSeedOut.Add(CurNode->ParentPointID);
303
304 CurNode = GetNodeForPointSetID(CurNode->ParentPointID);
305 if (CurNode == nullptr || CurNode->bFrozen == false)
306 {
307 PathToSeedOut.Reset();
308 return false;
309 }
310 }
311 return true;
312 }
313
314private:
315
316 // information about each active/computed point
317 struct FGraphNode
318 {
319 int32 PointID;
320 int32 ParentPointID;
321 int32 SeedPointID;
322 double GraphDistance;
323 bool bFrozen;
324 };
325
326 // To avoid constructing FGraphNode for all input points (because we are computing a "local" param),
327 // we only allocate on demand, and then store a sparse mapping in IDToNodeIndexMap
328 TMap<int32, int32> IDToNodeIndexMap;
329 TDynamicVector<FGraphNode> AllocatedNodes;
330
331 // queue of nodes to process (for dijkstra front propagation)
332 FIndexPriorityQueue Queue;
333
334 TArray<FSeedPoint> SeedPoints;
335
336 // max distances encountered during last compute
337 double MaxGraphDistance;
338
339 int32 MaxGraphDistancePointID;
340
341 FGraphNode* GetNodeForPointSetID(int32 PointSetID, bool bCreateIfMissing)
342 {
343 const int32* AllocatedIndex = IDToNodeIndexMap.Find(PointSetID);
344 if (AllocatedIndex == nullptr)
345 {
346 if (bCreateIfMissing)
347 {
348 FGraphNode NewNode{ PointSetID, -1, 0, false };
349 int32 NewIndex = AllocatedNodes.Num();
350 AllocatedNodes.Add(NewNode);
351 IDToNodeIndexMap.Add(PointSetID, NewIndex);
352 return &AllocatedNodes[NewIndex];
353 }
354 else
355 {
356 return nullptr;
357 }
358 }
359 else
360 {
361 return &AllocatedNodes[*AllocatedIndex];
362 }
363 }
364
365
366 const FGraphNode* GetNodeForPointSetID(int32 PointSetID) const
367 {
368 const int32* AllocatedIndex = IDToNodeIndexMap.Find(PointSetID);
369 return (AllocatedIndex != nullptr) ? &AllocatedNodes[*AllocatedIndex] : nullptr;
370 }
371
372
373 // given new Distance/UV at Parent, check if any of its neighbours are in the queue,
374 // and if they are, and the new graph distance is shorter, update their queue position
375 // (this is basically the update step of Disjktras algorithm)
376 void UpdateNeighboursSparse(FGraphNode* Parent)
377 {
379 double ParentDist = Parent->GraphDistance;
380
381 for (int32 NbrPointID : PointSet->VtxVerticesItr(Parent->PointID))
382 {
383 FGraphNode* NbrNode = GetNodeForPointSetID(NbrPointID, true);
384 if (NbrNode->bFrozen)
385 {
386 continue;
387 }
388
391 {
392 int SeedPointID = SeedPoints[Parent->SeedPointID].PointID;
394 }
395 double NbrDist = ParentDist + LocalDist;
396
397 if (Queue.Contains(NbrPointID))
398 {
399 if (NbrDist < NbrNode->GraphDistance)
400 {
401 NbrNode->ParentPointID = Parent->PointID;
402 NbrNode->GraphDistance = NbrDist;
403 NbrNode->SeedPointID = Parent->SeedPointID;
404 Queue.Update(NbrPointID, float(NbrNode->GraphDistance));
405 }
406 }
407 else
408 {
409 NbrNode->ParentPointID = Parent->PointID;
410 NbrNode->GraphDistance = NbrDist;
411 NbrNode->SeedPointID = Parent->SeedPointID;
412 Queue.Insert(NbrPointID, float(NbrNode->GraphDistance));
413 }
414 }
415 }
416
417};
418
419
420} // end namespace UE::Geometry
421} // end namespace UE
#define check(expr)
Definition AssertionMacros.h:314
#define ensure( InExpression)
Definition AssertionMacros.h:464
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
#define X(Name, Desc)
Definition FormatStringSan.h:47
UE::Math::TVector< double > FVector3d
Definition MathFwd.h:60
Definition Array.h:670
UE_REWRITE SizeType Num() const
Definition Array.h:1144
Definition UnrealString.h.inl:34
static RealType Max(const RealType A, const RealType B)
Definition MathUtil.h:246
Definition FunctionFwd.h:19
bool Contains(int NodeID) const
Definition IndexPriorityQueue.h:106
void Clear(bool bFreeMemory=true)
Definition IndexPriorityQueue.h:79
int GetCount() const
Definition IndexPriorityQueue.h:88
void Insert(int NodeID, float priority)
Definition IndexPriorityQueue.h:121
void Initialize(int MaxNodeID)
Definition IndexPriorityQueue.h:67
int Dequeue()
Definition IndexPriorityQueue.h:142
void Clear()
Definition DynamicVector.h:578
Definition MeshDijkstra.h:25
TMeshDijkstra(const PointSetType *PointSetIn)
Definition MeshDijkstra.h:55
int32 GetSeedExternalIDForPointSetID(int32 PointID)
Definition MeshDijkstra.h:245
const PointSetType * PointSet
Definition MeshDijkstra.h:28
bool HasDistance(int32 PointID) const
Definition MeshDijkstra.h:260
int32 GetMaxGraphDistancePointID() const
Definition MeshDijkstra.h:236
TUniqueFunction< double(int32 FromVID, int32 ToVID, int32 SeedVID, double EuclideanDistance)> GetWeightedDistanceFunc
Definition MeshDijkstra.h:48
bool FindPathToNearestSeed(int32 PointID, TArray< int32 > &PathToSeedOut, int32 MaxLength=100000)
Definition MeshDijkstra.h:283
double GetMaxGraphDistance() const
Definition MeshDijkstra.h:227
void ComputeToMaxDistance(const TArray< FSeedPoint > &SeedPointsIn, double ComputeToMaxDistanceIn)
Definition MeshDijkstra.h:105
bool ComputeToTargetPoint(const TArray< FSeedPoint > &SeedPointsIn, int32 TargetPointID, double ComputeToMaxDistanceIn=TNumericLimits< double >::Max())
Definition MeshDijkstra.h:173
double GetDistance(int32 PointID) const
Definition MeshDijkstra.h:270
bool bEnableDistanceWeighting
Definition MeshDijkstra.h:41
void ComputeToMaxDistance(const TArray< FVector2d > &SeedPointsIn, double ComputeToMaxDistanceIn)
Definition MeshDijkstra.h:152
static double InvalidDistance()
Definition MeshDijkstra.h:71
TUniqueFunction< FVector3d(int32)> GetPositionFunc
Definition MeshDijkstra.h:35
void Reset()
Definition MeshDijkstra.h:76
Definition AdvancedWidgetsModule.cpp:13
Definition NumericLimits.h:41
Definition MeshDijkstra.h:90
double StartDistance
Definition MeshDijkstra.h:96
int32 PointID
Definition MeshDijkstra.h:94
int32 ExternalID
Definition MeshDijkstra.h:92