1 // Copyright (C) 2014-2022 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "GeomAlgoAPI_CanonicalRecognition.h"
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)
27 # ifdef OCC_VERSION_DEVELOPMENT
28 # define OCC_VERSION_LARGE ((OCC_VERSION_MAJOR << 24 | OCC_VERSION_MINOR << 16 | OCC_VERSION_MAINTENANCE << 8)-1)
30 # define OCC_VERSION_LARGE (OCC_VERSION_MAJOR << 24 | OCC_VERSION_MINOR << 16 | OCC_VERSION_MAINTENANCE << 8)
34 #if OCC_VERSION_LARGE > 0x07050303
35 #include <ShapeAnalysis_CanonicalRecognition.hxx>
38 #include <TopoDS_Shape.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>
47 static bool isValidDirection(const std::vector<double>& theDir)
49 return (theDir.size() == 3) && (gp_Vec(theDir[0], theDir[1], theDir[2]).Magnitude() > 0.);
52 bool GeomAlgoAPI_CanonicalRecognition::isPlane(const GeomShapePtr& theShape, double theTolerance,
53 std::vector<double>& theNormal, std::vector<double>& theOrigin)
58 const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
62 bool aIsValidNormal = isValidDirection(theNormal);
63 bool aIsValidOrigin = theOrigin.size() == 3;
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]));
72 #if OCC_VERSION_LARGE > 0x07050303
73 ShapeAnalysis_CanonicalRecognition aRecognition(aShape);
75 if (aRecognition.GetStatus() == 0)
76 aResult = aRecognition.IsPlane(theTolerance, aPln);
83 gp_Pnt aOrig = aPln.Location();
84 if (theOrigin.size() != 3)
86 theOrigin[0] = aOrig.X();
87 theOrigin[1] = aOrig.Y();
88 theOrigin[2] = aOrig.Z();
90 gp_Dir aNorm = aPln.Axis().Direction();
91 if (theNormal.size() != 3)
93 theNormal[0] = aNorm.X();
94 theNormal[1] = aNorm.Y();
95 theNormal[2] = aNorm.Z();
100 bool GeomAlgoAPI_CanonicalRecognition::isSphere(const GeomShapePtr& theShape, double theTolerance,
101 std::vector<double>& theOrigin, double& theRadius)
106 const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
110 bool aIsValidOrigin = theOrigin.size() == 3;
111 bool aIsValidRadius = theRadius > 0;
113 if (aIsValidOrigin && aIsValidRadius)
115 aSphere.SetLocation(gp_Pnt(theOrigin[0], theOrigin[1], theOrigin[2]));
116 aSphere.SetRadius(theRadius);
119 aSphere.SetRadius(1.0);
121 bool aResult = false;
123 #if OCC_VERSION_LARGE > 0x07050303
124 ShapeAnalysis_CanonicalRecognition aRecognition(aShape);
126 if (aRecognition.GetStatus() == 0)
127 aResult = aRecognition.IsSphere(theTolerance, aSphere);
134 gp_Pnt aLoc = aSphere.Location();
135 if (theOrigin.size() != 3)
137 theOrigin[0] = aLoc.X();
138 theOrigin[1] = aLoc.Y();
139 theOrigin[2] = aLoc.Z();
140 theRadius = aSphere.Radius();
145 bool GeomAlgoAPI_CanonicalRecognition::isCone(const GeomShapePtr& theShape, double theTolerance,
146 std::vector<double>& theAxis, std::vector<double>& theApex,
147 double& theHalfAngle)
152 const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
156 bool aIsValidAxis = isValidDirection(theAxis);
157 bool aIsValidApex = theApex.size() == 3;
158 bool aIsValidAngle = theHalfAngle > 0;
160 if (aIsValidAxis && aIsValidApex && aIsValidAngle)
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);
167 aCone.SetRadius(1.0);
169 bool aResult = false;
171 #if OCC_VERSION_LARGE > 0x07050303
172 ShapeAnalysis_CanonicalRecognition aRecognition(aShape);
174 if (aRecognition.GetStatus() == 0)
175 aResult = aRecognition.IsCone(theTolerance, aCone);
182 gp_Dir aDir = aCone.Axis().Direction();
183 if (theAxis.size() != 3)
185 theAxis[0] = aDir.X();
186 theAxis[1] = aDir.Y();
187 theAxis[2] = aDir.Z();
189 gp_Pnt aApex = aCone.Apex();
190 if (theApex.size() != 3)
192 theApex[0] = aApex.X();
193 theApex[1] = aApex.Y();
194 theApex[2] = aApex.Z();
196 theHalfAngle = aCone.SemiAngle();
201 bool GeomAlgoAPI_CanonicalRecognition::isCylinder(const GeomShapePtr& theShape, double theTolerance,
202 std::vector<double>& theAxis, std::vector<double>& theOrigin,
208 const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
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)
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);
224 aCylinder.SetRadius(1.0);
226 bool aResult = false;
228 #if OCC_VERSION_LARGE > 0x07050303
229 ShapeAnalysis_CanonicalRecognition aRecognition(aShape);
231 if (aRecognition.GetStatus() == 0)
232 aResult = aRecognition.IsCylinder(theTolerance, aCylinder);
239 gp_Dir aDir = aCylinder.Axis().Direction();
240 if (theAxis.size() != 3)
242 theAxis[0] = aDir.X();
243 theAxis[1] = aDir.Y();
244 theAxis[2] = aDir.Z();
246 gp_Pnt aLoc = aCylinder.Location();
247 if (theOrigin.size() != 3)
249 theOrigin[0] = aLoc.X();
250 theOrigin[1] = aLoc.Y();
251 theOrigin[2] = aLoc.Z();
253 theRadius = aCylinder.Radius();
258 bool GeomAlgoAPI_CanonicalRecognition::isLine(const GeomShapePtr& theEdge, double theTolerance,
259 std::vector<double>& theDir, std::vector<double>& theOrigin)
264 const TopoDS_Shape& aShape = theEdge->impl<TopoDS_Shape>();
268 bool aIsValidDir = isValidDirection(theDir);
269 bool aIsValidOrigin = theOrigin.size() == 3;
271 if (aIsValidDir && aIsValidOrigin)
273 aLine.SetLocation(gp_Pnt(theOrigin[0], theOrigin[1], theOrigin[2]));
274 aLine.SetDirection(gp_Dir(theDir[0], theDir[1], theDir[2]));
277 bool aResult = false;
279 #if OCC_VERSION_LARGE > 0x07050303
280 ShapeAnalysis_CanonicalRecognition aRecognition(aShape);
282 if (aRecognition.GetStatus() == 0)
283 aResult = aRecognition.IsLine(theTolerance, aLine);
290 gp_Pnt aLoc = aLine.Location();
291 if (theOrigin.size() != 3)
293 theOrigin[0] = aLoc.X();
294 theOrigin[1] = aLoc.Y();
295 theOrigin[2] = aLoc.Z();
297 gp_Dir aDir = aLine.Direction();
298 if (theDir.size() != 3)
300 theDir[0] = aDir.X();
301 theDir[1] = aDir.Y();
302 theDir[2] = aDir.Z();
307 bool GeomAlgoAPI_CanonicalRecognition::isCircle(const GeomShapePtr& theEdge, double theTolerance,
308 std::vector<double>& theNormal, std::vector<double>& theOrigin,
314 const TopoDS_Shape& aShape = theEdge->impl<TopoDS_Shape>();
318 bool aIsValidNormal = isValidDirection(theNormal);
319 bool aIsValidOrigin = theOrigin.size() == 3;
320 bool aIsValidRadius = theRadius > 0;
322 if (aIsValidNormal && aIsValidOrigin && aIsValidRadius)
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);
330 aCircle.SetRadius(1.0);
332 bool aResult = false;
334 #if OCC_VERSION_LARGE > 0x07050303
335 ShapeAnalysis_CanonicalRecognition aRecognition(aShape);
337 if (aRecognition.GetStatus() == 0)
338 aResult = aRecognition.IsCircle(theTolerance, aCircle);
345 gp_Pnt aLoc = aCircle.Location();
346 if (theOrigin.size() != 3)
348 theOrigin[0] = aLoc.X();
349 theOrigin[1] = aLoc.Y();
350 theOrigin[2] = aLoc.Z();
352 gp_Dir aDir = aCircle.Axis().Direction();
353 if (theNormal.size() != 3)
355 theNormal[0] = aDir.X();
356 theNormal[1] = aDir.Y();
357 theNormal[2] = aDir.Z();
358 theRadius = aCircle.Radius();
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)
370 const TopoDS_Shape& aShape = theEdge->impl<TopoDS_Shape>();
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);
381 if (aIsValidNormal && aIsValidOrigin && aIsValidDirX && aIsValidRad1 && aIsValidRad2)
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);
392 aElips.SetMajorRadius(1.0);
394 bool aResult = false;
396 #if OCC_VERSION_LARGE > 0x07050303
397 ShapeAnalysis_CanonicalRecognition aRecognition(aShape);
399 if (aRecognition.GetStatus() == 0)
400 aResult = aRecognition.IsEllipse(theTolerance, aElips);
407 gp_Pnt aLoc = aElips.Position().Location();
408 if (theOrigin.size() != 3)
410 theOrigin[0] = aLoc.X();
411 theOrigin[1] = aLoc.Y();
412 theOrigin[2] = aLoc.Z();
414 gp_Dir aNorm = aElips.Position().Direction();
415 if (theNormal.size() != 3)
417 theNormal[0] = aNorm.X();
418 theNormal[1] = aNorm.Y();
419 theNormal[2] = aNorm.Z();
421 gp_Dir aDirX = aElips.Position().XDirection();
422 if (theDirX.size() != 3)
424 theDirX[0] = aDirX.X();
425 theDirX[1] = aDirX.Y();
426 theDirX[2] = aDirX.Z();
428 theMajorRadius = aElips.MajorRadius();
429 theMinorRadius = aElips.MinorRadius();
434 bool GeomAlgoAPI_CanonicalRecognition::isImplemented()
436 #if OCC_VERSION_LARGE > 0x07050303