Salome HOME
updated copyright message
[modules/shaper.git] / src / GeomAlgoAPI / GeomAlgoAPI_CanonicalRecognition.cpp
1 // Copyright (C) 2014-2023  CEA, EDF
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 "GeomAlgoAPI_CanonicalRecognition.h"
21
22 #include <Standard_Version.hxx>
23 // code from KERNEL_SRC/src/Basics/Basics_OCCTVersion.hxx
24 #ifdef OCC_VERSION_SERVICEPACK
25 #  define OCC_VERSION_LARGE (OCC_VERSION_MAJOR << 24 | OCC_VERSION_MINOR << 16 | OCC_VERSION_MAINTENANCE << 8 | OCC_VERSION_SERVICEPACK)
26 #else
27 #  ifdef OCC_VERSION_DEVELOPMENT
28 #    define OCC_VERSION_LARGE ((OCC_VERSION_MAJOR << 24 | OCC_VERSION_MINOR << 16 | OCC_VERSION_MAINTENANCE << 8)-1)
29 #  else
30 #    define OCC_VERSION_LARGE (OCC_VERSION_MAJOR << 24 | OCC_VERSION_MINOR << 16 | OCC_VERSION_MAINTENANCE << 8)
31 #  endif
32 #endif
33
34 #if OCC_VERSION_LARGE > 0x07050303
35 #include <ShapeAnalysis_CanonicalRecognition.hxx>
36 #endif
37
38 #include <TopoDS_Shape.hxx>
39
40 #include <gp_Pln.hxx>
41 #include <gp_Sphere.hxx>
42 #include <gp_Cone.hxx>
43 #include <gp_Cylinder.hxx>
44 #include <gp_Circ.hxx>
45 #include <gp_Elips.hxx>
46
47 static bool isValidDirection(const std::vector<double>& theDir)
48 {
49   return (theDir.size() == 3) && (gp_Vec(theDir[0], theDir[1], theDir[2]).Magnitude() > 0.);
50 }
51
52 bool GeomAlgoAPI_CanonicalRecognition::isPlane(const GeomShapePtr& theShape, double theTolerance,
53   std::vector<double>& theNormal, std::vector<double>& theOrigin)
54 {
55   if (!theShape.get())
56     return false;
57
58   const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
59   if (aShape.IsNull())
60     return false;
61
62   bool aIsValidNormal = isValidDirection(theNormal);
63   bool aIsValidOrigin = theOrigin.size() == 3;
64   gp_Pln aPln;
65   if (aIsValidNormal && aIsValidOrigin) {
66     aPln = gp_Pln(gp_Pnt(theOrigin[0], theOrigin[1], theOrigin[2]),
67       gp_Dir(theNormal[0], theNormal[1], theNormal[2]));
68   }
69
70   bool aResult = false;
71
72 #if OCC_VERSION_LARGE > 0x07050303
73   ShapeAnalysis_CanonicalRecognition aRecognition(aShape);
74   try {
75     if (aRecognition.GetStatus() == 0)
76       aResult = aRecognition.IsPlane(theTolerance, aPln);
77   }
78   catch (...) {
79     return false;
80   }
81 #endif
82
83   gp_Pnt aOrig = aPln.Location();
84   if (theOrigin.size() != 3)
85     theOrigin.resize(3);
86   theOrigin[0] = aOrig.X();
87   theOrigin[1] = aOrig.Y();
88   theOrigin[2] = aOrig.Z();
89
90   gp_Dir aNorm = aPln.Axis().Direction();
91   if (theNormal.size() != 3)
92     theNormal.resize(3);
93   theNormal[0] = aNorm.X();
94   theNormal[1] = aNorm.Y();
95   theNormal[2] = aNorm.Z();
96
97   return aResult;
98 }
99
100 bool GeomAlgoAPI_CanonicalRecognition::isSphere(const GeomShapePtr& theShape, double theTolerance,
101   std::vector<double>& theOrigin, double& theRadius)
102 {
103   if (!theShape.get())
104     return false;
105
106   const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
107   if (aShape.IsNull())
108     return false;
109
110   bool aIsValidOrigin = theOrigin.size() == 3;
111   bool aIsValidRadius = theRadius > 0;
112   gp_Sphere aSphere;
113   if (aIsValidOrigin && aIsValidRadius)
114   {
115     aSphere.SetLocation(gp_Pnt(theOrigin[0], theOrigin[1], theOrigin[2]));
116     aSphere.SetRadius(theRadius);
117   }
118   else
119     aSphere.SetRadius(1.0);
120
121   bool aResult = false;
122
123 #if OCC_VERSION_LARGE > 0x07050303
124   ShapeAnalysis_CanonicalRecognition aRecognition(aShape);
125   try {
126     if (aRecognition.GetStatus() == 0)
127       aResult = aRecognition.IsSphere(theTolerance, aSphere);
128   }
129   catch (...) {
130     return false;
131   }
132 #endif
133
134   gp_Pnt aLoc = aSphere.Location();
135   if (theOrigin.size() != 3)
136     theOrigin.resize(3);
137   theOrigin[0] = aLoc.X();
138   theOrigin[1] = aLoc.Y();
139   theOrigin[2] = aLoc.Z();
140   theRadius = aSphere.Radius();
141
142   return aResult;
143 }
144
145 bool GeomAlgoAPI_CanonicalRecognition::isCone(const GeomShapePtr& theShape, double theTolerance,
146   std::vector<double>& theAxis, std::vector<double>& theApex,
147   double& theHalfAngle)
148 {
149   if (!theShape.get())
150     return false;
151
152   const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
153   if (aShape.IsNull())
154     return false;
155
156   bool aIsValidAxis = isValidDirection(theAxis);
157   bool aIsValidApex = theApex.size() == 3;
158   bool aIsValidAngle = theHalfAngle > 0;
159   gp_Cone aCone;
160   if (aIsValidAxis && aIsValidApex && aIsValidAngle)
161   {
162     gp_Pnt aLoc(theApex[0], theApex[1], theApex[2]);
163     gp_Ax3 aAx3(aLoc, gp_Dir(theAxis[0], theAxis[1], theAxis[2]));
164     aCone.SetPosition(aAx3);
165   }
166   else
167     aCone.SetRadius(1.0);
168
169   bool aResult = false;
170
171 #if OCC_VERSION_LARGE > 0x07050303
172   ShapeAnalysis_CanonicalRecognition aRecognition(aShape);
173   try {
174     if (aRecognition.GetStatus() == 0)
175       aResult = aRecognition.IsCone(theTolerance, aCone);
176   }
177   catch (...) {
178     return false;
179   }
180 #endif
181
182   gp_Dir aDir = aCone.Axis().Direction();
183   if (theAxis.size() != 3)
184     theAxis.resize(3);
185   theAxis[0] = aDir.X();
186   theAxis[1] = aDir.Y();
187   theAxis[2] = aDir.Z();
188
189   gp_Pnt aApex = aCone.Apex();
190   if (theApex.size() != 3)
191     theApex.resize(3);
192   theApex[0] = aApex.X();
193   theApex[1] = aApex.Y();
194   theApex[2] = aApex.Z();
195
196   theHalfAngle = aCone.SemiAngle();
197
198   return aResult;
199 }
200
201 bool GeomAlgoAPI_CanonicalRecognition::isCylinder(const GeomShapePtr& theShape, double theTolerance,
202   std::vector<double>& theAxis, std::vector<double>& theOrigin,
203   double& theRadius)
204 {
205   if (!theShape.get())
206     return false;
207
208   const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
209   if (aShape.IsNull())
210     return false;
211
212   bool aIsValidAxis = isValidDirection(theAxis);
213   bool aIsValidOrigin = theOrigin.size() == 3;
214   bool aIsValidRadius = theRadius > 0;
215   gp_Cylinder aCylinder;
216   if (aIsValidAxis && aIsValidOrigin && aIsValidRadius)
217   {
218     gp_Pnt aLoc(theOrigin[0], theOrigin[0], theOrigin[0]);
219     gp_Ax3 aAx3(aLoc, gp_Dir(theAxis[0], theAxis[1], theAxis[2]));
220     aCylinder.SetPosition(aAx3);
221     aCylinder.SetRadius(theRadius);
222   }
223   else
224     aCylinder.SetRadius(1.0);
225
226   bool aResult = false;
227
228 #if OCC_VERSION_LARGE > 0x07050303
229   ShapeAnalysis_CanonicalRecognition aRecognition(aShape);
230   try {
231     if (aRecognition.GetStatus() == 0)
232       aResult = aRecognition.IsCylinder(theTolerance, aCylinder);
233   }
234   catch (...) {
235     return false;
236   }
237 #endif
238
239   gp_Dir aDir = aCylinder.Axis().Direction();
240   if (theAxis.size() != 3)
241     theAxis.resize(3);
242   theAxis[0] = aDir.X();
243   theAxis[1] = aDir.Y();
244   theAxis[2] = aDir.Z();
245
246   gp_Pnt aLoc = aCylinder.Location();
247   if (theOrigin.size() != 3)
248     theOrigin.resize(3);
249   theOrigin[0] = aLoc.X();
250   theOrigin[1] = aLoc.Y();
251   theOrigin[2] = aLoc.Z();
252
253   theRadius = aCylinder.Radius();
254
255   return aResult;
256 }
257
258 bool GeomAlgoAPI_CanonicalRecognition::isLine(const GeomShapePtr& theEdge, double theTolerance,
259   std::vector<double>& theDir, std::vector<double>& theOrigin)
260 {
261   if (!theEdge.get())
262     return false;
263
264   const TopoDS_Shape& aShape = theEdge->impl<TopoDS_Shape>();
265   if (aShape.IsNull())
266     return false;
267
268   bool aIsValidDir = isValidDirection(theDir);
269   bool aIsValidOrigin = theOrigin.size() == 3;
270   gp_Lin aLine;
271   if (aIsValidDir && aIsValidOrigin)
272   {
273     aLine.SetLocation(gp_Pnt(theOrigin[0], theOrigin[1], theOrigin[2]));
274     aLine.SetDirection(gp_Dir(theDir[0], theDir[1], theDir[2]));
275   }
276
277   bool aResult = false;
278
279 #if OCC_VERSION_LARGE > 0x07050303
280   ShapeAnalysis_CanonicalRecognition aRecognition(aShape);
281   try {
282     if (aRecognition.GetStatus() == 0)
283       aResult = aRecognition.IsLine(theTolerance, aLine);
284   }
285   catch (...) {
286     return false;
287   }
288 #endif
289
290   gp_Pnt aLoc = aLine.Location();
291   if (theOrigin.size() != 3)
292     theOrigin.resize(3);
293   theOrigin[0] = aLoc.X();
294   theOrigin[1] = aLoc.Y();
295   theOrigin[2] = aLoc.Z();
296
297   gp_Dir aDir = aLine.Direction();
298   if (theDir.size() != 3)
299     theDir.resize(3);
300   theDir[0] = aDir.X();
301   theDir[1] = aDir.Y();
302   theDir[2] = aDir.Z();
303
304   return aResult;
305 }
306
307 bool GeomAlgoAPI_CanonicalRecognition::isCircle(const GeomShapePtr& theEdge, double theTolerance,
308   std::vector<double>& theNormal, std::vector<double>& theOrigin,
309   double& theRadius)
310 {
311   if (!theEdge.get())
312     return false;
313
314   const TopoDS_Shape& aShape = theEdge->impl<TopoDS_Shape>();
315   if (aShape.IsNull())
316     return false;
317
318   bool aIsValidNormal = isValidDirection(theNormal);
319   bool aIsValidOrigin = theOrigin.size() == 3;
320   bool aIsValidRadius = theRadius > 0;
321   gp_Circ aCircle;
322   if (aIsValidNormal && aIsValidOrigin && aIsValidRadius)
323   {
324     gp_Ax2 aAx2(gp_Pnt(theOrigin[0], theOrigin[1], theOrigin[2]),
325       gp_Dir(theNormal[0], theNormal[1], theNormal[2]));
326     aCircle.SetPosition(aAx2);
327     aCircle.SetRadius(theRadius);
328   }
329   else
330     aCircle.SetRadius(1.0);
331
332   bool aResult = false;
333
334 #if OCC_VERSION_LARGE > 0x07050303
335   ShapeAnalysis_CanonicalRecognition aRecognition(aShape);
336   try {
337     if (aRecognition.GetStatus() == 0)
338       aResult = aRecognition.IsCircle(theTolerance, aCircle);
339   }
340   catch (...) {
341     return false;
342   }
343 #endif
344
345   gp_Pnt aLoc = aCircle.Location();
346   if (theOrigin.size() != 3)
347     theOrigin.resize(3);
348   theOrigin[0] = aLoc.X();
349   theOrigin[1] = aLoc.Y();
350   theOrigin[2] = aLoc.Z();
351
352   gp_Dir aDir = aCircle.Axis().Direction();
353   if (theNormal.size() != 3)
354     theNormal.resize(3);
355   theNormal[0] = aDir.X();
356   theNormal[1] = aDir.Y();
357   theNormal[2] = aDir.Z();
358   theRadius = aCircle.Radius();
359   return aResult;
360 }
361
362 bool GeomAlgoAPI_CanonicalRecognition::isEllipse(const GeomShapePtr& theEdge, double theTolerance,
363   std::vector<double>& theNormal, std::vector<double>& theDirX,
364   std::vector<double>& theOrigin,
365   double& theMajorRadius, double& theMinorRadius)
366 {
367   if (!theEdge.get())
368     return false;
369
370   const TopoDS_Shape& aShape = theEdge->impl<TopoDS_Shape>();
371   if (aShape.IsNull())
372     return false;
373
374   bool aIsValidNormal = isValidDirection(theNormal);
375   bool aIsValidOrigin = theOrigin.size() == 3;
376   bool aIsValidDirX = isValidDirection(theDirX);
377   bool aIsValidRad1 = (theMajorRadius > 0) && (theMajorRadius > theMinorRadius);
378   bool aIsValidRad2 = (theMinorRadius > 0) && (theMajorRadius > theMinorRadius);
379
380   gp_Elips aElips;
381   if (aIsValidNormal && aIsValidOrigin && aIsValidDirX && aIsValidRad1 && aIsValidRad2)
382   {
383     gp_Pnt anOrigin(theOrigin[0], theOrigin[1], theOrigin[2]);
384     gp_XYZ aNormal(theNormal[0], theNormal[1], theNormal[2]);
385     gp_XYZ aDirX(theDirX[0], theDirX[1], theDirX[2]);
386     Standard_Boolean isCollinear =
387         aNormal.CrossSquareMagnitude(aDirX) < Precision::SquareConfusion();
388     gp_Ax2 aAx2 = isCollinear ? gp_Ax2(anOrigin, aNormal) : gp_Ax2(anOrigin, aNormal, aDirX);
389     aElips = gp_Elips(aAx2, theMajorRadius, theMinorRadius);
390   }
391   else
392     aElips.SetMajorRadius(1.0);
393
394   bool aResult = false;
395
396 #if OCC_VERSION_LARGE > 0x07050303
397   ShapeAnalysis_CanonicalRecognition aRecognition(aShape);
398   try {
399     if (aRecognition.GetStatus() == 0)
400       aResult = aRecognition.IsEllipse(theTolerance, aElips);
401   }
402   catch (...) {
403     return false;
404   }
405 #endif
406
407   gp_Pnt aLoc = aElips.Position().Location();
408   if (theOrigin.size() != 3)
409     theOrigin.resize(3);
410   theOrigin[0] = aLoc.X();
411   theOrigin[1] = aLoc.Y();
412   theOrigin[2] = aLoc.Z();
413
414   gp_Dir aNorm = aElips.Position().Direction();
415   if (theNormal.size() != 3)
416     theNormal.resize(3);
417   theNormal[0] = aNorm.X();
418   theNormal[1] = aNorm.Y();
419   theNormal[2] = aNorm.Z();
420
421   gp_Dir aDirX = aElips.Position().XDirection();
422   if (theDirX.size() != 3)
423     theDirX.resize(3);
424   theDirX[0] = aDirX.X();
425   theDirX[1] = aDirX.Y();
426   theDirX[2] = aDirX.Z();
427
428   theMajorRadius = aElips.MajorRadius();
429   theMinorRadius = aElips.MinorRadius();
430
431   return aResult;
432 }
433
434 bool GeomAlgoAPI_CanonicalRecognition::isImplemented()
435 {
436 #if OCC_VERSION_LARGE > 0x07050303
437   return true;
438 #else
439   return false;
440 #endif
441 }