UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
VertexConnectedComponents.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "BoxTypes.h"
6#include "IndexTypes.h"
9
10namespace UE
11{
12namespace Geometry
13{
14
23{
24public:
26 {
27 Init(0);
28 }
29
31 {
32 Init(MaxVertexID);
33 }
34
35 void Init(int32 MaxVertexID)
36 {
37 DisjointSet.Init(MaxVertexID);
38 }
39
40 template<typename TriangleMeshType>
42 {
43 DisjointSet.Init(Mesh.MaxVertexID(), [&Mesh](int32 VID) -> bool { return Mesh.IsVertex(VID); });
44 }
45
46 template<typename TriangleMeshType>
48 {
49 for (int32 TID = 0; TID < Mesh.MaxTriangleID(); TID++)
50 {
51 if (Mesh.IsTriangle(TID))
52 {
53 FIndex3i Triangle = Mesh.GetTriangle(TID);
56 }
57 }
58 }
59
60 template<typename TriangleType>
62 {
63 for (const TriangleType& Triangle : Triangles)
64 {
67 }
68 }
69
70 // Note for meshes that may have floating (unreferenced) vertices, using a KeepSizeThreshold > 1 after calling ConnectTriangles will ensure the unreferenced vertices are skipped
71 template<typename TriangleMeshType>
73 {
75 for (int32 VID = 0; VID < Mesh.MaxVertexID(); VID++)
76 {
77 if (!Mesh.IsVertex(VID))
78 {
79 continue;
80 }
81 int32 SetID = DisjointSet.Find(VID);
83 {
84 continue;
85 }
86
87 int32 MaxSetSize = Mesh.VertexCount();
88 FVector3d Pt = Mesh.GetVertex(VID);
89 VertexHash.EnumeratePointsInBall(Pt, CloseVertexThreshold, [&Mesh, Pt](int32 OtherVID)
90 {
91 return DistanceSquared(Pt, Mesh.GetVertex(OtherVID));
92 }, [this, SetID, MaxSetSize](const int32& NbrVID, double DistSq)
93 {
95 return DisjointSet.Sizes[UnionSetID] < MaxSetSize; // stop iterating if all vertices are in the same component
96 });
97 VertexHash.InsertPointUnsafe(VID, Pt);
98 }
99 }
100
101 // TODO: support more overlap strategies, currently just uses AABB
102 // Note this merges components based on overlap of their bounding boxes as computed *before* any merges; multiple passes may merge additional components
103 template<typename TriangleMeshType>
105 {
107 for (int32 VID = 0; VID < Mesh.MaxVertexID(); VID++)
108 {
109 if (!Mesh.IsVertex(VID))
110 {
111 continue;
112 }
113 int32 SetID = DisjointSet.Find(VID);
115 {
116 continue;
117 }
118 FVector3d Pt = Mesh.GetVertex(VID);
119 FAxisAlignedBox3d& Bounds = SetIDToBounds.FindOrAdd(SetID, FAxisAlignedBox3d::Empty());
120 Bounds.Contain(Pt);
121 }
122 // For each component's bounding box
123 for (auto It = SetIDToBounds.CreateConstIterator(); It; ++It)
124 {
125 auto NextIt = It;
126 // Iterate over the subsequent component bounding boxes
127 ++NextIt;
128 for (; NextIt; ++NextIt)
129 {
130 // Union the two components if their bounds overlap
131 if (It.Value().Intersects(NextIt.Value()))
132 {
133 DisjointSet.Union(It.Key(), NextIt.Key());
134 }
135 }
136 }
137 }
138
139 template<typename TriangleMeshType>
141 {
143 for (int32 VID = 0; VID < Mesh.MaxVertexID(); VID++)
144 {
145 if (!Mesh.IsVertex(VID))
146 {
147 continue;
148 }
149 int32 SetID = DisjointSet.Find(VID);
151 {
152 continue;
153 }
154 if (FoundComponent == -1)
155 {
156 FoundComponent = SetID;
157 }
158 else if (FoundComponent != SetID)
159 {
160 return true;
161 }
162 }
163 return false;
164 }
165
167 {
169 for (int32 VID = 0; VID < MaxVID; VID++)
170 {
171 int32 SetID = DisjointSet.Find(VID);
173 {
174 continue;
175 }
176 if (FoundComponent == -1)
177 {
178 FoundComponent = SetID;
179 }
180 else if (FoundComponent != SetID)
181 {
182 return true;
183 }
184 }
185 return false;
186 }
187
188 // Map arbitrary set IDs to indices from 0 to k-1 (if there are k components)
189 template<typename TriangleMeshType>
191 {
192 TMap<int32, int32> ComponentMap;
193 int32 CurrentIdx = 0;
194 for (int32 VID = 0; VID < Mesh.MaxVertexID(); VID++)
195 {
196 if (!Mesh.IsVertex(VID))
197 {
198 continue;
199 }
200 int32 SetID = DisjointSet.Find(VID);
202 {
203 continue;
204 }
205 if (!ComponentMap.Contains(SetID))
206 {
207 ComponentMap.Add(SetID, CurrentIdx++);
208 }
209 }
210 return ComponentMap;
211 }
212
214 {
215 TMap<int32, int32> ComponentMap;
216 int32 CurrentIdx = 0;
217 for (int32 VID = 0; VID < MaxVID; VID++)
218 {
219 int32 SetID = DisjointSet.Find(VID);
221 {
222 continue;
223 }
224 if (!ComponentMap.Contains(SetID))
225 {
226 ComponentMap.Add(SetID, CurrentIdx++);
227 }
228 }
229 return ComponentMap;
230 }
231
232 // Return an ordering of the vertex indices so that each connected component is in a contiguous block
234 {
236 TArray<int32> Contiguous;
237 Contiguous.SetNum(MaxVID);
240 for (int32 VID = 0; VID < MaxVID; VID++)
241 {
242 int32 SetID = DisjointSet.Find(VID);
243 int32 SetSize = DisjointSet.Sizes[SetID];
244 if (SetSize == 1) // just place the single-element groups at the end, no need to track in map
245 {
247 Contiguous[LastSingleEntryIdx] = VID;
248 continue;
249 }
250 int32* Loc = ComponentLoc.Find(SetID);
251 if (Loc)
252 {
253 Contiguous[(*Loc)++] = VID;
254 }
255 else
256 {
257 Contiguous[FirstUnusedIdx] = VID;
258 ComponentLoc.Add(SetID, FirstUnusedIdx + 1);
259 FirstUnusedIdx += SetSize;
260 }
261 }
262 return Contiguous;
263 }
264
270 {
271 for (int32 ContigStart = 0, NextStart = -1; ContigStart < ContiguousComponentsArray.Num(); ContigStart = NextStart)
272 {
274 int32 ComponentSize = GetComponentSize(ComponentID);
275 NextStart = ContigStart + ComponentSize;
276 if (!ensure(NextStart <= ContiguousComponentsArray.Num()))
277 {
278 return false;
279 }
282 if (!bContinue)
283 {
284 return false;
285 }
286 }
287 return true;
288 }
289
290 inline int32 GetComponent(int32 VertexID)
291 {
292 return DisjointSet.Find(VertexID);
293 }
294
295 inline int32 GetComponentSize(int32 VertexID)
296 {
297 return DisjointSet.GetSize(VertexID);
298 }
299
300 template<typename TriangleType>
302 {
303 return GetComponent(Triangle[0]);
304 }
305
310
311
312protected:
313
315};
316
317
318} // end namespace UE::Geometry
319} // end namespace UE
#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
void Init()
Definition LockFreeList.h:4
Definition ArrayView.h:139
Definition Array.h:670
void SetNum(SizeType NewNum, EAllowShrinking AllowShrinking=UE::Core::Private::AllowShrinkingByDefault< AllocatorType >())
Definition Array.h:2308
UE_NODEBUG UE_FORCEINLINE_HINT SizeType Add(ElementType &&Item)
Definition Array.h:2696
UE_NODEBUG UE_FORCEINLINE_HINT bool Find(const ElementType &Item, SizeType &Index) const
Definition Array.h:1302
Definition AssetRegistryState.h:50
Definition UnrealString.h.inl:34
Definition VertexConnectedComponents.h:23
FVertexConnectedComponents(int32 MaxVertexID)
Definition VertexConnectedComponents.h:30
bool EnumerateContiguousComponentsFromArray(const TArray< int32 > &ContiguousComponentsArray, TFunctionRef< bool(int32, TArrayView< const int32 >)> ProcessComponentFn)
Definition VertexConnectedComponents.h:269
void ConnectOverlappingComponents(const TriangleMeshType &Mesh, int32 KeepSizeThreshold=0)
Definition VertexConnectedComponents.h:104
void ConnectVertices(int32 VertexID0, int32 VertexID1)
Definition VertexConnectedComponents.h:306
int32 GetComponent(int32 VertexID)
Definition VertexConnectedComponents.h:290
void Init(const TriangleMeshType &Mesh)
Definition VertexConnectedComponents.h:41
void ConnectTriangles(const TriangleMeshType &Mesh)
Definition VertexConnectedComponents.h:47
bool HasMultipleComponents(const TriangleMeshType &Mesh, int32 KeepSizeThreshold=0)
Definition VertexConnectedComponents.h:140
void ConnectTriangles(TArrayView< const TriangleType > Triangles)
Definition VertexConnectedComponents.h:61
bool HasMultipleComponents(int32 MaxVID, int32 KeepSizeThreshold=0)
Definition VertexConnectedComponents.h:166
FSizedDisjointSet DisjointSet
Definition VertexConnectedComponents.h:314
FVertexConnectedComponents()
Definition VertexConnectedComponents.h:25
TMap< int32, int32 > MakeComponentMap(int32 MaxVID, int32 KeepSizeThreshold=0)
Definition VertexConnectedComponents.h:213
void Init(int32 MaxVertexID)
Definition VertexConnectedComponents.h:35
int32 GetComponentSize(int32 VertexID)
Definition VertexConnectedComponents.h:295
void ConnectCloseVertices(const TriangleMeshType &Mesh, double CloseVertexThreshold, int32 KeepSizeThreshold=0)
Definition VertexConnectedComponents.h:72
TArray< int32 > MakeContiguousComponentsArray(int32 MaxVID)
Definition VertexConnectedComponents.h:233
int32 GetComponent(const TriangleType &Triangle)
Definition VertexConnectedComponents.h:301
TMap< int32, int32 > MakeComponentMap(const TriangleMeshType &Mesh, int32 KeepSizeThreshold=0)
Definition VertexConnectedComponents.h:190
Definition PointHashGrid3.h:33
T DistanceSquared(const UE::Math::TVector2< T > &V1, const UE::Math::TVector2< T > &V2)
Definition VectorTypes.h:82
Definition AdvancedWidgetsModule.cpp:13
Definition IndexTypes.h:158
Disjoint set with additional storage to track the size of each set.
Definition SizedDisjointSet.h:12
int32 Union(int32 A, int32 B)
Definition SizedDisjointSet.h:54
int32 Find(int32 Idx)
Definition SizedDisjointSet.h:74
void Init(int32 NumIDs)
Definition SizedDisjointSet.h:21
int32 GetSize(int32 Idx) const
Definition SizedDisjointSet.h:102
TArray< int32 > Sizes
Definition SizedDisjointSet.h:13
static TAxisAlignedBox3< double > Empty()
Definition BoxTypes.h:382
void Contain(const TVector< RealType > &V)
Definition BoxTypes.h:438