0026106: BRepMesh - revision of data model
[occt.git] / src / BRepMesh / BRepMesh_ModelPreProcessor.cxx
1 // Created on: 2016-07-04
2 // Copyright (c) 2016 OPEN CASCADE SAS
3 // Created by: Oleg AGASHIN
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <BRepMesh_ModelPreProcessor.hxx>
17 #include <BRepMesh_ShapeTool.hxx>
18 #include <BRep_Tool.hxx>
19 #include <IMeshData_Model.hxx>
20 #include <IMeshData_Edge.hxx>
21 #include <IMeshData_Wire.hxx>
22 #include <IMeshData_PCurve.hxx>
23 #include <OSD_Parallel.hxx>
24
25 namespace
26 {
27   //! Checks consistency of triangulation stored in topological face.
28   class TriangulationConsistency
29   {
30   public:
31     //! Constructor
32     TriangulationConsistency(const Handle(IMeshData_Model)& theModel)
33       : myModel (theModel)
34     {
35     }
36
37     //! Main functor.
38     void operator()(const Standard_Integer theFaceIndex) const
39     {
40       const IMeshData::IFaceHandle& aDFace = myModel->GetFace(theFaceIndex);
41       if (aDFace->IsSet(IMeshData_Outdated))
42       {
43         return;
44       }
45
46       TopLoc_Location aLoc;
47       const Handle(Poly_Triangulation)& aTriangulation =
48         BRep_Tool::Triangulation(aDFace->GetFace(), aLoc);
49
50       if (!aTriangulation.IsNull())
51       {
52         Standard_Boolean isTriangulationConsistent = 
53           aTriangulation->Deflection() < 1.1 * aDFace->GetDeflection();
54
55         if (isTriangulationConsistent)
56         {
57           // #25080: check that indices of links forming triangles are in range.
58           const Standard_Integer aNodesNb = aTriangulation->NbNodes();
59           const Poly_Array1OfTriangle& aTriangles = aTriangulation->Triangles();
60
61           Standard_Integer i = aTriangles.Lower();
62           for (; i <= aTriangles.Upper() && isTriangulationConsistent; ++i)
63           {
64             const Poly_Triangle& aTriangle = aTriangles(i);
65
66             Standard_Integer aNode[3];
67             aTriangle.Get(aNode[0], aNode[1], aNode[2]);
68             for (Standard_Integer j = 0; j < 3 && isTriangulationConsistent; ++j)
69             {
70               isTriangulationConsistent = (aNode[j] >= 1 && aNode[j] <= aNodesNb);
71             }
72           }
73         }
74
75         if (isTriangulationConsistent)
76         {
77           aDFace->SetStatus(IMeshData_Reused);
78           aDFace->SetDeflection(aTriangulation->Deflection());
79         }
80         else
81         {
82           aDFace->SetStatus(IMeshData_Outdated);
83         }
84       }
85     }
86
87   private:
88
89     Handle(IMeshData_Model) myModel;
90   };
91 }
92
93 //=======================================================================
94 // Function: Constructor
95 // Purpose : 
96 //=======================================================================
97 BRepMesh_ModelPreProcessor::BRepMesh_ModelPreProcessor()
98 {
99 }
100
101 //=======================================================================
102 // Function: Destructor
103 // Purpose : 
104 //=======================================================================
105 BRepMesh_ModelPreProcessor::~BRepMesh_ModelPreProcessor()
106 {
107 }
108
109 //=======================================================================
110 // Function: Perform
111 // Purpose : 
112 //=======================================================================
113 Standard_Boolean BRepMesh_ModelPreProcessor::Perform(
114   const Handle(IMeshData_Model)& theModel,
115   const IMeshTools_Parameters&   theParameters)
116 {
117   if (theModel.IsNull())
118   {
119     return Standard_False;
120   }
121
122   OSD_Parallel::For(0, theModel->FacesNb(), TriangulationConsistency(theModel), !theParameters.InParallel);
123
124   // Clean edges and faces from outdated polygons.
125   Handle(NCollection_IncAllocator) aTmpAlloc(new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE));
126   NCollection_Map<IMeshData_Face*> aUsedFaces(1, aTmpAlloc);
127   for (Standard_Integer aEdgeIt = 0; aEdgeIt < theModel->EdgesNb(); ++aEdgeIt)
128   {
129     const IMeshData::IEdgeHandle& aDEdge = theModel->GetEdge(aEdgeIt);
130     if (aDEdge->IsFree())
131     {
132       if (aDEdge->IsSet(IMeshData_Outdated))
133       {
134         TopLoc_Location aLoc;
135         BRep_Tool::Polygon3D(aDEdge->GetEdge(), aLoc);
136         BRepMesh_ShapeTool::NullifyEdge(aDEdge->GetEdge(), aLoc);
137       }
138
139       continue;
140     }
141     
142     for (Standard_Integer aPCurveIt = 0; aPCurveIt < aDEdge->PCurvesNb(); ++aPCurveIt)
143     {
144       // Find adjacent outdated face.
145       const IMeshData::IFaceHandle aDFace = aDEdge->GetPCurve(aPCurveIt)->GetFace();
146       if (!aUsedFaces.Contains(aDFace.get()))
147       {
148         aUsedFaces.Add(aDFace.get());
149         if (aDFace->IsSet(IMeshData_Outdated))
150         {
151           TopLoc_Location aLoc;
152           const Handle(Poly_Triangulation)& aTriangulation =
153             BRep_Tool::Triangulation(aDFace->GetFace(), aLoc);
154
155           // Clean all edges of oudated face.
156           for (Standard_Integer aWireIt = 0; aWireIt < aDFace->WiresNb(); ++aWireIt)
157           {
158             const IMeshData::IWireHandle& aDWire = aDFace->GetWire(aWireIt);
159             for (Standard_Integer aWireEdgeIt = 0; aWireEdgeIt < aDWire->EdgesNb(); ++aWireEdgeIt)
160             {
161               const IMeshData::IEdgeHandle aTmpDEdge = aDWire->GetEdge(aWireEdgeIt);
162               BRepMesh_ShapeTool::NullifyEdge(aTmpDEdge->GetEdge(), aTriangulation, aLoc);
163             }
164           }
165
166           BRepMesh_ShapeTool::NullifyFace(aDFace->GetFace());
167         }
168       }
169     }
170   }
171
172   return Standard_True;
173 }
174