UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
Delaunay2.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 "Containers/Array.h"
8#include "CoreMinimal.h"
10#include "HAL/PlatformCrt.h"
11#include "IndexTypes.h"
12#include "IndexTypes.h"
13#include "LineTypes.h"
14#include "Math/RandomStream.h"
15#include "Math/UnrealMathSSE.h"
16#include "Math/Vector2D.h"
17#include "MathUtil.h"
18#include "PlaneTypes.h"
19#include "Polygon2.h"
20#include "Templates/PimplPtr.h"
22#include "VectorTypes.h"
23
24
25namespace UE {
26namespace Geometry {
27template <typename T> class TGeneralPolygon2;
28template <typename T> class TPolygon2;
29
30using namespace UE::Math;
31
32// Internal representation of mesh connectivity; not exposed to interface
33struct FDelaunay2Connectivity;
34
36{
37public:
38
39 // Indicates result of triangulation
40 enum class EResult
41 {
42 Success,
43 // Has not yet tried to compute a triangulation
45 // No input points
47 // Input did not span a 2D basis (was 1D or 0D) so could not form a triangle
49 // Could not create triangulation containing all requested constraint edges, typically due to intersections between requested edges
51 // Uncategorized failure
53 };
54
55 // Options for selecting what triangles to include in the output, for constrained Delaunay triangulation of polygons
56 enum class EFillMode
57 {
58 // Fastest/simplest option: Keep all triangles if you'd have to cross a constrained edge to reach it from outside, ignoring edge orientation
59 Solid,
60 // Winding-number based fill options: Keep triangles based on the winding number
65 };
66
67
68 //
69 // Inputs
70 //
71
72 // Source for random permutations, used internally in the triangulation algorithm
74
75 // Option to keep extra vertex->edge adjacency data; useful if you will call ConstrainEdges many times on the same triangulation
77
78 // Option to validate that edges remain in the triangulation after multiple constraint edges passed in
79 // Only validates for the edges in the current call; if separate calls constrain additional edges, set this to 'false' and call HasEdges() on the full edge set
80 // TODO: Consider having the internal mesh remember what edges have been constrained, so we can set an error flag when constrained edges cross previous constrained edges
81 bool bValidateEdges = true;
82
83 // Option to automatically track duplicate vertices and treat edges that reference them as if they referenced the instance that was actually used in the triangulation
84 // Note: Cannot change this to 'true' *after* triangulation and then call ConstrainEdges; duplicate vertices will only be detected on their initial insertion
86
87 // TODO: it would often be useful to pass in sparse vertex data
89 //TFunction<bool(int32)> SkipVertexFn = nullptr;
90
99
100 // Triangulate a polygon, and optionally pass back the resulting triangles
101 // Uses the 'solid' fill mode, and fills the polygon regardless of the edge orientation
102 // Note: TrianglesOut may be empty or incomplete if the input is self-intersecting.
103 // Note this clears any previously-held triangulation data, and triangulates the passed-in polygon from scratch
104 template<typename RealType>
106 {
107 int32 NumVertices = Polygon.VertexCount();
108 TArray<FIndex2i> Edges;
109 Edges.Reserve(NumVertices - 1);
110 for (int32 Last = NumVertices - 1, Idx = 0; Idx < NumVertices; Last = Idx++)
111 {
112 Edges.Add(FIndex2i(Last, Idx));
113 }
114 bool bSuccess = Triangulate(Polygon.GetVertices(), Edges);
115 if (TrianglesOut)
116 {
118 }
119 return bSuccess;
120 }
121
122 // Triangulate a polygon, and optionally pass back the resulting triangles
123 // Uses a winding-number-based fill mode, and relies on the general polygon having correct orientations
124 // (Uses TGeneralPolygon2's OuterIsClockwise() to automatically choose between positive or negative winding)
125 // Note: TrianglesOut may be empty or incomplete if the input is self-intersecting.
126 // Note this clears any previously-held triangulation data, and triangulates the passed-in general polygon from scratch
127 template<typename RealType>
129 {
131 TArray<FIndex2i> AllEdges;
132
133 auto AppendVertices = [&AllVertices, &AllEdges](const TArray<TVector2<RealType>>& Vertices)
134 {
135 if (Vertices.IsEmpty())
136 {
137 return;
138 }
139
140 int32 StartIdx = AllVertices.Num();
141 AllVertices.Append(Vertices);
142 AllEdges.Reserve(AllEdges.Num() + Vertices.Num() - 1);
143 int32 NumVertices = Vertices.Num();
144 for (int32 Last = NumVertices - 1, Idx = 0; Idx < NumVertices; Last = Idx++)
145 {
146 AllEdges.Add(FIndex2i(StartIdx + Last, StartIdx + Idx));
147 }
148 };
149 AppendVertices(GeneralPolygon.GetOuter().GetVertices());
150 for (int32 HoleIdx = 0; HoleIdx < GeneralPolygon.GetHoles().Num(); HoleIdx++)
151 {
152 AppendVertices(GeneralPolygon.GetHoles()[HoleIdx].GetVertices());
153 }
154
155 bool bSuccess = Triangulate(AllVertices, AllEdges);
156 if (TrianglesOut)
157 {
160 {
161 *TrianglesOut = GetFilledTriangles(AllEdges, FillMode);
162 }
163 else
164 {
166 }
167 }
168 if (VerticesOut)
169 {
171 }
172 return bSuccess;
173 }
174
183
184 // Update the triangulation incrementally, assuming Vertices are unchanged before FirstNewIndex, and nothing after FirstNewIndex has been inserted yet
185 // Note that updating with new vertices *after* constraining edges may remove previously-constrained edges, unless we also add a way to tag constrained edges
187
188 // Get the triangulation as an array of triangles
189 // Note: This creates a new array each call, because the internal data structure does not have a triangle array
191
192 // Get the triangulation as an array with a corresponding adjacency array, indicating the adjacent triangle on each triangle edge (-1 if no adjacent triangle)
194
204 {
205 TArray<FIndex3i> Triangles;
206 GetFilledTriangles(Triangles, Edges, FillMode);
207 return Triangles;
208 }
209
221
238
249
250 // @return true if this is a constrained Delaunay triangulation
251 bool IsConstrained() const
252 {
253 return bIsConstrained;
254 }
255
256 // @return true if triangulation is Delaunay, useful for validating results (note: likely to be false if edges are constrained)
259
260 // @return true if triangulation has the given edges, useful for validating results
262
263 // Remap any references to duplicate vertices to only reference the vertices used in the triangulation
265
266 // @return true if the edge is in the triangulation
268
269 // @return true if the input had duplicate vertices, and so not all vertices could be used in the triangulation.
270 GEOMETRYCORE_API bool HasDuplicates() const;
271
272 // @return if bAutomaticallyFixEdgesToDuplicateVertices was set during triangulation, will return the remapped vertex index for any duplicate vertices, or Index if the vertex was not remapped.
274
275
276
287
296 template<typename RealType>
298 {
300 Delaunay.Triangulate(Sites);
301 return Delaunay.GetVoronoiCells(Sites, bIncludeBoundary, ClipBounds, ExpandBounds);
302 }
303
306 {
307 return Result;
308 }
309
312 {
313 return Result == EResult::Collinear || Result == EResult::Success;
314 }
315
316protected:
318
319 bool bIsConstrained = false;
320
321 // helper to perform standard validation on results after Triangulate or ConstrainEdges calls
322 UE_DEPRECATED(5.5, "No longer used by the implementation and may be removed")
324 {
325 return !bValidateEdges || HasEdges(Edges);
326 }
327
328private:
330
331 bool ValidateEdgesResult(TArrayView<const FIndex2i> Edges)
332 {
333 if (bValidateEdges && !HasEdges(Edges))
334 {
335 Result = EResult::MissingEdges;
336 return false;
337 }
338 return true;
339 }
340};
341
342} // end namespace UE::Geometry
343} // end namespace UE
bool bSuccess
Definition ConvexDecomposition3.cpp:819
#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
@ Num
Definition MetalRHIPrivate.h:234
const bool
Definition NetworkReplayStreaming.h:178
UE_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTemp(T &&Obj) noexcept
Definition UnrealTemplate.h:520
Definition ArrayView.h:139
Definition Array.h:670
UE_NODEBUG UE_FORCEINLINE_HINT SizeType Add(ElementType &&Item)
Definition Array.h:2696
UE_FORCEINLINE_HINT void Reserve(SizeType Number)
Definition Array.h:3016
Definition Delaunay2.h:36
GEOMETRYCORE_API void FixDuplicatesOnEdge(FIndex2i &Edge)
Definition Delaunay2.cpp:1808
bool bKeepFastEdgeAdjacencyData
Definition Delaunay2.h:76
EFillMode
Definition Delaunay2.h:57
GEOMETRYCORE_API bool ConstrainEdges(TArrayView< const TVector2< double > > Vertices, TArrayView< const FIndex2i > Edges)
Definition Delaunay2.cpp:1637
FRandomStream RandomStream
Definition Delaunay2.h:73
GEOMETRYCORE_API TArray< FIndex3i > GetTriangles() const
Definition Delaunay2.cpp:1689
GEOMETRYCORE_API bool HasEdge(const FIndex2i &Edge, bool bRemapDuplicates)
Definition Delaunay2.cpp:1814
EResult
Definition Delaunay2.h:41
GEOMETRYCORE_API bool HasEdges(TArrayView< const FIndex2i > Edges) const
Definition Delaunay2.cpp:1788
bool ValidateResult(TArrayView< const FIndex2i > Edges) const
Definition Delaunay2.h:323
GEOMETRYCORE_API TArray< TArray< FVector2d > > GetVoronoiCells(TArrayView< const FVector2d > Vertices, bool bIncludeBoundary=false, FAxisAlignedBox2d ClipBounds=FAxisAlignedBox2d::Empty(), double ExpandBounds=0.0) const
Definition Delaunay2.cpp:1761
bool bIsConstrained
Definition Delaunay2.h:319
TPimplPtr< FDelaunay2Connectivity > Connectivity
Definition Delaunay2.h:317
bool bAutomaticallyFixEdgesToDuplicateVertices
Definition Delaunay2.h:85
GEOMETRYCORE_API bool IsDelaunay(TArrayView< const FVector2f > Vertices, TArrayView< const FIndex2i > SkipEdges=TArrayView< const FIndex2i >()) const
Definition Delaunay2.cpp:1742
static TArray< TArray< TVector2< RealType > > > ComputeVoronoiCells(TArrayView< const TVector2< RealType > > Sites, bool bIncludeBoundary=false, TAxisAlignedBox2< RealType > ClipBounds=FAxisAlignedBox2f::Empty(), RealType ExpandBounds=(RealType) 0)
Definition Delaunay2.h:297
GEOMETRYCORE_API bool Triangulate(TArrayView< const TVector2< double > > Vertices, TArrayView< const FIndex2i > Edges=TArrayView< const FIndex2i >())
Definition Delaunay2.cpp:1617
GEOMETRYCORE_API bool GetFilledTrianglesGeneralizedWinding(TArray< FIndex3i > &TrianglesOut, TArrayView< const TVector2< double > > Vertices, TArrayView< const FIndex2i > Edges, EFillMode FillMode=EFillMode::PositiveWinding) const
Definition Delaunay2.cpp:1724
EResult GetResult() const
Definition Delaunay2.h:305
bool IsConstrained() const
Definition Delaunay2.h:251
bool Triangulate(const TGeneralPolygon2< RealType > &GeneralPolygon, TArray< FIndex3i > *TrianglesOut=nullptr, TArray< TVector2< RealType > > *VerticesOut=nullptr, bool bFallbackToGeneralizedWinding=false)
Definition Delaunay2.h:128
GEOMETRYCORE_API int32 RemapIfDuplicate(int32 Index) const
Definition Delaunay2.cpp:1832
bool Triangulate(const TPolygon2< RealType > &Polygon, TArray< FIndex3i > *TrianglesOut=nullptr)
Definition Delaunay2.h:105
bool bValidateEdges
Definition Delaunay2.h:81
GEOMETRYCORE_API void GetTrianglesAndAdjacency(TArray< FIndex3i > &Triangles, TArray< FIndex3i > &Adjacency) const
Definition Delaunay2.cpp:1698
TArray< FIndex3i > GetFilledTriangles(TArrayView< const FIndex2i > Edges, EFillMode FillMode=EFillMode::PositiveWinding)
Definition Delaunay2.h:203
GEOMETRYCORE_API bool HasDuplicates() const
Definition Delaunay2.cpp:1827
bool CanComputeVoronoiCells() const
Definition Delaunay2.h:311
Definition GeneralPolygon2.h:28
Definition Polygon2.h:30
Definition Sphere.cpp:10
Definition AdvancedWidgetsModule.cpp:13
U16 Index
Definition radfft.cpp:71
Definition RandomStream.h:20
Definition PimplPtr.h:50
Definition IndexTypes.h:27
Definition BoxTypes.h:637
static TAxisAlignedBox2< RealType > Empty()
Definition BoxTypes.h:706
Definition Vector2D.h:38