UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
IncrementalMeshDijkstra.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
22template<class PointSetType>
24{
25public:
28
35
36
42 {
44
45 int32 MaxID = PointSet->MaxVertexID();
46 Queue.Initialize(MaxID);
47
48 GetPositionFunc = [this](int32 PointID) { return PointSet->GetVertex(PointID); };
49
50 ForceInitializeAllNodes();
51 }
52
53 static double InvalidDistance() { return TNumericLimits<double>::Max(); };
54
59 {
65 double StartDistance = 0;
66 };
67
68
75 {
76 ++CurrentSeedTimestamp;
77
78 for (const FSeedPoint& SeedPoint : SeedPointsIn)
79 {
80 check(SeedPointExternalIDMap.Contains(SeedPoint.ExternalID) == false);
81 int32 NewIndex = SeedPoints.Num();
82 SeedPointExternalIDMap.Add(SeedPoint.ExternalID, NewIndex);
83 SeedPoints.Add(SeedPoint);
84
85 int32 PointID = SeedPoint.PointID;
86 if (ensure(Queue.Contains(PointID) == false))
87 {
88 FGraphNode* Node = GetNodeForPointSetID(PointID);
89 Node->GraphDistance = SeedPoint.StartDistance;
90 Node->FrozenTimestamp = CurrentSeedTimestamp;
91 Node->SeedID = NewIndex;
92 Queue.Insert(PointID, float(Node->GraphDistance));
93 }
94 }
95
96
97 while (Queue.GetCount() > 0)
98 {
99 int32 NextID = Queue.Dequeue();
100 FGraphNode* Node = GetNodeForPointSetID(NextID);
101 check(Node != nullptr);
102
103 Node->FrozenTimestamp = CurrentSeedTimestamp;
104 UpdateNeighboursSparse(Node);
105 }
106 }
107
112 {
113 const FGraphNode* Node = GetNodeForPointSetID(PointID);
114 if (Node == nullptr || Node->FrozenTimestamp == InvalidFrozenTimestamp)
115 {
116 return -1;
117 }
118 int32 SeedIndex = Node->SeedID;
119 return SeedPoints[SeedIndex].ExternalID;
120 }
121
122
127 {
128 int32 MaxID = PointSet->MaxVertexID();
129 double MaxDistance = 0;
131 for (int32 PointID = 0; PointID < MaxID; PointID++)
132 {
133 if (PointSet->IsVertex(PointID))
134 {
135 double Distance = GetDistance(PointID);
137 {
139 MaxDistancePointID = PointID;
140 }
141 }
142 }
143 return MaxDistancePointID;
144 }
145
146
150 bool HasDistance(int32 PointID) const
151 {
152 const FGraphNode* Node = GetNodeForPointSetID(PointID);
153 return (Node != nullptr && Node->FrozenTimestamp != InvalidFrozenTimestamp);
154 }
155
156
160 double GetDistance(int32 PointID) const
161 {
162 const FGraphNode* Node = GetNodeForPointSetID(PointID);
163 return (Node != nullptr && Node->FrozenTimestamp != InvalidFrozenTimestamp) ? Node->GraphDistance : InvalidDistance();
164 }
165
173 bool FindPathToNearestSeed(int32 PointID, TArray<int32>& PathToSeedOut, int32 MaxLength = 100000)
174 {
175 const FGraphNode* CurNode = GetNodeForPointSetID(PointID);
176 if (CurNode == nullptr || CurNode->FrozenTimestamp == InvalidFrozenTimestamp)
177 {
178 return false;
179 }
180
181 PathToSeedOut.Reset();
182 PathToSeedOut.Add(PointID);
183
184 int32 IterCount = 0;
185 while (IterCount++ < MaxLength)
186 {
187 if (CurNode->ParentPointID == -1)
188 {
189 return true;
190 }
191
192 PathToSeedOut.Add(CurNode->ParentPointID);
193
194 CurNode = GetNodeForPointSetID(CurNode->ParentPointID);
195 if (CurNode == nullptr || CurNode->FrozenTimestamp == InvalidFrozenTimestamp)
196 {
197 PathToSeedOut.Reset();
198 return false;
199 }
200 }
201 return true;
202 }
203
204private:
205
206 // information about each active/computed point
207 struct FGraphNode
208 {
209 int32 PointID;
210 int32 ParentPointID;
211 int32 SeedID;
212 double GraphDistance;
213 int32 FrozenTimestamp;
214 };
215
216 // currently all nodes are allocated on initialization
217 TArray<FGraphNode> AllocatedNodes;
218
219 // queue of nodes to process (for dijkstra front propagation)
220 FIndexPriorityQueue Queue;
221
222 TArray<FSeedPoint> SeedPoints;
223 TMap<int32, int32> SeedPointExternalIDMap;
224
225 const int32 InvalidFrozenTimestamp = -1;
226 int32 CurrentSeedTimestamp = 0;
227
228
229 void ForceInitializeAllNodes()
230 {
231 int32 MaxID = PointSet->MaxVertexID();
232 AllocatedNodes.SetNum(MaxID);
233 for (int32 k = 0; k < MaxID; ++k)
234 {
235 FGraphNode NewNode{ k, -1, -1, InvalidDistance(), InvalidFrozenTimestamp };
236 AllocatedNodes[k] = NewNode;
237 }
238 }
239
240
241 FGraphNode* GetNodeForPointSetID(int32 PointSetID)
242 {
243 return &AllocatedNodes[PointSetID];
244 }
245
246 const FGraphNode* GetNodeForPointSetID(int32 PointSetID) const
247 {
248 return &AllocatedNodes[PointSetID];
249 }
250
251
252 // given new Distance/UV at Parent, check if any of its neighbours are in the queue,
253 // and if they are, and the new graph distance is shorter, update their queue position
254 // (this is basically the update step of Disjktras algorithm)
255 void UpdateNeighboursSparse(FGraphNode* Parent)
256 {
258 double ParentDist = Parent->GraphDistance;
259
260 for (int32 NbrPointID : PointSet->VtxVerticesItr(Parent->PointID))
261 {
262 FGraphNode* NbrNode = GetNodeForPointSetID(NbrPointID);
263 if (NbrNode->FrozenTimestamp == CurrentSeedTimestamp)
264 {
265 continue;
266 }
267
269 if (Queue.Contains(NbrPointID))
270 {
271 if (NbrDist < NbrNode->GraphDistance)
272 {
273 NbrNode->ParentPointID = Parent->PointID;
274 NbrNode->SeedID = Parent->SeedID;
275 NbrNode->GraphDistance = NbrDist;
276 Queue.Update(NbrPointID, float(NbrNode->GraphDistance));
277 }
278 }
279 else
280 {
281 if (NbrDist < NbrNode->GraphDistance)
282 {
283 NbrNode->ParentPointID = Parent->PointID;
284 NbrNode->SeedID = Parent->SeedID;
285 NbrNode->GraphDistance = NbrDist;
286 Queue.Insert(NbrPointID, float(NbrNode->GraphDistance));
287 }
288 }
289 }
290 }
291
292};
293
294
295} // end namespace UE::Geometry
296} // 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
UE::Math::TVector< double > FVector3d
Definition MathFwd.h:60
Definition Array.h:670
void SetNum(SizeType NewNum, EAllowShrinking AllowShrinking=UE::Core::Private::AllowShrinkingByDefault< AllocatorType >())
Definition Array.h:2308
Definition UnrealString.h.inl:34
Definition FunctionFwd.h:19
bool Contains(int NodeID) const
Definition IndexPriorityQueue.h:106
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
Definition IncrementalMeshDijkstra.h:24
double GetDistance(int32 PointID) const
Definition IncrementalMeshDijkstra.h:160
int32 GetSeedExternalIDForPointSetID(int32 PointID)
Definition IncrementalMeshDijkstra.h:111
static double InvalidDistance()
Definition IncrementalMeshDijkstra.h:53
TIncrementalMeshDijkstra(const PointSetType *PointSetIn)
Definition IncrementalMeshDijkstra.h:41
bool HasDistance(int32 PointID) const
Definition IncrementalMeshDijkstra.h:150
const PointSetType * PointSet
Definition IncrementalMeshDijkstra.h:27
bool FindPathToNearestSeed(int32 PointID, TArray< int32 > &PathToSeedOut, int32 MaxLength=100000)
Definition IncrementalMeshDijkstra.h:173
void AddSeedPoints(const TArray< FSeedPoint > &SeedPointsIn)
Definition IncrementalMeshDijkstra.h:74
TUniqueFunction< FVector3d(int32)> GetPositionFunc
Definition IncrementalMeshDijkstra.h:34
int32 FindMaxGraphDistancePointID() const
Definition IncrementalMeshDijkstra.h:126
Definition AdvancedWidgetsModule.cpp:13
Definition NumericLimits.h:41
Definition IncrementalMeshDijkstra.h:59
int32 PointID
Definition IncrementalMeshDijkstra.h:63
int32 ExternalID
Definition IncrementalMeshDijkstra.h:61
double StartDistance
Definition IncrementalMeshDijkstra.h:65