Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:03:14

0001 // Created on: 2016-07-07
0002 // Copyright (c) 2016 OPEN CASCADE SAS
0003 // Created by: Oleg AGASHIN
0004 //
0005 // This file is part of Open CASCADE Technology software library.
0006 //
0007 // This library is free software; you can redistribute it and/or modify it under
0008 // the terms of the GNU Lesser General Public License version 2.1 as published
0009 // by the Free Software Foundation, with special exception defined in the file
0010 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0011 // distribution for complete text of the license and disclaimer of any warranty.
0012 //
0013 // Alternatively, this file may be used under the terms of Open CASCADE
0014 // commercial license or contractual agreement.
0015 
0016 #ifndef _BRepMesh_NodeInsertionMeshAlgo_HeaderFile
0017 #define _BRepMesh_NodeInsertionMeshAlgo_HeaderFile
0018 
0019 #include <BRepMesh_Classifier.hxx>
0020 #include <IMeshData_Wire.hxx>
0021 #include <IMeshData_Edge.hxx>
0022 #include <IMeshData_PCurve.hxx>
0023 #include <BRepMesh_Vertex.hxx>
0024 #include <TopExp_Explorer.hxx>
0025 #include <TopoDS_Vertex.hxx>
0026 #include <BRep_Tool.hxx>
0027 #include <Standard_ErrorHandler.hxx>
0028 #include <BRepMesh_Delaun.hxx>
0029 
0030 //! Extends base meshing algo in order to enable possibility 
0031 //! of addition of free vertices into the mesh.
0032 template<class RangeSplitter, class BaseAlgo>
0033 class BRepMesh_NodeInsertionMeshAlgo : public BaseAlgo
0034 {
0035 public:
0036 
0037   //! Constructor.
0038   BRepMesh_NodeInsertionMeshAlgo()
0039   {
0040   }
0041 
0042   //! Destructor.
0043   virtual ~BRepMesh_NodeInsertionMeshAlgo()
0044   {
0045   }
0046 
0047   //! Performs processing of the given face.
0048   virtual void Perform(
0049     const IMeshData::IFaceHandle& theDFace,
0050     const IMeshTools_Parameters&  theParameters,
0051     const Message_ProgressRange&  theRange) Standard_OVERRIDE
0052   {
0053     myRangeSplitter.Reset(theDFace, theParameters);
0054     myClassifier = new BRepMesh_Classifier;
0055     if (!theRange.More())
0056     {
0057       return;
0058     }
0059     BaseAlgo::Perform(theDFace, theParameters, theRange);
0060     myClassifier.Nullify();
0061   }
0062 
0063 protected:
0064 
0065   typedef NCollection_Shared<NCollection_Sequence<const gp_Pnt2d*> > SequenceOfPnt2d;
0066 
0067   //! Performs initialization of data structure using existing model data.
0068   virtual Standard_Boolean initDataStructure() Standard_OVERRIDE
0069   {
0070     Handle(NCollection_IncAllocator) aTmpAlloc = new NCollection_IncAllocator;
0071 
0072     const IMeshData::IFaceHandle& aDFace = this->getDFace();
0073     NCollection_Array1<Handle(SequenceOfPnt2d)> aWires(0, aDFace->WiresNb() - 1);
0074     for (Standard_Integer aWireIt = 0; aWireIt < aDFace->WiresNb(); ++aWireIt)
0075     {
0076       const IMeshData::IWireHandle& aDWire = aDFace->GetWire(aWireIt);
0077       if (aDWire->IsSet(IMeshData_SelfIntersectingWire) ||
0078          (aDWire->IsSet(IMeshData_OpenWire) && aWireIt != 0))
0079       {
0080         continue;
0081       }
0082 
0083       aWires(aWireIt) = collectWirePoints(aDWire, aTmpAlloc);
0084     }
0085 
0086     myRangeSplitter.AdjustRange();
0087     if (!myRangeSplitter.IsValid())
0088     {
0089       aDFace->SetStatus(IMeshData_Failure);
0090       return Standard_False;
0091     }
0092 
0093     const std::pair<Standard_Real, Standard_Real>& aDelta = myRangeSplitter.GetDelta();
0094     const std::pair<Standard_Real, Standard_Real>& aTolUV = myRangeSplitter.GetToleranceUV();
0095     const Standard_Real uCellSize = 14.0 * aTolUV.first;
0096     const Standard_Real vCellSize = 14.0 * aTolUV.second;
0097 
0098     this->getStructure()->Data()->SetCellSize (uCellSize    / aDelta.first, vCellSize     / aDelta.second);
0099     this->getStructure()->Data()->SetTolerance(aTolUV.first / aDelta.first, aTolUV.second / aDelta.second);
0100 
0101     for (Standard_Integer aWireIt = 0; aWireIt < aDFace->WiresNb(); ++aWireIt)
0102     {
0103       const Handle(SequenceOfPnt2d)& aWire = aWires(aWireIt);
0104       if (!aWire.IsNull() && !aWire->IsEmpty())
0105       {
0106         myClassifier->RegisterWire(*aWire, aTolUV,
0107                                    myRangeSplitter.GetRangeU(),
0108                                    myRangeSplitter.GetRangeV());
0109       }
0110     }
0111 
0112     if (this->getParameters().InternalVerticesMode)
0113     {
0114       insertInternalVertices();
0115     }
0116 
0117     return BaseAlgo::initDataStructure();
0118   }
0119 
0120   //! Adds the given 2d point to mesh data structure.
0121   //! Returns index of node in the structure.
0122   virtual Standard_Integer addNodeToStructure(
0123     const gp_Pnt2d&                thePoint,
0124     const Standard_Integer         theLocation3d,
0125     const BRepMesh_DegreeOfFreedom theMovability,
0126     const Standard_Boolean         isForceAdd) Standard_OVERRIDE
0127   {
0128     return BaseAlgo::addNodeToStructure(
0129       myRangeSplitter.Scale(thePoint, Standard_True),
0130       theLocation3d, theMovability, isForceAdd);
0131   }
0132 
0133   //! Returns 2d point associated to the given vertex.
0134   virtual gp_Pnt2d getNodePoint2d(
0135     const BRepMesh_Vertex& theVertex) const Standard_OVERRIDE
0136   {
0137     return myRangeSplitter.Scale(theVertex.Coord(), Standard_False);
0138   }
0139 
0140   //! Returns range splitter.
0141   const RangeSplitter& getRangeSplitter() const
0142   {
0143     return myRangeSplitter;
0144   }
0145 
0146   //! Returns classifier.
0147   const Handle(BRepMesh_Classifier)& getClassifier() const
0148   {
0149     return myClassifier;
0150   }
0151 
0152 private:
0153 
0154   //! Creates collection of points representing discrete wire.
0155   Handle(SequenceOfPnt2d) collectWirePoints(
0156     const IMeshData::IWireHandle&           theDWire,
0157     const Handle(NCollection_IncAllocator)& theAllocator)
0158   {
0159     Handle(SequenceOfPnt2d) aWirePoints = new SequenceOfPnt2d(theAllocator);
0160     for (Standard_Integer aEdgeIt = 0; aEdgeIt < theDWire->EdgesNb(); ++aEdgeIt)
0161     {
0162       const IMeshData::IEdgeHandle    aDEdge = theDWire->GetEdge(aEdgeIt);
0163       const IMeshData::IPCurveHandle& aPCurve = aDEdge->GetPCurve(
0164         this->getDFace().get(), theDWire->GetEdgeOrientation(aEdgeIt));
0165 
0166       Standard_Integer aPointIt, aEndIndex, aInc;
0167       if (aPCurve->IsForward())
0168       {
0169         // For an infinite cylinder (for example)
0170         // aPCurve->ParametersNb() == 0
0171 
0172         aEndIndex = aPCurve->ParametersNb() - 1;
0173         aPointIt = Min(0, aEndIndex);
0174         aInc = 1;
0175       }
0176       else
0177       {
0178         // For an infinite cylinder (for example)
0179         // aPCurve->ParametersNb() == 0
0180 
0181         aPointIt = aPCurve->ParametersNb() - 1;
0182         aEndIndex = Min(0, aPointIt);
0183         aInc = -1;
0184       }
0185 
0186       // For an infinite cylinder (for example)
0187       // this cycle will not be executed.
0188       for (; aPointIt != aEndIndex; aPointIt += aInc)
0189       {
0190         const gp_Pnt2d& aPnt2d = aPCurve->GetPoint(aPointIt);
0191         aWirePoints->Append(&aPnt2d);
0192         myRangeSplitter.AddPoint(aPnt2d);
0193       }
0194     }
0195 
0196     return aWirePoints;
0197   }
0198 
0199   //! Iterates over internal vertices of a face and 
0200   //! creates corresponding nodes in data structure.
0201   void insertInternalVertices()
0202   {
0203     TopExp_Explorer aExplorer(this->getDFace()->GetFace(), TopAbs_VERTEX, TopAbs_EDGE);
0204     for (; aExplorer.More(); aExplorer.Next())
0205     {
0206       const TopoDS_Vertex& aVertex = TopoDS::Vertex(aExplorer.Current());
0207       if (aVertex.Orientation() != TopAbs_INTERNAL)
0208       {
0209         continue;
0210       }
0211 
0212       insertInternalVertex(aVertex);
0213     }
0214   }
0215 
0216   //! Inserts the given vertex into mesh.
0217   void insertInternalVertex(const TopoDS_Vertex& theVertex)
0218   {
0219     try
0220     {
0221       OCC_CATCH_SIGNALS
0222 
0223         gp_Pnt2d aPnt2d = BRep_Tool::Parameters(theVertex, this->getDFace()->GetFace());
0224       // check UV values for internal vertices
0225       if (myClassifier->Perform(aPnt2d) != TopAbs_IN)
0226         return;
0227 
0228       this->registerNode(BRep_Tool::Pnt(theVertex), aPnt2d,
0229                          BRepMesh_Fixed, Standard_False);
0230     }
0231     catch (Standard_Failure const&)
0232     {
0233     }
0234   }
0235 
0236 private:
0237 
0238   RangeSplitter               myRangeSplitter;
0239   Handle(BRepMesh_Classifier) myClassifier;
0240 };
0241 
0242 #endif