#ifndef _DE_ShapeFixParameters_HeaderFile
#define _DE_ShapeFixParameters_HeaderFile
+#include <TopAbs_ShapeEnum.hxx>
+
//! Struct for shape healing parameters storage
struct DE_ShapeFixParameters
{
enum class FixMode : signed char
{
FixOrNot = -1, //!< Procedure will be executed or not (depending on the situation)
- NotFix = 0, //!< Procedure will be executed
- Fix = 1 //!< Procedure will be executed anyway
+ NotFix = 0, //!< Procedure will be executed
+ Fix = 1 //!< Procedure will be executed anyway
};
- double Tolerance3d = 1.e-6;
- double MaxTolerance3d = 1.0;
- double MinTolerance3d = 1.e-7;
- FixMode FixFreeShellMode = FixMode::FixOrNot;
- FixMode FixFreeFaceMode = FixMode::FixOrNot;
- FixMode FixFreeWireMode = FixMode::FixOrNot;
- FixMode FixSameParameterMode = FixMode::FixOrNot;
- FixMode FixSolidMode = FixMode::FixOrNot;
- FixMode FixShellOrientationMode = FixMode::FixOrNot;
- FixMode CreateOpenSolidMode = FixMode::NotFix;
- FixMode FixShellMode = FixMode::FixOrNot;
- FixMode FixFaceOrientationMode = FixMode::FixOrNot;
- FixMode FixFaceMode = FixMode::FixOrNot;
- FixMode FixWireMode = FixMode::FixOrNot;
- FixMode FixOrientationMode = FixMode::FixOrNot;
- FixMode FixAddNaturalBoundMode = FixMode::FixOrNot;
- FixMode FixMissingSeamMode = FixMode::FixOrNot;
- FixMode FixSmallAreaWireMode = FixMode::FixOrNot;
- FixMode RemoveSmallAreaFaceMode = FixMode::FixOrNot;
- FixMode FixIntersectingWiresMode = FixMode::FixOrNot;
- FixMode FixLoopWiresMode = FixMode::FixOrNot;
- FixMode FixSplitFaceMode = FixMode::FixOrNot;
- FixMode AutoCorrectPrecisionMode = FixMode::FixOrNot;
- FixMode ModifyTopologyMode = FixMode::NotFix;
- FixMode ModifyGeometryMode = FixMode::Fix;
- FixMode ClosedWireMode = FixMode::Fix;
- FixMode PreferencePCurveMode = FixMode::Fix;
- FixMode FixReorderMode = FixMode::FixOrNot;
- FixMode FixSmallMode = FixMode::FixOrNot;
- FixMode FixConnectedMode = FixMode::FixOrNot;
- FixMode FixEdgeCurvesMode = FixMode::FixOrNot;
- FixMode FixDegeneratedMode = FixMode::FixOrNot;
- FixMode FixLackingMode = FixMode::FixOrNot;
- FixMode FixSelfIntersectionMode = FixMode::FixOrNot;
- FixMode RemoveLoopMode = FixMode::FixOrNot;
- FixMode FixReversed2dMode = FixMode::FixOrNot;
- FixMode FixRemovePCurveMode = FixMode::FixOrNot;
- FixMode FixRemoveCurve3dMode = FixMode::FixOrNot;
- FixMode FixAddPCurveMode = FixMode::FixOrNot;
- FixMode FixAddCurve3dMode = FixMode::FixOrNot;
- FixMode FixSeamMode = FixMode::FixOrNot;
- FixMode FixShiftedMode = FixMode::FixOrNot;
- FixMode FixEdgeSameParameterMode = FixMode::NotFix;
- FixMode FixNotchedEdgesMode = FixMode::FixOrNot;
- FixMode FixTailMode = FixMode::NotFix;
- FixMode MaxTailAngle = FixMode::NotFix;
- FixMode MaxTailWidth = FixMode::FixOrNot;
- FixMode FixSelfIntersectingEdgeMode = FixMode::FixOrNot;
- FixMode FixIntersectingEdgesMode = FixMode::FixOrNot;
- FixMode FixNonAdjacentIntersectingEdgesMode = FixMode::FixOrNot;
- FixMode FixVertexPositionMode = FixMode::NotFix;
- FixMode FixVertexToleranceMode = FixMode::FixOrNot;
+ double Tolerance3d = 1.e-6;
+ double MaxTolerance3d = 1.0;
+ double MinTolerance3d = 1.e-7;
+ TopAbs_ShapeEnum DetalizationLevel = TopAbs_ShapeEnum::TopAbs_FACE;
+ bool NonManifold = false;
+ FixMode FixFreeShellMode = FixMode::FixOrNot;
+ FixMode FixFreeFaceMode = FixMode::FixOrNot;
+ FixMode FixFreeWireMode = FixMode::FixOrNot;
+ FixMode FixSameParameterMode = FixMode::FixOrNot;
+ FixMode FixSolidMode = FixMode::FixOrNot;
+ FixMode FixShellOrientationMode = FixMode::FixOrNot;
+ FixMode CreateOpenSolidMode = FixMode::NotFix;
+ FixMode FixShellMode = FixMode::FixOrNot;
+ FixMode FixFaceOrientationMode = FixMode::FixOrNot;
+ FixMode FixFaceMode = FixMode::FixOrNot;
+ FixMode FixWireMode = FixMode::FixOrNot;
+ FixMode FixOrientationMode = FixMode::FixOrNot;
+ FixMode FixAddNaturalBoundMode = FixMode::FixOrNot;
+ FixMode FixMissingSeamMode = FixMode::FixOrNot;
+ FixMode FixSmallAreaWireMode = FixMode::FixOrNot;
+ FixMode RemoveSmallAreaFaceMode = FixMode::FixOrNot;
+ FixMode FixIntersectingWiresMode = FixMode::FixOrNot;
+ FixMode FixLoopWiresMode = FixMode::FixOrNot;
+ FixMode FixSplitFaceMode = FixMode::FixOrNot;
+ FixMode AutoCorrectPrecisionMode = FixMode::FixOrNot;
+ FixMode ModifyTopologyMode = FixMode::NotFix;
+ FixMode ModifyGeometryMode = FixMode::Fix;
+ FixMode ClosedWireMode = FixMode::Fix;
+ FixMode PreferencePCurveMode = FixMode::Fix;
+ FixMode FixReorderMode = FixMode::FixOrNot;
+ FixMode FixSmallMode = FixMode::FixOrNot;
+ FixMode FixConnectedMode = FixMode::FixOrNot;
+ FixMode FixEdgeCurvesMode = FixMode::FixOrNot;
+ FixMode FixDegeneratedMode = FixMode::FixOrNot;
+ FixMode FixLackingMode = FixMode::FixOrNot;
+ FixMode FixSelfIntersectionMode = FixMode::FixOrNot;
+ FixMode RemoveLoopMode = FixMode::FixOrNot;
+ FixMode FixReversed2dMode = FixMode::FixOrNot;
+ FixMode FixRemovePCurveMode = FixMode::FixOrNot;
+ FixMode FixRemoveCurve3dMode = FixMode::FixOrNot;
+ FixMode FixAddPCurveMode = FixMode::FixOrNot;
+ FixMode FixAddCurve3dMode = FixMode::FixOrNot;
+ FixMode FixSeamMode = FixMode::FixOrNot;
+ FixMode FixShiftedMode = FixMode::FixOrNot;
+ FixMode FixEdgeSameParameterMode = FixMode::NotFix;
+ FixMode FixNotchedEdgesMode = FixMode::FixOrNot;
+ FixMode FixTailMode = FixMode::NotFix;
+ FixMode MaxTailAngle = FixMode::NotFix;
+ FixMode MaxTailWidth = FixMode::FixOrNot;
+ FixMode FixSelfIntersectingEdgeMode = FixMode::FixOrNot;
+ FixMode FixIntersectingEdgesMode = FixMode::FixOrNot;
+ FixMode FixNonAdjacentIntersectingEdgesMode = FixMode::FixOrNot;
+ FixMode FixVertexPositionMode = FixMode::NotFix;
+ FixMode FixVertexToleranceMode = FixMode::FixOrNot;
};
#endif // _DE_ShapeFixParameters_HeaderFile
#include <ShapeProcess_Operator.hxx>
#include <Standard_ErrorHandler.hxx>
#include <Standard_Failure.hxx>
-#include <TCollection_AsciiString.hxx>
#include <TColStd_SequenceOfAsciiString.hxx>
+#include <TCollection_AsciiString.hxx>
static NCollection_DataMap<TCollection_AsciiString, Handle(ShapeProcess_Operator)> aMapOfOperators;
+
+namespace
+{
+ //! Simple RAII class to lock the scope of the current operation.
+ class ScopeLock
+ {
+ public:
+ //! Constructor.
+ //! Locks the scope of the current operation.
+ //! @param theContext the context to lock.
+ //! @param theScopeName the name of the scope to lock.
+ ScopeLock(ShapeProcess_Context& theContext, const char* theScopeName)
+ : myContext(theContext)
+ {
+ myContext.SetScope(theScopeName);
+ }
+
+ //! Destructor.
+ //! Unlocks the scope of the current operation.
+ ~ScopeLock()
+ {
+ myContext.UnSetScope();
+ }
+
+ private:
+ ShapeProcess_Context& myContext; //!< The context to lock.
+ };
+}
+
+
//=======================================================================
//function : RegisterOperator
//purpose :
const Standard_CString seq,
const Message_ProgressRange& theProgress)
{
- context->SetScope ( seq );
+ ScopeLock aSequenceScope(*context, seq);
// get description of the sequence
TCollection_AsciiString sequence;
Message_Msg SMSG3 ("SP.Sequence.Warn.NoSeq"); // Sequence %s not found
context->Messenger()->Send (SMSG3 << seq, Message_Warning);
}
- context->UnSetScope();
return Standard_False;
}
TColStd_SequenceOfAsciiString sequenceOfOperators;
continue;
}
- context->SetScope ( oper.ToCString() );
+ ScopeLock anOperationScope(*context, oper.ToCString());
try {
OCC_CATCH_SIGNALS
if (op->Perform(context, aRange))
SMSG2 << oper << anException.GetMessageString();
context->Messenger()->Send (SMSG2, Message_Alarm);
}
- context->UnSetScope();
}
- context->UnSetScope();
return isDone;
}
+
+//=======================================================================
+//function : Perform
+//purpose :
+//=======================================================================
+Standard_Boolean ShapeProcess::Perform(const Handle(ShapeProcess_Context)& theContext,
+ const OperationsFlags& theOperations,
+ const Message_ProgressRange& theProgress)
+{
+ if (!theContext)
+ {
+ return Standard_False;
+ }
+
+ std::vector<std::pair<const char*, Handle(ShapeProcess_Operator)>> anOperators = getOperators(theOperations);
+ if (anOperators.empty())
+ {
+ return Standard_False;
+ }
+
+ Standard_Boolean anIsAnySuccess = Standard_False;
+ Message_ProgressScope aProgressScope(theProgress, nullptr, static_cast<Standard_Real>(anOperators.size()));
+ for (const auto& anOperator : anOperators)
+ {
+ const char* anOperationName = anOperator.first;
+ const Handle(ShapeProcess_Operator)& anOperation = anOperator.second;
+ Message_ProgressRange aProgressRange = aProgressScope.Next();
+ ScopeLock anOperationScope(*theContext, anOperationName); // Set operation scope.
+ try
+ {
+ OCC_CATCH_SIGNALS;
+ anIsAnySuccess |= anOperation->Perform(theContext, aProgressRange);
+ }
+ catch (const Standard_Failure& anException)
+ {
+ Message_Msg aMessage("SP.Sequence.Error.Except"); //Operator %s failed with exception %s
+ aMessage << anOperationName << anException.GetMessageString();
+ theContext->Messenger()->Send(aMessage, Message_Alarm);
+ }
+ }
+ return anIsAnySuccess;
+}
+
+//=======================================================================
+//function : getOperators
+//purpose :
+//=======================================================================
+std::vector<std::pair<const char*, Handle(ShapeProcess_Operator)>> ShapeProcess::getOperators(const OperationsFlags& theFlags)
+{
+ std::vector<std::pair<const char*, Handle(ShapeProcess_Operator)>> aResult;
+ for (std::underlying_type<Operation>::type anOperation = Operation::First; anOperation < Operation::Count; ++anOperation)
+ {
+ if (theFlags.test(anOperation))
+ {
+ const char* anOperationName = toOperationName(static_cast<Operation>(anOperation));
+ if (!anOperationName)
+ {
+ continue;
+ }
+ Handle(ShapeProcess_Operator) anOperator;
+ if (FindOperator(anOperationName, anOperator))
+ {
+ aResult.emplace_back(anOperationName, anOperator);
+ }
+ }
+ }
+ return aResult;
+}
+
+//=======================================================================
+//function : toOperationName
+//purpose :
+//=======================================================================
+const char* ShapeProcess::toOperationName(const Operation theOperation)
+{
+ switch (theOperation)
+ {
+ case Operation::DirectFaces:
+ return "DirectFaces";
+
+ case Operation::SameParameter:
+ return "SameParameter";
+
+ case Operation::SetTolerance:
+ return "SetTolerance";
+
+ case Operation::SplitAngle:
+ return "SplitAngle";
+
+ case Operation::BSplineRestriction:
+ return "BSplineRestriction";
+
+ case Operation::ElementaryToRevolution:
+ return "ElementaryToRevolution";
+
+ case Operation::SweptToElementary:
+ return "SweptToElementary";
+
+ case Operation::SurfaceToBSpline:
+ return "SurfaceToBSpline";
+
+ case Operation::ToBezier:
+ return "ToBezier";
+
+ case Operation::SplitContinuity:
+ return "SplitContinuity";
+
+ case Operation::SplitClosedFaces:
+ return "SplitClosedFaces";
+
+ case Operation::FixWireGaps:
+ return "FixWireGaps";
+
+ case Operation::FixFaceSize:
+ return "FixFaceSize";
+
+ case Operation::DropSmallSolids:
+ return "DropSmallSolids";
+
+ case Operation::DropSmallEdges:
+ return "DropSmallEdges";
+
+ case Operation::FixShape:
+ return "FixShape";
+
+ case Operation::SplitClosedEdges:
+ return "SplitClosedEdges";
+
+ case Operation::SplitCommonVertex:
+ return "SplitCommonVertex";
+ }
+ return nullptr;
+}
#ifndef _ShapeProcess_HeaderFile
#define _ShapeProcess_HeaderFile
+#include <Message_ProgressRange.hxx>
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Standard_Handle.hxx>
-#include <Message_ProgressRange.hxx>
+#include <bitset>
+#include <vector>
class ShapeProcess_Operator;
class ShapeProcess_Context;
class ShapeProcess
{
public:
-
DEFINE_STANDARD_ALLOC
+ //! Describes all available operations.
+ //! C++11 enum class is not used to allow implicit conversion to undelying type.
+ enum Operation : uint8_t
+ {
+ First = 0, // First operation index.
+ DirectFaces = First,
+ SameParameter,
+ SetTolerance,
+ SplitAngle,
+ BSplineRestriction,
+ ElementaryToRevolution,
+ SweptToElementary,
+ SurfaceToBSpline,
+ ToBezier,
+ SplitContinuity,
+ SplitClosedFaces,
+ FixWireGaps,
+ FixFaceSize,
+ DropSmallSolids,
+ DropSmallEdges,
+ FixShape,
+ SplitClosedEdges,
+ SplitCommonVertex,
+ Count // Number of operations.
+ };
+
+ // Bitset of operations. It is used to specify which operations should be performed.
+ // For example, to perform DirectFaces and SameParameter operations, use:
+ // ShapeProcess::OperationsFlags flags;
+ // flags.set(ShapeProcess::Operation::DirectFaces);
+ // flags.set(ShapeProcess::Operation::SameParameter);
+ // ShapeProcess::Perform(context, flags);
+ using OperationsFlags = std::bitset<Operation::Count>;
+public:
//! Registers operator to make it visible for Performer
Standard_EXPORT static Standard_Boolean RegisterOperator (const Standard_CString name, const Handle(ShapeProcess_Operator)& op);
const Standard_CString seq,
const Message_ProgressRange& theProgress = Message_ProgressRange());
+ //! Performs a specified sequence of operators on @p theContext.
+ //! @param theContext Context to perform operations on. Contains the shape to process
+ //! and processing parameters. If processing parameters are not set, default values are used.
+ //! Parameters should be in a scope of operation, for example,
+ //! instead of "FromSTEP.FixShape.Tolerance3d" we should use just "FixShape.Tolerance3d".
+ //! @param theOperations Bitset of operations to perform.
+ //! @param theProgress Progress indicator.
+ //! @return true if at least one operation was performed, false otherwise.
+ Standard_EXPORT static Standard_Boolean Perform(const Handle(ShapeProcess_Context)& theContext,
+ const OperationsFlags& theOperations,
+ const Message_ProgressRange& theProgress = Message_ProgressRange());
+
+private:
+ //! Returns operators to be performed according to the specified flags.
+ //! @param theFlags Bitset of operations flags.
+ //! @return List of operators to perform: pairs of operator name and operator handle.
+ static std::vector<std::pair<const char*, Handle(ShapeProcess_Operator)>> getOperators(const OperationsFlags& theFlags);
+
+ //! Converts operation flag to its name.
+ //! @param theOperation Operation flag.
+ //! @return Operation name.
+ static const char* toOperationName(const Operation theOperation);
};
#endif // _ShapeProcess_HeaderFile
XSAlgo.hxx
XSAlgo_AlgoContainer.cxx
XSAlgo_AlgoContainer.hxx
+XSAlgo_ShapeProcessor.cxx
+XSAlgo_ShapeProcessor.hxx
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
-
-#include <BRep_Builder.hxx>
-#include <BRep_Tool.hxx>
-#include <BRepBuilderAPI_MakeEdge.hxx>
-#include <Geom2d_Curve.hxx>
-#include <Geom_Curve.hxx>
-#include <Geom_Surface.hxx>
-#include <gp_Pnt.hxx>
-#include <gp_Pnt2d.hxx>
+#include <BRepTools_ReShape.hxx>
#include <Interface_Static.hxx>
-#include <Message_Msg.hxx>
#include <Resource_Manager.hxx>
#include <ShapeAlgo.hxx>
#include <ShapeAlgo_AlgoContainer.hxx>
#include <ShapeAlgo_ToolContainer.hxx>
-#include <ShapeAnalysis_Edge.hxx>
-#include <ShapeBuild_Edge.hxx>
-#include <ShapeBuild_ReShape.hxx>
-#include <ShapeCustom.hxx>
#include <ShapeExtend_MsgRegistrator.hxx>
-#include <ShapeFix_Edge.hxx>
#include <ShapeFix_Shape.hxx>
-#include <ShapeProcess.hxx>
#include <ShapeProcess_ShapeContext.hxx>
-#include <Standard_ErrorHandler.hxx>
-#include <Standard_Failure.hxx>
-#include <Standard_Transient.hxx>
-#include <Standard_Type.hxx>
-#include <TopExp.hxx>
-#include <TopoDS.hxx>
-#include <TopoDS_Edge.hxx>
-#include <TopoDS_Face.hxx>
-#include <TopoDS_Shape.hxx>
-#include <TopoDS_Vertex.hxx>
-#include <TopTools_DataMapOfShapeShape.hxx>
+#include <TopExp_Explorer.hxx>
#include <Transfer_FinderProcess.hxx>
#include <Transfer_TransientListBinder.hxx>
#include <Transfer_TransientProcess.hxx>
#include <TransferBRep.hxx>
#include <TransferBRep_ShapeBinder.hxx>
#include <TransferBRep_ShapeMapper.hxx>
-#include <UnitsMethods.hxx>
#include <XSAlgo_AlgoContainer.hxx>
-#include <TopExp_Explorer.hxx>
+#include <XSAlgo_ShapeProcessor.hxx>
IMPLEMENT_STANDARD_RTTIEXT(XSAlgo_AlgoContainer,Standard_Transient)
//function : PrepareForTransfer
//purpose :
//=======================================================================
-
void XSAlgo_AlgoContainer::PrepareForTransfer() const
{
- UnitsMethods::SetCasCadeLengthUnit(Interface_Static::IVal("xstep.cascade.unit"));
+ XSAlgo_ShapeProcessor::PrepareForTransfer();
}
//=======================================================================
aStr += ".exec.op";
if (!aRsc->Find(aStr.ToCString()))
{
-#ifdef OCCT_DEBUG
- {
- static Standard_Integer aTime = 0;
- if (!aTime)
- std::cout << "Warning: XSAlgo_AlgoContainer::ProcessShape(): Sequence " << aStr.ToCString() <<
- " is not defined in " << thePrscfile << " resource; do default processing" << std::endl;
- aTime++;
- }
-#endif
// if reading, do default ShapeFix
if (!strncmp(thePseq, "read.", 5))
{
}
catch (Standard_Failure const& anException)
{
-#ifdef OCCT_DEBUG
- std::cout << "Error: XSAlgo_AlgoContainer::ProcessShape(): Exception in ShapeFix::Shape" << std::endl;
- anException.Print(std::cout); std::cout << std::endl;
-#endif
(void)anException;
}
return aContext->Result();
return aContext->Result();
}
-//=======================================================================
-//function : PerformFixShape
-//purpose :
-//=======================================================================
-
-/*
-TopoDS_Shape XSAlgo_AlgoContainer::PerformFixShape(const TopoDS_Shape& S,
- const Handle(Transfer_TransientProcess)& TP,
- const Standard_Real Prec,
- const Standard_Real MaxTol) const
-{
- if ( S.IsNull() ) return S;
-
- TopoDS_Shape shape = S;
- // fixing shape
- try {
- OCC_CATCH_SIGNALS
- Handle(ShapeFix_Shape) sfs = ShapeAlgo::AlgoContainer()->ToolContainer()->FixShape();
- sfs->Init ( S );
- sfs->SetMsgRegistrator ( new ShapeExtend_MsgRegistrator );
- sfs->SetPrecision ( Prec );
- sfs->SetMaxTolerance ( MaxTol );
- sfs->FixFaceTool()->FixWireTool()->FixSameParameterMode() = Standard_False;
- sfs->Perform();
-
- shape = sfs->Shape();
-
- // to be removed when messages come
- if ( shape == S || shape.IsNull() ) return S;
-
- // update map to reflect the substitutions
- Handle(ShapeBuild_ReShape) context = sfs->Context();
- const ShapeExtend_DataMapOfShapeListOfMsg& msgmap =
- Handle(ShapeExtend_MsgRegistrator)::DownCast (sfs->MsgRegistrator())->MapShape();
- for ( Standard_Integer i=1; i <= TP->NbMapped(); i++ ) {
- Handle(Transfer_Binder) bnd = TP->MapItem ( i );
- Handle(TransferBRep_ShapeBinder) sb = Handle(TransferBRep_ShapeBinder)::DownCast ( bnd );
- if ( sb.IsNull() || sb->Result().IsNull() ) continue;
-
- TopoDS_Shape orig = sb->Result();
-
- // update messages (messages must be taken from each level in the substitution map)
- TopoDS_Shape cur, next = orig;
- do {
- cur = next;
- Message_ListOfMsg msglist;
- if (msgmap.IsBound (cur)) {
- msglist = msgmap.Find (cur);
- for (Message_ListIteratorOfListOfMsg iter (msglist); iter.More(); iter.Next()) {
- const Message_Msg& msg = iter.Value();
- sb->AddWarning (msg.Value(), msg.Original());
- }
- }
- next = context->Value (cur);
- } while (cur != next);
-
- // update shapes
- TopoDS_Shape res;
- if ( ! context->Status ( orig, res, Standard_True ) ) continue;
-
- sb->SetResult ( res );
- }
- }
- catch (Standard_Failure) {
-#ifdef OCCT_DEBUG
- std::cout << "Error: XSAlgo_AlgoContainer::PerformFixShape(): Exception in ShapeFix::Shape" << std::endl;
-#endif
- }
- return shape;
-}
-*/
-
-// ============================================================================
-// Method : MakeEdgeOnCurve
-// Purpose : for CheckPCurve
-// ============================================================================
-
-static TopoDS_Edge MakeEdgeOnCurve(const TopoDS_Edge& edge)
-{
- TopoDS_Edge result;
- //BRep_Builder B; // B not used - see below (skl)
- Handle(Geom_Curve) C3d;
- ShapeAnalysis_Edge sae;
- Standard_Real cf, cl;
- if (!sae.Curve3d (edge, C3d, cf, cl, Standard_False ))
- return result;
- gp_Pnt PV1 = C3d->Value(cf);
- gp_Pnt PV2 = C3d->Value(cl);
- BRepBuilderAPI_MakeEdge mkEdge(C3d, PV1, PV2, cf, cl);
-//:S4136 Standard_Real tol = BRep_Tool::Tolerance (edge);
- ShapeBuild_Edge SBE; //skl 10.07.2001
- SBE.SetRange3d(mkEdge,cf,cl); //skl 10.07.2001
- result = mkEdge.Edge();
-//:S4136 B.UpdateEdge(result,tol);
- return result;
-}
-
//=======================================================================
//function : CheckPCurve
//purpose :
//=======================================================================
-Standard_Boolean XSAlgo_AlgoContainer::CheckPCurve (const TopoDS_Edge& E,
- const TopoDS_Face& face,
- const Standard_Real preci,
- const Standard_Boolean isSeam) const
+Standard_Boolean XSAlgo_AlgoContainer::CheckPCurve(const TopoDS_Edge& theEdge,
+ const TopoDS_Face& theFace,
+ const Standard_Real thePrecision,
+ const Standard_Boolean theIsSeam) const
{
- Standard_Real w1, w2;
- Handle(Geom2d_Curve) thePC;
- ShapeAnalysis_Edge sae;
- if ( ! sae.PCurve (E, face, thePC, w1, w2, Standard_False ) ) {
- return Standard_False;
- }
-
- // Check for pcurve longer than surface
- Handle(Geom_Surface) surf = BRep_Tool::Surface(face);
- Standard_Real UF,UL,VF,VL;
- surf->Bounds (UF,UL,VF,VL);
- gp_Pnt2d PUV1, PUV2;
- PUV1 = thePC->Value(w1);
- PUV2 = thePC->Value(w2);
- // Multi-periodique ? mieux vaut jeter (attention aux valeurs infinies)
- Standard_Real DU = Abs (PUV1.X() - PUV2.X());
- Standard_Real DV = Abs (PUV1.Y() - PUV2.Y());
- if ( DU/8. > (UL/6. - UF/6.) || DV/8. > (VL/6. - VF/6.) ) {
- ShapeBuild_Edge().RemovePCurve(E,face);
-#ifdef OCCT_DEBUG
- std::cout<<"Removing pcurve periodic"<<std::endl;
-#endif
- return Standard_False;
- }
-
- // Second Check : 2D and 3D consistency (if the Pcurve has not been
- // dropped)
- // On verifie aussi qu on ne s enroule pas trop ...
- // ex. : UVV en DEGRES sur une surface en RADIANS, recalee = 57 tours !
-
- Handle(Geom_Curve) C3d;
- Standard_Real cf1, cl1;
- sae.Curve3d (E, C3d, cf1, cl1, Standard_False );
-
- gp_Pnt P1 = surf->Value(PUV1.X(), PUV1.Y());
- gp_Pnt P2 = surf->Value(PUV2.X(), PUV2.Y());
- TopoDS_Vertex V1 = TopExp::FirstVertex(E);
- TopoDS_Vertex V2 = TopExp::LastVertex(E);
- gp_Pnt PV1 = ( C3d.IsNull() ? BRep_Tool::Pnt(V1) : C3d->Value(cf1) );
- gp_Pnt PV2 = ( C3d.IsNull() ? BRep_Tool::Pnt(V2) : C3d->Value(cl1) );
- Standard_Real Dist11 = PV1.Distance(P1), Dist22 = PV2.Distance(P2);
-
- if (!((Dist11 <= preci) && (Dist22 <= preci))) {
- ShapeBuild_Edge().RemovePCurve(E,face);
-#ifdef OCCT_DEBUG
- std::cout<<"Removing pcurve points"<<std::endl;
-#endif
- return Standard_False;
- }
-
- //
- // pdn checking deviation between pcurve and 3D curve
- //
-
- // Make temporary edge for analysis
- if ( C3d.IsNull() ) return Standard_False;
- TopoDS_Edge edge = MakeEdgeOnCurve(E);
-
- // fill it with pcurve(s)
- BRep_Builder B;
- Handle(Geom2d_Curve) seamPC;
- if ( isSeam ) {
- Standard_Real f, l;
- TopoDS_Shape REdge = E.Reversed() ;
- if ( ! sae.PCurve ( TopoDS::Edge ( REdge ),
- face, seamPC, f, l, Standard_False ) ||
- seamPC == thePC )
- seamPC = Handle(Geom2d_Curve)::DownCast ( thePC->Copy() );
- B.UpdateEdge ( edge, thePC, seamPC, face, 0.);
- }
- else B.UpdateEdge ( edge, thePC, face, 0.);
- B.Range(edge,face,w1,w2);
- B.SameRange(edge, Standard_False );
- //:S4136
- Standard_Integer SPmode = Interface_Static::IVal("read.stdsameparameter.mode");
- if ( SPmode )
- B.SameParameter (edge, Standard_False );
-
- // call FixSP to see what it will do
- Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge;
- sfe->FixSameParameter(edge);
- Standard_Real tol = BRep_Tool::Tolerance (edge);
- // Standard_Real tolV1 = BRep_Tool::Tolerance(TopExp::FirstVertex(edge));
- // Standard_Real tolV2 = BRep_Tool::Tolerance(TopExp::LastVertex(edge));
- Standard_Boolean sr = BRep_Tool::SameRange ( edge );
- Standard_Boolean sp = BRep_Tool::SameParameter ( edge );
-
- // if result is not nice, try to call projection and take the best
- if ( tol > Min ( 1., 2.*preci ) || ! sr ) {
- //pdn trying to recompute pcurve
- TopoDS_Edge edgePr = MakeEdgeOnCurve(E);
- sfe->FixAddPCurve(edgePr, face, isSeam, preci);
- sfe->FixSameParameter(edgePr);
- Standard_Real tolPr = BRep_Tool::Tolerance (edgePr);
- //pdn choose the best pcurve
- if ( tolPr < tol || ! sr ) {
- // tolV1 = BRep_Tool::Tolerance(TopExp::FirstVertex(edgePr));
- // tolV2 = BRep_Tool::Tolerance(TopExp::LastVertex(edgePr));
- sr = BRep_Tool::SameRange ( edgePr );
- sp = BRep_Tool::SameParameter ( edgePr );
- tol = tolPr;
- edge = edgePr;
- }
- }
-
- // get corrected pcurve from the temporary edge, and put to original
- sae.PCurve ( edge, face, thePC, w1, w2, Standard_False );
- if ( isSeam ) {
- Standard_Real f, l;
- TopoDS_Shape REdge = edge.Reversed();
- sae.PCurve ( TopoDS::Edge ( REdge ), face, seamPC, f, l, Standard_False );
- if ( E.Orientation() == TopAbs_REVERSED ) //:abv 14.11.01: coneEl.sat loop
- B.UpdateEdge ( E, seamPC, thePC, face, tol );
- else
- B.UpdateEdge ( E, thePC, seamPC, face, tol );
- }
- else B.UpdateEdge ( E, thePC, face, tol );
-
- B.UpdateVertex(V1,tol);
- B.UpdateVertex(V2,tol);
- B.Range(E,face, w1, w2);
- if(BRep_Tool::SameRange(E))
- B.SameRange( E, sr );
- if(BRep_Tool::SameParameter(E))
- B.SameParameter ( E, sp );
-
- return Standard_True;
+ return XSAlgo_ShapeProcessor::CheckPCurve(theEdge, theFace, thePrecision, theIsSeam);
}
//=======================================================================
if ( TransientListBinder->NbTransients() == 1 ) resBinder = new TransferBRep_ShapeBinder(sub);
else if ( TransientListBinder->NbTransients() > 1 ) {
resBinder->AddResult(TransientListBinder);
-// resBinder->SetNext(TransientListBinder, Standard_True);
-#ifdef OCCT_DEBUG
- std::cout<<"Info: TransientListBinder created for split shape"<<std::endl;
- }
- else {
- std::cout<<"Warning: XSAlgo_AlgoContainer::MergeTransferInfo() "
- <<"No results were found for split shape. "<<std::endl;
- //<<"Transfer_FinderProcess->NbMapped() = "<<FP->NbMapped()<<std::endl;
-#endif
}
}
}
//! Checks quality of pcurve of the edge on the given face,
//! and corrects it if necessary.
- Standard_EXPORT virtual Standard_Boolean CheckPCurve (const TopoDS_Edge& edge, const TopoDS_Face& face, const Standard_Real preci, const Standard_Boolean isSeam) const;
+ Standard_EXPORT virtual Standard_Boolean CheckPCurve (const TopoDS_Edge& theEdge,
+ const TopoDS_Face& theFace,
+ const Standard_Real thePrecision,
+ const Standard_Boolean theIsSeam) const;
Standard_EXPORT virtual void MergeTransferInfo (const Handle(Transfer_TransientProcess)& TP, const Handle(Standard_Transient)& info, const Standard_Integer startTPitem = 1) const;
--- /dev/null
+// Copyright (c) 2000-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include "XSAlgo_ShapeProcessor.hxx"
+
+#include <BRepBuilderAPI_MakeEdge.hxx>
+#include <BRepTools_ReShape.hxx>
+#include <BRep_Builder.hxx>
+#include <BRep_Tool.hxx>
+#include <Geom_Curve.hxx>
+#include <Interface_Static.hxx>
+#include <Message_ListOfMsg.hxx>
+#include <Resource_Manager.hxx>
+#include <ShapeAnalysis_Edge.hxx>
+#include <ShapeBuild_Edge.hxx>
+#include <ShapeExtend_MsgRegistrator.hxx>
+#include <ShapeFix_Edge.hxx>
+#include <ShapeProcess_ShapeContext.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
+#include <TransferBRep.hxx>
+#include <TransferBRep_ShapeBinder.hxx>
+#include <TransferBRep_ShapeMapper.hxx>
+#include <Transfer_FinderProcess.hxx>
+#include <Transfer_TransientListBinder.hxx>
+#include <Transfer_TransientProcess.hxx>
+#include <UnitsMethods.hxx>
+
+//=============================================================================
+
+XSAlgo_ShapeProcessor::XSAlgo_ShapeProcessor(const ParameterMap& theParameters,
+ const DE_ShapeFixParameters& theShapeFixParameters)
+: myParameters(theParameters)
+{
+ FillParameterMap(theShapeFixParameters, myParameters);
+}
+
+//=============================================================================
+
+XSAlgo_ShapeProcessor::XSAlgo_ShapeProcessor(const DE_ShapeFixParameters& theParameters)
+{
+ ParameterMap aMap;
+ FillParameterMap(theParameters, aMap);
+ myParameters = aMap;
+}
+
+//=============================================================================
+
+TopoDS_Shape XSAlgo_ShapeProcessor::ProcessShape(const TopoDS_Shape& theShape,
+ const OperationsFlags& theOperations,
+ const Message_ProgressRange& theProgress)
+{
+ initializeContext(theShape);
+ return ShapeProcess::Perform(myContext, theOperations, theProgress) ? myContext->Result() : theShape;
+}
+
+//=============================================================================
+
+void XSAlgo_ShapeProcessor::initializeContext(const TopoDS_Shape& theShape)
+{
+ myContext = new ShapeProcess_ShapeContext(theShape, nullptr);
+ for (const auto& aParameter : myParameters)
+ {
+ myContext->ResourceManager()->SetResource(aParameter.first.c_str(), aParameter.second.c_str());
+ }
+ // Read and set detalization level.
+ auto aDetalizationLevelPtr = myParameters.find("DetalizationLevel");
+ if (aDetalizationLevelPtr != myParameters.end())
+ {
+ const TopAbs_ShapeEnum aDetalizationLevel = static_cast<TopAbs_ShapeEnum>(std::stoi(aDetalizationLevelPtr->second.c_str()));
+ myContext->SetDetalisation(aDetalizationLevel);
+ }
+ // Read and set non-manifold flag.
+ auto aNonManifoldPtr = myParameters.find("NonManifold");
+ if (aNonManifoldPtr != myParameters.end())
+ {
+ const Standard_Boolean aNonManifold = static_cast<Standard_Boolean>(std::stoi(aNonManifoldPtr->second.c_str()));
+ myContext->SetNonManifold(aNonManifold);
+ }
+}
+
+//=============================================================================
+
+void XSAlgo_ShapeProcessor::addMessages(const Handle(ShapeExtend_MsgRegistrator)& theMessages,
+ const TopoDS_Shape& theShape,
+ Handle(Transfer_Binder)& theBinder)
+{
+ if (theMessages.IsNull())
+ {
+ return;
+ }
+
+ const Message_ListOfMsg* aShapeMessages = theMessages->MapShape().Seek(theShape);
+ if (!aShapeMessages)
+ {
+ return;
+ }
+
+ for (Message_ListIteratorOfListOfMsg aMsgIter(*aShapeMessages); aMsgIter.More(); aMsgIter.Next())
+ {
+ const Message_Msg& aMessage = aMsgIter.Value();
+ theBinder->AddWarning(TCollection_AsciiString(aMessage.Value()).ToCString(),
+ TCollection_AsciiString(aMessage.Original()).ToCString());
+ }
+}
+
+//=============================================================================
+
+void XSAlgo_ShapeProcessor::MergeTransferInfo(const Handle(Transfer_TransientProcess)& theTransientProcess,
+ const Standard_Integer theFirstTPItemIndex) const
+{
+ if (myContext.IsNull())
+ {
+ return;
+ }
+
+ const TopTools_DataMapOfShapeShape& aShapesMap = myContext->Map();
+ Handle(ShapeExtend_MsgRegistrator) aMessages = myContext->Messages();
+ if (aShapesMap.IsEmpty() && (aMessages.IsNull() || aMessages->MapShape().IsEmpty()))
+ {
+ return;
+ }
+
+ for (Standard_Integer i = std::max(theFirstTPItemIndex, 1); i <= theTransientProcess->NbMapped(); ++i)
+ {
+ Handle(TransferBRep_ShapeBinder) aShapeBinder = Handle(TransferBRep_ShapeBinder)::DownCast(theTransientProcess->MapItem(i));
+ if (aShapeBinder.IsNull() || aShapeBinder->Result().IsNull())
+ {
+ continue;
+ }
+
+ const TopoDS_Shape anOriginalShape = aShapeBinder->Result();
+
+ if (aShapesMap.IsBound(anOriginalShape))
+ {
+ aShapeBinder->SetResult(aShapesMap.Find(anOriginalShape));
+ }
+ else if (!anOriginalShape.Location().IsIdentity())
+ {
+ TopLoc_Location aNullLoc;
+ TopoDS_Shape aTemporaryShape = anOriginalShape.Located(aNullLoc);
+ if (aShapesMap.IsBound(aTemporaryShape))
+ {
+ aShapeBinder->SetResult(aShapesMap.Find(aTemporaryShape));
+ }
+ }
+ else
+ {
+ // Some of edges may be modified.
+ BRepTools_ReShape aReShaper;
+ Standard_Boolean aHasModifiedEdges = Standard_False;
+ // Remember modifications.
+ for (TopExp_Explorer anExpSE(anOriginalShape, TopAbs_EDGE); anExpSE.More(); anExpSE.Next())
+ {
+ if (aShapesMap.IsBound(anExpSE.Current()))
+ {
+ aHasModifiedEdges = Standard_True;
+ TopoDS_Shape aModifiedShape = aShapesMap.Find(anExpSE.Current());
+ aReShaper.Replace(anExpSE.Current(), aModifiedShape);
+ }
+ }
+ // Apply modifications and store result in binder.
+ if (aHasModifiedEdges)
+ {
+ TopoDS_Shape aReshapedShape = aReShaper.Apply(anOriginalShape);
+ aShapeBinder->SetResult(aReshapedShape);
+ }
+ }
+
+ // update messages
+ addMessages(aMessages, anOriginalShape, aShapeBinder);
+ }
+}
+
+//=============================================================================
+
+void XSAlgo_ShapeProcessor::MergeTransferInfo(const Handle(Transfer_FinderProcess)& theFinderProcess) const
+{
+ if (myContext.IsNull())
+ {
+ return;
+ }
+
+ const TopTools_DataMapOfShapeShape& aShapesMap = myContext->Map();
+ Handle(ShapeExtend_MsgRegistrator) aMessages = myContext->Messages();
+
+ for (TopTools_DataMapIteratorOfDataMapOfShapeShape ShapeShapeIterator(aShapesMap); ShapeShapeIterator.More();
+ ShapeShapeIterator.Next())
+ {
+ const TopoDS_Shape anOriginalShape = ShapeShapeIterator.Key();
+ const TopoDS_Shape aResultShape = ShapeShapeIterator.Value();
+
+ Handle(TransferBRep_ShapeMapper) aResultMapper = TransferBRep::ShapeMapper(theFinderProcess, aResultShape);
+ Handle(Transfer_Binder) aResultBinder = theFinderProcess->Find(aResultMapper);
+
+ if (aResultBinder.IsNull())
+ {
+ aResultBinder = new TransferBRep_ShapeBinder(aResultShape);
+ //if <orig> shape was split, put entities corresponding to new shapes
+ // into Transfer_TransientListBinder.
+ if (anOriginalShape.ShapeType() > aResultShape.ShapeType())
+ {
+ TopoDS_Shape aSubShape;
+ Handle(Transfer_TransientListBinder) aTransientListBinder = new Transfer_TransientListBinder;
+ for (TopoDS_Iterator aSubShapeIter(aResultShape); aSubShapeIter.More(); aSubShapeIter.Next())
+ {
+ const TopoDS_Shape aCurrentSubShape = aSubShapeIter.Value();
+ Handle(Transfer_Finder) aSubShapeMapper = TransferBRep::ShapeMapper(theFinderProcess, aCurrentSubShape);
+ if (aSubShapeMapper.IsNull())
+ {
+ continue;
+ }
+
+ Handle(Standard_Transient) aTransientResult = theFinderProcess->FindTransient(aSubShapeMapper);
+ if (aTransientResult.IsNull())
+ {
+ continue;
+ }
+ aTransientListBinder->AddResult(aTransientResult);
+ aSubShape = aCurrentSubShape;
+ }
+ if (aTransientListBinder->NbTransients() == 1)
+ {
+ aResultBinder = new TransferBRep_ShapeBinder(aSubShape);
+ }
+ else if (aTransientListBinder->NbTransients() > 1)
+ {
+ aResultBinder->AddResult(aTransientListBinder);
+ }
+ }
+ }
+
+ Handle(TransferBRep_ShapeMapper) anOriginalMapper = TransferBRep::ShapeMapper(theFinderProcess, anOriginalShape);
+ Handle(Transfer_Binder) anOriginalBinder = theFinderProcess->Find(anOriginalMapper);
+ if (anOriginalBinder.IsNull())
+ {
+ theFinderProcess->Bind(anOriginalMapper, aResultBinder);
+ }
+ else
+ {
+ anOriginalBinder->AddResult(aResultBinder);
+ }
+
+ // update messages
+ addMessages(aMessages, anOriginalShape, aResultBinder);
+ }
+}
+
+//=============================================================================
+
+TopoDS_Edge XSAlgo_ShapeProcessor::MakeEdgeOnCurve(const TopoDS_Edge& aSourceEdge)
+{
+ TopoDS_Edge aResult;
+
+ Handle(Geom_Curve) aSourceGeomCurve;
+ Standard_Real aStartParam;
+ Standard_Real anEndParam;
+ ShapeAnalysis_Edge anEdgeAnalyzer;
+ if (!anEdgeAnalyzer.Curve3d(aSourceEdge, aSourceGeomCurve, aStartParam, anEndParam, Standard_False))
+ {
+ return aResult;
+ }
+ const gp_Pnt aCurveStartPt = aSourceGeomCurve->Value(aStartParam);
+ const gp_Pnt aCurveEndPt = aSourceGeomCurve->Value(anEndParam);
+ BRepBuilderAPI_MakeEdge anEdgeMaker(aSourceGeomCurve, aCurveStartPt, aCurveEndPt, aStartParam, anEndParam);
+ ShapeBuild_Edge SBE;
+ SBE.SetRange3d(anEdgeMaker, aStartParam, anEndParam);
+ aResult = anEdgeMaker.Edge();
+ return aResult;
+}
+
+//=============================================================================
+
+Standard_Boolean XSAlgo_ShapeProcessor::CheckPCurve(const TopoDS_Edge& theEdge,
+ const TopoDS_Face& theFace,
+ const Standard_Real thePrecision,
+ const Standard_Boolean theIsSeam)
+{
+ ShapeAnalysis_Edge anEdgeAnalyzer;
+
+ // Retrieve pcurve and its parameters.
+ Standard_Real aCurve2DParam1;
+ Standard_Real aCurve2DParam2;
+ Handle(Geom2d_Curve) aCurve2D;
+ if (!anEdgeAnalyzer.PCurve(theEdge, theFace, aCurve2D, aCurve2DParam1, aCurve2DParam2, Standard_False))
+ {
+ return Standard_False;
+ }
+
+ // Check for pcurve longer than surface.
+ Handle(Geom_Surface) aSurface = BRep_Tool::Surface(theFace);
+ Standard_Real aFaceSurfaceU1, aFaceSurfaceU2, aFaceSurfaceV1, aFaceSurfaceV2;
+ aSurface->Bounds(aFaceSurfaceU1, aFaceSurfaceU2, aFaceSurfaceV1, aFaceSurfaceV2);
+ const gp_Pnt2d aCurve2DPoint1 = aCurve2D->Value(aCurve2DParam1);
+ const gp_Pnt2d aCurve2DPoint2 = aCurve2D->Value(aCurve2DParam2);
+ // Multi-periodic? Better to discard (beware of infinite values)
+ const Standard_Real anEdgeSpanX = Abs(aCurve2DPoint1.X() - aCurve2DPoint2.X());
+ const Standard_Real anEdgeSpanY = Abs(aCurve2DPoint1.Y() - aCurve2DPoint2.Y());
+ // So if span of pcurve along U or V is longer than 6/8 of the surface span, discard it.
+ // Why exactly 6/8? No idea, but it's the same as in the original code.
+ if (anEdgeSpanX / 8. > (aFaceSurfaceU2 / 6. - aFaceSurfaceU1 / 6.)
+ || anEdgeSpanY / 8. > (aFaceSurfaceV2 / 6. - aFaceSurfaceV1 / 6.))
+ {
+ ShapeBuild_Edge().RemovePCurve(theEdge, theFace);
+ return Standard_False;
+ }
+
+ // Second Check: 2D and 3D consistency (if the Pcurve has not been dropped)
+ // We also check that it does not wrap around too much...
+ // Example: UVV in DEGREES on a surface in RADIANS, adjusted = 57 turns!
+ Handle(Geom_Curve) aCurve3D;
+ Standard_Real aCurve3DParam1;
+ Standard_Real aCurve3DParam2;
+ anEdgeAnalyzer.Curve3d(theEdge, aCurve3D, aCurve3DParam1, aCurve3DParam2, Standard_False);
+
+ const gp_Pnt aCurve3DPoint1 = aSurface->Value(aCurve2DPoint1.X(), aCurve2DPoint1.Y());
+ const gp_Pnt aCurve3DPoint2 = aSurface->Value(aCurve2DPoint2.X(), aCurve2DPoint2.Y());
+ const TopoDS_Vertex aVertex1 = TopExp::FirstVertex(theEdge);
+ const TopoDS_Vertex aVertex2 = TopExp::LastVertex(theEdge);
+ const gp_Pnt aPV1 = (aCurve3D.IsNull() ? BRep_Tool::Pnt(aVertex1) : aCurve3D->Value(aCurve3DParam1));
+ const gp_Pnt aPV2 = (aCurve3D.IsNull() ? BRep_Tool::Pnt(aVertex2) : aCurve3D->Value(aCurve3DParam2));
+ const Standard_Real aDist11 = aPV1.Distance(aCurve3DPoint1);
+ const Standard_Real aDist22 = aPV2.Distance(aCurve3DPoint2);
+
+ if (!((aDist11 <= thePrecision) && (aDist22 <= thePrecision)))
+ {
+ ShapeBuild_Edge().RemovePCurve(theEdge, theFace);
+ return Standard_False;
+ }
+
+ //
+ // pdn checking deviation between pcurve and 3D curve
+ //
+
+ // Make temporary edge for analysis
+ if (aCurve3D.IsNull())
+ {
+ return Standard_False;
+ }
+ TopoDS_Edge aTmpEdge = MakeEdgeOnCurve(theEdge);
+
+ // fill it with pcurve(s)
+ BRep_Builder aBuilder;
+ Handle(Geom2d_Curve) aSeamPCurve;
+ if (theIsSeam)
+ {
+ Standard_Real aSeamPCurveParam1;
+ Standard_Real aSeamPCurveParam2;
+ TopoDS_Edge aReversedEdge = TopoDS::Edge(theEdge.Reversed());
+ if (!anEdgeAnalyzer.PCurve(aReversedEdge, theFace, aSeamPCurve, aSeamPCurveParam1, aSeamPCurveParam2, Standard_False)
+ || aSeamPCurve == aCurve2D)
+ {
+ aSeamPCurve = Handle(Geom2d_Curve)::DownCast(aCurve2D->Copy());
+ }
+ aBuilder.UpdateEdge(aTmpEdge, aCurve2D, aSeamPCurve, theFace, 0.);
+ }
+ else
+ {
+ aBuilder.UpdateEdge(aTmpEdge, aCurve2D, theFace, 0.);
+ }
+ aBuilder.Range(aTmpEdge, theFace, aCurve2DParam1, aCurve2DParam2);
+ aBuilder.SameRange(aTmpEdge, Standard_False);
+ if (Interface_Static::IVal("read.stdsameparameter.mode"))
+ {
+ aBuilder.SameParameter(aTmpEdge, Standard_False);
+ }
+
+ // call FixSP to see what it will do
+ Handle(ShapeFix_Edge) anEdgeFixer = new ShapeFix_Edge;
+ anEdgeFixer->FixSameParameter(aTmpEdge);
+ Standard_Real aTolerance = BRep_Tool::Tolerance(aTmpEdge);
+ Standard_Boolean aSameRangeFlag = BRep_Tool::SameRange(aTmpEdge);
+ Standard_Boolean aSameParameterFlag = BRep_Tool::SameParameter(aTmpEdge);
+
+ // if result is not nice, try to call projection and take the best
+ if (aTolerance > Min(1., 2. * thePrecision) || !aSameRangeFlag)
+ {
+ //pdn trying to recompute pcurve
+ TopoDS_Edge anEdgePr = MakeEdgeOnCurve(theEdge);
+ anEdgeFixer->FixAddPCurve(anEdgePr, theFace, theIsSeam, thePrecision);
+ anEdgeFixer->FixSameParameter(anEdgePr);
+ const Standard_Real aTolerancePr = BRep_Tool::Tolerance(anEdgePr);
+ //pdn choose the best pcurve
+ if (aTolerancePr < aTolerance || !aSameRangeFlag)
+ {
+ aSameRangeFlag = BRep_Tool::SameRange(anEdgePr);
+ aSameParameterFlag = BRep_Tool::SameParameter(anEdgePr);
+ aTolerance = aTolerancePr;
+ aTmpEdge = anEdgePr;
+ }
+ }
+
+ // get corrected pcurve from the temporary edge, and put to original
+ anEdgeAnalyzer.PCurve(aTmpEdge, theFace, aCurve2D, aCurve2DParam1, aCurve2DParam2, Standard_False);
+ if (theIsSeam)
+ {
+ Standard_Real aReversedTmpEdgeParam1;
+ Standard_Real aReversedTmpEdgeParam2;
+ TopoDS_Edge aReversedTmpEdge = TopoDS::Edge(aTmpEdge.Reversed());
+ anEdgeAnalyzer
+ .PCurve(aReversedTmpEdge, theFace, aSeamPCurve, aReversedTmpEdgeParam1, aReversedTmpEdgeParam2, Standard_False);
+ if (theEdge.Orientation() == TopAbs_REVERSED) //:abv 14.11.01: coneEl.sat loop
+ {
+ aBuilder.UpdateEdge(theEdge, aSeamPCurve, aCurve2D, theFace, aTolerance);
+ }
+ else
+ {
+ aBuilder.UpdateEdge(theEdge, aCurve2D, aSeamPCurve, theFace, aTolerance);
+ }
+ }
+ else
+ {
+ aBuilder.UpdateEdge(theEdge, aCurve2D, theFace, aTolerance);
+ }
+
+ aBuilder.UpdateVertex(aVertex1, aTolerance);
+ aBuilder.UpdateVertex(aVertex2, aTolerance);
+ aBuilder.Range(theEdge, theFace, aCurve2DParam1, aCurve2DParam2);
+ if (BRep_Tool::SameRange(theEdge))
+ {
+ aBuilder.SameRange(theEdge, aSameRangeFlag);
+ }
+ if (BRep_Tool::SameParameter(theEdge))
+ {
+ aBuilder.SameParameter(theEdge, aSameParameterFlag);
+ }
+
+ return Standard_True;
+}
+
+//=============================================================================
+
+void XSAlgo_ShapeProcessor::FillParameterMap(const DE_ShapeFixParameters& theParameters,
+ XSAlgo_ShapeProcessor::ParameterMap& theMap)
+{
+ // Helper lambda to convert enum to string.
+ auto makeString = [](const DE_ShapeFixParameters::FixMode theMode)
+ {
+ return std::to_string(static_cast<std::underlying_type<DE_ShapeFixParameters::FixMode>::type>(theMode));
+ };
+
+ theMap.emplace("ShapeFix.Tolerance3d", std::to_string(theParameters.Tolerance3d));
+ theMap.emplace("ShapeFix.MaxTolerance3d", std::to_string(theParameters.MaxTolerance3d));
+ theMap.emplace("ShapeFix.MinTolerance3d", std::to_string(theParameters.MinTolerance3d));
+ theMap.emplace("DetalizationLevel", std::to_string(theParameters.DetalizationLevel));
+ theMap.emplace("NonManifold", std::to_string(theParameters.NonManifold));
+ theMap.emplace("ShapeFix.FixFreeShellMode", makeString(theParameters.FixFreeShellMode));
+ theMap.emplace("ShapeFix.FixFreeFaceMode", makeString(theParameters.FixFreeFaceMode));
+ theMap.emplace("ShapeFix.FixFreeWireMode", makeString(theParameters.FixFreeWireMode));
+ theMap.emplace("ShapeFix.FixSameParameterMode", makeString(theParameters.FixSameParameterMode));
+ theMap.emplace("ShapeFix.FixSolidMode", makeString(theParameters.FixSolidMode));
+ theMap.emplace("ShapeFix.FixShellOrientationMode", makeString(theParameters.FixShellOrientationMode));
+ theMap.emplace("ShapeFix.CreateOpenSolidMode", makeString(theParameters.CreateOpenSolidMode));
+ theMap.emplace("ShapeFix.FixShellMode", makeString(theParameters.FixShellMode));
+ theMap.emplace("ShapeFix.FixFaceOrientationMode", makeString(theParameters.FixFaceOrientationMode));
+ theMap.emplace("ShapeFix.FixFaceMode", makeString(theParameters.FixFaceMode));
+ theMap.emplace("ShapeFix.FixWireMode", makeString(theParameters.FixWireMode));
+ theMap.emplace("ShapeFix.FixOrientationMode", makeString(theParameters.FixOrientationMode));
+ theMap.emplace("ShapeFix.FixAddNaturalBoundMode", makeString(theParameters.FixAddNaturalBoundMode));
+ theMap.emplace("ShapeFix.FixMissingSeamMode", makeString(theParameters.FixMissingSeamMode));
+ theMap.emplace("ShapeFix.FixSmallAreaWireMode", makeString(theParameters.FixSmallAreaWireMode));
+ theMap.emplace("ShapeFix.RemoveSmallAreaFaceMode", makeString(theParameters.RemoveSmallAreaFaceMode));
+ theMap.emplace("ShapeFix.FixIntersectingWiresMode", makeString(theParameters.FixIntersectingWiresMode));
+ theMap.emplace("ShapeFix.FixLoopWiresMode", makeString(theParameters.FixLoopWiresMode));
+ theMap.emplace("ShapeFix.FixSplitFaceMode", makeString(theParameters.FixSplitFaceMode));
+ theMap.emplace("ShapeFix.AutoCorrectPrecisionMode", makeString(theParameters.AutoCorrectPrecisionMode));
+ theMap.emplace("ShapeFix.ModifyTopologyMode", makeString(theParameters.ModifyTopologyMode));
+ theMap.emplace("ShapeFix.ModifyGeometryMode", makeString(theParameters.ModifyGeometryMode));
+ theMap.emplace("ShapeFix.ClosedWireMode", makeString(theParameters.ClosedWireMode));
+ theMap.emplace("ShapeFix.PreferencePCurveMode", makeString(theParameters.PreferencePCurveMode));
+ theMap.emplace("ShapeFix.FixReorderMode", makeString(theParameters.FixReorderMode));
+ theMap.emplace("ShapeFix.FixSmallMode", makeString(theParameters.FixSmallMode));
+ theMap.emplace("ShapeFix.FixConnectedMode", makeString(theParameters.FixConnectedMode));
+ theMap.emplace("ShapeFix.FixEdgeCurvesMode", makeString(theParameters.FixEdgeCurvesMode));
+ theMap.emplace("ShapeFix.FixDegeneratedMode", makeString(theParameters.FixDegeneratedMode));
+ theMap.emplace("ShapeFix.FixLackingMode", makeString(theParameters.FixLackingMode));
+ theMap.emplace("ShapeFix.FixSelfIntersectionMode", makeString(theParameters.FixSelfIntersectionMode));
+ theMap.emplace("ShapeFix.RemoveLoopMode", makeString(theParameters.RemoveLoopMode));
+ theMap.emplace("ShapeFix.FixReversed2dMode", makeString(theParameters.FixReversed2dMode));
+ theMap.emplace("ShapeFix.FixRemovePCurveMode", makeString(theParameters.FixRemovePCurveMode));
+ theMap.emplace("ShapeFix.FixRemoveCurve3dMode", makeString(theParameters.FixRemoveCurve3dMode));
+ theMap.emplace("ShapeFix.FixAddPCurveMode", makeString(theParameters.FixAddPCurveMode));
+ theMap.emplace("ShapeFix.FixAddCurve3dMode", makeString(theParameters.FixAddCurve3dMode));
+ theMap.emplace("ShapeFix.FixSeamMode", makeString(theParameters.FixSeamMode));
+ theMap.emplace("ShapeFix.FixShiftedMode", makeString(theParameters.FixShiftedMode));
+ theMap.emplace("ShapeFix.FixEdgeSameParameterMode", makeString(theParameters.FixEdgeSameParameterMode));
+ theMap.emplace("ShapeFix.FixNotchedEdgesMode", makeString(theParameters.FixNotchedEdgesMode));
+ theMap.emplace("ShapeFix.FixTailMode", makeString(theParameters.FixTailMode));
+ theMap.emplace("ShapeFix.MaxTailAngle", makeString(theParameters.MaxTailAngle));
+ theMap.emplace("ShapeFix.MaxTailWidth", makeString(theParameters.MaxTailWidth));
+ theMap.emplace("ShapeFix.FixSelfIntersectingEdgeMode", makeString(theParameters.FixSelfIntersectingEdgeMode));
+ theMap.emplace("ShapeFix.FixIntersectingEdgesMode", makeString(theParameters.FixIntersectingEdgesMode));
+ theMap.emplace("ShapeFix.FixNonAdjacentIntersectingEdgesMode", makeString(theParameters.FixNonAdjacentIntersectingEdgesMode));
+ theMap.emplace("ShapeFix.FixVertexPositionMode", makeString(theParameters.FixVertexPositionMode));
+ theMap.emplace("ShapeFix.FixVertexToleranceMode", makeString(theParameters.FixVertexToleranceMode));
+}
+
+//=============================================================================
+
+void XSAlgo_ShapeProcessor::PrepareForTransfer()
+{
+ UnitsMethods::SetCasCadeLengthUnit(Interface_Static::IVal("xstep.cascade.unit"));
+}
--- /dev/null
+// Copyright (c) 2000-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _XSAlgo_ShapeProcessor_HeaderFile
+#define _XSAlgo_ShapeProcessor_HeaderFile
+
+#include <DE_ShapeFixParameters.hxx>
+#include <ShapeProcess.hxx>
+#include <TopAbs_ShapeEnum.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Face.hxx>
+
+#include <unordered_map>
+
+class ShapeProcess_ShapeContext;
+class ShapeExtend_MsgRegistrator;
+class Transfer_TransientProcess;
+class Transfer_FinderProcess;
+class Transfer_Binder;
+
+//! Shape Processing module.
+//! Allows to define and apply general Shape Processing as a customizable sequence of operators.
+class XSAlgo_ShapeProcessor
+{
+public:
+ using OperationsFlags = ShapeProcess::OperationsFlags;
+ using ParameterMap = std::unordered_map<std::string, std::string>;
+
+public:
+ //! Constructor.
+ //! @param theParameters Pre-filled parameter map to be used in the processing.
+ //! @param theShapeFixParameters Shape healing parameters to be used in the processing.
+ //! If @p theParameters has some shape healing values, they will override the
+ //! corresponding values from @p theShapeFixParameters.
+ Standard_EXPORT XSAlgo_ShapeProcessor(const ParameterMap& theParameters,
+ const DE_ShapeFixParameters& theShapeFixParameters = {});
+
+ //! Constructor.
+ //! @param theParameters Parameters to be used in the processing.
+ Standard_EXPORT XSAlgo_ShapeProcessor(const DE_ShapeFixParameters& theParameters);
+
+ //! Process the shape by applying the specified operations.
+ //! @param theShape Shape to process.
+ //! @param theOperations Operations to be performed.
+ //! @param theProgress Progress indicator.
+ //! @return Processed shape. May be the same as the input shape if no modifications were made.
+ Standard_EXPORT TopoDS_Shape ProcessShape(const TopoDS_Shape& theShape,
+ const OperationsFlags& theOperations,
+ const Message_ProgressRange& theProgress);
+
+ //! Get the context of the last processing.
+ //! Only valid after the ProcessShape() method was called.
+ //! @return Shape context.
+ Handle(ShapeProcess_ShapeContext) GetContext() { return myContext; }
+
+ //! Merge the results of the shape processing with the transfer process.
+ //! @param theTransientProcess Transfer process to merge with.
+ //! @param theFirstTPItemIndex Index of the first item in the transfer process to merge with.
+ Standard_EXPORT void MergeTransferInfo(const Handle(Transfer_TransientProcess)& theTransientProcess,
+ const Standard_Integer theFirstTPItemIndex) const;
+
+ //! Merge the results of the shape processing with the finder process.
+ //! @param theFinderProcess Finder process to merge with.
+ Standard_EXPORT void MergeTransferInfo(const Handle(Transfer_FinderProcess)& theFinderProcess) const;
+
+ //! Check quality of pcurve of the edge on the given face, and correct it if necessary.
+ //! @param theEdge Edge to check.
+ //! @param theFace Face on which the edge is located.
+ //! @param thePrecision Precision to use for checking.
+ //! @param theIsSeam Flag indicating whether the edge is a seam edge.
+ //! @return True if the pcurve was corrected, false if it was dropped.
+ Standard_EXPORT static Standard_Boolean CheckPCurve(const TopoDS_Edge& theEdge,
+ const TopoDS_Face& theFace,
+ const Standard_Real thePrecision,
+ const Standard_Boolean theIsSeam);
+
+ //! Fill the parameter map with the values from the specified parameters.
+ //! @param theParameters Parameters to be used in the processing.
+ //! @param theMap Map to fill.
+ Standard_EXPORT static void FillParameterMap(const DE_ShapeFixParameters& theParameters, ParameterMap& theMap);
+
+ //! The function is designed to set the length unit for the application before performing a
+ //! transfer operation. It ensures that the length unit is correctly configured based on the
+ //! value associated with the key "xstep.cascade.unit".
+ Standard_EXPORT static void PrepareForTransfer();
+
+private:
+ //! Initialize the context with the specified shape.
+ //! @param theShape Shape to process.
+ void initializeContext(const TopoDS_Shape& theShape);
+
+ //! Add messages from the specified shape to the transfer binder.
+ //! @param theMessages Container with messages.
+ //! @param theShape Shape to get messages from.
+ //! @param theBinder Transfer binder to add messages to.
+ static void addMessages(const Handle(ShapeExtend_MsgRegistrator)& theMessages,
+ const TopoDS_Shape& theShape,
+ Handle(Transfer_Binder)& theBinder);
+
+ //! Create a new edge with the same geometry as the source edge.
+ //! @param theSourceEdge Source edge.
+ //! @return New edge with the same geometry.
+ static TopoDS_Edge MakeEdgeOnCurve(const TopoDS_Edge& aSourceEdge);
+
+private:
+ ParameterMap myParameters; //!< Parameters to be used in the processing.
+ Handle(ShapeProcess_ShapeContext) myContext; //!< Shape context.
+};
+
+#endif // _XSAlgo_ShapeProcessor_HeaderFile