Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-21 09:16:37

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   //! Constructor.
0037   BRepMesh_NodeInsertionMeshAlgo() = default;
0038 
0039   //! Destructor.
0040   ~BRepMesh_NodeInsertionMeshAlgo() override = default;
0041 
0042   //! Performs processing of the given face.
0043   void Perform(const IMeshData::IFaceHandle& theDFace,
0044                const IMeshTools_Parameters&  theParameters,
0045                const Message_ProgressRange&  theRange) override
0046   {
0047     myRangeSplitter.Reset(theDFace, theParameters);
0048     myClassifier = new BRepMesh_Classifier;
0049     if (!theRange.More())
0050     {
0051       return;
0052     }
0053     BaseAlgo::Perform(theDFace, theParameters, theRange);
0054     myClassifier.Nullify();
0055   }
0056 
0057 protected:
0058   typedef NCollection_Shared<NCollection_Sequence<const gp_Pnt2d*>> SequenceOfPnt2d;
0059 
0060   //! Performs initialization of data structure using existing model data.
0061   bool initDataStructure() override
0062   {
0063     occ::handle<NCollection_IncAllocator> aTmpAlloc = new NCollection_IncAllocator;
0064 
0065     const IMeshData::IFaceHandle&                    aDFace = this->getDFace();
0066     NCollection_Array1<occ::handle<SequenceOfPnt2d>> aWires(0, aDFace->WiresNb() - 1);
0067     for (int aWireIt = 0; aWireIt < aDFace->WiresNb(); ++aWireIt)
0068     {
0069       const IMeshData::IWireHandle& aDWire = aDFace->GetWire(aWireIt);
0070       if (aDWire->IsSet(IMeshData_SelfIntersectingWire)
0071           || (aDWire->IsSet(IMeshData_OpenWire) && aWireIt != 0))
0072       {
0073         continue;
0074       }
0075 
0076       aWires(aWireIt) = collectWirePoints(aDWire, aTmpAlloc);
0077     }
0078 
0079     myRangeSplitter.AdjustRange();
0080     if (!myRangeSplitter.IsValid())
0081     {
0082       aDFace->SetStatus(IMeshData_Failure);
0083       return false;
0084     }
0085 
0086     const std::pair<double, double>& aDelta    = myRangeSplitter.GetDelta();
0087     const std::pair<double, double>& aTolUV    = myRangeSplitter.GetToleranceUV();
0088     const double                     uCellSize = 14.0 * aTolUV.first;
0089     const double                     vCellSize = 14.0 * aTolUV.second;
0090 
0091     this->getStructure()->Data()->SetCellSize(uCellSize / aDelta.first, vCellSize / aDelta.second);
0092     this->getStructure()->Data()->SetTolerance(aTolUV.first / aDelta.first,
0093                                                aTolUV.second / aDelta.second);
0094 
0095     for (int aWireIt = 0; aWireIt < aDFace->WiresNb(); ++aWireIt)
0096     {
0097       const occ::handle<SequenceOfPnt2d>& aWire = aWires(aWireIt);
0098       if (!aWire.IsNull() && !aWire->IsEmpty())
0099       {
0100         myClassifier->RegisterWire(*aWire,
0101                                    aTolUV,
0102                                    myRangeSplitter.GetRangeU(),
0103                                    myRangeSplitter.GetRangeV());
0104       }
0105     }
0106 
0107     if (this->getParameters().InternalVerticesMode)
0108     {
0109       insertInternalVertices();
0110     }
0111 
0112     return BaseAlgo::initDataStructure();
0113   }
0114 
0115   //! Adds the given 2d point to mesh data structure.
0116   //! Returns index of node in the structure.
0117   int addNodeToStructure(const gp_Pnt2d&                thePoint,
0118                          const int                      theLocation3d,
0119                          const BRepMesh_DegreeOfFreedom theMovability,
0120                          const bool                     isForceAdd) override
0121   {
0122     return BaseAlgo::addNodeToStructure(myRangeSplitter.Scale(thePoint, true),
0123                                         theLocation3d,
0124                                         theMovability,
0125                                         isForceAdd);
0126   }
0127 
0128   //! Returns 2d point associated to the given vertex.
0129   gp_Pnt2d getNodePoint2d(const BRepMesh_Vertex& theVertex) const override
0130   {
0131     return myRangeSplitter.Scale(theVertex.Coord(), false);
0132   }
0133 
0134   //! Returns range splitter.
0135   const RangeSplitter& getRangeSplitter() const { return myRangeSplitter; }
0136 
0137   //! Returns classifier.
0138   const occ::handle<BRepMesh_Classifier>& getClassifier() const { return myClassifier; }
0139 
0140 private:
0141   //! Creates collection of points representing discrete wire.
0142   occ::handle<SequenceOfPnt2d> collectWirePoints(
0143     const IMeshData::IWireHandle&                theDWire,
0144     const occ::handle<NCollection_IncAllocator>& theAllocator)
0145   {
0146     occ::handle<SequenceOfPnt2d> aWirePoints = new SequenceOfPnt2d(theAllocator);
0147     for (int aEdgeIt = 0; aEdgeIt < theDWire->EdgesNb(); ++aEdgeIt)
0148     {
0149       const IMeshData::IEdgeHandle    aDEdge = theDWire->GetEdge(aEdgeIt);
0150       const IMeshData::IPCurveHandle& aPCurve =
0151         aDEdge->GetPCurve(this->getDFace().get(), theDWire->GetEdgeOrientation(aEdgeIt));
0152 
0153       int aPointIt, aEndIndex, aInc;
0154       if (aPCurve->IsForward())
0155       {
0156         // For an infinite cylinder (for example)
0157         // aPCurve->ParametersNb() == 0
0158 
0159         aEndIndex = aPCurve->ParametersNb() - 1;
0160         aPointIt  = (std::min)(0, aEndIndex);
0161         aInc      = 1;
0162       }
0163       else
0164       {
0165         // For an infinite cylinder (for example)
0166         // aPCurve->ParametersNb() == 0
0167 
0168         aPointIt  = aPCurve->ParametersNb() - 1;
0169         aEndIndex = (std::min)(0, aPointIt);
0170         aInc      = -1;
0171       }
0172 
0173       // For an infinite cylinder (for example)
0174       // this cycle will not be executed.
0175       for (; aPointIt != aEndIndex; aPointIt += aInc)
0176       {
0177         const gp_Pnt2d& aPnt2d = aPCurve->GetPoint(aPointIt);
0178         aWirePoints->Append(&aPnt2d);
0179         myRangeSplitter.AddPoint(aPnt2d);
0180       }
0181     }
0182 
0183     return aWirePoints;
0184   }
0185 
0186   //! Iterates over internal vertices of a face and
0187   //! creates corresponding nodes in data structure.
0188   void insertInternalVertices()
0189   {
0190     TopExp_Explorer aExplorer(this->getDFace()->GetFace(), TopAbs_VERTEX, TopAbs_EDGE);
0191     for (; aExplorer.More(); aExplorer.Next())
0192     {
0193       const TopoDS_Vertex& aVertex = TopoDS::Vertex(aExplorer.Current());
0194       if (aVertex.Orientation() != TopAbs_INTERNAL)
0195       {
0196         continue;
0197       }
0198 
0199       insertInternalVertex(aVertex);
0200     }
0201   }
0202 
0203   //! Inserts the given vertex into mesh.
0204   void insertInternalVertex(const TopoDS_Vertex& theVertex)
0205   {
0206     try
0207     {
0208       OCC_CATCH_SIGNALS
0209 
0210       gp_Pnt2d aPnt2d = BRep_Tool::Parameters(theVertex, this->getDFace()->GetFace());
0211       // check UV values for internal vertices
0212       if (myClassifier->Perform(aPnt2d) != TopAbs_IN)
0213         return;
0214 
0215       this->registerNode(BRep_Tool::Pnt(theVertex), aPnt2d, BRepMesh_Fixed, false);
0216     }
0217     catch (Standard_Failure const&)
0218     {
0219     }
0220   }
0221 
0222 private:
0223   RangeSplitter                    myRangeSplitter;
0224   occ::handle<BRepMesh_Classifier> myClassifier;
0225 };
0226 
0227 #endif