// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "Core/CADKernelArchive.h" #include "Core/CADEntity.h" #include "Core/HaveStates.h" #include "Core/MetadataDictionary.h" #include "Core/OrientedEntity.h" #include "Core/Types.h" #include "Geo/GeoEnum.h" #include "Topo/TopologicalFace.h" #include "Topo/TopologicalShapeEntity.h" namespace UE::CADKernel { class FBody; class FCADKernelArchive; class FDatabase; class FTopologicalFace; class FTopologyReport; struct FFaceSubset; namespace ShellTools { void UnlinkFromOther(TArray& Faces, TArray& VerticesToLink); } class CADKERNEL_API FOrientedFace : public TOrientedEntity { public: FOrientedFace(TSharedPtr& InEntity, EOrientation InOrientation) : TOrientedEntity(InEntity, InOrientation) { } FOrientedFace() : TOrientedEntity() { } }; class CADKERNEL_API FShell : public FTopologicalShapeEntity { friend class FEntity; private: TArray TopologicalFaces; FShell() = default; FShell(const TArray InTopologicalFaces, bool bIsInnerShell = false) : FTopologicalShapeEntity() , TopologicalFaces(InTopologicalFaces) { if (bIsInnerShell) { SetInner(); } } FShell(const TArray>& InTopologicalFaces, bool bIsInnerShell = true); FShell(const TArray>& InTopologicalFaces, const TArray& InOrientations, bool bIsInnerShell = true); public: virtual ~FShell() override { FShell::Empty(); } virtual void Serialize(FCADKernelArchive& Ar) override { FTopologicalShapeEntity::Serialize(Ar); SerializeIdents(Ar, (TArray>&) TopologicalFaces); } virtual void SpawnIdent(FDatabase& Database) override { if (!FEntity::SetId(Database)) { return; } SpawnIdentOnEntities((TArray>&) TopologicalFaces, Database); } virtual void ResetMarkersRecursively() const override { ResetMarkers(); ResetMarkersRecursivelyOnEntities((TArray>&) TopologicalFaces); } void RemoveFaces(); void RemoveDeletedOrDegeneratedFaces(); virtual void Empty() override; void Add(TSharedRef InTopologicalFace, EOrientation InOrientation); void Add(TArray& Faces); #ifdef CADKERNEL_DEV virtual FInfoEntity& GetInfo(FInfoEntity&) const override; #endif virtual EEntity GetEntityType() const override { return EEntity::Shell; } virtual int32 FaceCount() const override { return TopologicalFaces.Num(); } void ReplaceFaces(TArray& NewFaces) { Swap(TopologicalFaces, NewFaces); NewFaces.Reset(); } const TArray& GetFaces() const { return TopologicalFaces; } TArray& GetFaces() { return TopologicalFaces; } virtual void GetFaces(TArray& OutFaces) override; virtual void Merge(TSharedPtr& Shell); virtual void PropagateBodyOrientation() override; virtual void CompleteMetaData() override; /** * Update each FOrientedFace::Direction according to FOrientedFace::Entity->IsBackOriented() flag */ virtual void UpdateShellOrientation(); void CheckTopology(TArray& Subshells); void UnlinkFromOther(TArray& OutVerticesToLink) { TArray Faces; GetFaces(Faces); ShellTools::UnlinkFromOther(Faces, OutVerticesToLink); } #ifdef CADKERNEL_DEV virtual void FillTopologyReport(FTopologyReport& Report) const override; #endif /** * @return true if the shell has at least one border edge */ bool IsOpenShell(); bool IsInner() const { return ((States & EHaveStates::IsInner) == EHaveStates::IsInner); } bool IsOuter() const { return ((States & EHaveStates::IsInner) != EHaveStates::IsInner); } void SetInner() { States |= EHaveStates::IsInner; } void SetOuter() { States &= ~EHaveStates::IsInner; } /** * Orient each connected sub-shell: each connected face will have the same orientation * Each connected subset of faces will be oriented: * - towards the outside if it's a closed subset (without border edge) * - according to its main/average orientation if it's an open shell * @return SwapFaceCount for report purpose */ int32 Orient(); virtual void Remove(const FTopologicalShapeEntity*) override; }; }