Salome HOME
11237f535c2bdcb5931677deee1cee329129dfd3
[modules/geom.git] / src / GEOMImpl / GEOMImpl_ConformityDriver.cxx
1 // Copyright (C) 2013-2023  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "GEOMImpl_ConformityDriver.hxx"
21
22 // internal includes
23 #include "GEOMImpl_IConformity.hxx"
24
25 // KERNEL includes
26 #include <utilities.h>
27 #include <Basics_Utils.hxx>
28
29 // GEOM includes
30 #include "GEOM_Function.hxx"
31 #include "GEOMImpl_Types.hxx"
32
33 #include <BOPAlgo_ArgumentAnalyzer.hxx>
34 #include <BRepTools.hxx>
35 #include <BRepTools_ReShape.hxx>
36 #include <BRepLib.hxx>
37 #include <BRep_Tool.hxx>
38
39 #include <TopExp_Explorer.hxx>
40 #include <GEOMUtils.hxx>
41 #include <TColStd_HArray2OfInteger.hxx>
42
43 namespace
44 {
45   //=======================================================================
46   //function : ConvertShapesToIndices
47   //purpose  : Convert sub-shapes of shapes to sequence of indices
48   //=======================================================================
49   Handle(TColStd_HArray1OfInteger) ConvertShapesToIndices(const TopoDS_Shape& theShape,
50                                                           const TopTools_ListOfShape& theShapes)
51   {
52     Handle(TColStd_HArray1OfInteger) aSeqOfIDs = new TColStd_HArray1OfInteger(1, theShapes.Size());
53
54     TopTools_IndexedMapOfShape anIndices;
55     TopExp::MapShapes(theShape, anIndices);
56
57     TopTools_ListIteratorOfListOfShape itSub(theShapes);
58     for (int index = 1; itSub.More(); itSub.Next(), ++index)
59     {
60       int id = anIndices.FindIndex(itSub.Value());
61       aSeqOfIDs->SetValue(index, id);
62     }
63
64     return aSeqOfIDs;
65   }
66
67   //=======================================================================
68   //function : ConvertShapesToIndices
69   //purpose  : Convert list of pair shapes to sequence of indices
70   //=======================================================================
71   Handle(TColStd_HArray2OfInteger) ConvertShapesToIndices(
72     const TopoDS_Shape& theShape,
73     const NCollection_List<std::pair<TopoDS_Shape, TopoDS_Shape>>& theShapes)
74   {
75     Handle(TColStd_HArray2OfInteger) aSeqOfIDs = new TColStd_HArray2OfInteger(1, theShapes.Size(), 1, 2);
76
77     TopTools_IndexedMapOfShape anIndices;
78     TopExp::MapShapes(theShape, anIndices);
79
80     NCollection_List<std::pair<TopoDS_Shape, TopoDS_Shape>>::Iterator itSub(theShapes);
81     for (int index = 1; itSub.More(); itSub.Next(), ++index)
82     {
83       int anID1 = anIndices.FindIndex(itSub.Value().first);
84       aSeqOfIDs->SetValue(index, 1, anID1);
85
86       int anID2 = anIndices.FindIndex(itSub.Value().second);
87       aSeqOfIDs->SetValue(index, 2, anID2);
88     }
89
90     return aSeqOfIDs;
91   }
92 }
93
94 //=======================================================================
95 //function : GetID
96 //purpose  :
97 //=======================================================================
98 const Standard_GUID& GEOMImpl_ConformityDriver::GetID()
99 {
100   static Standard_GUID aGUID("B77BABDA-C0A1-4E65-9B1E-7EFC4448077E");
101   return aGUID;
102 }
103
104 //=======================================================================
105 //function : GEOMImpl_ConformityDriver
106 //purpose  :
107 //=======================================================================
108 GEOMImpl_ConformityDriver::GEOMImpl_ConformityDriver()
109 {
110 }
111
112 //=======================================================================
113 //function : Execute
114 //purpose  :
115 //=======================================================================
116 Standard_Integer GEOMImpl_ConformityDriver::Execute(Handle(TFunction_Logbook)& log) const
117 {
118   if (Label().IsNull()) return 0;
119   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
120   GEOMImpl_IConformity aCI(aFunction);
121
122   Standard_Integer aType = aFunction->GetType();
123
124   Handle(GEOM_Function) aRefShape = aCI.GetShape();
125   if (aRefShape.IsNull()) return 0;
126
127   TopoDS_Shape aShape = aRefShape->GetValue();
128
129   switch (aType)
130   {
131   case CONFORMITY_UPDATE_TOL:
132   {
133     Standard_Real aTolerance = updateTolerance(aShape);
134     aFunction->SetReal(CHECKCONFORMITY_RET_TOLERANCE, aTolerance);
135   }
136   break;
137   case CONFORMITY_CHECK_SHAPE:
138   {
139     NCollection_List<std::pair<TopoDS_Shape, TopoDS_Shape>> aFailedShape;
140     Handle(TColStd_HArray1OfInteger) aTypesOfCheck;
141     checkShape(aShape, aFailedShape, aTypesOfCheck);
142
143     Handle(TColStd_HArray2OfInteger) anArray = ConvertShapesToIndices(aShape, aFailedShape);
144     aFunction->SetIntegerArray(CHECKCONFORMITY_RET_TYPES_CHECKS, aTypesOfCheck);
145     aCI.SetListOfShapesIndices(anArray);
146   }
147   }
148
149   return 1;
150 }
151
152 //=======================================================================
153 //function : checkShape
154 //purpose  :
155 //=======================================================================
156 void GEOMImpl_ConformityDriver::checkShape(const TopoDS_Shape & theShape,
157                                            NCollection_List<std::pair<TopoDS_Shape, TopoDS_Shape>>& theFailedShape,
158                                            Handle(TColStd_HArray1OfInteger)& theTypesOfCheck) const
159 {
160   BOPAlgo_ArgumentAnalyzer anAnalyzer;
161   performAnalyze(theShape, anAnalyzer);
162
163   const BOPAlgo_ListOfCheckResult& aResult = anAnalyzer.GetCheckResult();
164   theTypesOfCheck = new TColStd_HArray1OfInteger(1, aResult.Size());
165
166   BOPAlgo_ListOfCheckResult::Iterator anIter(aResult);
167   for (int index = 1; anIter.More(); anIter.Next(), ++index)
168   {
169     theTypesOfCheck->SetValue(index, anIter.Value().GetCheckStatus());
170     std::pair<TopoDS_Shape, TopoDS_Shape> aPair;
171     aPair.first = anIter.Value().GetFaultyShapes1().First();
172     if (anIter.Value().GetFaultyShapes1().Size() != 1)
173       aPair.second = anIter.Value().GetFaultyShapes1().Last();
174     theFailedShape.Append(aPair);
175   }
176 }
177
178 //=======================================================================
179 //function : updateTolerance
180 //purpose  :
181 //=======================================================================
182 Standard_Real GEOMImpl_ConformityDriver::updateTolerance(const TopoDS_Shape& theShape) const
183 {
184   Standard_Real aTolerance = INFINITY;
185
186   TopoDS_Shape aResShape = theShape;
187
188   BRepLib::UpdateTolerances(aResShape, Standard_False);
189
190   for (const auto& aType : { TopAbs_VERTEX, TopAbs_EDGE, TopAbs_FACE })
191   {
192     for (TopExp_Explorer anExp(aResShape, aType); anExp.More(); anExp.Next())
193     {
194       Standard_Real aCurTolerance = INFINITY;
195       switch (aType)
196       {
197       case TopAbs_VERTEX:
198         aCurTolerance = BRep_Tool::Tolerance(TopoDS::Vertex(anExp.Value()));
199         break;
200       case TopAbs_EDGE:
201         aCurTolerance = BRep_Tool::Tolerance(TopoDS::Edge(anExp.Value()));
202         break;
203       case TopAbs_FACE:
204         aCurTolerance = BRep_Tool::Tolerance(TopoDS::Face(anExp.Value()));
205         break;
206       }
207       aTolerance = Min(aTolerance, aCurTolerance);
208     }
209   }
210
211   TopoDS_Shape aShape = theShape;
212   GEOMUtils::FixShapeTolerance(aShape, aTolerance, Standard_True);
213
214   Standard_Real aResTol = 0.;
215   for (const auto& aType : { TopAbs_VERTEX, TopAbs_EDGE, TopAbs_FACE })
216   {
217     for (TopExp_Explorer anExp(aShape, aType); anExp.More(); anExp.Next())
218     {
219       Standard_Real aCurTolerance = INFINITY;
220       switch (aType)
221       {
222       case TopAbs_VERTEX:
223         aCurTolerance = BRep_Tool::Tolerance(TopoDS::Vertex(anExp.Value()));
224         break;
225       case TopAbs_EDGE:
226         aCurTolerance = BRep_Tool::Tolerance(TopoDS::Edge(anExp.Value()));
227         break;
228       case TopAbs_FACE:
229         aCurTolerance = BRep_Tool::Tolerance(TopoDS::Face(anExp.Value()));
230         break;
231       }
232       aResTol = Max(aResTol, aCurTolerance);
233     }
234   }
235
236   return aResTol;
237 }
238
239 //=======================================================================
240 //function : performAnalyze
241 //purpose  : 
242 //=======================================================================
243 void GEOMImpl_ConformityDriver::performAnalyze(const TopoDS_Shape& theShape,
244                                                BOPAlgo_ArgumentAnalyzer& theAnalyzer) const
245 {
246   theAnalyzer.SetShape1(theShape);
247
248   theAnalyzer.CurveOnSurfaceMode() = Standard_True;
249   theAnalyzer.SelfInterMode() = Standard_True;
250   theAnalyzer.SmallEdgeMode() = Standard_True;
251
252   theAnalyzer.Perform();
253 }