UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
CycleTriangulator.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2#pragma once
3
4#include "Core/Factory.h"
5
6#include "Math/SlopeUtils.h"
7#include "Mesh/MeshEnum.h"
10
11#ifdef CADKERNEL_DEV
12#include "UI/DefineForDebug.h"
13#endif
14
15namespace UE::CADKernel
16{
17class FGrid;
18class FFaceMesh;
19class FIntersectionSegmentTool;
20class FIsoSegment;
21class FIsoTriangulator;
22
23typedef TFunction<double(const FVector2d&, const FVector2d&, double)> SlopeMethod;
25
43
45{
47 FIsoNode* StartNode = nullptr;
48
50 FIsoNode* EndNode = nullptr;
51
52 int32 NodeIndices[2] = { -1, -1 };
53 FIsoNode* Nodes[2] = { nullptr , nullptr };
54
56
57 bool bForceNodes = false;
58
65
67 {
68 return (Nodes[0] ? 1 : 0) + (Nodes[1] ? 1 : 0);
69 }
70
71 void AddTo(TArray<FIsoNode*>& PolygonNodes)
72 {
73 for(int32 Index = 0; Index < 2; Index++)
74 {
75 if (Nodes[Index])
76 {
77 PolygonNodes.Add(Nodes[Index]);
78 }
79 }
80 }
81
88
89 void Reset()
90 {
91 NodeIndices[0] = -1;
92 NodeIndices[1] = -1;
93 Nodes[0] = nullptr;
94 Nodes[1] = nullptr;
97 bForceNodes = false;
98 }
99
101 {
102 for (int32 Index = 0; Index < 2; Index++)
103 {
104 if (Nodes[Index] == ForbiddenNode)
105 {
107 bForceNodes = false;
108 }
109 }
110 }
111};
112
114
116{
117private:
118 const FGrid& Grid;
119
120 int32 NodeCount = 0;
121 const TArray<FIsoSegment*>& Cycle;
122 const TArray<bool>& CycleOrientation;
123
125 const FIntersectionIsoSegmentTool& InnerToOuterIsoSegmentsIntersectionTool;
126 FFaceMesh& Mesh;
127 TFactory<FIsoSegment>& IsoSegmentFactory;
128
129 FIntersectionSegmentTool CycleIntersectionTool;
130
131 TArray<FIsoSegment*> SegmentStack;
132
133 // Array of segments that failed to mesh
134 TArray<FIsoSegment*> UnmeshedSegment;
135
136 bool bFirstRun = true;
137
138 // Sub cycle data
139 int32 SubCycleNodeCount = 0;
140 TArray<FIsoNode*> SubCycleNodes;
141
142 TArray<TPair<int32, double>> VertexIndexToSlopes;
143 double MeanSquareLength = 0;
144 bool bAcuteTriangle = false;
145
146 int32 IntersectionCountAllowed = 0;
147 int32 MaxIntersectionCounted = 0;
148
149 int32 FirstSideStartIndex = -1;
150 int32 FirstSideEndIndex = -1;
151 int32 TriangleThirdIndex = -1;
152 FIsoNode* FirstSideStartNode;
153 FIsoNode* FirstSideEndNode;
154 FIsoNode* TriangleThirdNode;
155
156 // Candidates nodes for FindCandidateNodes
157 TArray<FCandidateNode> CandidateNodes;
158 FCandidateNode* ExtremityCandidateNodes[2] = { nullptr, nullptr };
159 TArray<FNodeIntersectionCount> NodeToIntersection;
160
161 // Final polygon nodes
162 TArray<FIsoNode*> PolygonNodes;
163
164
165 bool bNeedIntersectionToolUpdate = true;
166
167 const SlopeMethod GetSlopeAtStartNode = CounterClockwiseSlope;
168 const SlopeMethod GetSlopeAtEndNode = ClockwiseSlope;
169
170public:
172
173 bool MeshCycle();
174
175private:
176 bool CanCycleBeMeshed();
177 FIsoSegment* FindNextSegment(const FIsoSegment* StartSegment, const FIsoNode* StartNode, SlopeMethod GetSlope) const;
178
179 void InitializeArrays();
180 void CleanContext();
181 void InitializeCycleForMeshing();
182 void FillSegmentStack();
183
184 bool BuildTheBestPolygon(FIsoSegment* SegmentToMesh, bool bOrientation);
185
186 int32 NextIndex(int32 Index)
187 {
188 return (Index + 1) == SubCycleNodeCount ? 0 : Index + 1;
189 };
190
191 int32 PreviousIndex(int32 Index)
192 {
193 return Index == 0 ? SubCycleNodeCount - 1 : Index - 1;
194 };
195
200 bool FindTheCycleToMesh(FIsoSegment* Segment, bool bOrientation, int32& StartIndexForMinLength);
201
202 bool FindTheBestAcuteTriangle();
203
208 bool FindCandidateNodes(int32 StartIndex);
209
210 bool FindTheBestCandidateNode();
211
212 bool BuildTheBestPolygonFromTheSelectedTriangle();
213
214 void FindComplementaryNodes(FAdditionalIso& Side);
215 void ValidateAddNodesAccordingSlopeWithSide(FAdditionalIso& Side);
219 void ValidateComplementaryNodesWithInsideAndIntersectionsCriteria(FAdditionalIso& Side);
220 bool ValidComplementaryNodeOrDeleteIt(FAdditionalIso& Side, int32 Index);
221 bool IsInnerSideSegmentInsideCycle(FAdditionalIso& Side);
222
223 void SelectFinalNodes(FAdditionalIso& Side1, FAdditionalIso& Side2);
224 void ComputeSideCandidateEquilateralCriteria(FAdditionalIso& Side);
225
226 bool BuildTriangle(TArray<FIsoNode*>& CandidatNodes);
227
228 bool BuildQuadrilateral(TArray<FIsoNode*>& CandidatNodes);
229 bool BuildPentagon(TArray<FIsoNode*>& CandidatNodes);
230
231 bool BuildSmallPolygon(TArray<FIsoNode*>& CandidatNodes, bool bCheckIntersectionWithIso);
232
233
234 bool BuildSegmentIfNeeded(TArray<FIsoNode*>& CandidatNodes);
235 bool BuildSegmentIfNeeded(FIsoNode* NodeA, FIsoNode* NodeB);
236 bool BuildSegmentIfNeeded(FIsoNode* NodeA, FIsoNode* NodeB, FIsoSegment* ABSegment);
237
238 void SortCycleIntersectionToolIfNeeded();
239
240 int32 IsIntersectingIso(const TArray<FIsoNode*>& Nodes)
241 {
242 for (int32 IndexA = 0; IndexA < Nodes.Num() - 1; ++IndexA)
243 {
244 for (int32 IndexB = IndexA + 1; IndexB < Nodes.Num() - 1; ++IndexB)
245 {
246 if (InnerToOuterIsoSegmentsIntersectionTool.DoesIntersect(*Nodes[IndexA], *Nodes[IndexB]))
247 {
248 return true;
249 }
250 }
251 }
252 return false;
253 }
254
255 int32 CountIntersectionWithIso()
256 {
257 FirstSideStartNode = SubCycleNodes[FirstSideStartIndex];
258 FirstSideEndNode = SubCycleNodes[FirstSideEndIndex];
259
260 NodeToIntersection.Reserve(CandidateNodes.Num());
261 int32 Max = 0;
262 for (int32 Index = 0; Index < CandidateNodes.Num(); ++Index)
263 {
264 FCandidateNode& CNode = CandidateNodes[Index];
265 if (!CNode.bIsValid)
266 {
267 continue;
268 }
269
270 const FIsoNode* Node = CNode.Node;
271
272 int32 IntersectionCount = InnerToOuterIsoSegmentsIntersectionTool.CountIntersections(*FirstSideStartNode, *Node);
273 IntersectionCount = FMath::Max(IntersectionCount, InnerToOuterIsoSegmentsIntersectionTool.CountIntersections(*FirstSideEndNode, *Node));
274
275 NodeToIntersection.Emplace(&CNode, IntersectionCount);
277 {
279 }
280 }
281 return Max;
282 }
283
287 bool ConfirmIntersection(const FIsoNode* Start, const FIsoNode* End, const FIsoNode* Candidate, const FIsoSegment* IntersectedSegment) const;
288};
289
290namespace Polygon
291{
292
293enum ETriangleOfPentagon : uint8
294{
295 Triangle012 = 0,
296 Triangle013,
297 Triangle014,
298 Triangle023,
299 Triangle024,
300 Triangle034,
301 Triangle123,
302 Triangle124,
303 Triangle134,
304 Triangle234,
305 NoTriangle,
306};
307
308// Triangle to vertex indices (cf ETriangle)
309constexpr uint8 TrianglesOfPentagon[10][3] = { { 0, 1, 2 }, { 0, 1, 3 }, { 0, 1, 4 }, { 0, 2, 3 }, { 0, 2, 4 }, { 0, 3, 4 }, { 1, 2, 3 }, { 1, 2, 4 }, { 1, 3, 4 }, { 2, 3, 4 } };
310
311// Triangles of pentagon or pair of pentagon Triangles
312enum class EPentagon : uint8
313{
314 None = 0x00u,
315 P012_023_034 = 0x01u,
316 P012_024_234 = 0x02u,
317 P012_023_034_or_P012_024_234 = 0x03u,
318 P013_034_123 = 0x04u,
319 P012_023_034_or_P013_034_123 = 0x05u,
320 P014_123_134 = 0x08u,
321 P013_034_123_or_P014_123_134 = 0x0Cu,
322 P014_124_234 = 0x10u,
323 P012_024_234_or_P014_124_234 = 0x12u,
324 P014_123_134_or_P014_124_234 = 0x18u,
325 All = 0x1Fu,
326};
327ENUM_CLASS_FLAGS(EPentagon);
328
329// pentagon (or pair) containing the triangle (cf ETriangle)
330constexpr EPentagon TriangleToPentagon[10] = {
331 EPentagon::P012_023_034_or_P012_024_234, // Triangle012
332 EPentagon::P013_034_123, // Triangle013
333 EPentagon::P014_123_134_or_P014_124_234, // Triangle014
334 EPentagon::P012_023_034, // Triangle023
335 EPentagon::P012_024_234, // Triangle024
336 EPentagon::P012_023_034_or_P013_034_123, // Triangle034
337 EPentagon::P013_034_123_or_P014_123_134, // Triangle123
338 EPentagon::P014_124_234, // Triangle124
339 EPentagon::P014_123_134, // Triangle134
340 EPentagon::P012_024_234_or_P014_124_234 // Triangle234
341};
342
343void MeshTriangle(const FGrid& Grid, FIsoNode** Nodes, FFaceMesh& Mesh);
344void MeshQuadrilateral(const FGrid& Grid, FIsoNode** Nodes, FFaceMesh& Mesh);
345void MeshPentagon(const FGrid& Grid, FIsoNode** Nodes, FFaceMesh& Mesh);
346}
347
348}
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 ENUM_CLASS_FLAGS(Enum)
Definition EnumClassFlags.h:6
uint8_t uint8
Definition binka_ue_file_header.h:8
Definition Array.h:670
UE_REWRITE SizeType Num() const
Definition Array.h:1144
UE_FORCEINLINE_HINT SizeType Emplace(ArgsType &&... Args)
Definition Array.h:2561
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 AndroidPlatformMisc.h:14
Definition CycleTriangulator.h:116
bool MeshCycle()
Definition CycleTriangulator.cpp:32
Definition FaceMesh.h:16
Definition Grid.h:46
Definition IntersectionIsoSegmentTool.h:114
int32 CountIntersections(const FIsoNode &StartNode, const FIsoNode &EndNode) const
Definition IntersectionIsoSegmentTool.cpp:140
bool DoesIntersect(const FIsoNode &StartNode, const FIsoNode &EndNode) const
Definition IntersectionIsoSegmentTool.cpp:151
Definition IntersectionSegmentTool.h:395
Definition IsoNode.h:62
Definition IsoSegment.h:52
Definition IsoTriangulator.h:79
Definition Factory.h:18
@ None
Definition EnvQueryTypes.h:117
@ All
Definition LogVerbosity.h:56
void MeshQuadrilateral(const FGrid &Grid, FIsoNode **Nodes, FFaceMesh &Mesh)
Definition CycleTriangulator.cpp:1398
void MeshTriangle(const FGrid &Grid, FIsoNode **Nodes, FFaceMesh &Mesh)
Definition CycleTriangulator.cpp:1386
void MeshPentagon(const FGrid &Grid, FIsoNode **Nodes, FFaceMesh &Mesh)
Definition CycleTriangulator.cpp:1448
constexpr double TwoPiSlope
Definition SlopeUtils.h:81
Definition CADEntity.cpp:23
double ClockwiseSlope(const FVector2d &StartPoint, const FVector2d &EndPoint, double ReferenceSlope)
Definition SlopeUtils.h:306
TFunction< double(const FVector2d &, const FVector2d &, double)> SlopeMethod
Definition CycleTriangulator.h:23
EGridSpace
Definition MeshEnum.h:17
@ UniformScaled
Definition MeshEnum.h:20
double CounterClockwiseSlope(const FVector2d &StartPoint, const FVector2d &EndPoint, double ReferenceSlope)
Definition SlopeUtils.h:311
@ End
Definition GeoEnum.h:101
@ Start
Definition GeoEnum.h:100
TFunction< int32(int32)> NextIndexMethod
Definition CycleTriangulator.h:24
@ false
Definition radaudio_common.h:23
U16 Index
Definition radfft.cpp:71
Definition Tuple.h:652
Definition CycleTriangulator.h:45
double EquilateralCriteria[2]
Definition CycleTriangulator.h:55
int32 EndIndex
Definition CycleTriangulator.h:49
FAdditionalIso(int32 InStartIndex, int32 InEndIndex, FIsoNode *InStartNode, FIsoNode *InEndNode)
Definition CycleTriangulator.h:59
void AddTo(TArray< FIsoNode * > &PolygonNodes)
Definition CycleTriangulator.h:71
FIsoNode * Nodes[2]
Definition CycleTriangulator.h:53
void RemoveCandidate(int32 Index)
Definition CycleTriangulator.h:82
int32 NodeIndices[2]
Definition CycleTriangulator.h:52
int32 CandidateNodeCount()
Definition CycleTriangulator.h:66
int32 StartIndex
Definition CycleTriangulator.h:46
FIsoNode * StartNode
Definition CycleTriangulator.h:47
void Reset()
Definition CycleTriangulator.h:89
void RemoveCandidateIfPresent(FIsoNode *ForbiddenNode)
Definition CycleTriangulator.h:100
bool bForceNodes
Definition CycleTriangulator.h:57
FIsoNode * EndNode
Definition CycleTriangulator.h:50
Definition CycleTriangulator.h:27
FCandidateNode(FIsoNode *InNode, double InSlopeAtStartNode, double InSlopeAtEndNode, int32 InIndex)
Definition CycleTriangulator.h:35
double SlopeAtStartNode
Definition CycleTriangulator.h:29
int32 Index
Definition CycleTriangulator.h:31
FIsoNode * Node
Definition CycleTriangulator.h:28
bool bIsValid
Definition CycleTriangulator.h:32
double SlopeAtEndNode
Definition CycleTriangulator.h:30