Files
UnrealEngine/Engine/Source/Runtime/Datasmith/CADKernel/Base/Private/Topo/Model.cpp
2025-05-18 13:04:45 +08:00

200 lines
4.3 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "Topo/Model.h"
#include "Core/EntityGeom.h"
#include "Topo/Body.h"
#include "Topo/TopologicalEdge.h"
#include "Topo/TopologicalFace.h"
#include "Topo/TopologicalVertex.h"
#ifdef CADKERNEL_DEV
#include "Topo/TopologyReport.h"
#endif
namespace UE::CADKernel
{
void FModel::AddEntity(TSharedRef<FTopologicalEntity> Entity)
{
switch (Entity->GetEntityType())
{
case EEntity::Body:
Add(StaticCastSharedRef<FBody>(Entity));
break;
default:
break;
}
}
bool FModel::Contains(TSharedPtr<FTopologicalEntity> Entity)
{
switch(Entity->GetEntityType())
{
case EEntity::Body:
return Bodies.Find(StaticCastSharedPtr<FBody>(Entity)) != INDEX_NONE;
default:
return false;
}
}
void FModel::PrintBodyAndShellCount()
{
int32 NbBody = 0;
int32 NbShell = 0;
TArray<TSharedPtr<FBody>> NewBodies;
for (TSharedPtr<FBody> Body : Bodies)
{
NbShell += Body->GetShells().Num();
NbBody++;
}
FMessage::Printf(Log, TEXT("Body count %d shell count %d \n"), NbBody, NbShell);
}
int32 FModel::FaceCount() const
{
int32 FaceCount = 0;
for (const TSharedPtr<FBody>& Body : Bodies)
{
FaceCount += Body->FaceCount();
}
return FaceCount;
}
void FModel::RemoveEmptyBodies()
{
TArray<TSharedPtr<FBody>> NewBodies;
NewBodies.Reserve(Bodies.Num());
for (const TSharedPtr<FBody>& Body : Bodies)
{
if (!Body->IsDeleted() && Body->ShellCount())
{
NewBodies.Add(Body);
}
else
{
Body->Delete();
Body->ResetHost();
}
}
Bodies = MoveTemp(NewBodies);
}
void FModel::GetFaces(TArray<FTopologicalFace*>& OutFaces)
{
for (const TSharedPtr<FBody>& Body : Bodies)
{
Body->GetFaces(OutFaces);
}
}
void FModel::PropagateBodyOrientation()
{
for (TSharedPtr<FBody>& Body : Bodies)
{
Body->PropagateBodyOrientation();
}
}
void FModel::CompleteMetaData()
{
for (TSharedPtr<FBody>& Body : Bodies)
{
Body->CompleteMetaData();
}
}
struct FBodyShell
{
TSharedPtr<FBody> Body;
TSharedPtr<FShell> Shell;
FBodyShell(TSharedPtr<FBody> InBody, TSharedPtr<FShell> InShell)
: Body(InBody)
, Shell(InShell)
{
}
};
void FModel::CheckTopology()
{
TArray<FBodyShell> IsolatedBodies;
IsolatedBodies.Reserve(Bodies.Num()*2);
int32 ShellCount = 0;
for (TSharedPtr<FBody> Body : Bodies)
{
for (TSharedPtr<FShell> Shell : Body->GetShells())
{
ShellCount++;
TArray<FFaceSubset> SubShells;
Shell->CheckTopology(SubShells);
if (SubShells.Num() == 1 )
{
if (Shell->FaceCount() < 3 )
{
IsolatedBodies.Emplace(Body, Shell);
}
else
{
if (SubShells[0].BorderEdgeCount > 0 || SubShells[0].NonManifoldEdgeCount > 0)
{
#ifdef CORETECHBRIDGE_DEBUG
FMessage::Printf(Log, TEXT("Body %d shell %d CADId %d is opened and has %d faces "), Body->GetKioId(), Shell->GetKioId(), Shell->GetId(), Shell->FaceCount());
#else
FMessage::Printf(Log, TEXT("Body %d shell %d is opened and has %d faces "), Body->GetId(), Shell->GetId(), Shell->FaceCount());
#endif
FMessage::Printf(Log, TEXT("and has %d border edges and %d nonManifold edges\n"), SubShells[0].BorderEdgeCount, SubShells[0].NonManifoldEdgeCount);
}
else
{
#ifdef CORETECHBRIDGE_DEBUG
FMessage::Printf(Log, TEXT("Body %d shell %d CADId %d is closed and has %d faces\n"), Body->GetKioId(), Shell->GetKioId(), Shell->GetId(), Shell->FaceCount());
#else
FMessage::Printf(Log, TEXT("Body %d shell %d is closed and has %d faces\n"), Body->GetId(), Shell->GetId(), Shell->FaceCount());
#endif
}
}
}
else
{
#ifdef CORETECHBRIDGE_DEBUG
FMessage::Printf(Log, TEXT("Body %d shell %d CADId %d has %d subshells\n"), Body->GetKioId(), Shell->GetKioId(), Shell->GetId(), SubShells.Num());
#else
FMessage::Printf(Log, TEXT("Body %d shell %d has %d subshells\n"), Body->GetId(), Shell->GetId(), SubShells.Num());
#endif
for (const FFaceSubset& Subset : SubShells)
{
FMessage::Printf(Log, TEXT(" - Subshell of %d faces %d border edges and %d nonManifold edges\n"), Subset. Faces.Num(), Subset.BorderEdgeCount, Subset.NonManifoldEdgeCount);
}
}
}
}
}
#ifdef CADKERNEL_DEV
void FModel::FillTopologyReport(FTopologyReport& Report) const
{
for (TSharedPtr<FBody> Body : Bodies)
{
Body->FillTopologyReport(Report);
}
Report.ResetMarkers();
}
#endif
void FModel::Orient()
{
for (TSharedPtr<FBody> Body : Bodies)
{
Body->Orient();
}
}
}