Files
2025-05-18 13:04:45 +08:00

1442 lines
41 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "TechSoftBridge.h"
#ifdef USE_TECHSOFT_SDK
#include "CADSceneGraph.h"
#include "TechSoftInterface.h"
#include "TechSoftFileParser.h"
#include "TechSoftUtils.h"
#include "TUniqueTechSoftObj.h"
#include "Core/Session.h"
#include "Geo/Curves/Curve.h"
#include "Geo/Curves/NURBSCurveData.h"
#include "Geo/Surfaces/NurbsSurfaceData.h"
#include "Geo/Surfaces/Surface.h"
#include "Topo/Body.h"
#include "Topo/Model.h"
#include "Topo/Shell.h"
#include "Topo/TopologicalEdge.h"
#include "Topo/TopologicalFace.h"
#include "Topo/TopologicalLink.h"
#include "Topo/TopologicalVertex.h"
#include "Utils/StringUtil.h"
#include "UI/Display.h"
#ifdef CADKERNEL_DEV
#include "CADFileReport.h"
#endif
namespace CADLibrary
{
namespace TechSoftUtils
{
template<typename... InArgTypes>
A3DStatus GetCurveAsNurbs(const A3DCrvBase* A3DCurve, A3DCrvNurbsData* DataPtr, InArgTypes&&... Args)
{
return TechSoftInterface::GetCurveAsNurbs(A3DCurve, DataPtr, Forward<InArgTypes>(Args)...);
};
template<typename... InArgTypes>
A3DStatus GetSurfaceAsNurbs(const A3DSurfBase* A3DSurface, A3DSurfNurbsData* DataPtr, InArgTypes&&... Args)
{
return TechSoftInterface::GetSurfaceAsNurbs(A3DSurface, DataPtr, Forward<InArgTypes>(Args)...);
};
UE::CADKernel::FMatrixH CreateCoordinateSystem(const A3DMiscCartesianTransformationData& Transformation, double UnitScale = 1.0)
{
using namespace UE::CADKernel;
FVector Origin(Transformation.m_sOrigin.m_dX, Transformation.m_sOrigin.m_dY, Transformation.m_sOrigin.m_dZ);
FVector Ox(Transformation.m_sXVector.m_dX, Transformation.m_sXVector.m_dY, Transformation.m_sXVector.m_dZ);
FVector Oy(Transformation.m_sYVector.m_dX, Transformation.m_sYVector.m_dY, Transformation.m_sYVector.m_dZ);
Ox.Normalize();
Oy.Normalize();
if (!FMath::IsNearlyEqual(UnitScale, 1.))
{
Origin *= UnitScale;
}
FVector Oz = Ox ^ Oy;
FMatrixH Matrix = FMatrixH(Origin, Ox, Oy, Oz);
if (!FMath::IsNearlyEqual(Transformation.m_sScale.m_dX, 1.) || !FMath::IsNearlyEqual(Transformation.m_sScale.m_dY, 1.) || !FMath::IsNearlyEqual(Transformation.m_sScale.m_dZ, 1.))
{
FMatrixH Scale = FMatrixH::MakeScaleMatrix(Transformation.m_sScale.m_dX, Transformation.m_sScale.m_dY, Transformation.m_sScale.m_dZ);
Matrix *= Scale;
}
return Matrix;
}
void FillInt32Array(const int32 Count, const A3DInt32* Values, TArray<int32>& OutInt32Array)
{
OutInt32Array.Reserve(Count);
for (int32 Index = 0; Index < Count; Index++)
{
OutInt32Array.Add(Values[Index]);
}
};
void FillDoubleArray(const int32 Count, const double* Values, TArray<double>& OutDoubleArray)
{
OutDoubleArray.Reserve(Count);
for (int32 Index = 0; Index < Count; Index++)
{
OutDoubleArray.Add(Values[Index]);
}
};
void FillDoubleArray(const int32 UCount, const int32 VCount, const double* Values, TArray<double>& OutDoubleArray)
{
OutDoubleArray.SetNum(UCount * VCount);
for (int32 Undex = 0, ValueIndex = 0; Undex < UCount; ++Undex)
{
int32 Index = Undex;
for (int32 Vndex = 0; Vndex < VCount; ++Vndex, Index += UCount, ++ValueIndex)
{
OutDoubleArray[Index] = Values[ValueIndex];
}
}
}
void FillPointArray(const int32 Count, const A3DVector3dData* Points, TArray<FVector>& OutPointsArray, double UnitScale = 1.0)
{
using namespace UE::CADKernel;
OutPointsArray.Reserve(Count);
for (int32 Index = 0; Index < Count; Index++)
{
OutPointsArray.Emplace(Points[Index].m_dX, Points[Index].m_dY, Points[Index].m_dZ);
}
if (!FMath::IsNearlyEqual(UnitScale, 1.))
{
for (FVector& Point : OutPointsArray)
{
Point *= UnitScale;
}
}
};
void FillPointArray(const int32 UCount, const int32 VCount, const A3DVector3dData* Points, TArray<FVector>& OutPointsArray, double UnitScale = 1.0)
{
using namespace UE::CADKernel;
OutPointsArray.SetNum(UCount * VCount);
for (int32 Undex = 0, PointIndex = 0; Undex < UCount; ++Undex)
{
int32 Index = Undex;
for (int32 Vndex = 0; Vndex < VCount; ++Vndex, Index += UCount, ++PointIndex)
{
OutPointsArray[Index].Set(Points[PointIndex].m_dX, Points[PointIndex].m_dY, Points[PointIndex].m_dZ);
}
}
if (!FMath::IsNearlyEqual(UnitScale, 1.))
{
for (FVector& Point : OutPointsArray)
{
Point *= UnitScale;
}
}
};
UE::CADKernel::FSurfacicBoundary GetSurfacicBoundary(A3DDomainData& Domain, const TechSoftUtils::FUVReparameterization& UVReparameterization)
{
using namespace UE::CADKernel;
FVector2d Min(Domain.m_sMin.m_dX, Domain.m_sMin.m_dY);
FVector2d Max(Domain.m_sMax.m_dX, Domain.m_sMax.m_dY);
if (UVReparameterization.GetNeedApply())
{
UVReparameterization.Apply(Min);
UVReparameterization.Apply(Max);
}
EIso UIndex = UVReparameterization.GetSwapUV() ? EIso::IsoV : EIso::IsoU;
EIso VIndex = UVReparameterization.GetSwapUV() ? EIso::IsoU : EIso::IsoV;
FSurfacicBoundary Boundary;
Boundary[UIndex].Min = FMath::Min(Min.X, Max.X);
Boundary[UIndex].Max = FMath::Max(Min.X, Max.X);
Boundary[VIndex].Min = FMath::Min(Min.Y, Max.Y);
Boundary[VIndex].Max = FMath::Max(Min.Y, Max.Y);
return Boundary;
}
UE::CADKernel::FLinearBoundary GetLinearBoundary(A3DIntervalData& A3DDomain)
{
UE::CADKernel::FLinearBoundary Domain(A3DDomain.m_dMin, A3DDomain.m_dMax);
return Domain;
}
UE::CADKernel::FLinearBoundary GetLinearBoundary(const A3DCrvBase* A3DCurve)
{
TUniqueTSObj<A3DIntervalData> A3DDomain(A3DCurve);
UE::CADKernel::FLinearBoundary Domain(A3DDomain->m_dMin, A3DDomain->m_dMax);
return Domain;
}
} // namespace TechSoftUtils
FTechSoftBridge::FTechSoftBridge(FTechSoftFileParser& InParser, UE::CADKernel::FSession& InSession)
: Parser(InParser)
, Session(InSession)
, Model(InSession.GetModel())
, GeometricTolerance(Session.GetGeometricTolerance())
, EdgeLengthTolerance(Session.GetGeometricTolerance() * 2.)
, SquareGeometricTolerance(FMath::Square(Session.GetGeometricTolerance()))
, SquareJoiningVertexTolerance(SquareGeometricTolerance * 2)
{
}
const A3DRiBrepModel* FTechSoftBridge::GetA3DBody(UE::CADKernel::FBody* BRepModel)
{
const A3DEntity** BodyPtr = CADKernelToTechSoft.Find(BRepModel);
if (BodyPtr)
{
return (A3DRiBrepModel*)*BodyPtr;
}
return nullptr;
}
UE::CADKernel::FBody* FTechSoftBridge::GetBody(A3DRiBrepModel* A3DBRepModel)
{
TSharedPtr<UE::CADKernel::FBody>* BodyPtr = TechSoftToCADKernel.Find(A3DBRepModel);
if (BodyPtr && !(*BodyPtr)->IsDeleted())
{
return (*BodyPtr).Get();
}
return nullptr;
}
UE::CADKernel::FBody* FTechSoftBridge::AddBody(A3DRiBrepModel* A3DBRepModel, FArchiveCADObject& ArchiveBody)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().BodyCount++;
#endif
//UE::CADKernel working unit is mm
BodyScale = ArchiveBody.Unit * 10.;
FArchiveCADObject BRepMetaData;
Parser.ExtractMetaData(A3DBRepModel, BRepMetaData);
FString* Name = ArchiveBody.MetaData.Find(TEXT("Name"));
if (Name != nullptr)
{
BRepMetaData.MetaData.FindOrAdd(TEXT("Name")) = *Name;
}
if (TSharedPtr<UE::CADKernel::FBody>* BodyPtr = TechSoftToCADKernel.Find(A3DBRepModel))
{
return (*BodyPtr)->IsDeleted() ? nullptr : (*BodyPtr).Get();
}
TSharedRef<UE::CADKernel::FBody> Body = UE::CADKernel::FEntity::MakeShared<UE::CADKernel::FBody>();
AddMetaData(BRepMetaData, *Body);
Body->SetDisplayData(ArchiveBody.ColorUId, ArchiveBody.MaterialUId);
TUniqueTSObj<A3DRiBrepModelData> BRepModelData(A3DBRepModel);
if (BRepModelData.IsValid())
{
TraverseBrepData(BRepModelData->m_pBrepData, Body);
}
if (Body->FaceCount() == 0 || bConvertionFailed)
{
Body->Delete();
return nullptr;
}
Model.Add(Body);
TechSoftToCADKernel.Add(A3DBRepModel, Body);
CADKernelToTechSoft.Add(&*Body, A3DBRepModel);
return &*Body;
}
void FTechSoftBridge::TraverseBrepData(const A3DTopoBrepData* A3DBrepData, TSharedRef<UE::CADKernel::FBody>& Body)
{
FArchiveCADObject MetaData;
Parser.ExtractMetaData(A3DBrepData, MetaData);
{
TUniqueTSObj<A3DTopoBodyData> TopoBodyData(A3DBrepData);
if (TopoBodyData.IsValid())
{
if (TopoBodyData->m_pContext)
{
TUniqueTSObj<A3DTopoContextData> TopoContextData(TopoBodyData->m_pContext);
if (TopoContextData.IsValid())
{
if (TopoContextData->m_bHaveScale)
{
BodyScale *= TopoContextData->m_dScale;
}
}
}
}
}
TUniqueTSObj<A3DTopoBrepDataData> TopoBrepData(A3DBrepData);
if (TopoBrepData.IsValid())
{
for (A3DUns32 Index = 0; Index < TopoBrepData->m_uiConnexSize; ++Index)
{
TraverseConnex(TopoBrepData->m_ppConnexes[Index], Body);
if (bConvertionFailed)
{
return;
}
}
}
}
void FTechSoftBridge::TraverseConnex(const A3DTopoConnex* A3DTopoConnex, TSharedRef<UE::CADKernel::FBody>& Body)
{
FArchiveCADObject MetaData;
Parser.ExtractMetaData(A3DTopoConnex, MetaData);
TUniqueTSObj<A3DTopoConnexData> TopoConnexData(A3DTopoConnex);
if (TopoConnexData.IsValid())
{
for (A3DUns32 Index = 0; Index < TopoConnexData->m_uiShellSize; ++Index)
{
TraverseShell(TopoConnexData->m_ppShells[Index], Body);
if (bConvertionFailed)
{
return;
}
}
}
}
void FTechSoftBridge::TraverseShell(const A3DTopoShell* A3DShell, TSharedRef<UE::CADKernel::FBody>& Body)
{
FArchiveCADObject MetaData;
Parser.ExtractMetaData(A3DShell, MetaData);
TSharedRef<UE::CADKernel::FShell> Shell = UE::CADKernel::FEntity::MakeShared<UE::CADKernel::FShell>();
Body->AddShell(Shell);
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().ShellCount++;
#endif
Shell->SetDisplayData(*Body);
AddMetaData(MetaData, *Shell);
TUniqueTSObj<A3DTopoShellData> ShellData(A3DShell);
if (ShellData.IsValid())
{
A3DEdgeToEdge.Empty();
for (A3DUns32 Index = 0; Index < ShellData->m_uiFaceSize; ++Index)
{
AddFace(ShellData->m_ppFaces[Index], ShellData->m_pucOrientationWithShell[Index] == 1 ? UE::CADKernel::Front : UE::CADKernel::Back, Shell, Index);
if (bConvertionFailed)
{
return;
}
}
}
}
static bool bUseCurveAsNurbs = true;
TSharedPtr<UE::CADKernel::FCurve> FTechSoftBridge::AddCurve(const A3DCrvBase* A3DCurve, const TechSoftUtils::FUVReparameterization& UVReparameterization)
{
TSharedPtr<UE::CADKernel::FCurve> Curve = TSharedPtr<UE::CADKernel::FCurve>();
A3DEEntityType eType;
A3DInt32 Ret = TechSoftInterface::GetEntityType(A3DCurve, &eType);
if (Ret == A3D_SUCCESS)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().CurveCount++;
#endif
switch (eType)
{
case kA3DTypeCrvNurbs:
Curve = AddCurveNurbs(A3DCurve, UVReparameterization);
break;
case kA3DTypeCrvLine:
Curve = AddCurveLine(A3DCurve, UVReparameterization);
break;
case kA3DTypeCrvCircle:
Curve = AddCurveCircle(A3DCurve, UVReparameterization);
break;
case kA3DTypeCrvEllipse:
Curve = AddCurveEllipse(A3DCurve, UVReparameterization);
break;
case kA3DTypeCrvParabola:
Curve = AddCurveParabola(A3DCurve, UVReparameterization);
break;
case kA3DTypeCrvHyperbola:
Curve = AddCurveHyperbola(A3DCurve, UVReparameterization);
break;
case kA3DTypeCrvHelix:
Curve = AddCurveHelix(A3DCurve, UVReparameterization);
break;
case kA3DTypeCrvPolyLine:
Curve = AddCurvePolyLine(A3DCurve, UVReparameterization);
break;
case kA3DTypeCrvComposite:
Curve = AddCurveComposite(A3DCurve, UVReparameterization);
break;
default:
Curve = AddCurveAsNurbs(A3DCurve, UVReparameterization);
break;
}
}
UE::CADKernel::FLinearBoundary Boundary = TechSoftUtils::GetLinearBoundary(A3DCurve);
return Curve;
}
TSharedPtr<UE::CADKernel::FCurve> FTechSoftBridge::AddCurveLine(const A3DCrvLine* A3DCurve, const TechSoftUtils::FUVReparameterization& UVReparameterization)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().CurveLineCount++;
#endif
if (bUseCurveAsNurbs)
{
return AddCurveAsNurbs(A3DCurve, UVReparameterization);
}
TUniqueTSObj<A3DCrvLineData> CrvLineData(A3DCurve);
if (!CrvLineData.IsValid())
{
return TSharedPtr<UE::CADKernel::FCurve>();
}
bool bIs2D = (bool)CrvLineData->m_bIs2D;
// Todo
return TSharedPtr<UE::CADKernel::FCurve>();
}
TSharedPtr<UE::CADKernel::FCurve> FTechSoftBridge::AddCurveCircle(const A3DCrvCircle* A3DCurve, const TechSoftUtils::FUVReparameterization& UVReparameterization)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().CurveCircleCount++;
#endif
if (bUseCurveAsNurbs)
{
return AddCurveAsNurbs(A3DCurve, UVReparameterization);
}
TUniqueTSObj<A3DCrvCircleData> CrvCircleData(A3DCurve);
if (!CrvCircleData.IsValid())
{
return TSharedPtr<UE::CADKernel::FCurve>();
}
bool bIs2D = (bool)CrvCircleData->m_bIs2D;
// Todo
return TSharedPtr<UE::CADKernel::FCurve>();
}
TSharedPtr<UE::CADKernel::FCurve> FTechSoftBridge::AddCurveEllipse(const A3DCrvEllipse* A3DCurve, const TechSoftUtils::FUVReparameterization& UVReparameterization)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().CurveEllipseCount++;
#endif
if (bUseCurveAsNurbs)
{
return AddCurveAsNurbs(A3DCurve, UVReparameterization);
}
TUniqueTSObj<A3DCrvEllipseData> CrvEllipseData(A3DCurve);
if (!CrvEllipseData.IsValid())
{
return TSharedPtr<UE::CADKernel::FCurve>();
}
bool bIs2D = (bool)CrvEllipseData->m_bIs2D;
// Todo
return TSharedPtr<UE::CADKernel::FCurve>();
}
TSharedPtr<UE::CADKernel::FCurve> FTechSoftBridge::AddCurveParabola(const A3DCrvParabola* A3DCurve, const TechSoftUtils::FUVReparameterization& UVReparameterization)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().CurveParabolaCount++;
#endif
if (bUseCurveAsNurbs)
{
return AddCurveAsNurbs(A3DCurve, UVReparameterization);
}
TUniqueTSObj<A3DCrvParabolaData> CrvParabolaData(A3DCurve);
if (!CrvParabolaData.IsValid())
{
return TSharedPtr<UE::CADKernel::FCurve>();
}
bool bIs2D = (bool)CrvParabolaData->m_bIs2D;
// Todo
return TSharedPtr<UE::CADKernel::FCurve>();
}
TSharedPtr<UE::CADKernel::FCurve> FTechSoftBridge::AddCurveHyperbola(const A3DCrvHyperbola* A3DCurve, const TechSoftUtils::FUVReparameterization& UVReparameterization)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().CurveHyperbolaCount++;
#endif
if (bUseCurveAsNurbs)
{
return AddCurveAsNurbs(A3DCurve, UVReparameterization);
}
TUniqueTSObj<A3DCrvHyperbolaData> CrvHyperbolaData(A3DCurve);
if (!CrvHyperbolaData.IsValid())
{
return TSharedPtr<UE::CADKernel::FCurve>();
}
bool bIs2D = (bool)CrvHyperbolaData->m_bIs2D;
// Todo
return TSharedPtr<UE::CADKernel::FCurve>();
}
TSharedPtr<UE::CADKernel::FCurve> FTechSoftBridge::AddCurveHelix(const A3DCrvHelix* A3DCurve, const TechSoftUtils::FUVReparameterization& UVReparameterization)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().CurveHelixCount++;
#endif
if (bUseCurveAsNurbs)
{
return AddCurveAsNurbs(A3DCurve, UVReparameterization);
}
TUniqueTSObj<A3DCrvHelixData> CrvHelixData(A3DCurve);
if (!CrvHelixData.IsValid())
{
return TSharedPtr<UE::CADKernel::FCurve>();
}
bool bIs2D = (bool)CrvHelixData->m_bIs2D;
return TSharedPtr<UE::CADKernel::FCurve>();
}
TSharedPtr<UE::CADKernel::FCurve> FTechSoftBridge::AddCurvePolyLine(const A3DCrvPolyLine* A3DCurve, const TechSoftUtils::FUVReparameterization& UVReparameterization)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().CurvePolyLineCount++;
#endif
if (bUseCurveAsNurbs)
{
return AddCurveAsNurbs(A3DCurve, UVReparameterization);
}
TUniqueTSObj<A3DCrvPolyLineData> CrvPolyLineData(A3DCurve);
if (!CrvPolyLineData.IsValid())
{
return TSharedPtr<UE::CADKernel::FCurve>();
}
bool bIs2D = (bool)CrvPolyLineData->m_bIs2D;
// Todo
return TSharedPtr<UE::CADKernel::FCurve>();
}
TSharedPtr<UE::CADKernel::FCurve> FTechSoftBridge::AddCurveComposite(const A3DCrvComposite* A3DCurve, const TechSoftUtils::FUVReparameterization& UVReparameterization)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().CurveCompositeCount++;
#endif
if (bUseCurveAsNurbs)
{
return AddCurveAsNurbs(A3DCurve, UVReparameterization);
}
TUniqueTSObj<A3DCrvCompositeData> CrvCompositeData(A3DCurve);
if (!CrvCompositeData.IsValid())
{
return TSharedPtr<UE::CADKernel::FCurve>();
}
bool bIs2D = (bool)CrvCompositeData->m_bIs2D;
// Todo
return TSharedPtr<UE::CADKernel::FCurve>();
}
TSharedPtr<UE::CADKernel::FCurve> AddCurveNurbsFromData(A3DCrvNurbsData& A3DNurbs, const TechSoftUtils::FUVReparameterization& UVReparameterization)
{
UE::CADKernel::FNurbsCurveData Nurbs;
Nurbs.Dimension = A3DNurbs.m_bIs2D ? 2 : 3;
Nurbs.bIsRational = (bool)A3DNurbs.m_bRational;
Nurbs.Degree = A3DNurbs.m_uiDegree;
TechSoftUtils::FillPointArray(A3DNurbs.m_uiCtrlSize, A3DNurbs.m_pCtrlPts, Nurbs.Poles);
if (Nurbs.Dimension == 2)
{
UVReparameterization.Process(Nurbs.Poles);
}
TechSoftUtils::FillDoubleArray(A3DNurbs.m_uiKnotSize, A3DNurbs.m_pdKnots, Nurbs.NodalVector);
if (Nurbs.bIsRational)
{
TechSoftUtils::FillDoubleArray(A3DNurbs.m_uiCtrlSize, A3DNurbs.m_pdWeights, Nurbs.Weights);
}
A3DCrvNurbsGet(NULL, &A3DNurbs);
return UE::CADKernel::FCurve::MakeNurbsCurve(Nurbs);
}
TSharedPtr<UE::CADKernel::FCurve> FTechSoftBridge::AddCurveNurbs(const A3DCrvNurbs* A3DNurbs, const TechSoftUtils::FUVReparameterization& UVReparameterization)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().CurveLineCount++;
#endif
TUniqueTSObj<A3DCrvNurbsData> CrvNurbsData(A3DNurbs);
if (!CrvNurbsData.IsValid())
{
return TSharedPtr<UE::CADKernel::FCurve>();
}
return AddCurveNurbsFromData(*CrvNurbsData, UVReparameterization);
}
TSharedPtr<UE::CADKernel::FCurve> FTechSoftBridge::AddCurveAsNurbs(const A3DCrvBase* A3DCurve, const TechSoftUtils::FUVReparameterization& UVReparameterization)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().CurveAsNurbsCount++;
#endif
TUniqueTSObj<A3DCrvNurbsData> NurbsData;
A3DDouble Tolerance = 1e-3;
A3DBool bUseSameParameterization = true;
NurbsData.FillWith(&TechSoftUtils::GetCurveAsNurbs, A3DCurve, Tolerance, bUseSameParameterization);
if (!NurbsData.IsValid())
{
return TSharedPtr<UE::CADKernel::FCurve>();
}
return AddCurveNurbsFromData(*NurbsData, UVReparameterization);
}
TSharedPtr<UE::CADKernel::FTopologicalEdge> FTechSoftBridge::AddEdge(const A3DTopoCoEdge* A3DCoedge, const TSharedRef<UE::CADKernel::FSurface>& Surface, const TechSoftUtils::FUVReparameterization& UVReparameterization, UE::CADKernel::EOrientation& OutOrientation)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().EdgeCount++;
#endif
TUniqueTSObj<A3DTopoCoEdgeData> CoEdgeData(A3DCoedge);
if (!CoEdgeData.IsValid())
{
return TSharedPtr<UE::CADKernel::FTopologicalEdge>();
}
if (CoEdgeData->m_pUVCurve == nullptr)
{
bConvertionFailed = true;
FailureReason = EFailureReason::Curve3D;
return TSharedPtr<UE::CADKernel::FTopologicalEdge>();
}
TSharedPtr<UE::CADKernel::FCurve> Curve = AddCurve(CoEdgeData->m_pUVCurve, UVReparameterization);
if (!Curve.IsValid())
{
return TSharedPtr<UE::CADKernel::FTopologicalEdge>();
}
TSharedRef<UE::CADKernel::FRestrictionCurve> RestrictionCurve = UE::CADKernel::FEntity::MakeShared<UE::CADKernel::FRestrictionCurve>(Surface, Curve.ToSharedRef());
TSharedPtr<UE::CADKernel::FTopologicalEdge> Edge = UE::CADKernel::FTopologicalEdge::Make(RestrictionCurve);
if (!Edge.IsValid())
{
return TSharedPtr<UE::CADKernel::FTopologicalEdge>();
}
A3DEdgeToEdge.Emplace(A3DCoedge, Edge);
OutOrientation = CoEdgeData->m_ucOrientationUVWithLoop > 0 ? UE::CADKernel::EOrientation::Front : UE::CADKernel::EOrientation::Back;
return Edge;
}
TSharedPtr<UE::CADKernel::FTopologicalLoop> FTechSoftBridge::AddLoop(const A3DTopoLoop* A3DLoop, const TSharedRef<UE::CADKernel::FSurface>& Surface, const TechSoftUtils::FUVReparameterization& UVReparameterization, const bool bIsExternalLoop)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().LoopCount++;
#endif
TArray<TSharedPtr<UE::CADKernel::FTopologicalEdge>> Edges;
TArray<UE::CADKernel::EOrientation> Directions;
TUniqueTSObj<A3DTopoLoopData> TopoLoopData(A3DLoop);
if (!TopoLoopData.IsValid())
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().DegeneratedLoopCount++;
#endif
return TSharedPtr<UE::CADKernel::FTopologicalLoop>();
}
bool bLoopOrientation = (bool)TopoLoopData->m_ucOrientationWithSurface;
for (A3DUns32 Index = 0; Index < TopoLoopData->m_uiCoEdgeSize; ++Index)
{
UE::CADKernel::EOrientation Orientation;
TSharedPtr<UE::CADKernel::FTopologicalEdge> Edge = AddEdge(TopoLoopData->m_ppCoEdges[Index], Surface, UVReparameterization, Orientation);
if (!Edge.IsValid())
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().DegeneratedEdgeCount++;
#endif
continue;
}
Edges.Emplace(Edge);
Directions.Emplace(Orientation);
}
if (Edges.Num() == 0)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().DegeneratedLoopCount++;
#endif
return TSharedPtr<UE::CADKernel::FTopologicalLoop>();
}
TSharedPtr<UE::CADKernel::FTopologicalLoop> Loop = UE::CADKernel::FTopologicalLoop::Make(Edges, Directions, bIsExternalLoop, GeometricTolerance);
// Link the edges of the loop with their neighbors if possible
for (A3DUns32 Index = 0; Index < TopoLoopData->m_uiCoEdgeSize; ++Index)
{
const A3DTopoCoEdge* A3DCoedge = TopoLoopData->m_ppCoEdges[Index];
TSharedPtr<UE::CADKernel::FTopologicalEdge>* Edge = A3DEdgeToEdge.Find(A3DCoedge);
if (Edge == nullptr || !Edge->IsValid() || (*Edge)->IsDeleted())
{
continue;
}
TUniqueTSObj<A3DTopoCoEdgeData> CoEdgeData(A3DCoedge);
if (!CoEdgeData.IsValid())
{
continue;
}
if (CoEdgeData->m_pNeighbor)
{
const A3DTopoCoEdge* Neighbor = CoEdgeData->m_pNeighbor;
while (Neighbor && Neighbor != A3DCoedge)
{
TSharedPtr<UE::CADKernel::FTopologicalEdge>* TwinEdge = A3DEdgeToEdge.Find(Neighbor);
if (TwinEdge != nullptr && TwinEdge->IsValid() && !(*TwinEdge)->IsDeleted())
{
(*Edge)->LinkIfCoincident(*TwinEdge->Get(), EdgeLengthTolerance, SquareJoiningVertexTolerance);
}
// Next
TUniqueTSObj<A3DTopoCoEdgeData> NeighborData(Neighbor);
if (NeighborData.IsValid())
{
Neighbor = NeighborData->m_pNeighbor;
}
else
{
break;
}
}
}
}
return Loop;
}
void FTechSoftBridge::AddFace(const A3DTopoFace* A3DFace, UE::CADKernel::EOrientation Orientation, TSharedRef<UE::CADKernel::FShell>& Shell, uint32 ShellIndex)
{
using namespace UE::CADKernel;
#ifdef CADKERNEL_DEV
FCADFileReport::Get().FaceCount++;
#endif
FArchiveCADObject MetaData;
Parser.ExtractMetaData(A3DFace, MetaData);
TUniqueTSObj<A3DTopoFaceData> TopoFaceData(A3DFace);
if (!TopoFaceData.IsValid())
{
#ifdef CADKERNEL_DEV
FCADFileReport::Get().FailedFaceCount++;
#endif
return;
}
const A3DSurfBase* A3DSurface = TopoFaceData->m_pSurface;
TechSoftUtils::FUVReparameterization UVReparameterization;
TSharedPtr<FSurface> SurfacePtr = AddSurface(A3DSurface, UVReparameterization);
if (!SurfacePtr.IsValid())
{
#ifdef CADKERNEL_DEV
FCADFileReport::Get().DegeneratedSurfaceCount++;
FCADFileReport::Get().FailedFaceCount++;
#endif
return;
}
if (UVReparameterization.GetNeedSwapOrientation())
{
SwapOrientation(Orientation);
}
TSharedRef<FSurface> Surface = SurfacePtr.ToSharedRef();
TSharedRef<FTopologicalFace> Face = FEntity::MakeShared<FTopologicalFace>(Surface);
if (TopoFaceData->m_bHasTrimDomain)
{
FSurfacicBoundary SurfaceBoundary = TechSoftUtils::GetSurfacicBoundary(TopoFaceData->m_sSurfaceDomain, UVReparameterization);
Surface->TrimBoundaryTo(SurfaceBoundary);
}
if (!TopoFaceData->m_uiLoopSize)
{
Face->ApplyNaturalLoops();
}
else
{
TArray<TSharedPtr<FTopologicalLoop>> Loops;
const uint32 OuterLoopIndex = TopoFaceData->m_uiOuterLoopIndex;
for (A3DUns32 Index = 0; Index < TopoFaceData->m_uiLoopSize; ++Index)
{
const bool bIsExternalLoop = (Index == OuterLoopIndex);
TSharedPtr<FTopologicalLoop> Loop = AddLoop(TopoFaceData->m_ppLoops[Index], Surface, UVReparameterization, bIsExternalLoop);
if (!Loop.IsValid())
{
continue;
}
TArray<FVector2d> LoopSampling;
Loop->Get2DSampling(LoopSampling);
FAABB2D Boundary;
Boundary += LoopSampling;
Loop->Boundary.Set(Boundary.GetMin(), Boundary.GetMax());
// Check if the loop is not composed with only degenerated edge
bool bDegeneratedLoop = true;
for (const FOrientedEdge& Edge : Loop->GetEdges())
{
if (!Edge.Entity->IsDegenerated())
{
bDegeneratedLoop = false;
break;
}
}
if (bDegeneratedLoop)
{
continue;
}
Loops.Add(Loop);
}
if (Loops.Num() > 1)
{
// Check external loop
TSharedPtr<FTopologicalLoop> ExternalLoop;
FSurfacicBoundary ExternalBoundary;
ExternalBoundary.Init();
for (const TSharedPtr<FTopologicalLoop>& Loop : Loops)
{
// fast but not accurate test to check if the loop is inside an other loop based of the bounding box
switch (Loop->Boundary.IsInside(ExternalBoundary, Surface->GetIsoTolerances()))
{
case ESituation::Undefined:
{
// accurate test to check if the loop is inside an other loop
if (!Loop->IsInside(*ExternalLoop))
{
ExternalBoundary = Loop->Boundary;
ExternalLoop = Loop;
}
break;
}
case ESituation::Outside:
{
ExternalBoundary = Loop->Boundary;
ExternalLoop = Loop;
break;
}
default:
break;
}
}
if (!ExternalLoop->IsExternal())
{
#ifdef CADKERNEL_DEV
FCADFileReport::Get().WrongExternalLoopCount++;
FMessage::Printf(Log, TEXT("ERROR: Face %d had wrong external loop\n"), Face->GetId());
#endif
for (TSharedPtr<FTopologicalLoop>& Loop : Loops)
{
if (Loop->IsExternal())
{
Loop->SetInternal();
break;
}
}
ExternalLoop->SetExternal();
}
}
if (Loops.Num() == 0)
{
#ifdef CADKERNEL_DEV
FCADFileReport::Get().FailedFaceCount++;
#endif
Face->SetAsDegenerated();
Face->Delete();
return;
}
else
{
int32 DoubtfulLoopOrientationCount = 0;
Face->AddLoops(Loops, DoubtfulLoopOrientationCount);
#ifdef CADKERNEL_DEV
FCADFileReport::Get().DoubtfulLoopOrientationCount += DoubtfulLoopOrientationCount;
#endif
}
}
if (Face->GetLoops().Num() == 0)
{
#ifdef CADKERNEL_DEV
FMessage::Printf(EVerboseLevel::Log, TEXT("A Face is degenerate, this face is ignored\n"));
FCADFileReport::Get().FailedFaceCount++;
#endif
Face->SetAsDegenerated();
Face->Delete();
return;
}
AddMetaData(MetaData, *Face);
Face->CompleteMetaData();
Face->SetHostId(ShellIndex);
Shell->Add(Face, Orientation);
}
static bool bUseSurfaceAsNurbs = true;
TSharedPtr<UE::CADKernel::FSurface> FTechSoftBridge::AddSurface(const A3DSurfBase* A3DSurface, TechSoftUtils::FUVReparameterization& OutUVReparameterization)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().SurfaceCount++;
#endif
FArchiveCADObject MetaData;
Parser.ExtractMetaData(A3DSurface, MetaData);
A3DEEntityType Type;
int32 Ret = TechSoftInterface::GetEntityType(A3DSurface, &Type);
if (Ret == A3D_SUCCESS)
{
switch (Type)
{
case kA3DTypeSurfBlend01:
return AddBlend01Surface(A3DSurface, OutUVReparameterization);
case kA3DTypeSurfBlend02:
return AddBlend02Surface(A3DSurface, OutUVReparameterization);
case kA3DTypeSurfBlend03:
return AddBlend03Surface(A3DSurface, OutUVReparameterization);
case kA3DTypeSurfNurbs:
return AddNurbsSurface(A3DSurface, OutUVReparameterization);
case kA3DTypeSurfCone:
return AddConeSurface(A3DSurface, OutUVReparameterization);
case kA3DTypeSurfCylinder:
return AddCylinderSurface(A3DSurface, OutUVReparameterization);
case kA3DTypeSurfCylindrical:
return AddCylindricalSurface(A3DSurface, OutUVReparameterization);
case kA3DTypeSurfOffset:
return AddOffsetSurface(A3DSurface, OutUVReparameterization);
case kA3DTypeSurfPipe:
return AddPipeSurface(A3DSurface, OutUVReparameterization);
case kA3DTypeSurfPlane:
return AddPlaneSurface(A3DSurface, OutUVReparameterization);
case kA3DTypeSurfRuled:
return AddRuledSurface(A3DSurface, OutUVReparameterization);
case kA3DTypeSurfSphere:
return AddSphereSurface(A3DSurface, OutUVReparameterization);
case kA3DTypeSurfRevolution:
return AddRevolutionSurface(A3DSurface, OutUVReparameterization);
case kA3DTypeSurfExtrusion:
return AddExtrusionSurface(A3DSurface, OutUVReparameterization);
case kA3DTypeSurfFromCurves:
return AddSurfaceFromCurves(A3DSurface, OutUVReparameterization);
case kA3DTypeSurfTorus:
return AddTorusSurface(A3DSurface, OutUVReparameterization);
case kA3DTypeSurfTransform:
return AddTransformSurface(A3DSurface, OutUVReparameterization);
default:
return AddSurfaceAsNurbs(A3DSurface, OutUVReparameterization);
}
}
else if (Ret == A3D_NOT_IMPLEMENTED)
{
return AddSurfaceAsNurbs(A3DSurface, OutUVReparameterization);
}
return TSharedPtr<UE::CADKernel::FSurface>();
}
TSharedPtr<UE::CADKernel::FSurface> FTechSoftBridge::AddConeSurface(const A3DSurfBase* Surface, TechSoftUtils::FUVReparameterization& OutUVReparameterization)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().ConeSurfaceCount++;
#endif
TUniqueTSObj<A3DSurfConeData> A3DConeData(Surface);
if (!A3DConeData.IsValid())
{
return TSharedPtr<UE::CADKernel::FSurface>();
}
OutUVReparameterization.AddUVTransform(A3DConeData->m_sParam);
OutUVReparameterization.ScaleUVTransform(1, BodyScale);
if (A3DConeData->m_dSemiAngle < 0)
{
OutUVReparameterization.SetNeedSwapOrientation();
}
UE::CADKernel::FMatrixH CoordinateSystem = TechSoftUtils::CreateCoordinateSystem(A3DConeData->m_sTrsf, BodyScale);
UE::CADKernel::FSurfacicBoundary Boundary = TechSoftUtils::GetSurfacicBoundary(A3DConeData->m_sParam.m_sUVDomain, OutUVReparameterization);
return UE::CADKernel::FSurface::MakeConeSurface(GeometricTolerance, CoordinateSystem, A3DConeData->m_dRadius * BodyScale, A3DConeData->m_dSemiAngle, Boundary);
}
TSharedPtr<UE::CADKernel::FSurface> FTechSoftBridge::AddCylinderSurface(const A3DSurfBase* Surface, TechSoftUtils::FUVReparameterization& OutUVReparameterization)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().CylinderSurfaceCount++;
#endif
TUniqueTSObj<A3DSurfCylinderData> A3DCylinderData(Surface);
if (!A3DCylinderData.IsValid())
{
return TSharedPtr<UE::CADKernel::FSurface>();
}
OutUVReparameterization.AddUVTransform(A3DCylinderData->m_sParam);
OutUVReparameterization.ScaleUVTransform(1, BodyScale);
UE::CADKernel::FMatrixH CoordinateSystem = TechSoftUtils::CreateCoordinateSystem(A3DCylinderData->m_sTrsf, BodyScale);
UE::CADKernel::FSurfacicBoundary Boundary = TechSoftUtils::GetSurfacicBoundary(A3DCylinderData->m_sParam.m_sUVDomain, OutUVReparameterization);
return UE::CADKernel::FSurface::MakeCylinderSurface(GeometricTolerance, CoordinateSystem, A3DCylinderData->m_dRadius * BodyScale, Boundary);
}
TSharedPtr<UE::CADKernel::FSurface> FTechSoftBridge::AddLinearTransfoSurface(const A3DSurfBase* Surface, TechSoftUtils::FUVReparameterization& OutUVReparameterization)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().LinearTransfoSurfaceCount++;
#endif
if (bUseSurfaceAsNurbs)
{
return AddSurfaceAsNurbs(Surface, OutUVReparameterization);
}
// Todo
return TSharedPtr<UE::CADKernel::FSurface>();
}
TSharedPtr<UE::CADKernel::FSurface> FTechSoftBridge::AddNurbsSurface(const A3DSurfNurbs* Nurbs, TechSoftUtils::FUVReparameterization& OutUVReparameterization)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().NurbsSurfaceCount++;
#endif
TUniqueTSObj<A3DSurfNurbsData> A3DNurbsData(Nurbs);
if (!A3DNurbsData.IsValid())
{
return TSharedPtr<UE::CADKernel::FSurface>();
}
return AddSurfaceNurbs(*A3DNurbsData, OutUVReparameterization);
}
TSharedPtr<UE::CADKernel::FSurface> FTechSoftBridge::AddOffsetSurface(const A3DSurfBase* Surface, TechSoftUtils::FUVReparameterization& OutUVReparameterization)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().OffsetSurfaceCount++;
#endif
if (bUseSurfaceAsNurbs)
{
return AddSurfaceAsNurbs(Surface, OutUVReparameterization);
}
return TSharedPtr<UE::CADKernel::FSurface>();
}
TSharedPtr<UE::CADKernel::FSurface> FTechSoftBridge::AddPlaneSurface(const A3DSurfPlane* Surface, TechSoftUtils::FUVReparameterization& OutUVReparameterization)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().PlaneSurfaceCount++;
#endif
TUniqueTSObj<A3DSurfPlaneData> A3DPlaneData(Surface);
if (!A3DPlaneData.IsValid())
{
return TSharedPtr<UE::CADKernel::FSurface>();
}
OutUVReparameterization.AddUVTransform(A3DPlaneData->m_sParam);
OutUVReparameterization.ScaleUVTransform(BodyScale, BodyScale);
UE::CADKernel::FMatrixH CoordinateSystem = TechSoftUtils::CreateCoordinateSystem(A3DPlaneData->m_sTrsf, BodyScale);
UE::CADKernel::FSurfacicBoundary Boundary = TechSoftUtils::GetSurfacicBoundary(A3DPlaneData->m_sParam.m_sUVDomain, OutUVReparameterization);
return UE::CADKernel::FSurface::MakePlaneSurface(GeometricTolerance, CoordinateSystem, Boundary);
}
TSharedPtr<UE::CADKernel::FSurface> FTechSoftBridge::AddRevolutionSurface(const A3DSurfRevolution* Surface, TechSoftUtils::FUVReparameterization& OutUVReparameterization)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().RevolutionSurfaceCount++;
#endif
if (bUseSurfaceAsNurbs)
{
return AddSurfaceAsNurbs(Surface, OutUVReparameterization);
}
TUniqueTSObj<A3DSurfRevolutionData> A3DRevolutionData(Surface);
if (!A3DRevolutionData.IsValid())
{
return TSharedPtr<UE::CADKernel::FSurface>();
}
return TSharedPtr<UE::CADKernel::FSurface>();
}
TSharedPtr<UE::CADKernel::FSurface> FTechSoftBridge::AddRuledSurface(const A3DSurfBase* Surface, TechSoftUtils::FUVReparameterization& OutUVReparameterization)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().RuledSurfaceCount++;
#endif
if (bUseSurfaceAsNurbs)
{
return AddSurfaceAsNurbs(Surface, OutUVReparameterization);
}
TUniqueTSObj<A3DSurfRuledData> A3DRuledData(Surface);
if (!A3DRuledData.IsValid())
{
return TSharedPtr<UE::CADKernel::FSurface>();
}
return TSharedPtr<UE::CADKernel::FSurface>();
}
TSharedPtr<UE::CADKernel::FSurface> FTechSoftBridge::AddSphereSurface(const A3DSurfBase* Surface, TechSoftUtils::FUVReparameterization& OutUVReparameterization)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().SphereSurfaceCount++;
#endif
TUniqueTSObj<A3DSurfSphereData> A3DSphereData(Surface);
if (!A3DSphereData.IsValid())
{
return TSharedPtr<UE::CADKernel::FSurface>();
}
OutUVReparameterization.AddUVTransform(A3DSphereData->m_sParam);
UE::CADKernel::FMatrixH CoordinateSystem = TechSoftUtils::CreateCoordinateSystem(A3DSphereData->m_sTrsf, BodyScale);
UE::CADKernel::FSurfacicBoundary Boundary = TechSoftUtils::GetSurfacicBoundary(A3DSphereData->m_sParam.m_sUVDomain, OutUVReparameterization);
return UE::CADKernel::FSurface::MakeSphericalSurface(GeometricTolerance, CoordinateSystem, A3DSphereData->m_dRadius * BodyScale, Boundary);
}
TSharedPtr<UE::CADKernel::FSurface> FTechSoftBridge::AddTorusSurface(const A3DSurfBase* Surface, TechSoftUtils::FUVReparameterization& OutUVReparameterization)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().TorusSurfaceCount++;
#endif
TUniqueTSObj<A3DSurfTorusData> A3DTorusData(Surface);
if (!A3DTorusData.IsValid())
{
return TSharedPtr<UE::CADKernel::FSurface>();
}
OutUVReparameterization.AddUVTransform(A3DTorusData->m_sParam);
UE::CADKernel::FMatrixH CoordinateSystem = TechSoftUtils::CreateCoordinateSystem(A3DTorusData->m_sTrsf, BodyScale);
UE::CADKernel::FSurfacicBoundary Boundary = TechSoftUtils::GetSurfacicBoundary(A3DTorusData->m_sParam.m_sUVDomain, OutUVReparameterization);
return UE::CADKernel::FSurface::MakeTorusSurface(GeometricTolerance, CoordinateSystem, A3DTorusData->m_dMajorRadius * BodyScale, A3DTorusData->m_dMinorRadius * BodyScale, Boundary);
}
TSharedPtr<UE::CADKernel::FSurface> FTechSoftBridge::AddBlend01Surface(const A3DSurfBase* Surface, TechSoftUtils::FUVReparameterization& OutUVReparameterization)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().Blend01SurfaceCount++;
#endif
if (bUseSurfaceAsNurbs)
{
return AddSurfaceAsNurbs(Surface, OutUVReparameterization);
}
TUniqueTSObj<A3DSurfBlend01Data> A3DBlend01Data(Surface);
if (!A3DBlend01Data.IsValid())
{
return TSharedPtr<UE::CADKernel::FSurface>();
}
return TSharedPtr<UE::CADKernel::FSurface>();
}
TSharedPtr<UE::CADKernel::FSurface> FTechSoftBridge::AddBlend02Surface(const A3DSurfBase* Surface, TechSoftUtils::FUVReparameterization& OutUVReparameterization)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().Blend02SurfaceCount++;
#endif
if (bUseSurfaceAsNurbs)
{
return AddSurfaceAsNurbs(Surface, OutUVReparameterization);
}
TUniqueTSObj<A3DSurfBlend02Data> A3DBlend02Data(Surface);
if (!A3DBlend02Data.IsValid())
{
return TSharedPtr<UE::CADKernel::FSurface>();
}
return TSharedPtr<UE::CADKernel::FSurface>();
}
TSharedPtr<UE::CADKernel::FSurface> FTechSoftBridge::AddBlend03Surface(const A3DSurfBase* Surface, TechSoftUtils::FUVReparameterization& OutUVReparameterization)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().Blend03SurfaceCount++;
#endif
if (bUseSurfaceAsNurbs)
{
return AddSurfaceAsNurbs(Surface, OutUVReparameterization);
}
return TSharedPtr<UE::CADKernel::FSurface>();
}
TSharedPtr<UE::CADKernel::FSurface> FTechSoftBridge::AddCylindricalSurface(const A3DSurfBase* Surface, TechSoftUtils::FUVReparameterization& OutUVReparameterization)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().CylindricalSurfaceCount++;
#endif
if (bUseSurfaceAsNurbs)
{
return AddSurfaceAsNurbs(Surface, OutUVReparameterization);
}
TUniqueTSObj<A3DSurfCylindricalData> A3DCylindricalData(Surface);
if (!A3DCylindricalData.IsValid())
{
return TSharedPtr<UE::CADKernel::FSurface>();
}
return TSharedPtr<UE::CADKernel::FSurface>();
}
TSharedPtr<UE::CADKernel::FSurface> FTechSoftBridge::AddPipeSurface(const A3DSurfBase* Surface, TechSoftUtils::FUVReparameterization& OutUVReparameterization)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().PipeSurfaceCount++;
#endif
if (bUseSurfaceAsNurbs)
{
return AddSurfaceAsNurbs(Surface, OutUVReparameterization);
}
TUniqueTSObj<A3DSurfPipeData> A3DPipeData(Surface);
if (!A3DPipeData.IsValid())
{
return TSharedPtr<UE::CADKernel::FSurface>();
}
return TSharedPtr<UE::CADKernel::FSurface>();
}
TSharedPtr<UE::CADKernel::FSurface> FTechSoftBridge::AddExtrusionSurface(const A3DSurfBase* Surface, TechSoftUtils::FUVReparameterization& OutUVReparameterization)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().ExtrusionSurfaceCount++;
#endif
if (bUseSurfaceAsNurbs)
{
return AddSurfaceAsNurbs(Surface, OutUVReparameterization);
}
TUniqueTSObj<A3DSurfExtrusionData> A3DExtrusionData(Surface);
if (!A3DExtrusionData.IsValid())
{
return TSharedPtr<UE::CADKernel::FSurface>();
}
return TSharedPtr<UE::CADKernel::FSurface>();
}
TSharedPtr<UE::CADKernel::FSurface> FTechSoftBridge::AddSurfaceFromCurves(const A3DSurfBase* Surface, TechSoftUtils::FUVReparameterization& OutUVReparameterization)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().SurfaceFromCurvesCount++;
#endif
if (bUseSurfaceAsNurbs)
{
return AddSurfaceAsNurbs(Surface, OutUVReparameterization);
}
TUniqueTSObj<A3DSurfFromCurvesData> A3DFromCurvesData(Surface);
if (!A3DFromCurvesData.IsValid())
{
return TSharedPtr<UE::CADKernel::FSurface>();
}
return TSharedPtr<UE::CADKernel::FSurface>();
}
TSharedPtr<UE::CADKernel::FSurface> FTechSoftBridge::AddTransformSurface(const A3DSurfBase* Surface, TechSoftUtils::FUVReparameterization& OutUVReparameterization)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().TransformSurfaceCount++;
#endif
if (bUseSurfaceAsNurbs)
{
return AddSurfaceAsNurbs(Surface, OutUVReparameterization);
}
TUniqueTSObj<A3DSurfFromCurvesData> A3DTransformData(Surface);
if (!A3DTransformData.IsValid())
{
return TSharedPtr<UE::CADKernel::FSurface>();
}
return TSharedPtr<UE::CADKernel::FSurface>();
}
TSharedPtr<UE::CADKernel::FSurface> FTechSoftBridge::AddSurfaceNurbs(const A3DSurfNurbsData& A3DNurbsData, TechSoftUtils::FUVReparameterization& OutUVReparameterization)
{
using namespace UE::CADKernel;
FNurbsSurfaceData NurbsData;
NurbsData.PoleUCount = A3DNurbsData.m_uiUCtrlSize;
NurbsData.PoleVCount = A3DNurbsData.m_uiVCtrlSize;
int32 PoleCount = A3DNurbsData.m_uiUCtrlSize * A3DNurbsData.m_uiVCtrlSize;
NurbsData.UDegree = A3DNurbsData.m_uiUDegree;
NurbsData.VDegree = A3DNurbsData.m_uiVDegree;
TechSoftUtils::FillDoubleArray(A3DNurbsData.m_uiUKnotSize, A3DNurbsData.m_pdUKnots, NurbsData.UNodalVector);
TechSoftUtils::FillDoubleArray(A3DNurbsData.m_uiVKnotSize, A3DNurbsData.m_pdVKnots, NurbsData.VNodalVector);
TArray<FVector> Poles;
TechSoftUtils::FillPointArray(NurbsData.PoleUCount, NurbsData.PoleVCount, A3DNurbsData.m_pCtrlPts, NurbsData.Poles);
if (!FMath::IsNearlyEqual(BodyScale, 1.))
{
for (FVector& Point : NurbsData.Poles)
{
Point *= BodyScale;
}
}
bool bIsRational = false;
if (A3DNurbsData.m_pdWeights)
{
bIsRational = true;
TechSoftUtils::FillDoubleArray(NurbsData.PoleUCount, NurbsData.PoleVCount, A3DNurbsData.m_pdWeights, NurbsData.Weights);
}
return UE::CADKernel::FSurface::MakeNurbsSurface(GeometricTolerance, NurbsData);
}
TSharedPtr<UE::CADKernel::FSurface> FTechSoftBridge::AddSurfaceAsNurbs(const A3DSurfBase* Surface, TechSoftUtils::FUVReparameterization& OutUVReparameterization)
{
#ifdef CADKERNEL_DEV
UE::CADKernel::FCADFileReport::Get().SurfaceAsNurbsCount++;
#endif
TUniqueTSObj<A3DSurfNurbsData> A3DNurbsData;
A3DDouble Tolerance = 1e-3;
A3DBool bUseSameParameterization = true;
A3DNurbsData.FillWith(&TechSoftUtils::GetSurfaceAsNurbs, Surface, Tolerance, bUseSameParameterization);
if (!A3DNurbsData.IsValid())
{
return TSharedPtr<UE::CADKernel::FSurface>();
}
return AddSurfaceNurbs(*A3DNurbsData, OutUVReparameterization);
}
void FTechSoftBridge::AddMetaData(FArchiveCADObject& MetaData, UE::CADKernel::FTopologicalShapeEntity& Entity)
{
FString* Name = MetaData.MetaData.Find(TEXT("Name"));
if (Name != nullptr)
{
Entity.SetName(*Name);
}
Entity.SetDisplayData(MetaData.ColorUId, MetaData.MaterialUId);
}
}
#endif // USE_TECHSOFT_SDK