Skip to content

Commit 7d22130

Browse files
committed
Inclusion filter consolidation
1 parent 024e8cd commit 7d22130

20 files changed

+766
-1173
lines changed
1.53 KB
Binary file not shown.
9.46 KB
Binary file not shown.
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// Copyright 2025 Timothé Lapetite and contributors
2+
// Released under the MIT license https://opensource.org/license/MIT/
3+
4+
#include "Misc/Filters/PCGExInclusionFilter.h"
5+
6+
7+
#include "Paths/PCGExPaths.h"
8+
9+
10+
#define LOCTEXT_NAMESPACE "PCGExInclusionFilterDefinition"
11+
#define PCGEX_NAMESPACE PCGExInclusionFilterDefinition
12+
13+
bool UPCGExInclusionFilterFactory::SupportsCollectionEvaluation() const
14+
{
15+
return Config.bCheckAgainstDataBounds;
16+
}
17+
18+
TSharedPtr<PCGExPointFilter::IFilter> UPCGExInclusionFilterFactory::CreateFilter() const
19+
{
20+
return MakeShared<PCGExPointFilter::FInclusionFilter>(this);
21+
}
22+
23+
FName UPCGExInclusionFilterFactory::GetInputLabel() const
24+
{
25+
return PCGEx::SourceTargetsLabel;
26+
}
27+
28+
void UPCGExInclusionFilterFactory::InitConfig_Internal()
29+
{
30+
Super::InitConfig_Internal();
31+
LocalFidelity = Config.Fidelity;
32+
LocalExpansion = Config.Tolerance;
33+
LocalExpansionZ = -1;
34+
LocalProjection = Config.ProjectionDetails;
35+
LocalSampleInputs = Config.SampleInputs;
36+
WindingMutation = Config.WindingMutation;
37+
bScaleTolerance = Config.bSplineScalesTolerance;
38+
}
39+
40+
namespace PCGExPointFilter
41+
{
42+
bool FInclusionFilter::Init(FPCGExContext* InContext, const TSharedPtr<PCGExData::FFacade>& InPointDataFacade)
43+
{
44+
if (!IFilter::Init(InContext, InPointDataFacade)) { return false; }
45+
46+
bCheckAgainstDataBounds = TypedFilterFactory->Config.bCheckAgainstDataBounds;
47+
InTransforms = InPointDataFacade->GetIn()->GetConstTransformValueRange();
48+
49+
if (bCheckAgainstDataBounds)
50+
{
51+
PCGExData::FProxyPoint ProxyPoint;
52+
InPointDataFacade->Source->GetDataAsProxyPoint(ProxyPoint);
53+
bCollectionTestResult = Test(ProxyPoint);
54+
}
55+
56+
return true;
57+
}
58+
59+
#define PCGEX_CHECK_MAX if (TypedFilterFactory->Config.bUseMaxInclusionCount && InclusionsCount > TypedFilterFactory->Config.MaxInclusionCount) { return TypedFilterFactory->Config.bInvert; }
60+
#define PCGEX_CHECK_MIN if (TypedFilterFactory->Config.bUseMinInclusionCount && InclusionsCount < TypedFilterFactory->Config.MinInclusionCount) { return TypedFilterFactory->Config.bInvert; }
61+
62+
bool FInclusionFilter::Test(const PCGExData::FProxyPoint& Point) const
63+
{
64+
int32 InclusionsCount = 0;
65+
PCGExPathInclusion::EFlags Flags = Handler->GetInclusionFlags(
66+
Point.GetLocation(), InclusionsCount,
67+
TypedFilterFactory->Config.Pick == EPCGExSplineFilterPick::Closest);
68+
69+
PCGEX_CHECK_MAX
70+
PCGEX_CHECK_MIN
71+
72+
const bool bPass = Handler->TestFlags(Flags);
73+
return TypedFilterFactory->Config.bInvert ? !bPass : bPass;
74+
}
75+
76+
bool FInclusionFilter::Test(const int32 PointIndex) const
77+
{
78+
if (bCheckAgainstDataBounds) { return bCollectionTestResult; }
79+
80+
int32 InclusionsCount = 0;
81+
PCGExPathInclusion::EFlags Flags = Handler->GetInclusionFlags(
82+
InTransforms[PointIndex].GetLocation(), InclusionsCount,
83+
TypedFilterFactory->Config.Pick == EPCGExSplineFilterPick::Closest);
84+
85+
PCGEX_CHECK_MAX
86+
PCGEX_CHECK_MIN
87+
88+
const bool bPass = Handler->TestFlags(Flags);
89+
return TypedFilterFactory->Config.bInvert ? !bPass : bPass;
90+
}
91+
92+
bool FInclusionFilter::Test(const TSharedPtr<PCGExData::FPointIO>& IO, const TSharedPtr<PCGExData::FPointIOCollection>& ParentCollection) const
93+
{
94+
PCGExData::FProxyPoint ProxyPoint;
95+
IO->GetDataAsProxyPoint(ProxyPoint);
96+
return Test(ProxyPoint);
97+
}
98+
99+
#undef PCGEX_CHECK_MAX
100+
#undef PCGEX_CHECK_MIN
101+
}
102+
103+
TArray<FPCGPinProperties> UPCGExInclusionFilterProviderSettings::InputPinProperties() const
104+
{
105+
TArray<FPCGPinProperties> PinProperties = Super::InputPinProperties();
106+
PCGEX_PIN_ANY(PCGEx::SourceTargetsLabel, TEXT("Path, splines, polygons, ... will be used for testing"), Required, {})
107+
return PinProperties;
108+
}
109+
110+
PCGEX_CREATE_FILTER_FACTORY(Inclusion)
111+
112+
#if WITH_EDITOR
113+
FString UPCGExInclusionFilterProviderSettings::GetDisplayName() const
114+
{
115+
return PCGExPathInclusion::ToString(Config.CheckType);
116+
}
117+
#endif
118+
119+
#undef LOCTEXT_NAMESPACE
120+
#undef PCGEX_NAMESPACE

Source/PCGExtendedToolkit/Private/Misc/Filters/PCGExPathAlphaFilter.cpp

Lines changed: 7 additions & 206 deletions
Original file line numberDiff line numberDiff line change
@@ -9,220 +9,21 @@
99
#define LOCTEXT_NAMESPACE "PCGExPathAlphaFilterDefinition"
1010
#define PCGEX_NAMESPACE PCGExPathAlphaFilterDefinition
1111

12-
bool UPCGExPathAlphaFilterFactory::SupportsProxyEvaluation() const
13-
{
14-
return Config.CompareAgainst == EPCGExInputValueType::Constant;
15-
}
16-
17-
bool UPCGExPathAlphaFilterFactory::WantsPreparation(FPCGExContext* InContext)
18-
{
19-
return true;
20-
}
21-
22-
PCGExFactories::EPreparationResult UPCGExPathAlphaFilterFactory::Prepare(FPCGExContext* InContext, const TSharedPtr<PCGExMT::FTaskManager>& AsyncManager)
23-
{
24-
PCGExFactories::EPreparationResult Result = Super::Prepare(InContext, AsyncManager);
25-
if (Result != PCGExFactories::EPreparationResult::Success) { return Result; }
26-
27-
Splines = MakeShared<TArray<TSharedPtr<FPCGSplineStruct>>>();
28-
29-
if (TArray<FPCGTaggedData> Targets = InContext->InputData.GetInputsByPin(PCGExPaths::SourcePathsLabel);
30-
!Targets.IsEmpty())
31-
{
32-
for (const FPCGTaggedData& TaggedData : Targets)
33-
{
34-
const UPCGBasePointData* PathData = Cast<UPCGBasePointData>(TaggedData.Data);
35-
if (!PathData) { continue; }
36-
37-
const bool bIsClosedLoop = PCGExPaths::GetClosedLoop(PathData);
38-
if (Config.SampleInputs == EPCGExSplineSamplingIncludeMode::ClosedLoopOnly && !bIsClosedLoop) { continue; }
39-
if (Config.SampleInputs == EPCGExSplineSamplingIncludeMode::OpenSplineOnly && bIsClosedLoop) { continue; }
40-
41-
if (TSharedPtr<FPCGSplineStruct> SplineStruct = PCGExPaths::MakeSplineFromPoints(PathData->GetConstTransformValueRange(), Config.PointType, bIsClosedLoop, true))
42-
{
43-
Splines->Add(SplineStruct);
44-
}
45-
}
46-
}
47-
48-
if (Splines->IsEmpty())
49-
{
50-
PCGE_LOG_C(Error, GraphAndLog, InContext, FTEXT("No splines (no input matches criteria or empty dataset)"));
51-
return PCGExFactories::EPreparationResult::MissingData;
52-
}
53-
54-
return Result;
55-
}
56-
57-
TSharedPtr<PCGExPointFilter::IFilter> UPCGExPathAlphaFilterFactory::CreateFilter() const
58-
{
59-
return MakeShared<PCGExPointFilter::FPathAlphaFilter>(this);
60-
}
61-
62-
void UPCGExPathAlphaFilterFactory::BeginDestroy()
63-
{
64-
Splines.Reset();
65-
SegmentsNum.Reset();
66-
Super::BeginDestroy();
67-
}
68-
69-
bool UPCGExPathAlphaFilterFactory::RegisterConsumableAttributesWithData(FPCGExContext* InContext, const UPCGData* InData) const
70-
{
71-
if (!Super::RegisterConsumableAttributesWithData(InContext, InData)) { return false; }
72-
73-
FName Consumable = NAME_None;
74-
PCGEX_CONSUMABLE_CONDITIONAL(Config.CompareAgainst == EPCGExInputValueType::Attribute, Config.OperandB, Consumable)
75-
76-
return true;
77-
}
78-
79-
namespace PCGExPointFilter
80-
{
81-
bool FPathAlphaFilter::Init(FPCGExContext* InContext, const TSharedPtr<PCGExData::FFacade>& InPointDataFacade)
82-
{
83-
if (!IFilter::Init(InContext, InPointDataFacade)) { return false; }
84-
85-
OperandB = TypedFilterFactory->Config.GetValueSettingOperandB();
86-
if (!OperandB->Init(PointDataFacade)) { return false; }
87-
88-
InTransforms = InPointDataFacade->GetIn()->GetConstTransformValueRange();
89-
90-
return true;
91-
}
92-
93-
bool FPathAlphaFilter::Test(const PCGExData::FProxyPoint& Point) const
94-
{
95-
const TArray<TSharedPtr<FPCGSplineStruct>>& SplinesRef = *Splines.Get();
96-
const TArray<double>& SegmentsNumRef = *SegmentsNum.Get();
97-
98-
const FVector Pos = Point.Transform.GetLocation();
99-
double Time = 0;
100-
101-
if (TypedFilterFactory->Config.TimeConsolidation == EPCGExSplineTimeConsolidation::Min) { Time = MAX_dbl; }
102-
103-
if (TypedFilterFactory->Config.Pick == EPCGExSplineFilterPick::Closest)
104-
{
105-
double ClosestDist = MAX_dbl;
106-
for (int i = 0; i < Splines->Num(); i++)
107-
{
108-
const TSharedPtr<const FPCGSplineStruct> Spline = SplinesRef[i];
109-
110-
double LocalTime = Spline->FindInputKeyClosestToWorldLocation(Pos);
111-
FTransform T = Spline->GetTransformAtSplineInputKey(static_cast<float>(LocalTime), ESplineCoordinateSpace::World, true);
112-
LocalTime /= SegmentsNumRef[i];
113-
114-
const double D = FVector::DistSquared(T.GetLocation(), Pos);
115-
116-
if (D > ClosestDist) { continue; }
117-
118-
Time = LocalTime;
119-
}
120-
}
121-
else
122-
{
123-
for (int i = 0; i < Splines->Num(); i++)
124-
{
125-
const TSharedPtr<const FPCGSplineStruct> Spline = SplinesRef[i];
126-
127-
double LocalTime = Spline->FindInputKeyClosestToWorldLocation(Pos);
128-
LocalTime /= SegmentsNumRef[i];
129-
130-
switch (TypedFilterFactory->Config.TimeConsolidation)
131-
{
132-
case EPCGExSplineTimeConsolidation::Min:
133-
Time = FMath::Min(LocalTime, Time);
134-
break;
135-
case EPCGExSplineTimeConsolidation::Max:
136-
Time = FMath::Max(LocalTime, Time);
137-
break;
138-
case EPCGExSplineTimeConsolidation::Average:
139-
Time += LocalTime;
140-
break;
141-
}
142-
}
143-
144-
if (TypedFilterFactory->Config.TimeConsolidation == EPCGExSplineTimeConsolidation::Average)
145-
{
146-
Time /= SegmentsNumRef.Num();
147-
}
148-
}
149-
150-
return PCGExCompare::Compare(TypedFilterFactory->Config.Comparison, Time, TypedFilterFactory->Config.OperandBConstant, TypedFilterFactory->Config.Tolerance);
151-
}
152-
153-
bool FPathAlphaFilter::Test(const int32 PointIndex) const
154-
{
155-
const TArray<TSharedPtr<FPCGSplineStruct>>& SplinesRef = *Splines.Get();
156-
const TArray<double>& SegmentsNumRef = *SegmentsNum.Get();
157-
158-
const FVector Pos = InTransforms[PointIndex].GetLocation();
159-
double Time = 0;
160-
161-
if (TypedFilterFactory->Config.TimeConsolidation == EPCGExSplineTimeConsolidation::Min) { Time = MAX_dbl; }
162-
163-
if (TypedFilterFactory->Config.Pick == EPCGExSplineFilterPick::Closest)
164-
{
165-
double ClosestDist = MAX_dbl;
166-
for (int i = 0; i < Splines->Num(); i++)
167-
{
168-
const TSharedPtr<const FPCGSplineStruct> Spline = SplinesRef[i];
169-
170-
double LocalTime = Spline->FindInputKeyClosestToWorldLocation(Pos);
171-
FTransform T = Spline->GetTransformAtSplineInputKey(static_cast<float>(LocalTime), ESplineCoordinateSpace::World, true);
172-
LocalTime /= SegmentsNumRef[i];
173-
174-
const double D = FVector::DistSquared(T.GetLocation(), Pos);
175-
176-
if (D > ClosestDist) { continue; }
177-
178-
Time = LocalTime;
179-
}
180-
}
181-
else
182-
{
183-
for (int i = 0; i < Splines->Num(); i++)
184-
{
185-
const TSharedPtr<const FPCGSplineStruct> Spline = SplinesRef[i];
186-
187-
double LocalTime = Spline->FindInputKeyClosestToWorldLocation(Pos);
188-
LocalTime /= SegmentsNumRef[i];
189-
190-
switch (TypedFilterFactory->Config.TimeConsolidation)
191-
{
192-
case EPCGExSplineTimeConsolidation::Min:
193-
Time = FMath::Min(LocalTime, Time);
194-
break;
195-
case EPCGExSplineTimeConsolidation::Max:
196-
Time = FMath::Max(LocalTime, Time);
197-
break;
198-
case EPCGExSplineTimeConsolidation::Average:
199-
Time += LocalTime;
200-
break;
201-
}
202-
}
203-
204-
if (TypedFilterFactory->Config.TimeConsolidation == EPCGExSplineTimeConsolidation::Average)
205-
{
206-
Time /= SegmentsNumRef.Num();
207-
}
208-
}
209-
210-
const double B = OperandB ? OperandB->Read(PointIndex) : TypedFilterFactory->Config.OperandBConstant;
211-
return PCGExCompare::Compare(TypedFilterFactory->Config.Comparison, Time, B, TypedFilterFactory->Config.Tolerance);
212-
}
213-
}
214-
215-
TArray<FPCGPinProperties> UPCGExPathAlphaFilterProviderSettings::InputPinProperties() const
12+
TArray<FPCGPinProperties> UDEPRECATED_PCGExPathAlphaFilterProviderSettings::InputPinProperties() const
21613
{
21714
TArray<FPCGPinProperties> PinProperties = Super::InputPinProperties();
21815
PCGEX_PIN_POINTS(PCGExPaths::SourcePathsLabel, TEXT("Paths will be used for testing"), Required, {})
21916
return PinProperties;
22017
}
22118

222-
PCGEX_CREATE_FILTER_FACTORY(PathAlpha)
19+
UPCGExFactoryData* UDEPRECATED_PCGExPathAlphaFilterProviderSettings::CreateFactory(FPCGExContext* InContext, UPCGExFactoryData* InFactory) const
20+
{
21+
PCGE_LOG_C(Error, GraphAndLog, InContext, FTEXT("This filter is deprecated, use 'Filter : Time' instead."));
22+
return nullptr;
23+
}
22324

22425
#if WITH_EDITOR
225-
FString UPCGExPathAlphaFilterProviderSettings::GetDisplayName() const
26+
FString UDEPRECATED_PCGExPathAlphaFilterProviderSettings::GetDisplayName() const
22627
{
22728
FString DisplayName = TEXT("Alpha ") + PCGExCompare::ToString(Config.Comparison);
22829

0 commit comments

Comments
 (0)