1 // Copyright (C) 2007-2023 CEA, EDF, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 #include <GEOMImpl_IMeasureOperations.hxx>
24 #include <GEOMImpl_IMeasure.hxx>
25 #include <GEOMImpl_MeasureDriver.hxx>
27 #include <GEOMImpl_IPatchFace.hxx>
28 #include <GEOMImpl_IProximity.hxx>
29 #include <GEOMImpl_PatchFaceDriver.hxx>
30 #include <GEOMImpl_ShapeProximityDriver.hxx>
32 #include <GEOMImpl_Types.hxx>
34 #include <GEOMImpl_IConformity.hxx>
35 #include <GEOMImpl_ConformityDriver.hxx>
37 #include <GEOMUtils.hxx>
39 #include <GEOMAlgo_AlgoTools.hxx>
40 #include <GEOMAlgo_KindOfName.hxx>
41 #include <GEOMAlgo_ShapeInfoFiller.hxx>
43 #include <GEOM_PythonDump.hxx>
45 #include <utilities.h>
48 #include <Bnd_Box.hxx>
49 #include <BOPAlgo_CheckerSI.hxx>
50 #include <TopTools_ListOfShape.hxx>
51 #include <BOPDS_DS.hxx>
52 #include <BOPDS_MapOfPair.hxx>
53 #include <BOPDS_Pair.hxx>
54 #include <BOPTools_AlgoTools.hxx>
55 #include <BRepBndLib.hxx>
56 #include <BRepBuilderAPI_Copy.hxx>
57 #include <BRepCheck_ListIteratorOfListOfStatus.hxx>
58 #include <BRepCheck_Shell.hxx>
59 #include <BRepClass3d_SolidClassifier.hxx>
60 #include <BRepClass_FaceClassifier.hxx>
61 #include <BRepExtrema_DistShapeShape.hxx>
62 #include <BRepExtrema_ShapeProximity.hxx>
63 #include <BRepExtrema_SelfIntersection.hxx>
64 #include <BRepExtrema_MapOfIntegerPackedMapOfInteger.hxx>
65 #include <BRepGProp.hxx>
66 #include <BRepTools.hxx>
67 #include <BRep_Tool.hxx>
68 #include <Geom_Line.hxx>
69 #include <GeomAPI_ProjectPointOnCurve.hxx>
70 #include <GeomAPI_ProjectPointOnSurf.hxx>
71 #include <GeomLProp_CLProps.hxx>
72 #include <GeomLProp_SLProps.hxx>
73 #include <Geom_Plane.hxx>
74 #include <GProp_GProps.hxx>
75 #include <GProp_PrincipalProps.hxx>
76 #include <ShapeAnalysis_Surface.hxx>
78 #include <TopExp_Explorer.hxx>
80 #include <TopoDS_Edge.hxx>
81 #include <TopTools_IndexedMapOfShape.hxx>
82 #include <TopTools_DataMapIteratorOfDataMapOfIntegerListOfShape.hxx>
83 #include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
84 #include <TopTools_ListIteratorOfListOfShape.hxx>
85 #include <TopTools_ListOfShape.hxx>
86 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
90 //=============================================================================
94 //=============================================================================
95 GEOMImpl_IMeasureOperations::GEOMImpl_IMeasureOperations (GEOM_Engine* theEngine)
96 : GEOM_IOperations(theEngine)
98 MESSAGE("GEOMImpl_IMeasureOperations::GEOMImpl_IMeasureOperations");
101 //=============================================================================
105 //=============================================================================
106 GEOMImpl_IMeasureOperations::~GEOMImpl_IMeasureOperations()
108 MESSAGE("GEOMImpl_IMeasureOperations::~GEOMImpl_IMeasureOperations");
111 //=============================================================================
112 /*! Get kind and parameters of the given shape.
114 //=============================================================================
115 GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape
116 (Handle(GEOM_Object) theShape,
117 Handle(TColStd_HSequenceOfInteger)& theIntegers,
118 Handle(TColStd_HSequenceOfReal)& theDoubles)
121 ShapeKind aKind = SK_NO_SHAPE;
123 if (theIntegers.IsNull()) theIntegers = new TColStd_HSequenceOfInteger;
124 else theIntegers->Clear();
126 if (theDoubles.IsNull()) theDoubles = new TColStd_HSequenceOfReal;
127 else theDoubles->Clear();
129 if (theShape.IsNull())
132 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
133 if (aRefShape.IsNull()) return aKind;
135 TopoDS_Shape aShape = aRefShape->GetValue();
136 if (aShape.IsNull()) return aKind;
138 int geom_type = theShape->GetType();
140 // check if it's advanced shape
141 if ( geom_type > USER_TYPE ) {
147 GEOMAlgo_ShapeInfoFiller aSF;
148 aSF.SetShape(aShape);
151 Standard_Integer iErr = aSF.ErrorStatus();
154 SetErrorCode("Error in GEOMAlgo_ShapeInfoFiller");
157 const GEOMAlgo_ShapeInfo& anInfo = aSF.Info();
159 // specific processing for some "advanced" objects
160 switch ( geom_type ) {
162 // local coordinate system
163 // (+) geompy.kind.LCS xc yc zc xx xy xz yx yy yz zx zy zz
165 TopoDS_Face aFace = TopoDS::Face( aShape );
166 Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast( BRep_Tool::Surface( aFace ) );
167 gp_Pnt aC = aPlane->Pln().Location();
168 gp_Ax3 anAx3 = aPlane->Pln().Position();
170 theDoubles->Append(aC.X());
171 theDoubles->Append(aC.Y());
172 theDoubles->Append(aC.Z());
174 gp_Dir aD = anAx3.XDirection();
175 theDoubles->Append(aD.X());
176 theDoubles->Append(aD.Y());
177 theDoubles->Append(aD.Z());
178 aD = anAx3.YDirection();
179 theDoubles->Append(aD.X());
180 theDoubles->Append(aD.Y());
181 theDoubles->Append(aD.Z());
182 aD = anAx3.Direction();
183 theDoubles->Append(aD.X());
184 theDoubles->Append(aD.Y());
185 theDoubles->Append(aD.Z());
192 TopAbs_ShapeEnum aType = anInfo.Type();
195 case TopAbs_COMPOUND:
196 case TopAbs_COMPSOLID:
198 // (+) geompy.kind.COMPOUND nb_solids nb_faces nb_edges nb_vertices
199 // (+) geompy.kind.COMPSOLID nb_solids nb_faces nb_edges nb_vertices
200 // ??? "nb_faces" - all faces or only 'standalone' faces?
201 if (aType == TopAbs_COMPOUND)
204 aKind = SK_COMPSOLID;
206 //theIntegers->Append(anInfo.NbSubShapes(TopAbs_COMPOUND));
207 //theIntegers->Append(anInfo.NbSubShapes(TopAbs_COMPSOLID));
208 theIntegers->Append(anInfo.NbSubShapes(TopAbs_SOLID));
209 theIntegers->Append(anInfo.NbSubShapes(TopAbs_FACE));
210 theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
211 theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
217 // (+) geompy.kind.SHELL geompy.info.closed nb_faces nb_edges nb_vertices
218 // (+) geompy.kind.SHELL geompy.info.unclosed nb_faces nb_edges nb_vertices
221 theIntegers->Append((int)anInfo.KindOfClosed());
223 theIntegers->Append(anInfo.NbSubShapes(TopAbs_FACE));
224 theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
225 theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
231 // (+) geompy.kind.WIRE geompy.info.closed nb_edges nb_vertices
232 // (+) geompy.kind.WIRE geompy.info.unclosed nb_edges nb_vertices
235 theIntegers->Append((int)anInfo.KindOfClosed());
237 theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
238 theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
246 GEOMAlgo_KindOfName aKN = anInfo.KindOfName();
249 case GEOMAlgo_KN_SPHERE:
250 // (+) geompy.kind.SPHERE xc yc zc R
254 gp_Pnt aC = anInfo.Location();
255 theDoubles->Append(aC.X());
256 theDoubles->Append(aC.Y());
257 theDoubles->Append(aC.Z());
259 theDoubles->Append(anInfo.Radius1());
262 case GEOMAlgo_KN_CYLINDER:
263 // (+) geompy.kind.CYLINDER xb yb zb dx dy dz R H
267 gp_Pnt aC = anInfo.Location();
268 theDoubles->Append(aC.X());
269 theDoubles->Append(aC.Y());
270 theDoubles->Append(aC.Z());
272 gp_Ax3 anAx3 = anInfo.Position();
273 gp_Dir aD = anAx3.Direction();
274 theDoubles->Append(aD.X());
275 theDoubles->Append(aD.Y());
276 theDoubles->Append(aD.Z());
278 theDoubles->Append(anInfo.Radius1());
279 theDoubles->Append(anInfo.Height());
282 case GEOMAlgo_KN_BOX:
283 // (+) geompy.kind.BOX xc yc zc ax ay az
287 gp_Pnt aC = anInfo.Location();
288 theDoubles->Append(aC.X());
289 theDoubles->Append(aC.Y());
290 theDoubles->Append(aC.Z());
292 gp_Ax3 anAx3 = anInfo.Position();
293 gp_Dir aD = anAx3.Direction();
294 gp_Dir aX = anAx3.XDirection();
297 if (aD.IsParallel(gp::DZ(), Precision::Angular()) &&
298 aX.IsParallel(gp::DX(), Precision::Angular())) {
299 theDoubles->Append(anInfo.Length()); // ax'
300 theDoubles->Append(anInfo.Width()); // ay'
301 theDoubles->Append(anInfo.Height()); // az'
303 else if (aD.IsParallel(gp::DZ(), Precision::Angular()) &&
304 aX.IsParallel(gp::DY(), Precision::Angular())) {
305 theDoubles->Append(anInfo.Width()); // ay'
306 theDoubles->Append(anInfo.Length()); // ax'
307 theDoubles->Append(anInfo.Height()); // az'
309 else if (aD.IsParallel(gp::DX(), Precision::Angular()) &&
310 aX.IsParallel(gp::DZ(), Precision::Angular())) {
311 theDoubles->Append(anInfo.Height()); // az'
312 theDoubles->Append(anInfo.Width()); // ay'
313 theDoubles->Append(anInfo.Length()); // ax'
315 else if (aD.IsParallel(gp::DX(), Precision::Angular()) &&
316 aX.IsParallel(gp::DY(), Precision::Angular())) {
317 theDoubles->Append(anInfo.Height()); // az'
318 theDoubles->Append(anInfo.Length()); // ax'
319 theDoubles->Append(anInfo.Width()); // ay'
321 else if (aD.IsParallel(gp::DY(), Precision::Angular()) &&
322 aX.IsParallel(gp::DZ(), Precision::Angular())) {
323 theDoubles->Append(anInfo.Width()); // ay'
324 theDoubles->Append(anInfo.Height()); // az'
325 theDoubles->Append(anInfo.Length()); // ax'
327 else if (aD.IsParallel(gp::DY(), Precision::Angular()) &&
328 aX.IsParallel(gp::DX(), Precision::Angular())) {
329 theDoubles->Append(anInfo.Length()); // ax'
330 theDoubles->Append(anInfo.Height()); // az'
331 theDoubles->Append(anInfo.Width()); // ay'
334 // (+) geompy.kind.ROTATED_BOX xo yo zo zx zy zz xx xy xz ax ay az
335 aKind = SK_ROTATED_BOX;
337 // Direction and XDirection
338 theDoubles->Append(aD.X());
339 theDoubles->Append(aD.Y());
340 theDoubles->Append(aD.Z());
342 theDoubles->Append(aX.X());
343 theDoubles->Append(aX.Y());
344 theDoubles->Append(aX.Z());
347 theDoubles->Append(anInfo.Length());
348 theDoubles->Append(anInfo.Width());
349 theDoubles->Append(anInfo.Height());
353 case GEOMAlgo_KN_TORUS:
354 // (+) geompy.kind.TORUS xc yc zc dx dy dz R_1 R_2
358 gp_Pnt aO = anInfo.Location();
359 theDoubles->Append(aO.X());
360 theDoubles->Append(aO.Y());
361 theDoubles->Append(aO.Z());
363 gp_Ax3 anAx3 = anInfo.Position();
364 gp_Dir aD = anAx3.Direction();
365 theDoubles->Append(aD.X());
366 theDoubles->Append(aD.Y());
367 theDoubles->Append(aD.Z());
369 theDoubles->Append(anInfo.Radius1());
370 theDoubles->Append(anInfo.Radius2());
373 case GEOMAlgo_KN_CONE:
374 // (+) geompy.kind.CONE xb yb zb dx dy dz R_1 R_2 H
378 gp_Pnt aO = anInfo.Location();
379 theDoubles->Append(aO.X());
380 theDoubles->Append(aO.Y());
381 theDoubles->Append(aO.Z());
383 gp_Ax3 anAx3 = anInfo.Position();
384 gp_Dir aD = anAx3.Direction();
385 theDoubles->Append(aD.X());
386 theDoubles->Append(aD.Y());
387 theDoubles->Append(aD.Z());
389 theDoubles->Append(anInfo.Radius1());
390 theDoubles->Append(anInfo.Radius2());
391 theDoubles->Append(anInfo.Height());
394 case GEOMAlgo_KN_POLYHEDRON:
395 // (+) geompy.kind.POLYHEDRON nb_faces nb_edges nb_vertices
397 aKind = SK_POLYHEDRON;
399 theIntegers->Append(anInfo.NbSubShapes(TopAbs_FACE));
400 theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
401 theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
405 // (+) geompy.kind.SOLID nb_faces nb_edges nb_vertices
407 theIntegers->Append(anInfo.NbSubShapes(TopAbs_FACE));
408 theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
409 theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
419 GEOMAlgo_KindOfName aKN = anInfo.KindOfName();
421 case GEOMAlgo_KN_SPHERE:
422 // (+) geompy.kind.SPHERE2D xc yc zc R
426 gp_Pnt aC = anInfo.Location();
427 theDoubles->Append(aC.X());
428 theDoubles->Append(aC.Y());
429 theDoubles->Append(aC.Z());
431 theDoubles->Append(anInfo.Radius1());
434 case GEOMAlgo_KN_CYLINDER:
435 // (+) geompy.kind.CYLINDER2D xb yb zb dx dy dz R H
437 aKind = SK_CYLINDER2D;
439 gp_Pnt aO = anInfo.Location();
440 theDoubles->Append(aO.X());
441 theDoubles->Append(aO.Y());
442 theDoubles->Append(aO.Z());
444 gp_Ax3 anAx3 = anInfo.Position();
445 gp_Dir aD = anAx3.Direction();
446 theDoubles->Append(aD.X());
447 theDoubles->Append(aD.Y());
448 theDoubles->Append(aD.Z());
450 theDoubles->Append(anInfo.Radius1());
451 theDoubles->Append(anInfo.Height());
454 case GEOMAlgo_KN_TORUS:
455 // (+) geompy.kind.TORUS2D xc yc zc dx dy dz R_1 R_2
459 gp_Pnt aO = anInfo.Location();
460 theDoubles->Append(aO.X());
461 theDoubles->Append(aO.Y());
462 theDoubles->Append(aO.Z());
464 gp_Ax3 anAx3 = anInfo.Position();
465 gp_Dir aD = anAx3.Direction();
466 theDoubles->Append(aD.X());
467 theDoubles->Append(aD.Y());
468 theDoubles->Append(aD.Z());
470 theDoubles->Append(anInfo.Radius1());
471 theDoubles->Append(anInfo.Radius2());
474 case GEOMAlgo_KN_CONE:
475 // (+) geompy.kind.CONE2D xc yc zc dx dy dz R_1 R_2 H
479 gp_Pnt aO = anInfo.Location();
480 theDoubles->Append(aO.X());
481 theDoubles->Append(aO.Y());
482 theDoubles->Append(aO.Z());
484 gp_Ax3 anAx3 = anInfo.Position();
485 gp_Dir aD = anAx3.Direction();
486 theDoubles->Append(aD.X());
487 theDoubles->Append(aD.Y());
488 theDoubles->Append(aD.Z());
490 theDoubles->Append(anInfo.Radius1());
491 theDoubles->Append(anInfo.Radius2());
492 theDoubles->Append(anInfo.Height());
495 case GEOMAlgo_KN_DISKCIRCLE:
496 // (+) geompy.kind.DISK_CIRCLE xc yc zc dx dy dz R
498 aKind = SK_DISK_CIRCLE;
500 gp_Pnt aC = anInfo.Location();
501 theDoubles->Append(aC.X());
502 theDoubles->Append(aC.Y());
503 theDoubles->Append(aC.Z());
505 gp_Ax3 anAx3 = anInfo.Position();
506 gp_Dir aD = anAx3.Direction();
507 theDoubles->Append(aD.X());
508 theDoubles->Append(aD.Y());
509 theDoubles->Append(aD.Z());
511 theDoubles->Append(anInfo.Radius1());
514 case GEOMAlgo_KN_DISKELLIPSE:
515 // (+) geompy.kind.DISK_ELLIPSE xc yc zc dx dy dz R_1 R_2
517 aKind = SK_DISK_ELLIPSE;
519 gp_Pnt aC = anInfo.Location();
520 theDoubles->Append(aC.X());
521 theDoubles->Append(aC.Y());
522 theDoubles->Append(aC.Z());
524 gp_Ax3 anAx3 = anInfo.Position();
525 gp_Dir aD = anAx3.Direction();
526 theDoubles->Append(aD.X());
527 theDoubles->Append(aD.Y());
528 theDoubles->Append(aD.Z());
530 theDoubles->Append(anInfo.Radius1());
531 theDoubles->Append(anInfo.Radius2());
534 case GEOMAlgo_KN_RECTANGLE:
535 case GEOMAlgo_KN_TRIANGLE:
536 case GEOMAlgo_KN_QUADRANGLE:
537 case GEOMAlgo_KN_POLYGON:
538 // (+) geompy.kind.POLYGON xo yo zo dx dy dz nb_edges nb_vertices
542 gp_Pnt aO = anInfo.Location();
543 theDoubles->Append(aO.X());
544 theDoubles->Append(aO.Y());
545 theDoubles->Append(aO.Z());
547 gp_Ax3 anAx3 = anInfo.Position();
548 gp_Dir aD = anAx3.Direction();
549 theDoubles->Append(aD.X());
550 theDoubles->Append(aD.Y());
551 theDoubles->Append(aD.Z());
553 theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
554 theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
557 case GEOMAlgo_KN_PLANE: // infinite
558 // (+) geompy.kind.PLANE xo yo zo dx dy dz
562 gp_Pnt aC = anInfo.Location();
563 theDoubles->Append(aC.X());
564 theDoubles->Append(aC.Y());
565 theDoubles->Append(aC.Z());
567 gp_Ax3 anAx3 = anInfo.Position();
568 gp_Dir aD = anAx3.Direction();
569 theDoubles->Append(aD.X());
570 theDoubles->Append(aD.Y());
571 theDoubles->Append(aD.Z());
573 if (anInfo.KindOfBounds() != GEOMAlgo_KB_INFINITE)
575 // (+) geompy.kind.PLANAR xo yo zo dx dy dz nb_edges nb_vertices
578 theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
579 theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
584 // ??? geompy.kind.FACE nb_edges nb_vertices _surface_type_id_
585 // (+) geompy.kind.FACE nb_edges nb_vertices
586 theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
587 theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
596 GEOMAlgo_KindOfName aKN = anInfo.KindOfName();
598 case GEOMAlgo_KN_CIRCLE:
600 // (+) geompy.kind.CIRCLE xc yc zc dx dy dz R
603 gp_Pnt aC = anInfo.Location();
604 theDoubles->Append(aC.X());
605 theDoubles->Append(aC.Y());
606 theDoubles->Append(aC.Z());
608 gp_Ax3 anAx3 = anInfo.Position();
609 gp_Dir aD = anAx3.Direction();
610 theDoubles->Append(aD.X());
611 theDoubles->Append(aD.Y());
612 theDoubles->Append(aD.Z());
614 theDoubles->Append(anInfo.Radius1());
617 case GEOMAlgo_KN_ARCCIRCLE:
619 // (+) geompy.kind.ARC_CIRCLE xc yc zc dx dy dz R x1 y1 z1 x2 y2 z2
620 aKind = SK_ARC_CIRCLE;
622 gp_Pnt aC = anInfo.Location();
623 theDoubles->Append(aC.X());
624 theDoubles->Append(aC.Y());
625 theDoubles->Append(aC.Z());
627 gp_Ax3 anAx3 = anInfo.Position();
628 gp_Dir aD = anAx3.Direction();
629 theDoubles->Append(aD.X());
630 theDoubles->Append(aD.Y());
631 theDoubles->Append(aD.Z());
633 theDoubles->Append(anInfo.Radius1());
635 gp_Pnt aP1 = anInfo.Pnt1();
636 theDoubles->Append(aP1.X());
637 theDoubles->Append(aP1.Y());
638 theDoubles->Append(aP1.Z());
640 gp_Pnt aP2 = anInfo.Pnt2();
641 theDoubles->Append(aP2.X());
642 theDoubles->Append(aP2.Y());
643 theDoubles->Append(aP2.Z());
646 case GEOMAlgo_KN_ELLIPSE:
648 // (+) geompy.kind.ELLIPSE xc yc zc dx dy dz R_1 R_2 xVx yVx zVx xVy yVy zVy
651 gp_Pnt aC = anInfo.Location();
652 theDoubles->Append(aC.X());
653 theDoubles->Append(aC.Y());
654 theDoubles->Append(aC.Z());
656 gp_Ax3 anAx3 = anInfo.Position();
657 gp_Dir aD = anAx3.Direction();
658 theDoubles->Append(aD.X());
659 theDoubles->Append(aD.Y());
660 theDoubles->Append(aD.Z());
662 theDoubles->Append(anInfo.Radius1());
663 theDoubles->Append(anInfo.Radius2());
665 gp_Dir aXD = anAx3.XDirection();
666 theDoubles->Append(aXD.X());
667 theDoubles->Append(aXD.Y());
668 theDoubles->Append(aXD.Z());
670 gp_Dir aYD = anAx3.YDirection();
671 theDoubles->Append(aYD.X());
672 theDoubles->Append(aYD.Y());
673 theDoubles->Append(aYD.Z());
676 case GEOMAlgo_KN_ARCELLIPSE:
678 // (+) geompy.kind.ARC_ELLIPSE xc yc zc dx dy dz R_1 R_2 x1 y1 z1 x2 y2 z2 xVx yVx zVx xVy yVy zVy
679 aKind = SK_ARC_ELLIPSE;
681 gp_Pnt aC = anInfo.Location();
682 theDoubles->Append(aC.X());
683 theDoubles->Append(aC.Y());
684 theDoubles->Append(aC.Z());
686 gp_Ax3 anAx3 = anInfo.Position();
687 gp_Dir aD = anAx3.Direction();
688 theDoubles->Append(aD.X());
689 theDoubles->Append(aD.Y());
690 theDoubles->Append(aD.Z());
692 theDoubles->Append(anInfo.Radius1());
693 theDoubles->Append(anInfo.Radius2());
695 gp_Pnt aP1 = anInfo.Pnt1();
696 theDoubles->Append(aP1.X());
697 theDoubles->Append(aP1.Y());
698 theDoubles->Append(aP1.Z());
700 gp_Pnt aP2 = anInfo.Pnt2();
701 theDoubles->Append(aP2.X());
702 theDoubles->Append(aP2.Y());
703 theDoubles->Append(aP2.Z());
705 gp_Dir aXD = anAx3.XDirection();
706 theDoubles->Append(aXD.X());
707 theDoubles->Append(aXD.Y());
708 theDoubles->Append(aXD.Z());
710 gp_Dir aYD = anAx3.YDirection();
711 theDoubles->Append(aYD.X());
712 theDoubles->Append(aYD.Y());
713 theDoubles->Append(aYD.Z());
716 case GEOMAlgo_KN_LINE:
718 // ??? geompy.kind.LINE x1 y1 z1 x2 y2 z2
719 // (+) geompy.kind.LINE x1 y1 z1 dx dy dz
722 gp_Pnt aO = anInfo.Location();
723 theDoubles->Append(aO.X());
724 theDoubles->Append(aO.Y());
725 theDoubles->Append(aO.Z());
727 gp_Dir aD = anInfo.Direction();
728 theDoubles->Append(aD.X());
729 theDoubles->Append(aD.Y());
730 theDoubles->Append(aD.Z());
733 case GEOMAlgo_KN_SEGMENT:
735 // (+) geompy.kind.SEGMENT x1 y1 z1 x2 y2 z2
738 gp_Pnt aP1 = anInfo.Pnt1();
739 theDoubles->Append(aP1.X());
740 theDoubles->Append(aP1.Y());
741 theDoubles->Append(aP1.Z());
743 gp_Pnt aP2 = anInfo.Pnt2();
744 theDoubles->Append(aP2.X());
745 theDoubles->Append(aP2.Y());
746 theDoubles->Append(aP2.Z());
749 case GEOMAlgo_KN_CURVEBSPLINE:
751 // (+) geompy.kind.CRV_BSPLINE p d np nk nw nm x1 y1 z1 ... xnp ynp znp k1 ... knk w1 ... wnw m1 ... mnm
752 aKind = SK_CRV_BSPLINE;
753 Standard_Integer aNbPoles = anInfo.NbPoles();
754 Standard_Integer aNbKnots = anInfo.NbKnots();
755 Standard_Integer aNbWeights = anInfo.NbWeights();
756 Standard_Integer aNbMultiplicities = anInfo.NbMultiplicities();
758 theIntegers->Append(anInfo.KindOfPeriod() == GEOMAlgo_KP_PERIODIC ? 1 : 0);
759 theIntegers->Append(anInfo.Degree());
760 theIntegers->Append(aNbPoles);
761 theIntegers->Append(aNbKnots);
762 theIntegers->Append(aNbWeights);
763 theIntegers->Append(aNbMultiplicities);
767 Handle(TColgp_HArray1OfPnt) aPoles = anInfo.Poles();
768 if (aPoles.IsNull() || aPoles->Length() != aNbPoles) {
769 SetErrorCode("B-Spline Curve: no or wrong number of poles given");
772 for (i=1; i<=aNbPoles; i++) {
773 const gp_Pnt &aP = aPoles->Value(i);
774 theDoubles->Append(aP.X());
775 theDoubles->Append(aP.Y());
776 theDoubles->Append(aP.Z());
781 Handle(TColStd_HArray1OfReal) aKnots = anInfo.Knots();
782 if (aKnots.IsNull() || aKnots->Length() != aNbKnots) {
783 SetErrorCode("B-Spline Curve: no or wrong number of knots given");
786 for (i=1; i<=aNbKnots; i++)
787 theDoubles->Append(aKnots->Value(i));
790 if (aNbWeights > 0) {
791 Handle(TColStd_HArray1OfReal) aWeights = anInfo.Weights();
792 if (aNbWeights > 0 && (aWeights.IsNull() || aWeights->Length() != aNbWeights)) {
793 SetErrorCode("B-Spline Curve: no or wrong number of weights given");
796 for (i=1; i<=aNbWeights; i++)
797 theDoubles->Append(aWeights->Value(i));
800 if (aNbMultiplicities > 0) {
801 Handle(TColStd_HArray1OfInteger) aMults = anInfo.Multiplicities();
802 if (aMults.IsNull() || aMults->Length() != aNbMultiplicities) {
803 SetErrorCode("B-Spline Curve: no or wrong number of multiplicities given");
806 for (i=1; i<=aNbMultiplicities; i++)
807 theIntegers->Append(aMults->Value(i));
811 case GEOMAlgo_KN_CURVEBEZIER:
813 // (+) geompy.kind.CRV_BEZIER np nw x1 y1 z1 ... xnp ynp znp w1 ... wnw
814 aKind = SK_CRV_BEZIER;
815 Standard_Integer aNbPoles = anInfo.NbPoles();
816 Standard_Integer aNbWeights = anInfo.NbWeights();
818 theIntegers->Append(aNbPoles);
819 theIntegers->Append(aNbWeights);
823 Handle(TColgp_HArray1OfPnt) aPoles = anInfo.Poles();
824 if (aPoles.IsNull() || aPoles->Length() != aNbPoles) {
825 SetErrorCode("Bezier Curve: no or wrong number of poles given");
828 for (i=1; i<=aNbPoles; i++) {
829 const gp_Pnt &aP = aPoles->Value(i);
830 theDoubles->Append(aP.X());
831 theDoubles->Append(aP.Y());
832 theDoubles->Append(aP.Z());
836 if (aNbWeights > 0) {
837 Handle(TColStd_HArray1OfReal) aWeights = anInfo.Weights();
838 if (aNbWeights > 0 && (aWeights.IsNull() || aWeights->Length() != aNbWeights)) {
839 SetErrorCode("B-Spline Curve: no or wrong number of weights given");
842 for (i=1; i<=aNbWeights; i++)
843 theDoubles->Append(aWeights->Value(i));
847 case GEOMAlgo_KN_HYPERBOLA:
849 // (+) geompy.kind.HYPERBOLA xc yc zc dx dy dz R_1 R_2 xVx yVx zVx xVy yVy zVy
850 aKind = SK_HYPERBOLA;
852 gp_Pnt aC = anInfo.Location();
853 theDoubles->Append(aC.X());
854 theDoubles->Append(aC.Y());
855 theDoubles->Append(aC.Z());
857 gp_Ax3 anAx3 = anInfo.Position();
858 gp_Dir aD = anAx3.Direction();
859 theDoubles->Append(aD.X());
860 theDoubles->Append(aD.Y());
861 theDoubles->Append(aD.Z());
863 theDoubles->Append(anInfo.Radius1());
864 theDoubles->Append(anInfo.Radius2());
866 gp_Dir aXD = anAx3.XDirection();
867 theDoubles->Append(aXD.X());
868 theDoubles->Append(aXD.Y());
869 theDoubles->Append(aXD.Z());
871 gp_Dir aYD = anAx3.YDirection();
872 theDoubles->Append(aYD.X());
873 theDoubles->Append(aYD.Y());
874 theDoubles->Append(aYD.Z());
877 case GEOMAlgo_KN_PARABOLA:
879 // (+) geompy.kind.PARABOLA xc yc zc dx dy dz F xVx yVx zVx xVy yVy zVy
882 gp_Pnt aC = anInfo.Location();
883 theDoubles->Append(aC.X());
884 theDoubles->Append(aC.Y());
885 theDoubles->Append(aC.Z());
887 gp_Ax3 anAx3 = anInfo.Position();
888 gp_Dir aD = anAx3.Direction();
889 theDoubles->Append(aD.X());
890 theDoubles->Append(aD.Y());
891 theDoubles->Append(aD.Z());
893 theDoubles->Append(anInfo.Radius1());
895 gp_Dir aXD = anAx3.XDirection();
896 theDoubles->Append(aXD.X());
897 theDoubles->Append(aXD.Y());
898 theDoubles->Append(aXD.Z());
900 gp_Dir aYD = anAx3.YDirection();
901 theDoubles->Append(aYD.X());
902 theDoubles->Append(aYD.Y());
903 theDoubles->Append(aYD.Z());
907 // ??? geompy.kind.EDGE nb_vertices _curve_type_id_
908 // (+) geompy.kind.EDGE nb_vertices
909 theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
916 // (+) geompy.kind.VERTEX x y z
919 gp_Pnt aP = anInfo.Location();
920 theDoubles->Append(aP.X());
921 theDoubles->Append(aP.Y());
922 theDoubles->Append(aP.Z());
932 //=============================================================================
936 //=============================================================================
937 void GEOMImpl_IMeasureOperations::GetPosition
938 (Handle(GEOM_Object) theShape,
939 Standard_Real& Ox, Standard_Real& Oy, Standard_Real& Oz,
940 Standard_Real& Zx, Standard_Real& Zy, Standard_Real& Zz,
941 Standard_Real& Xx, Standard_Real& Xy, Standard_Real& Xz)
945 //Set default values: global CS
946 Ox = Oy = Oz = Zx = Zy = Xy = Xz = 0.;
949 if (theShape.IsNull()) return;
951 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
952 if (aRefShape.IsNull()) return;
954 TopoDS_Shape aShape = aRefShape->GetValue();
955 if (aShape.IsNull()) {
956 SetErrorCode("The Objects has NULL Shape");
963 gp_Ax3 anAx3 = GEOMUtils::GetPosition(aShape);
965 gp_Pnt anOri = anAx3.Location();
966 gp_Dir aDirZ = anAx3.Direction();
967 gp_Dir aDirX = anAx3.XDirection();
970 anOri.Coord(Ox, Oy, Oz);
971 aDirZ.Coord(Zx, Zy, Zz);
972 aDirX.Coord(Xx, Xy, Xz);
974 catch (Standard_Failure& aFail) {
975 SetErrorCode(aFail.GetMessageString());
982 //=============================================================================
986 //=============================================================================
987 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetCentreOfMass
988 (Handle(GEOM_Object) theShape)
992 if (theShape.IsNull()) return NULL;
994 //Add a new CentreOfMass object
995 Handle(GEOM_Object) aCDG = GetEngine()->AddObject(GEOM_CDG);
997 //Add a new CentreOfMass function
998 Handle(GEOM_Function) aFunction =
999 aCDG->AddFunction(GEOMImpl_MeasureDriver::GetID(), CDG_MEASURE);
1000 if (aFunction.IsNull()) return NULL;
1002 //Check if the function is set correctly
1003 if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
1005 GEOMImpl_IMeasure aCI (aFunction);
1007 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1008 if (aRefShape.IsNull()) return NULL;
1010 aCI.SetBase(aRefShape);
1012 //Compute the CentreOfMass value
1015 if (!GetSolver()->ComputeFunction(aFunction)) {
1016 SetErrorCode("Measure driver failed to compute centre of mass");
1020 catch (Standard_Failure& aFail) {
1021 SetErrorCode(aFail.GetMessageString());
1025 //Make a Python command
1026 GEOM::TPythonDump(aFunction) << aCDG << " = geompy.MakeCDG(" << theShape << ")";
1032 //=============================================================================
1036 //=============================================================================
1037 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetVertexByIndex
1038 (Handle(GEOM_Object) theShape,
1039 Standard_Integer theIndex,
1040 Standard_Boolean theUseOri)
1044 if (theShape.IsNull()) return NULL;
1046 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1047 if (aRefShape.IsNull()) return NULL;
1049 //Add a new Vertex object
1050 Handle(GEOM_Object) aVertex = GetEngine()->AddObject(GEOM_POINT);
1053 Handle(GEOM_Function) aFunction =
1054 aVertex->AddFunction(GEOMImpl_MeasureDriver::GetID(), VERTEX_BY_INDEX);
1055 if (aFunction.IsNull()) return NULL;
1057 //Check if the function is set correctly
1058 if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
1060 GEOMImpl_IMeasure aCI (aFunction);
1061 aCI.SetBase(aRefShape);
1062 aCI.SetIndex(theIndex);
1063 aCI.SetUseOri(theUseOri);
1068 if (!GetSolver()->ComputeFunction(aFunction)) {
1069 SetErrorCode("Vertex by index driver failed.");
1073 catch (Standard_Failure& aFail) {
1074 SetErrorCode(aFail.GetMessageString());
1078 //Make a Python command
1079 GEOM::TPythonDump(aFunction) << aVertex << " = geompy.GetVertexByIndex("
1082 << theUseOri << ")";
1088 //=============================================================================
1092 //=============================================================================
1093 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetNormal
1094 (Handle(GEOM_Object) theFace,
1095 Handle(GEOM_Object) theOptionalPoint)
1099 if (theFace.IsNull()) return NULL;
1101 //Add a new Normale object
1102 Handle(GEOM_Object) aNorm = GetEngine()->AddObject(GEOM_VECTOR);
1104 //Add a new Normale function
1105 Handle(GEOM_Function) aFunction =
1106 aNorm->AddFunction(GEOMImpl_MeasureDriver::GetID(), VECTOR_FACE_NORMALE);
1107 if (aFunction.IsNull()) return NULL;
1109 //Check if the function is set correctly
1110 if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
1112 GEOMImpl_IMeasure aCI (aFunction);
1114 Handle(GEOM_Function) aFace = theFace->GetLastFunction();
1115 if (aFace.IsNull()) return NULL;
1119 if (!theOptionalPoint.IsNull()) {
1120 Handle(GEOM_Function) anOptPnt = theOptionalPoint->GetLastFunction();
1121 aCI.SetPoint(anOptPnt);
1124 //Compute the Normale value
1127 if (!GetSolver()->ComputeFunction(aFunction)) {
1128 SetErrorCode("Measure driver failed to compute normake of face");
1132 catch (Standard_Failure& aFail) {
1133 SetErrorCode(aFail.GetMessageString());
1137 //Make a Python command
1138 GEOM::TPythonDump pd (aFunction);
1139 pd << aNorm << " = geompy.GetNormal(" << theFace;
1140 if (!theOptionalPoint.IsNull()) {
1141 pd << ", " << theOptionalPoint;
1149 //=============================================================================
1151 * GetBasicProperties
1153 //=============================================================================
1154 void GEOMImpl_IMeasureOperations::GetBasicProperties (Handle(GEOM_Object) theShape,
1155 const Standard_Real theTolerance,
1156 Standard_Real& theLength,
1157 Standard_Real& theSurfArea,
1158 Standard_Real& theVolume)
1162 if (theShape.IsNull()) return;
1164 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1165 if (aRefShape.IsNull()) return;
1167 TopoDS_Shape aShape = aRefShape->GetValue();
1168 if (aShape.IsNull()) {
1169 SetErrorCode("The Objects has NULL Shape");
1173 //Compute the parameters
1174 GProp_GProps LProps, SProps;
1175 Standard_Real anEps = theTolerance >= 0 ? theTolerance : 1.e-6;
1178 BRepGProp::LinearProperties(aShape, LProps, Standard_True);
1179 theLength = LProps.Mass();
1181 BRepGProp::SurfaceProperties(aShape, SProps, anEps, Standard_True);
1182 theSurfArea = SProps.Mass();
1185 if (aShape.ShapeType() < TopAbs_SHELL) {
1186 for (TopExp_Explorer Exp (aShape, TopAbs_SOLID); Exp.More(); Exp.Next()) {
1187 GProp_GProps VProps;
1188 BRepGProp::VolumeProperties(Exp.Current(), VProps, anEps, Standard_True);
1189 theVolume += VProps.Mass();
1193 catch (Standard_Failure& aFail) {
1194 SetErrorCode(aFail.GetMessageString());
1201 //=============================================================================
1205 //=============================================================================
1206 void GEOMImpl_IMeasureOperations::GetInertia
1207 (Handle(GEOM_Object) theShape,
1208 Standard_Real& I11, Standard_Real& I12, Standard_Real& I13,
1209 Standard_Real& I21, Standard_Real& I22, Standard_Real& I23,
1210 Standard_Real& I31, Standard_Real& I32, Standard_Real& I33,
1211 Standard_Real& Ix , Standard_Real& Iy , Standard_Real& Iz)
1215 if (theShape.IsNull()) return;
1217 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1218 if (aRefShape.IsNull()) return;
1220 TopoDS_Shape aShape = aRefShape->GetValue();
1221 if (aShape.IsNull()) {
1222 SetErrorCode("The Objects has NULL Shape");
1226 //Compute the parameters
1227 GProp_GProps System;
1231 if (aShape.ShapeType() == TopAbs_VERTEX ||
1232 aShape.ShapeType() == TopAbs_EDGE ||
1233 aShape.ShapeType() == TopAbs_WIRE) {
1234 BRepGProp::LinearProperties(aShape, System, Standard_True);
1235 } else if (aShape.ShapeType() == TopAbs_FACE ||
1236 aShape.ShapeType() == TopAbs_SHELL) {
1237 BRepGProp::SurfaceProperties(aShape, System, Standard_True);
1239 BRepGProp::VolumeProperties(aShape, System, Standard_True);
1241 gp_Mat I = System.MatrixOfInertia();
1255 GProp_PrincipalProps Pr = System.PrincipalProperties();
1256 Pr.Moments(Ix,Iy,Iz);
1258 catch (Standard_Failure& aFail) {
1259 SetErrorCode(aFail.GetMessageString());
1266 //=============================================================================
1270 //=============================================================================
1271 void GEOMImpl_IMeasureOperations::GetBoundingBox
1272 (Handle(GEOM_Object) theShape,
1273 const Standard_Boolean precise,
1274 Standard_Real& Xmin, Standard_Real& Xmax,
1275 Standard_Real& Ymin, Standard_Real& Ymax,
1276 Standard_Real& Zmin, Standard_Real& Zmax)
1280 if (theShape.IsNull()) return;
1282 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1283 if (aRefShape.IsNull()) return;
1285 TopoDS_Shape aShape = aRefShape->GetValue();
1286 if (aShape.IsNull()) {
1287 SetErrorCode("The Objects has NULL Shape");
1291 //Compute the parameters
1296 BRepBuilderAPI_Copy aCopyTool (aShape);
1297 if (!aCopyTool.IsDone()) {
1298 SetErrorCode("GetBoundingBox Error: Bad shape detected");
1302 aShape = aCopyTool.Shape();
1304 // remove triangulation to obtain more exact boundaries
1305 BRepTools::Clean(aShape);
1307 BRepBndLib::Add(aShape, B);
1310 if (!GEOMUtils::PreciseBoundingBox(aShape, B)) {
1311 SetErrorCode("GetBoundingBox Error: Bounding box cannot be precised");
1316 B.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
1318 catch (Standard_Failure& aFail) {
1319 SetErrorCode(aFail.GetMessageString());
1326 //=============================================================================
1330 //=============================================================================
1331 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetBoundingBox
1332 (Handle(GEOM_Object) theShape,
1333 const Standard_Boolean precise)
1337 if (theShape.IsNull()) return NULL;
1339 //Add a new BoundingBox object
1340 Handle(GEOM_Object) aBnd = GetEngine()->AddObject(GEOM_BOX);
1342 //Add a new BoundingBox function
1343 const int aType = (precise ? BND_BOX_MEASURE_PRECISE : BND_BOX_MEASURE);
1344 Handle(GEOM_Function) aFunction =
1345 aBnd->AddFunction(GEOMImpl_MeasureDriver::GetID(), aType);
1346 if (aFunction.IsNull()) return NULL;
1348 //Check if the function is set correctly
1349 if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
1351 GEOMImpl_IMeasure aCI (aFunction);
1353 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1354 if (aRefShape.IsNull()) return NULL;
1356 aCI.SetBase(aRefShape);
1358 //Compute the BoundingBox value
1361 if (!GetSolver()->ComputeFunction(aFunction)) {
1362 SetErrorCode("Measure driver failed to compute a bounding box");
1366 catch (Standard_Failure& aFail) {
1367 SetErrorCode(aFail.GetMessageString());
1371 //Make a Python command
1372 GEOM::TPythonDump aPd(aFunction);
1374 aPd << aBnd << " = geompy.MakeBoundingBox(" << theShape;
1386 //=============================================================================
1390 //=============================================================================
1391 void GEOMImpl_IMeasureOperations::GetTolerance
1392 (Handle(GEOM_Object) theShape,
1393 Standard_Real& FaceMin, Standard_Real& FaceMax,
1394 Standard_Real& EdgeMin, Standard_Real& EdgeMax,
1395 Standard_Real& VertMin, Standard_Real& VertMax)
1399 if (theShape.IsNull()) return;
1401 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1402 if (aRefShape.IsNull()) return;
1404 TopoDS_Shape aShape = aRefShape->GetValue();
1405 if (aShape.IsNull()) {
1406 SetErrorCode("The Objects has NULL Shape");
1410 //Compute the parameters
1412 FaceMin = EdgeMin = VertMin = RealLast();
1413 FaceMax = EdgeMax = VertMax = -RealLast();
1417 for (TopExp_Explorer ExF (aShape, TopAbs_FACE); ExF.More(); ExF.Next()) {
1418 TopoDS_Face Face = TopoDS::Face(ExF.Current());
1419 T = BRep_Tool::Tolerance(Face);
1425 for (TopExp_Explorer ExE (aShape, TopAbs_EDGE); ExE.More(); ExE.Next()) {
1426 TopoDS_Edge Edge = TopoDS::Edge(ExE.Current());
1427 T = BRep_Tool::Tolerance(Edge);
1433 for (TopExp_Explorer ExV (aShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
1434 TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current());
1435 T = BRep_Tool::Tolerance(Vertex);
1442 catch (Standard_Failure& aFail) {
1443 SetErrorCode(aFail.GetMessageString());
1450 //=============================================================================
1454 //=============================================================================
1455 bool GEOMImpl_IMeasureOperations::CheckShape (Handle(GEOM_Object) theShape,
1456 const Standard_Boolean theIsCheckGeom,
1457 std::list<ShapeError> &theErrors)
1462 if (theShape.IsNull()) return false;
1464 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1465 if (aRefShape.IsNull()) return false;
1467 TopoDS_Shape aShape = aRefShape->GetValue();
1468 if (aShape.IsNull()) {
1469 SetErrorCode("The Objects has NULL Shape");
1473 //Compute the parameters
1474 bool isValid = false;
1477 BRepCheck_Analyzer ana (aShape, theIsCheckGeom);
1478 if (ana.IsValid()) {
1481 FillErrors(ana, aShape, theErrors);
1484 catch (Standard_Failure& aFail) {
1485 SetErrorCode(aFail.GetMessageString());
1493 //=============================================================================
1497 //=============================================================================
1498 TCollection_AsciiString GEOMImpl_IMeasureOperations::PrintShapeErrors
1499 (Handle(GEOM_Object) theShape,
1500 const std::list<ShapeError> &theErrors)
1502 TCollection_AsciiString aDump;
1504 if (theShape.IsNull()) {
1508 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1510 if (aRefShape.IsNull()) {
1514 TopoDS_Shape aShape = aRefShape->GetValue();
1516 if (aShape.IsNull()) {
1517 SetErrorCode("The Objects has NULL Shape");
1521 if (!theErrors.empty()) {
1522 // The shape is not valid. Prepare errors for dump.
1523 TopTools_IndexedMapOfShape anIndices;
1524 std::list<ShapeError>::const_iterator anIter = theErrors.begin();
1525 Standard_Integer nbv, nbe, nbw, nbf, nbs, nbo;
1526 nbv = nbe = nbw = nbf = nbs = nbo = 0;
1528 // Map sub-shapes and their indices
1529 TopExp::MapShapes(aShape, anIndices);
1531 const Standard_Integer aNbSubShapes = anIndices.Extent();
1532 TColStd_MapOfInteger aMapPbInd;
1534 aDump += " -- The Shape has problems :\n";
1535 aDump += " Check Count\n";
1536 aDump += " ------------------------------------------------\n";
1538 for (; anIter != theErrors.end(); anIter++) {
1539 Standard_Integer aNbShapes = anIter->incriminated.size();
1541 switch(anIter->error) {
1542 case BRepCheck_InvalidPointOnCurve:
1543 aDump += " Invalid Point on Curve ................... ";
1545 case BRepCheck_InvalidPointOnCurveOnSurface:
1546 aDump += " Invalid Point on CurveOnSurface .......... ";
1548 case BRepCheck_InvalidPointOnSurface:
1549 aDump += " Invalid Point on Surface ................. ";
1551 case BRepCheck_No3DCurve:
1552 aDump += " No 3D Curve .............................. ";
1554 case BRepCheck_Multiple3DCurve:
1555 aDump += " Multiple 3D Curve ........................ ";
1557 case BRepCheck_Invalid3DCurve:
1558 aDump += " Invalid 3D Curve ......................... ";
1560 case BRepCheck_NoCurveOnSurface:
1561 aDump += " No Curve on Surface ...................... ";
1563 case BRepCheck_InvalidCurveOnSurface:
1564 aDump += " Invalid Curve on Surface ................. ";
1566 case BRepCheck_InvalidCurveOnClosedSurface:
1567 aDump += " Invalid Curve on closed Surface .......... ";
1569 case BRepCheck_InvalidSameRangeFlag:
1570 aDump += " Invalid SameRange Flag ................... ";
1572 case BRepCheck_InvalidSameParameterFlag:
1573 aDump += " Invalid SameParameter Flag ............... ";
1575 case BRepCheck_InvalidDegeneratedFlag:
1576 aDump += " Invalid Degenerated Flag ................. ";
1578 case BRepCheck_FreeEdge:
1579 aDump += " Free Edge ................................ ";
1581 case BRepCheck_InvalidMultiConnexity:
1582 aDump += " Invalid MultiConnexity ................... ";
1584 case BRepCheck_InvalidRange:
1585 aDump += " Invalid Range ............................ ";
1587 case BRepCheck_EmptyWire:
1588 aDump += " Empty Wire ............................... ";
1590 case BRepCheck_RedundantEdge:
1591 aDump += " Redundant Edge ........................... ";
1593 case BRepCheck_SelfIntersectingWire:
1594 aDump += " Self Intersecting Wire ................... ";
1596 case BRepCheck_NoSurface:
1597 aDump += " No Surface ............................... ";
1599 case BRepCheck_InvalidWire:
1600 aDump += " Invalid Wire ............................. ";
1602 case BRepCheck_RedundantWire:
1603 aDump += " Redundant Wire ........................... ";
1605 case BRepCheck_IntersectingWires:
1606 aDump += " Intersecting Wires ....................... ";
1608 case BRepCheck_InvalidImbricationOfWires:
1609 aDump += " Invalid Imbrication of Wires ............. ";
1611 case BRepCheck_EmptyShell:
1612 aDump += " Empty Shell .............................. ";
1614 case BRepCheck_RedundantFace:
1615 aDump += " Redundant Face ........................... ";
1617 case BRepCheck_UnorientableShape:
1618 aDump += " Unorientable Shape ....................... ";
1620 case BRepCheck_NotClosed:
1621 aDump += " Not Closed ............................... ";
1623 case BRepCheck_NotConnected:
1624 aDump += " Not Connected ............................ ";
1626 case BRepCheck_SubshapeNotInShape:
1627 aDump += " Sub-shape not in Shape ................... ";
1629 case BRepCheck_BadOrientation:
1630 aDump += " Bad Orientation .......................... ";
1632 case BRepCheck_BadOrientationOfSubshape:
1633 aDump += " Bad Orientation of Sub-shape ............. ";
1635 case BRepCheck_InvalidToleranceValue:
1636 aDump += " Invalid Tolerance Value .................. ";
1638 case BRepCheck_CheckFail:
1639 aDump += " Check Shape Failure ...................... ";
1645 aDump += TCollection_AsciiString(aNbShapes) + "\n";
1647 // Count types of shape.
1648 std::list<int>::const_iterator aShIter = anIter->incriminated.begin();
1650 for (; aShIter != anIter->incriminated.end(); aShIter++) {
1651 const Standard_Integer anIndex = *aShIter;
1653 if (anIndex > 0 && anIndex <= aNbSubShapes && aMapPbInd.Add(anIndex)) {
1654 const TopoDS_Shape &aSubShape = anIndices.FindKey(anIndex);
1655 const TopAbs_ShapeEnum aType = aSubShape.ShapeType();
1658 case TopAbs_VERTEX : nbv++; break;
1659 case TopAbs_EDGE : nbe++; break;
1660 case TopAbs_WIRE : nbw++; break;
1661 case TopAbs_FACE : nbf++; break;
1662 case TopAbs_SHELL : nbs++; break;
1663 case TopAbs_SOLID : nbo++; break;
1670 const Standard_Integer aNbFaultyShapes = nbv + nbe + nbw + nbf + nbs + nbo;
1671 aDump += " ------------------------------------------------\n";
1672 aDump += "*** Shapes with problems : ";
1673 aDump += TCollection_AsciiString(aNbFaultyShapes) + "\n";
1676 aDump += "VERTEX : ";
1677 if (nbv < 10) aDump += " ";
1678 aDump += TCollection_AsciiString(nbv) + "\n";
1682 if (nbe < 10) aDump += " ";
1683 aDump += TCollection_AsciiString(nbe) + "\n";
1687 if (nbw < 10) aDump += " ";
1688 aDump += TCollection_AsciiString(nbw) + "\n";
1692 if (nbf < 10) aDump += " ";
1693 aDump += TCollection_AsciiString(nbf) + "\n";
1696 aDump += "SHELL : ";
1697 if (nbs < 10) aDump += " ";
1698 aDump += TCollection_AsciiString(nbs) + "\n";
1701 aDump += "SOLID : ";
1702 if (nbo < 10) aDump += " ";
1703 aDump += TCollection_AsciiString(nbo) + "\n";
1710 //=============================================================================
1712 * CheckSelfIntersections
1714 //=============================================================================
1715 bool GEOMImpl_IMeasureOperations::CheckSelfIntersections
1716 (Handle(GEOM_Object) theShape,
1717 const SICheckLevel theCheckLevel,
1718 Handle(TColStd_HSequenceOfInteger)& theIntersections)
1722 if (theIntersections.IsNull())
1723 theIntersections = new TColStd_HSequenceOfInteger;
1725 theIntersections->Clear();
1727 if (theShape.IsNull())
1730 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1731 if (aRefShape.IsNull()) return false;
1733 TopoDS_Shape aShape = aRefShape->GetValue();
1734 if (aShape.IsNull()) return false;
1737 TopoDS_Shape aScopy;
1739 GEOMAlgo_AlgoTools::CopyShape(aShape, aScopy);
1741 // Map sub-shapes and their indices
1742 TopTools_IndexedMapOfShape anIndices;
1743 TopExp::MapShapes(aScopy, anIndices);
1745 TopTools_ListOfShape aLCS;
1746 aLCS.Append(aScopy);
1748 BOPAlgo_CheckerSI aCSI; // checker of self-interferences
1749 aCSI.SetArguments(aLCS);
1750 aCSI.SetLevelOfCheck(theCheckLevel);
1752 // 1. Launch the checker
1754 Standard_Boolean iErr = aCSI.HasErrors();
1757 Standard_Integer aNbS, n1, n2;
1758 BOPDS_MapIteratorOfMapOfPair aItMPK;
1760 // 2. Take the shapes from DS
1761 const BOPDS_DS& aDS = aCSI.DS();
1762 aNbS=aDS.NbShapes();
1764 // 3. Get the pairs of interfered shapes
1765 const BOPDS_MapOfPair& aMPK=aDS.Interferences();
1766 aItMPK.Initialize(aMPK);
1767 for (; aItMPK.More(); aItMPK.Next()) {
1768 const BOPDS_Pair& aPK=aItMPK.Value();
1769 aPK.Indices(n1, n2);
1771 if (n1 > aNbS || n2 > aNbS){
1772 return false; // Error
1774 const TopoDS_Shape& aS1 = aDS.Shape(n1);
1775 const TopoDS_Shape& aS2 = aDS.Shape(n2);
1777 theIntersections->Append(anIndices.FindIndex(aS1));
1778 theIntersections->Append(anIndices.FindIndex(aS2));
1785 return theIntersections->IsEmpty();
1788 //=============================================================================
1790 * CheckSelfIntersectionsFast
1792 //=============================================================================
1793 bool GEOMImpl_IMeasureOperations::CheckSelfIntersectionsFast
1794 (Handle(GEOM_Object) theShape,
1795 float theDeflection, double theTolerance,
1796 Handle(TColStd_HSequenceOfInteger)& theIntersections)
1800 if (theIntersections.IsNull())
1801 theIntersections = new TColStd_HSequenceOfInteger;
1803 theIntersections->Clear();
1805 if (theShape.IsNull())
1808 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1809 if (aRefShape.IsNull()) return false;
1811 TopoDS_Shape aShape = aRefShape->GetValue();
1812 if (aShape.IsNull()) return false;
1815 TopoDS_Shape aScopy;
1817 GEOMAlgo_AlgoTools::CopyShape(aShape, aScopy);
1818 GEOMUtils::MeshShape(aScopy, theDeflection);
1820 // Map sub-shapes and their indices
1821 TopTools_IndexedMapOfShape anIndices;
1822 TopExp::MapShapes(aScopy, anIndices);
1824 // Checker of fast interferences
1825 BRepExtrema_SelfIntersection aTool(aScopy, (theTolerance <= 0.) ? 0.0 : theTolerance);
1827 // Launch the checker
1830 const BRepExtrema_MapOfIntegerPackedMapOfInteger& intersections = aTool.OverlapElements();
1832 std::set<Standard_Integer> processed;
1834 for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator it(intersections); it.More(); it.Next()) {
1835 Standard_Integer idxLeft = it.Key();
1836 if (processed.count(idxLeft) > 0) continue; // already added
1837 processed.insert(idxLeft);
1838 const TColStd_PackedMapOfInteger& overlaps = it.Value();
1839 for (TColStd_MapIteratorOfPackedMapOfInteger subit(overlaps); subit.More(); subit.Next()) {
1840 Standard_Integer idxRight = subit.Key();
1841 if (processed.count(idxRight) > 0) continue; // already added
1842 const TopoDS_Shape& aS1 = aTool.GetSubShape(idxLeft);
1843 const TopoDS_Shape& aS2 = aTool.GetSubShape(idxRight);
1844 theIntersections->Append(anIndices.FindIndex(aS1));
1845 theIntersections->Append(anIndices.FindIndex(aS2));
1852 return theIntersections->IsEmpty();
1855 //=============================================================================
1859 //=============================================================================
1860 bool GEOMImpl_IMeasureOperations::CheckBOPArguments
1861 (const Handle(GEOM_Object) &theShape)
1865 if (theShape.IsNull()) {
1869 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1871 if (aRefShape.IsNull()) {
1875 TopoDS_Shape aShape = aRefShape->GetValue();
1877 if (aShape.IsNull()) {
1881 //Compute the parameters
1882 bool isValid = GEOMUtils::CheckBOPArguments(aShape);
1889 //=============================================================================
1893 //=============================================================================
1894 bool GEOMImpl_IMeasureOperations::FastIntersect (Handle(GEOM_Object) theShape1, Handle(GEOM_Object) theShape2,
1895 double theTolerance, float theDeflection,
1896 Handle(TColStd_HSequenceOfInteger)& theIntersections1,
1897 Handle(TColStd_HSequenceOfInteger)& theIntersections2)
1900 bool isGood = false;
1902 if (theIntersections1.IsNull())
1903 theIntersections1 = new TColStd_HSequenceOfInteger;
1905 theIntersections1->Clear();
1907 if (theIntersections2.IsNull())
1908 theIntersections2 = new TColStd_HSequenceOfInteger;
1910 theIntersections2->Clear();
1912 if (theShape1.IsNull() || theShape2.IsNull()) {
1913 SetErrorCode("Objects have NULL Shape");
1917 if (theShape1 == theShape2) {
1918 SetErrorCode("Objects are equal");
1921 Handle(GEOM_Function) aRefShape1 = theShape1->GetLastFunction();
1922 Handle(GEOM_Function) aRefShape2 = theShape2->GetLastFunction();
1923 if (aRefShape1.IsNull() || aRefShape2.IsNull()) return isGood;
1925 TopoDS_Shape aShape1 = aRefShape1->GetValue();
1926 TopoDS_Shape aShape2 = aRefShape2->GetValue();
1927 if (aShape1.IsNull() || aShape2.IsNull()) return isGood;
1930 TopoDS_Shape aScopy1, aScopy2;
1931 GEOMAlgo_AlgoTools::CopyShape(aShape1, aScopy1);
1932 GEOMAlgo_AlgoTools::CopyShape(aShape2, aScopy2);
1934 GEOMUtils::MeshShape(aScopy1, theDeflection);
1935 GEOMUtils::MeshShape(aScopy2, theDeflection);
1937 // Map sub-shapes and their indices
1938 TopTools_IndexedMapOfShape anIndices1, anIndices2;
1939 TopExp::MapShapes(aScopy1, anIndices1);
1940 TopExp::MapShapes(aScopy2, anIndices2);
1942 TopTools_ListOfShape aLCS1, aLCS2;
1943 aLCS1.Append(aScopy1); aLCS2.Append(aScopy2);
1945 BRepExtrema_ShapeProximity aBSP; // checker of fast interferences
1946 aBSP.LoadShape1(aScopy1); aBSP.LoadShape2(aScopy2);
1947 aBSP.SetTolerance((theTolerance <= 0.) ? 0.0 : theTolerance);
1949 // 1. Launch the checker
1952 // 2. Get sets of IDs of overlapped faces
1953 for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt1 (aBSP.OverlapSubShapes1()); anIt1.More(); anIt1.Next())
1955 const TopoDS_Shape& aS1 = aBSP.GetSubShape1(anIt1.Key());
1956 theIntersections1->Append(anIndices1.FindIndex(aS1));
1959 for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt2 (aBSP.OverlapSubShapes2()); anIt2.More(); anIt2.Next())
1961 const TopoDS_Shape& aS2 = aBSP.GetSubShape2(anIt2.Key());
1962 theIntersections2->Append(anIndices2.FindIndex(aS2));
1965 isGood = !theIntersections1->IsEmpty() && !theIntersections1->IsEmpty();
1973 //=============================================================================
1977 //=============================================================================
1978 TCollection_AsciiString GEOMImpl_IMeasureOperations::IsGoodForSolid (Handle(GEOM_Object) theShape)
1982 TCollection_AsciiString aRes = "";
1984 if (theShape.IsNull()) {
1985 aRes = "WRN_NULL_OBJECT_OR_SHAPE";
1988 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1989 if (aRefShape.IsNull()) {
1990 aRes = "WRN_NULL_OBJECT_OR_SHAPE";
1993 TopoDS_Shape aShape = aRefShape->GetValue();
1994 if (aShape.IsNull()) {
1995 aRes = "WRN_NULL_OBJECT_OR_SHAPE";
1998 if (aShape.ShapeType() == TopAbs_COMPOUND) {
1999 TopoDS_Iterator It (aShape, Standard_True, Standard_True);
2000 if (It.More()) aShape = It.Value();
2002 if (aShape.ShapeType() == TopAbs_SHELL) {
2003 BRepCheck_Shell chkShell (TopoDS::Shell(aShape));
2004 if (chkShell.Closed() == BRepCheck_NotClosed) {
2005 aRes = "WRN_SHAPE_UNCLOSED";
2009 aRes = "WRN_SHAPE_NOT_SHELL";
2021 //=============================================================================
2025 //=============================================================================
2026 TCollection_AsciiString GEOMImpl_IMeasureOperations::WhatIs (Handle(GEOM_Object) theShape)
2030 TCollection_AsciiString Astr;
2032 if (theShape.IsNull()) return Astr;
2034 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
2035 if (aRefShape.IsNull()) return Astr;
2037 TopoDS_Shape aShape = aRefShape->GetValue();
2038 if (aShape.IsNull()) {
2039 SetErrorCode("The Objects has NULL Shape");
2043 //Compute the parameters
2044 if (aShape.ShapeType() == TopAbs_EDGE) {
2045 if (BRep_Tool::Degenerated(TopoDS::Edge(aShape))) {
2046 Astr = Astr + " It is a degenerated edge \n";
2050 Astr = Astr + " Number of sub-shapes : \n";
2054 int iType, nbTypes [TopAbs_SHAPE], nbFlatType [TopAbs_SHAPE];
2055 for (iType = 0; iType < TopAbs_SHAPE; ++iType) {
2057 nbFlatType[iType] = 0;
2059 nbTypes[aShape.ShapeType()]++;
2061 TopTools_MapOfShape aMapOfShape;
2062 aMapOfShape.Add(aShape);
2063 TopTools_ListOfShape aListOfShape;
2064 aListOfShape.Append(aShape);
2066 TopTools_ListIteratorOfListOfShape itL (aListOfShape);
2067 for (; itL.More(); itL.Next()) {
2068 TopoDS_Shape sp = itL.Value();
2069 TopoDS_Iterator it (sp);
2070 for (; it.More(); it.Next()) {
2071 TopoDS_Shape s = it.Value();
2072 if (aMapOfShape.Add(s)) {
2073 aListOfShape.Append(s);
2074 nbTypes[s.ShapeType()]++;
2075 if ((sp.ShapeType() == TopAbs_COMPOUND) || (sp.ShapeType() == TopAbs_COMPSOLID)) {
2076 nbFlatType[s.ShapeType()]++;
2082 Astr = Astr + " VERTEX : " + TCollection_AsciiString(nbTypes[TopAbs_VERTEX]) + "\n";
2083 Astr = Astr + " EDGE : " + TCollection_AsciiString(nbTypes[TopAbs_EDGE]) + "\n";
2084 Astr = Astr + " WIRE : " + TCollection_AsciiString(nbTypes[TopAbs_WIRE]) + "\n";
2085 Astr = Astr + " FACE : " + TCollection_AsciiString(nbTypes[TopAbs_FACE]) + "\n";
2086 Astr = Astr + " SHELL : " + TCollection_AsciiString(nbTypes[TopAbs_SHELL]) + "\n";
2087 Astr = Astr + " SOLID : " + TCollection_AsciiString(nbTypes[TopAbs_SOLID]) + "\n";
2088 Astr = Astr + " COMPSOLID : " + TCollection_AsciiString(nbTypes[TopAbs_COMPSOLID]) + "\n";
2089 Astr = Astr + " COMPOUND : " + TCollection_AsciiString(nbTypes[TopAbs_COMPOUND]) + "\n";
2090 Astr = Astr + " SHAPE : " + TCollection_AsciiString(aMapOfShape.Extent()) + "\n";
2092 if ((aShape.ShapeType() == TopAbs_COMPOUND) || (aShape.ShapeType() == TopAbs_COMPSOLID)){
2093 Astr = Astr + " --------------------- \n Flat content : \n";
2094 if (nbFlatType[TopAbs_VERTEX] > 0)
2095 Astr = Astr + " VERTEX : " + TCollection_AsciiString(nbFlatType[TopAbs_VERTEX]) + "\n";
2096 if (nbFlatType[TopAbs_EDGE] > 0)
2097 Astr = Astr + " EDGE : " + TCollection_AsciiString(nbFlatType[TopAbs_EDGE]) + "\n";
2098 if (nbFlatType[TopAbs_WIRE] > 0)
2099 Astr = Astr + " WIRE : " + TCollection_AsciiString(nbFlatType[TopAbs_WIRE]) + "\n";
2100 if (nbFlatType[TopAbs_FACE] > 0)
2101 Astr = Astr + " FACE : " + TCollection_AsciiString(nbFlatType[TopAbs_FACE]) + "\n";
2102 if (nbFlatType[TopAbs_SHELL] > 0)
2103 Astr = Astr + " SHELL : " + TCollection_AsciiString(nbFlatType[TopAbs_SHELL]) + "\n";
2104 if (nbFlatType[TopAbs_SOLID] > 0)
2105 Astr = Astr + " SOLID : " + TCollection_AsciiString(nbFlatType[TopAbs_SOLID]) + "\n";
2108 catch (Standard_Failure& aFail) {
2109 SetErrorCode(aFail.GetMessageString());
2117 //=============================================================================
2121 //=============================================================================
2123 GEOMImpl_IMeasureOperations::AreCoordsInside(Handle(GEOM_Object) theShape,
2124 const std::vector<double>& coords,
2127 std::vector<bool> isInsideRes;
2128 if (!theShape.IsNull()) {
2129 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
2130 if (!aRefShape.IsNull()) {
2131 TopoDS_Shape aShape = aRefShape->GetValue();
2132 if (!aShape.IsNull())
2134 TopTools_IndexedMapOfShape mapShape;
2136 TopExp_Explorer anExp;
2137 for ( anExp.Init( aShape, TopAbs_SOLID ); anExp.More(); anExp.Next() )
2138 mapShape.Add( anExp.Current() );
2139 for ( anExp.Init( aShape, TopAbs_FACE, TopAbs_SOLID ); anExp.More(); anExp.Next() )
2140 mapShape.Add( anExp.Current() );
2141 for ( anExp.Init( aShape, TopAbs_EDGE, TopAbs_FACE ); anExp.More(); anExp.Next() )
2142 mapShape.Add( anExp.Current() );
2143 for ( anExp.Init( aShape, TopAbs_VERTEX, TopAbs_EDGE ); anExp.More(); anExp.Next() )
2144 mapShape.Add( anExp.Current() ); //// ?????????
2146 size_t nb_points = coords.size()/3, nb_points_inside = 0;
2147 isInsideRes.resize( nb_points, false );
2149 for ( int iS = 1; iS <= mapShape.Extent(); ++iS )
2151 if ( nb_points_inside == nb_points )
2153 aShape = mapShape( iS );
2154 switch ( aShape.ShapeType() ) {
2157 BRepClass3d_SolidClassifier SC( TopoDS::Solid( aShape ));
2158 for ( size_t i = 0; i < nb_points; i++)
2160 if ( isInsideRes[ i ]) continue;
2161 gp_Pnt aPnt( coords[3*i], coords[3*i+1], coords[3*i+2] );
2162 SC.Perform( aPnt, tolerance );
2163 isInsideRes[ i ] = (( SC.State() == TopAbs_IN ) || ( SC.State() == TopAbs_ON ));
2164 nb_points_inside += isInsideRes[ i ];
2170 Standard_Real u1,u2,v1,v2;
2171 const TopoDS_Face& face = TopoDS::Face( aShape );
2172 Handle(Geom_Surface) surf = BRep_Tool::Surface( face );
2173 surf->Bounds( u1,u2,v1,v2 );
2174 GeomAPI_ProjectPointOnSurf project;
2175 project.Init(surf, u1,u2, v1,v2, tolerance );
2176 for ( size_t i = 0; i < nb_points; i++)
2178 if ( isInsideRes[ i ]) continue;
2179 gp_Pnt aPnt( coords[3*i], coords[3*i+1], coords[3*i+2] );
2180 project.Perform( aPnt );
2181 if ( project.IsDone() &&
2182 project.NbPoints() > 0 &&
2183 project.LowerDistance() <= tolerance )
2186 project.LowerDistanceParameters(u, v);
2187 gp_Pnt2d uv( u, v );
2188 BRepClass_FaceClassifier FC ( face, uv, tolerance );
2189 isInsideRes[ i ] = (( FC.State() == TopAbs_IN ) || ( FC.State() == TopAbs_ON ));
2190 nb_points_inside += isInsideRes[ i ];
2198 const TopoDS_Edge& edge = TopoDS::Edge( aShape );
2199 Handle(Geom_Curve) curve = BRep_Tool::Curve( edge, f, l );
2200 GeomAPI_ProjectPointOnCurve project;
2201 project.Init( curve, f, l );
2202 for ( size_t i = 0; i < nb_points; i++)
2204 if ( isInsideRes[ i ]) continue;
2205 gp_Pnt aPnt( coords[3*i], coords[3*i+1], coords[3*i+2] );
2206 project.Perform( aPnt );
2207 isInsideRes[ i ] = ( project.NbPoints() > 0 &&
2208 project.LowerDistance() <= tolerance );
2209 nb_points_inside += isInsideRes[ i ];
2215 gp_Pnt aVPnt = BRep_Tool::Pnt( TopoDS::Vertex( aShape ));
2216 for ( size_t i = 0; i < nb_points; i++)
2218 if ( isInsideRes[ i ]) continue;
2219 gp_Pnt aPnt( coords[3*i], coords[3*i+1], coords[3*i+2] );
2220 isInsideRes[ i ] = ( aPnt.SquareDistance( aVPnt ) <= tolerance * tolerance );
2221 nb_points_inside += isInsideRes[ i ];
2226 } // switch ( aShape.ShapeType() )
2234 //=============================================================================
2238 //=============================================================================
2240 GEOMImpl_IMeasureOperations::GetMinDistance (Handle(GEOM_Object) theShape1,
2241 Handle(GEOM_Object) theShape2,
2250 Standard_Real MinDist = 1.e9;
2252 if (theShape1.IsNull() || theShape2.IsNull()) return MinDist;
2254 Handle(GEOM_Function) aRefShape1 = theShape1->GetLastFunction();
2255 Handle(GEOM_Function) aRefShape2 = theShape2->GetLastFunction();
2256 if (aRefShape1.IsNull() || aRefShape2.IsNull()) return MinDist;
2258 TopoDS_Shape aShape1 = aRefShape1->GetValue();
2259 TopoDS_Shape aShape2 = aRefShape2->GetValue();
2260 if (aShape1.IsNull() || aShape2.IsNull()) {
2261 SetErrorCode("One of Objects has NULL Shape");
2265 //Compute the parameters
2269 gp_Pnt aPnt1, aPnt2;
2271 MinDist = GEOMUtils::GetMinDistance(aShape1, aShape2, aPnt1, aPnt2);
2273 if (MinDist >= 0.0) {
2274 aPnt1.Coord(X1, Y1, Z1);
2275 aPnt2.Coord(X2, Y2, Z2);
2280 catch (Standard_Failure& aFail) {
2281 SetErrorCode(aFail.GetMessageString());
2289 //=======================================================================
2291 * Get coordinates of closest points of two shapes
2293 //=======================================================================
2294 Standard_Integer GEOMImpl_IMeasureOperations::ClosestPoints (Handle(GEOM_Object) theShape1,
2295 Handle(GEOM_Object) theShape2,
2296 Handle(TColStd_HSequenceOfReal)& theDoubles)
2299 Standard_Integer nbSolutions = 0;
2301 if (theShape1.IsNull() || theShape2.IsNull()) return nbSolutions;
2303 Handle(GEOM_Function) aRefShape1 = theShape1->GetLastFunction();
2304 Handle(GEOM_Function) aRefShape2 = theShape2->GetLastFunction();
2305 if (aRefShape1.IsNull() || aRefShape2.IsNull()) return nbSolutions;
2307 TopoDS_Shape aShape1 = aRefShape1->GetValue();
2308 TopoDS_Shape aShape2 = aRefShape2->GetValue();
2309 if (aShape1.IsNull() || aShape2.IsNull()) {
2310 SetErrorCode("One of Objects has NULL Shape");
2314 // Compute the extremities
2319 // additional workaround for bugs 19899, 19908 and 19910 from Mantis
2321 double dist = GEOMUtils::GetMinDistanceSingular(aShape1, aShape2, P1s, P2s);
2322 bool singularBetter = dist >= 0;
2324 BRepExtrema_DistShapeShape dst (aShape1, aShape2);
2326 nbSolutions = dst.NbSolution();
2327 if (theDoubles.IsNull()) theDoubles = new TColStd_HSequenceOfReal;
2330 for (int i = 1; i <= nbSolutions; i++) {
2331 P1 = dst.PointOnShape1(i);
2332 P2 = dst.PointOnShape2(i);
2334 theDoubles->Append(P1.X());
2335 theDoubles->Append(P1.Y());
2336 theDoubles->Append(P1.Z());
2337 theDoubles->Append(P2.X());
2338 theDoubles->Append(P2.Y());
2339 theDoubles->Append(P2.Z());
2341 Standard_Real Dist = P1.Distance(P2);
2342 singularBetter = singularBetter && dist < Dist;
2346 if (singularBetter) {
2347 if (theDoubles.IsNull()) theDoubles = new TColStd_HSequenceOfReal;
2348 else theDoubles->Clear();
2352 theDoubles->Append(P1s.X());
2353 theDoubles->Append(P1s.Y());
2354 theDoubles->Append(P1s.Z());
2355 theDoubles->Append(P2s.X());
2356 theDoubles->Append(P2s.Y());
2357 theDoubles->Append(P2s.Z());
2360 catch (Standard_Failure& aFail) {
2361 SetErrorCode(aFail.GetMessageString());
2369 //=======================================================================
2371 * Get coordinates of point
2373 //=======================================================================
2374 void GEOMImpl_IMeasureOperations::PointCoordinates (Handle(GEOM_Object) theShape,
2375 Standard_Real& theX, Standard_Real& theY, Standard_Real& theZ)
2379 if (theShape.IsNull())
2382 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
2383 if (aRefShape.IsNull())
2386 TopoDS_Shape aShape = aRefShape->GetValue();
2387 if (aShape.IsNull() || aShape.ShapeType() != TopAbs_VERTEX)
2389 SetErrorCode( "Shape must be a vertex" );
2395 gp_Pnt aPnt = BRep_Tool::Pnt( TopoDS::Vertex( aShape ) );
2402 catch (Standard_Failure& aFail)
2404 SetErrorCode( aFail.GetMessageString() );
2408 //=======================================================================
2410 * Compute angle (in degrees) between two lines
2412 //=======================================================================
2413 Standard_Real GEOMImpl_IMeasureOperations::GetAngle (Handle(GEOM_Object) theLine1,
2414 Handle(GEOM_Object) theLine2)
2416 if (theLine1->GetType() == GEOM_VECTOR &&
2417 theLine2->GetType() == GEOM_VECTOR)
2418 return GetAngleBtwVectors(theLine1, theLine2);
2422 Standard_Real anAngle = -1.0;
2424 if (theLine1.IsNull() || theLine2.IsNull())
2427 Handle(GEOM_Function) aRefLine1 = theLine1->GetLastFunction();
2428 Handle(GEOM_Function) aRefLine2 = theLine2->GetLastFunction();
2429 if (aRefLine1.IsNull() || aRefLine2.IsNull())
2432 TopoDS_Shape aLine1 = aRefLine1->GetValue();
2433 TopoDS_Shape aLine2 = aRefLine2->GetValue();
2434 if (aLine1.IsNull() || aLine2.IsNull() ||
2435 aLine1.ShapeType() != TopAbs_EDGE ||
2436 aLine2.ShapeType() != TopAbs_EDGE)
2438 SetErrorCode("Two edges must be given");
2444 TopoDS_Edge E1 = TopoDS::Edge(aLine1);
2445 TopoDS_Edge E2 = TopoDS::Edge(aLine2);
2448 Handle(Geom_Curve) C1 = BRep_Tool::Curve(E1,fp,lp);
2449 Handle(Geom_Curve) C2 = BRep_Tool::Curve(E2,fp,lp);
2451 if ( C1.IsNull() || C2.IsNull() ||
2452 !C1->IsKind(STANDARD_TYPE(Geom_Line)) ||
2453 !C2->IsKind(STANDARD_TYPE(Geom_Line)))
2455 SetErrorCode("The edges must be linear");
2459 Handle(Geom_Line) L1 = Handle(Geom_Line)::DownCast(C1);
2460 Handle(Geom_Line) L2 = Handle(Geom_Line)::DownCast(C2);
2462 gp_Lin aLin1 = L1->Lin();
2463 gp_Lin aLin2 = L2->Lin();
2465 anAngle = aLin1.Angle(aLin2);
2466 anAngle *= 180. / M_PI; // convert radians into degrees
2468 if (anAngle > 90.0) {
2469 anAngle = 180.0 - anAngle;
2474 catch (Standard_Failure& aFail)
2476 SetErrorCode(aFail.GetMessageString());
2482 //=======================================================================
2484 * Compute angle (in degrees) between two vectors
2486 //=======================================================================
2487 Standard_Real GEOMImpl_IMeasureOperations::GetAngleBtwVectors (Handle(GEOM_Object) theVec1,
2488 Handle(GEOM_Object) theVec2)
2492 Standard_Real anAngle = -1.0;
2494 if (theVec1.IsNull() || theVec2.IsNull())
2497 if (theVec1->GetType() != GEOM_VECTOR || theVec2->GetType() != GEOM_VECTOR) {
2498 SetErrorCode("Two vectors must be given");
2502 Handle(GEOM_Function) aRefVec1 = theVec1->GetLastFunction();
2503 Handle(GEOM_Function) aRefVec2 = theVec2->GetLastFunction();
2504 if (aRefVec1.IsNull() || aRefVec2.IsNull())
2507 TopoDS_Shape aVec1 = aRefVec1->GetValue();
2508 TopoDS_Shape aVec2 = aRefVec2->GetValue();
2509 if (aVec1.IsNull() || aVec2.IsNull() ||
2510 aVec1.ShapeType() != TopAbs_EDGE ||
2511 aVec2.ShapeType() != TopAbs_EDGE)
2513 SetErrorCode("Two edges must be given");
2519 TopoDS_Edge aE1 = TopoDS::Edge(aVec1);
2520 TopoDS_Edge aE2 = TopoDS::Edge(aVec2);
2522 TopoDS_Vertex aP11, aP12, aP21, aP22;
2523 TopExp::Vertices(aE1, aP11, aP12, Standard_True);
2524 TopExp::Vertices(aE2, aP21, aP22, Standard_True);
2525 if (aP11.IsNull() || aP12.IsNull() || aP21.IsNull() || aP22.IsNull()) {
2526 SetErrorCode("Bad edge given");
2530 gp_Vec aV1 (BRep_Tool::Pnt(aP11), BRep_Tool::Pnt(aP12));
2531 gp_Vec aV2 (BRep_Tool::Pnt(aP21), BRep_Tool::Pnt(aP22)) ;
2533 anAngle = aV1.Angle(aV2);
2534 anAngle *= 180. / M_PI; // convert radians into degrees
2538 catch (Standard_Failure& aFail)
2540 SetErrorCode(aFail.GetMessageString());
2547 //=============================================================================
2551 //=============================================================================
2552 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IMeasureOperations::PatchFace(Handle(GEOM_Object) theShape)
2556 if (theShape.IsNull()) return NULL;
2558 Handle(GEOM_Object) aPatchFace = GetEngine()->AddObject(GEOM_PATCH_FACE);
2559 Handle(GEOM_Function) aFunction = aPatchFace->AddFunction(GEOMImpl_PatchFaceDriver::GetID(), 1);
2560 if (aFunction.IsNull()) return NULL;
2562 //Check if the function is set correctly
2563 if (aFunction->GetDriverGUID() != GEOMImpl_PatchFaceDriver::GetID()) return NULL;
2565 GEOMImpl_IPatchFace aPI(aFunction);
2566 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
2567 if (aRefShape.IsNull()) return NULL;
2569 aPI.SetShape(aRefShape);
2570 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2576 if (!GetSolver()->ComputeFunction(aFunction))
2578 SetErrorCode("patch face driver failed");
2582 // Get result compound and collect all faces into result sequence
2583 TopoDS_Shape aResCompound = aFunction->GetValue();
2584 TopTools_IndexedMapOfShape anIndices;
2585 TopExp::MapShapes(aResCompound, anIndices);
2587 Handle(TColStd_HArray1OfInteger) anArray;
2588 for (TopExp_Explorer anExpW(aResCompound, TopAbs_FACE); anExpW.More(); anExpW.Next())
2590 TopoDS_Shape aValue = anExpW.Value();
2591 anArray = new TColStd_HArray1OfInteger(1, 1);
2592 anArray->SetValue(1, anIndices.FindIndex(aValue));
2594 Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(aPatchFace, anArray);
2595 if (!anObj.IsNull())
2597 aSeq->Append(anObj);
2601 catch (Standard_Failure& aFail)
2603 SetErrorCode(aFail.GetMessageString());
2607 //Make a Python command
2608 GEOM::TPythonDump(aFunction, true)
2609 << "[" << aSeq << "] = geompy.PatchFace(" << theShape << ")";
2615 //=============================================================================
2617 * CurveCurvatureByParam
2619 //=============================================================================
2620 Standard_Real GEOMImpl_IMeasureOperations::CurveCurvatureByParam
2621 (Handle(GEOM_Object) theCurve, Standard_Real& theParam)
2624 Standard_Real aRes = -1.0;
2626 if(theCurve.IsNull()) return aRes;
2628 Handle(GEOM_Function) aRefShape = theCurve->GetLastFunction();
2629 if(aRefShape.IsNull()) return aRes;
2631 TopoDS_Shape aShape = aRefShape->GetValue();
2632 if(aShape.IsNull()) {
2633 SetErrorCode("One of Objects has NULL Shape");
2637 Standard_Real aFP, aLP, aP;
2638 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(TopoDS::Edge(aShape), aFP, aLP);
2639 aP = aFP + (aLP - aFP) * theParam;
2641 if(aCurve.IsNull()) return aRes;
2646 GeomLProp_CLProps Prop = GeomLProp_CLProps
2647 (aCurve, aP, 2, Precision::Confusion());
2648 aRes = fabs(Prop.Curvature());
2651 catch (Standard_Failure& aFail) {
2652 SetErrorCode(aFail.GetMessageString());
2656 if( aRes > Precision::Confusion() )
2665 //=============================================================================
2667 * CurveCurvatureByPoint
2669 //=============================================================================
2670 Standard_Real GEOMImpl_IMeasureOperations::CurveCurvatureByPoint
2671 (Handle(GEOM_Object) theCurve, Handle(GEOM_Object) thePoint)
2674 Standard_Real aRes = -1.0;
2676 if( theCurve.IsNull() || thePoint.IsNull() ) return aRes;
2678 Handle(GEOM_Function) aRefCurve = theCurve->GetLastFunction();
2679 Handle(GEOM_Function) aRefPoint = thePoint->GetLastFunction();
2680 if( aRefCurve.IsNull() || aRefPoint.IsNull() ) return aRes;
2682 TopoDS_Edge anEdge = TopoDS::Edge(aRefCurve->GetValue());
2683 TopoDS_Vertex aPnt = TopoDS::Vertex(aRefPoint->GetValue());
2684 if( anEdge.IsNull() || aPnt.IsNull() ) {
2685 SetErrorCode("One of Objects has NULL Shape");
2689 Standard_Real aFP, aLP;
2690 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFP, aLP);
2691 if(aCurve.IsNull()) return aRes;
2692 gp_Pnt aPoint = BRep_Tool::Pnt(aPnt);
2697 GeomAPI_ProjectPointOnCurve PPCurve(aPoint, aCurve, aFP, aLP);
2698 if(PPCurve.NbPoints()>0) {
2699 GeomLProp_CLProps Prop = GeomLProp_CLProps
2700 (aCurve, PPCurve.LowerDistanceParameter(), 2, Precision::Confusion());
2701 aRes = fabs(Prop.Curvature());
2705 catch (Standard_Failure& aFail) {
2706 SetErrorCode(aFail.GetMessageString());
2710 if( aRes > Precision::Confusion() )
2719 //=============================================================================
2721 * getSurfaceCurvatures
2723 //=============================================================================
2724 Standard_Real GEOMImpl_IMeasureOperations::getSurfaceCurvatures
2725 (const Handle(Geom_Surface)& aSurf,
2726 Standard_Real theUParam,
2727 Standard_Real theVParam,
2728 Standard_Boolean theNeedMaxCurv)
2731 Standard_Real aRes = 1.0;
2733 if (aSurf.IsNull()) return aRes;
2737 GeomLProp_SLProps Prop = GeomLProp_SLProps
2738 (aSurf, theUParam, theVParam, 2, Precision::Confusion());
2739 if(Prop.IsCurvatureDefined()) {
2740 if(Prop.IsUmbilic()) {
2741 //cout<<"is umbilic"<<endl;
2742 aRes = fabs(Prop.MeanCurvature());
2745 //cout<<"is not umbilic"<<endl;
2746 double c1 = fabs(Prop.MaxCurvature());
2747 double c2 = fabs(Prop.MinCurvature());
2756 catch (Standard_Failure& aFail) {
2757 SetErrorCode(aFail.GetMessageString());
2761 if( fabs(aRes) > Precision::Confusion() )
2770 //=============================================================================
2772 * MaxSurfaceCurvatureByParam
2774 //=============================================================================
2775 Standard_Real GEOMImpl_IMeasureOperations::MaxSurfaceCurvatureByParam
2776 (Handle(GEOM_Object) theSurf,
2777 Standard_Real& theUParam,
2778 Standard_Real& theVParam)
2781 Standard_Real aRes = -1.0;
2783 if (theSurf.IsNull()) return aRes;
2785 Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2786 if(aRefShape.IsNull()) return aRes;
2788 TopoDS_Shape aShape = aRefShape->GetValue();
2789 if(aShape.IsNull()) {
2790 SetErrorCode("One of Objects has NULL Shape");
2794 TopoDS_Face F = TopoDS::Face(aShape);
2795 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
2797 //Compute the parameters
2798 Standard_Real U1,U2,V1,V2;
2799 BRepTools::UVBounds(F,U1,U2,V1,V2);
2800 Standard_Real U = U1 + (U2-U1)*theUParam;
2801 Standard_Real V = V1 + (V2-V1)*theVParam;
2803 return getSurfaceCurvatures(aSurf, U, V, true);
2807 //=============================================================================
2809 * MaxSurfaceCurvatureByPoint
2811 //=============================================================================
2812 Standard_Real GEOMImpl_IMeasureOperations::MaxSurfaceCurvatureByPoint
2813 (Handle(GEOM_Object) theSurf, Handle(GEOM_Object) thePoint)
2816 Standard_Real aRes = -1.0;
2818 if( theSurf.IsNull() || thePoint.IsNull() ) return aRes;
2820 Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2821 Handle(GEOM_Function) aRefPoint = thePoint->GetLastFunction();
2822 if( aRefShape.IsNull() || aRefPoint.IsNull() ) return aRes;
2824 TopoDS_Face aFace = TopoDS::Face(aRefShape->GetValue());
2825 TopoDS_Vertex aPnt = TopoDS::Vertex(aRefPoint->GetValue());
2826 if( aFace.IsNull() || aPnt.IsNull() ) {
2827 SetErrorCode("One of Objects has NULL Shape");
2831 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
2832 if(aSurf.IsNull()) return aRes;
2833 gp_Pnt aPoint = BRep_Tool::Pnt(aPnt);
2835 //Compute the parameters
2836 ShapeAnalysis_Surface sas(aSurf);
2837 gp_Pnt2d UV = sas.ValueOfUV(aPoint,Precision::Confusion());
2839 return getSurfaceCurvatures(aSurf, UV.X(), UV.Y(), true);
2843 //=============================================================================
2845 * MinSurfaceCurvatureByParam
2847 //=============================================================================
2848 Standard_Real GEOMImpl_IMeasureOperations::MinSurfaceCurvatureByParam
2849 (Handle(GEOM_Object) theSurf,
2850 Standard_Real& theUParam,
2851 Standard_Real& theVParam)
2854 Standard_Real aRes = -1.0;
2856 if (theSurf.IsNull()) return aRes;
2858 Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2859 if(aRefShape.IsNull()) return aRes;
2861 TopoDS_Shape aShape = aRefShape->GetValue();
2862 if(aShape.IsNull()) {
2863 SetErrorCode("One of Objects has NULL Shape");
2867 TopoDS_Face F = TopoDS::Face(aShape);
2868 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
2870 //Compute the parameters
2871 Standard_Real U1,U2,V1,V2;
2872 BRepTools::UVBounds(F,U1,U2,V1,V2);
2873 Standard_Real U = U1 + (U2-U1)*theUParam;
2874 Standard_Real V = V1 + (V2-V1)*theVParam;
2876 return getSurfaceCurvatures(aSurf, U, V, false);
2880 //=============================================================================
2882 * MinSurfaceCurvatureByPoint
2884 //=============================================================================
2885 Standard_Real GEOMImpl_IMeasureOperations::MinSurfaceCurvatureByPoint
2886 (Handle(GEOM_Object) theSurf, Handle(GEOM_Object) thePoint)
2889 Standard_Real aRes = -1.0;
2891 if( theSurf.IsNull() || thePoint.IsNull() ) return aRes;
2893 Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2894 Handle(GEOM_Function) aRefPoint = thePoint->GetLastFunction();
2895 if( aRefShape.IsNull() || aRefPoint.IsNull() ) return aRes;
2897 TopoDS_Face aFace = TopoDS::Face(aRefShape->GetValue());
2898 TopoDS_Vertex aPnt = TopoDS::Vertex(aRefPoint->GetValue());
2899 if( aFace.IsNull() || aPnt.IsNull() ) {
2900 SetErrorCode("One of Objects has NULL Shape");
2904 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
2905 if(aSurf.IsNull()) return aRes;
2906 gp_Pnt aPoint = BRep_Tool::Pnt(aPnt);
2908 //Compute the parameters
2909 ShapeAnalysis_Surface sas(aSurf);
2910 gp_Pnt2d UV = sas.ValueOfUV(aPoint,Precision::Confusion());
2912 return getSurfaceCurvatures(aSurf, UV.X(), UV.Y(), false);
2915 //=============================================================================
2917 * SurfaceCurvatureByPointAndDirection
2919 //=============================================================================
2920 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::SurfaceCurvatureByPointAndDirection
2921 (Handle(GEOM_Object) theSurf,
2922 Handle(GEOM_Object) thePoint,
2923 Handle(GEOM_Object) theDirection)
2927 if (theSurf.IsNull() || thePoint.IsNull() || theDirection.IsNull()) return NULL;
2929 Handle(GEOM_Function) aSurf = theSurf->GetLastFunction();
2930 Handle(GEOM_Function) aPoint = thePoint->GetLastFunction();
2931 Handle(GEOM_Function) aDirection = theDirection->GetLastFunction();
2932 if (aSurf.IsNull() || aPoint.IsNull() || aDirection.IsNull()) return NULL;
2934 //Add a new CurvatureVector object
2935 //Handle(GEOM_Object) aCV = GetEngine()->AddObject(GEOM_CURVATURE_VEC);
2936 Handle(GEOM_Object) aCV = GetEngine()->AddObject(GEOM_VECTOR);
2938 //Add a new CurvatureVector function
2939 Handle(GEOM_Function) aFunction =
2940 aCV->AddFunction(GEOMImpl_MeasureDriver::GetID(), CURVATURE_VEC_MEASURE);
2941 if (aFunction.IsNull()) return NULL;
2943 //Check if the function is set correctly
2944 if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
2946 GEOMImpl_IMeasure aCI (aFunction);
2948 aCI.SetPoint(aPoint);
2949 aCI.SetDirection(aDirection);
2951 //Compute the CurvatureVector
2954 if (!GetSolver()->ComputeFunction(aFunction)) {
2955 SetErrorCode("Measure driver failed to compute a surface curvature");
2959 catch (Standard_Failure& aFail) {
2960 SetErrorCode(aFail.GetMessageString());
2964 //Make a Python command
2965 GEOM::TPythonDump(aFunction) << aCV << " = geompy.CurvatureOnFace(" << theSurf
2966 << ", " << thePoint << ", " << theDirection << ")";
2972 //=============================================================================
2976 //=============================================================================
2977 Handle(TColStd_HArray1OfReal) GEOMImpl_IMeasureOperations::XYZtoUV
2978 (Handle(GEOM_Object) theSurf,
2979 const Handle(TColStd_HArray1OfReal)& theXYZlist,
2984 Handle(TColStd_HArray1OfReal) aRet;
2986 // Check list of coordinates
2987 int nbC = theXYZlist->Length();
2989 if (nbP * 3 != nbC) {
2990 SetErrorCode("Coordinates list length is not divisible by 3");
2995 if (theSurf.IsNull()) {
2996 SetErrorCode("The shape is NULL");
3000 Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
3001 if (aRefShape.IsNull()) {
3002 SetErrorCode("The shape is NULL");
3006 TopoDS_Shape aShape = aRefShape->GetValue();
3007 if (aShape.IsNull()) {
3008 SetErrorCode("The shape is NULL");
3012 // The shape can be a face, a shell of one face or a compound with one face
3014 if (aShape.ShapeType() == TopAbs_FACE) {
3015 F = TopoDS::Face(aShape);
3017 else if (aShape.ShapeType() < TopAbs_FACE) {
3018 TopExp_Explorer Exp (aShape, TopAbs_FACE);
3020 F = TopoDS::Face(Exp.Current());
3023 SetErrorCode("There should be only one face");
3029 SetErrorCode("There are no faces");
3034 Standard_Real aTol = BRep_Tool::Tolerance(F);
3035 Standard_Real squareTolerance = aTol * aTol;
3037 // Compute parameters
3038 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
3039 aRet = new TColStd_HArray1OfReal (0, nbP * 2 - 1);
3041 Standard_Real U1,U2, V1,V2;
3042 BRepTools::UVBounds(F, U1, U2, V1, V2);
3043 Standard_Real dU = U2 - U1;
3044 Standard_Real dV = V2 - V1;
3046 int iCLower = theXYZlist->Lower();
3047 for (int iP = 0; iP < nbP; iP++) {
3048 gp_Pnt aP (theXYZlist->Value(iCLower + iP * 3),
3049 theXYZlist->Value(iCLower + iP * 3 + 1),
3050 theXYZlist->Value(iCLower + iP * 3 + 2));
3051 try { // as GEOMUtils::ProjectPointOnFace can throw exceptions
3053 gp_Pnt aPonF = GEOMUtils::ProjectPointOnFace(aP, F, U, V, aTol);
3054 if (aP.SquareDistance(aPonF) < squareTolerance) {
3056 // Normalize parameters to be in [0, 1]
3060 aRet->SetValue(iP * 2 , U);
3061 aRet->SetValue(iP * 2 + 1, V);
3064 SetErrorCode("Point too far from face");
3068 catch (Standard_Failure& aFail) {
3069 SetErrorCode(aFail.GetMessageString());
3078 //=============================================================================
3082 //=============================================================================
3083 Handle(TColStd_HArray1OfReal) GEOMImpl_IMeasureOperations::UVtoXYZ
3084 (Handle(GEOM_Object) theSurf,
3085 const Handle(TColStd_HArray1OfReal)& theUVlist,
3090 Handle(TColStd_HArray1OfReal) aRet;
3092 // Check list of parameters
3093 int nbC = theUVlist->Length();
3095 if (nbP * 2 != nbC) {
3096 SetErrorCode("Parameters list length is not divisible by 2");
3101 if (theSurf.IsNull()) {
3102 SetErrorCode("The shape is NULL");
3106 Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
3107 if (aRefShape.IsNull()) {
3108 SetErrorCode("The shape is NULL");
3112 TopoDS_Shape aShape = aRefShape->GetValue();
3113 if (aShape.IsNull()) {
3114 SetErrorCode("The shape is NULL");
3118 // The shape can be a face, a shell of one face or a compound with one face
3120 if (aShape.ShapeType() == TopAbs_FACE) {
3121 F = TopoDS::Face(aShape);
3123 else if (aShape.ShapeType() < TopAbs_FACE) {
3124 TopExp_Explorer Exp (aShape, TopAbs_FACE);
3126 F = TopoDS::Face(Exp.Current());
3129 SetErrorCode("There should be only one face");
3135 SetErrorCode("There are no faces");
3140 Standard_Real squareTolerance = BRep_Tool::Tolerance(F);
3141 squareTolerance = squareTolerance * squareTolerance;
3143 // Compute coordinates
3144 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
3145 aRet = new TColStd_HArray1OfReal (0, nbP * 3 - 1);
3147 Standard_Real U1,U2, V1,V2;
3148 BRepTools::UVBounds(F, U1, U2, V1, V2);
3149 Standard_Real dU = U2 - U1;
3150 Standard_Real dV = V2 - V1;
3152 Standard_Real tol = 1.e-4;
3153 Standard_Real pc = Precision::Confusion();
3155 int iCLower = theUVlist->Lower();
3156 for (int iP = 0; iP < nbP; iP++) {
3157 Standard_Real U = theUVlist->Value(iCLower + iP * 2);
3158 Standard_Real V = theUVlist->Value(iCLower + iP * 2 + 1);
3161 // Get real parameters from given normalized ones in [0, 1]
3162 if (!(-pc < U && U < 1 + pc) || !(-pc < V && V < 1 + pc)) {
3163 SetErrorCode("Normalized parameter is out of range [0,1]");
3170 gp_Pnt2d aP2d (U, V);
3172 BRepClass_FaceClassifier aClsf (F, aP2d, tol);
3173 if (aClsf.State() != TopAbs_IN && aClsf.State() != TopAbs_ON) {
3174 SetErrorCode("Given parameters are out of face");
3177 gp_Pnt surfPnt = aSurf->Value(U, V);
3179 aRet->SetValue(iP * 3 , surfPnt.X());
3180 aRet->SetValue(iP * 3 + 1, surfPnt.Y());
3181 aRet->SetValue(iP * 3 + 2, surfPnt.Z());
3188 //=============================================================================
3191 * Find all self-intersected 2D curves.
3192 * \param theChecks list of failed checks, contains type of check and failed shapes
3194 //=============================================================================
3195 std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects>
3196 GEOMImpl_IMeasureOperations::SelfIntersected2D(const std::list<FailedChecks>& theChecks)
3199 MESSAGE("GEOMImpl_IMeasureOperations::selfIntersected2D");
3201 std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects> aSelfInters2D;
3205 for (std::list<FailedChecks>::const_iterator anIter(theChecks.begin());
3206 anIter != theChecks.end(); ++anIter)
3208 if (anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_InvalidCurveOnSurface)
3209 aSelfInters2D.push_back(anIter->FailedShapes);
3212 catch (Standard_Failure& aFail)
3214 SetErrorCode(aFail.GetMessageString());
3215 return aSelfInters2D;
3219 return aSelfInters2D;
3224 static bool checkTypes(const GEOMImpl_IMeasureOperations::CoupleOfObjects& theShapes,
3225 const int theShapeType1,
3226 const int theShapeType2)
3228 if (theShapeType1 == -1 && theShapeType2 == -1)
3231 TopAbs_ShapeEnum aShapeType1 = theShapes.first.IsNull()
3233 : theShapes.first->GetValue().ShapeType();
3234 TopAbs_ShapeEnum aShapeType2 = theShapes.second.IsNull()
3236 : theShapes.second->GetValue().ShapeType();
3238 if (theShapeType1 == -1)
3239 return aShapeType1 == theShapeType2 || aShapeType2 == theShapeType2;
3240 else if (theShapeType2 == -1)
3241 return aShapeType1 == theShapeType1 || aShapeType2 == theShapeType1;
3242 return (aShapeType1 == theShapeType1 && aShapeType2 == theShapeType2) ||
3243 (aShapeType1 == theShapeType2 && aShapeType2 == theShapeType1);
3247 //=============================================================================
3249 * InterferingSubshapes
3250 * Find pairs of interfering sub-shapes, by default all pairs of interfering shapes are returned.
3251 * \param theChecks list of failed checks, contains type of check and failed shapes
3252 * \param theShapeType1 Type of shape.
3253 * \param theShapeType2 Type of shape.
3255 //=============================================================================
3256 std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects>
3257 GEOMImpl_IMeasureOperations::InterferingSubshapes
3258 (const std::list<FailedChecks>& theChecks,
3259 const int theShapeType1,
3260 const int theShapeType2)
3263 MESSAGE("GEOMImpl_IMeasureOperations::interferingSubshapes");
3265 std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects> anInterfer;
3269 for (std::list<FailedChecks>::const_iterator anIter(theChecks.begin());
3270 anIter != theChecks.end(); ++anIter)
3272 if (anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_SelfIntersect &&
3273 checkTypes(anIter->FailedShapes, theShapeType1, theShapeType2))
3274 anInterfer.push_back(anIter->FailedShapes);
3277 catch (Standard_Failure& aFail)
3279 SetErrorCode(aFail.GetMessageString());
3287 //=============================================================================
3290 * Find edges, which are fully covered by tolerances of vertices.
3291 * \param theChecks list of failed checks, contains type of check and failed shapes
3293 //=============================================================================
3294 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IMeasureOperations::SmallEdges(
3295 const std::list<FailedChecks>& theChecks)
3298 MESSAGE("GEOMImpl_IMeasureOperations::smallEdges");
3300 Handle(TColStd_HSequenceOfTransient) aSmallEdges = new TColStd_HSequenceOfTransient;
3304 for (std::list<FailedChecks>::const_iterator anIter(theChecks.begin());
3305 anIter != theChecks.end(); ++anIter)
3307 if (anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_TooSmallEdge)
3308 aSmallEdges->Append(anIter->FailedShapes.first);
3311 catch (Standard_Failure& aFail)
3313 SetErrorCode(aFail.GetMessageString());
3321 //=============================================================================
3324 * find remote objects (sub-shape on a shape).
3325 * \param theShape Shape for check.
3326 * \param theShapeType Type of shape.
3327 * \param theSubShapeType Type of sub-shape.
3328 * \param theTolerance tolerance.
3330 //=============================================================================
3331 std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects>
3332 GEOMImpl_IMeasureOperations::DistantShapes
3333 (const std::list<FailedChecks>& theChecks,
3334 const int theShapeType,
3335 const int theSubShapeType,
3336 double theTolerance)
3339 MESSAGE("GEOMImpl_IMeasureOperations::distantShapes");
3341 std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects> aDistShapes;
3345 for (std::list<FailedChecks>::const_iterator anIter(theChecks.begin());
3346 anIter != theChecks.end(); ++anIter)
3348 Handle(GEOM_Object) aSubShape = anIter->FailedShapes.first;
3349 Handle(GEOM_Object) aShape = anIter->FailedShapes.second;
3350 if ((anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_InvalidCurveOnSurface ||
3351 anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_IncompatibilityOfVertex ||
3352 anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_IncompatibilityOfEdge ||
3353 anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_IncompatibilityOfFace) &&
3354 aShape && (theShapeType == -1 || aShape->GetValue().ShapeType() == theShapeType) &&
3355 aSubShape && (theSubShapeType == -1 || aSubShape->GetValue().ShapeType() == theSubShapeType))
3358 Standard_Real aDist = Precision::Infinite();
3359 if (anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_InvalidCurveOnSurface)
3360 aDist = ComputeTolerance(aSubShape, aShape);
3361 if (aDist > theTolerance)
3362 aDistShapes.push_back(anIter->FailedShapes);
3366 catch (Standard_Failure& aFail)
3368 SetErrorCode(aFail.GetMessageString());
3376 //=============================================================================
3378 * CheckConformityShape
3379 * Perform analyse of shape and find imperfections in the shape.
3380 * \param theShape Shape for analyse.
3382 //=============================================================================
3383 void GEOMImpl_IMeasureOperations::CheckConformityShape(Handle(GEOM_Object) theShape, std::list<FailedChecks>& theChecks)
3386 MESSAGE("GEOMImpl_IMeasureOperations::checkShape");
3388 Handle(GEOM_Object) aConformity = GetEngine()->AddObject(GEOM_CHECKCONFORMITY);
3389 Handle(GEOM_Function) aFunction = aConformity->AddFunction(GEOMImpl_ConformityDriver::GetID(), CONFORMITY_CHECK_SHAPE);
3390 if (aFunction.IsNull()) return;
3392 //Check if the function is set correctly
3393 if (aFunction->GetDriverGUID() != GEOMImpl_ConformityDriver::GetID()) return;
3395 GEOMImpl_IConformity aCI(aFunction);
3397 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
3398 if (aRefShape.IsNull()) return;
3400 aCI.SetShape(aRefShape);
3405 if (!GetSolver()->ComputeFunction(aFunction))
3407 SetErrorCode("Failed: checkShape");
3410 Handle(TColStd_HArray1OfInteger) aTypesChecks = aFunction->GetIntegerArray(CHECKCONFORMITY_RET_TYPES_CHECKS);
3411 Handle(TColStd_HArray2OfInteger) aRes = aCI.GetListOfShapesIndices();
3415 for (Standard_Integer anIndex = 1; anIndex <= aRes->NbRows(); ++anIndex)
3417 std::pair<Handle(GEOM_Object), Handle(GEOM_Object)> aPair;
3418 Handle(TColStd_HArray1OfInteger) anArray;
3419 anArray = new TColStd_HArray1OfInteger(1, 1);
3420 anArray->SetValue(1, aRes->Value(anIndex, 1));
3422 Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray);
3423 if (!anObj.IsNull())
3424 aPair.first = anObj;
3426 anArray = new TColStd_HArray1OfInteger(1, 1);
3427 anArray->SetValue(1, aRes->Value(anIndex, 2));
3429 anObj = GetEngine()->AddSubShape(theShape, anArray);
3430 if (!anObj.IsNull())
3431 aPair.second = anObj;
3432 theChecks.push_back({ aTypesChecks->Value(anIndex), aPair });
3435 catch (Standard_Failure& aFail)
3437 SetErrorCode(aFail.GetMessageString());
3445 //=============================================================================
3448 * Compute possible tolerance for the shape, minimize tolerance of shape as well
3449 * as tolerance of sub-shapes as much as possible
3450 * \param theShape Shape for compute tolerance.
3452 //=============================================================================
3453 double GEOMImpl_IMeasureOperations::UpdateTolerance(Handle(GEOM_Object) theShape)
3456 MESSAGE("GEOMImpl_IMeasureOperations::updateTolerance");
3458 double aResTol = -1;
3459 Handle(GEOM_Object) aConformity = GetEngine()->AddObject(GEOM_CHECKCONFORMITY);
3460 Handle(GEOM_Function) aFunction = aConformity->AddFunction(GEOMImpl_ConformityDriver::GetID(), CONFORMITY_UPDATE_TOL);
3461 if (aFunction.IsNull()) return aResTol;
3463 //Check if the function is set correctly
3464 if (aFunction->GetDriverGUID() != GEOMImpl_ConformityDriver::GetID()) return aResTol;
3466 GEOMImpl_IConformity aCI(aFunction);
3468 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
3469 if (aRefShape.IsNull()) return aResTol;
3471 aCI.SetShape(aRefShape);
3476 if (!GetSolver()->ComputeFunction(aFunction))
3478 SetErrorCode("Failed: updateTolerance");
3481 aResTol = aFunction->GetReal(CHECKCONFORMITY_RET_TOLERANCE);
3483 catch (Standard_Failure& aFail)
3485 SetErrorCode(aFail.GetMessageString());
3493 //=============================================================================
3496 * Compute distance from the edge to the face.
3498 //=============================================================================
3499 double GEOMImpl_IMeasureOperations::ComputeTolerance(Handle(GEOM_Object) theEdge,
3500 Handle(GEOM_Object) theFace)
3502 double aMaxDist = Precision::Infinite();
3503 if (theEdge.IsNull() || theFace.IsNull())
3506 Handle(GEOM_Function) aRefEdge = theEdge->GetLastFunction();
3507 Handle(GEOM_Function) aRefFace = theFace->GetLastFunction();
3508 if (aRefEdge.IsNull() || aRefFace.IsNull())
3511 TopoDS_Edge aEdge = TopoDS::Edge(aRefEdge->GetValue());
3512 TopoDS_Face aFace = TopoDS::Face(aRefFace->GetValue());
3513 if (aEdge.IsNull() || aFace.IsNull())
3516 double aParam = 0.0;
3517 BOPTools_AlgoTools::ComputeTolerance(aFace, aEdge, aMaxDist, aParam);
3521 //=======================================================================
3522 //function : FillErrorsSub
3523 //purpose : Fill the errors list of subshapes on shape.
3524 //=======================================================================
3525 void GEOMImpl_IMeasureOperations::FillErrorsSub
3526 (const BRepCheck_Analyzer &theAna,
3527 const TopoDS_Shape &theShape,
3528 const TopAbs_ShapeEnum theSubType,
3529 TopTools_DataMapOfIntegerListOfShape &theMapErrors) const
3531 TopExp_Explorer anExp(theShape, theSubType);
3532 TopTools_MapOfShape aMapSubShapes;
3534 for (; anExp.More(); anExp.Next()) {
3535 const TopoDS_Shape &aSubShape = anExp.Current();
3537 if (aMapSubShapes.Add(aSubShape)) {
3538 const Handle(BRepCheck_Result) &aRes = theAna.Result(aSubShape);
3540 for (aRes->InitContextIterator();
3541 aRes->MoreShapeInContext();
3542 aRes->NextShapeInContext()) {
3543 if (aRes->ContextualShape().IsSame(theShape)) {
3544 BRepCheck_ListIteratorOfListOfStatus itl(aRes->StatusOnShape());
3546 if (itl.Value() != BRepCheck_NoError) {
3547 // Add all errors for theShape and its sub-shape.
3548 for (;itl.More(); itl.Next()) {
3549 const Standard_Integer aStat = (Standard_Integer)itl.Value();
3551 if (!theMapErrors.IsBound(aStat)) {
3552 TopTools_ListOfShape anEmpty;
3554 theMapErrors.Bind(aStat, anEmpty);
3557 TopTools_ListOfShape &theShapes = theMapErrors.ChangeFind(aStat);
3559 theShapes.Append(aSubShape);
3560 theShapes.Append(theShape);
3571 //=======================================================================
3572 //function : FillErrors
3573 //purpose : Fill the errors list.
3574 //=======================================================================
3575 void GEOMImpl_IMeasureOperations::FillErrors
3576 (const BRepCheck_Analyzer &theAna,
3577 const TopoDS_Shape &theShape,
3578 TopTools_DataMapOfIntegerListOfShape &theMapErrors,
3579 TopTools_MapOfShape &theMapShapes) const
3581 if (theMapShapes.Add(theShape)) {
3582 // Fill errors of child shapes.
3583 for (TopoDS_Iterator iter(theShape); iter.More(); iter.Next()) {
3584 FillErrors(theAna, iter.Value(), theMapErrors, theMapShapes);
3587 // Fill errors of theShape.
3588 const Handle(BRepCheck_Result) &aRes = theAna.Result(theShape);
3590 if (!aRes.IsNull()) {
3591 BRepCheck_ListIteratorOfListOfStatus itl(aRes->Status());
3593 if (itl.Value() != BRepCheck_NoError) {
3594 // Add all errors for theShape.
3595 for (;itl.More(); itl.Next()) {
3596 const Standard_Integer aStat = (Standard_Integer)itl.Value();
3598 if (!theMapErrors.IsBound(aStat)) {
3599 TopTools_ListOfShape anEmpty;
3601 theMapErrors.Bind(aStat, anEmpty);
3604 theMapErrors.ChangeFind(aStat).Append(theShape);
3609 // Add errors of subshapes on theShape.
3610 const TopAbs_ShapeEnum aType = theShape.ShapeType();
3614 FillErrorsSub(theAna, theShape, TopAbs_VERTEX, theMapErrors);
3617 FillErrorsSub(theAna, theShape, TopAbs_WIRE, theMapErrors);
3618 FillErrorsSub(theAna, theShape, TopAbs_EDGE, theMapErrors);
3619 FillErrorsSub(theAna, theShape, TopAbs_VERTEX, theMapErrors);
3622 FillErrorsSub(theAna, theShape, TopAbs_SHELL, theMapErrors);
3630 //=======================================================================
3631 //function : FillErrors
3632 //purpose : Fill the errors list.
3633 //=======================================================================
3634 void GEOMImpl_IMeasureOperations::FillErrors
3635 (const BRepCheck_Analyzer &theAna,
3636 const TopoDS_Shape &theShape,
3637 std::list<ShapeError> &theErrors) const
3639 // Fill the errors map.
3640 TopTools_DataMapOfIntegerListOfShape aMapErrors;
3641 TopTools_MapOfShape aMapShapes;
3643 FillErrors(theAna, theShape, aMapErrors, aMapShapes);
3645 // Map sub-shapes and their indices
3646 TopTools_IndexedMapOfShape anIndices;
3648 TopExp::MapShapes(theShape, anIndices);
3650 TopTools_DataMapIteratorOfDataMapOfIntegerListOfShape aMapIter(aMapErrors);
3652 for (; aMapIter.More(); aMapIter.Next()) {
3655 anError.error = (BRepCheck_Status)aMapIter.Key();
3657 TopTools_ListIteratorOfListOfShape aListIter(aMapIter.Value());
3658 TopTools_MapOfShape aMapUnique;
3660 for (; aListIter.More(); aListIter.Next()) {
3661 const TopoDS_Shape &aShape = aListIter.Value();
3663 if (aMapUnique.Add(aShape)) {
3664 const Standard_Integer anIndex = anIndices.FindIndex(aShape);
3666 anError.incriminated.push_back(anIndex);
3670 if (!anError.incriminated.empty()) {
3671 theErrors.push_back(anError);
3676 //=======================================================================
3677 //function : ShapeProximityCalculator
3678 //purpose : returns an object to compute the proximity value
3679 //=======================================================================
3680 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::ShapeProximityCalculator
3681 (Handle(GEOM_Object) theShape1,
3682 Handle(GEOM_Object) theShape2)
3686 if (theShape1.IsNull() || theShape2.IsNull())
3689 Handle(GEOM_Function) aShapeFunc1 = theShape1->GetLastFunction();
3690 Handle(GEOM_Function) aShapeFunc2 = theShape2->GetLastFunction();
3691 if (aShapeFunc1.IsNull() || aShapeFunc2.IsNull())
3694 Handle(GEOM_Object) aProximityCalc = GetEngine()->AddObject(GEOM_SHAPE_PROXIMITY);
3695 if (aProximityCalc.IsNull())
3698 Handle(GEOM_Function) aProximityFuncCoarse =
3699 aProximityCalc->AddFunction(GEOMImpl_ShapeProximityDriver::GetID(), PROXIMITY_COARSE);
3700 //Check if the function is set correctly
3701 if (aProximityFuncCoarse.IsNull() ||
3702 aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID())
3705 GEOMImpl_IProximity aProximity (aProximityFuncCoarse);
3706 aProximity.SetShapes(aShapeFunc1, aShapeFunc2);
3708 //Make a Python command
3709 GEOM::TPythonDump pd (aProximityFuncCoarse);
3710 pd << "p = geompy.ShapeProximity()\n";
3711 pd << "p.setShapes(" << theShape1 << ", " << theShape2 << ")";
3714 return aProximityCalc;
3717 //=======================================================================
3718 //function : SetShapeSampling
3719 //purpose : set number sample points to compute the coarse proximity
3720 //=======================================================================
3721 void GEOMImpl_IMeasureOperations::SetShapeSampling(Handle(GEOM_Object) theCalculator,
3722 Handle(GEOM_Object) theShape,
3723 const Standard_Integer theNbSamples)
3726 if (theShape.IsNull() ||
3727 theCalculator.IsNull() ||
3728 theCalculator->GetNbFunctions() <= 0 ||
3732 Handle(GEOM_Function) aProximityFuncCoarse = theCalculator->GetFunction(1);
3733 if (aProximityFuncCoarse.IsNull() ||
3734 aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID())
3737 Handle(GEOM_Function) aShapeFunc = theShape->GetLastFunction();
3738 if (aShapeFunc.IsNull())
3741 GEOMImpl_IProximity aProximity(aProximityFuncCoarse);
3742 Handle(GEOM_Function) aShape1, aShape2;
3743 aProximity.GetShapes(aShape1, aShape2);
3744 if (aShape1->GetValue() == aShapeFunc->GetValue())
3745 aProximity.SetNbSamples(PROXIMITY_ARG_SAMPLES1, theNbSamples);
3746 else if (aShape2->GetValue() == aShapeFunc->GetValue())
3747 aProximity.SetNbSamples(PROXIMITY_ARG_SAMPLES2, theNbSamples);
3749 //Make a Python command
3750 GEOM::TPythonDump(aProximityFuncCoarse, /*append=*/true) <<
3751 "p.setSampling(" << theShape << ", " << theNbSamples << ")";
3756 //=======================================================================
3757 //function : GetCoarseProximity
3758 //purpose : compute coarse proximity
3759 //=======================================================================
3760 Standard_Real GEOMImpl_IMeasureOperations::GetCoarseProximity(Handle(GEOM_Object) theCalculator,
3764 if (theCalculator.IsNull())
3767 Handle(GEOM_Function) aProximityFuncCoarse = theCalculator->GetFunction(1);
3768 if (aProximityFuncCoarse.IsNull() ||
3769 aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID() ||
3770 aProximityFuncCoarse->GetType() != PROXIMITY_COARSE)
3774 // We have to recompute the function each time,
3775 // because the number of samples can be changed
3778 if (!GetSolver()->ComputeFunction(aProximityFuncCoarse)) {
3779 SetErrorCode("shape proximity driver failed");
3783 catch (Standard_Failure& aFail) {
3784 SetErrorCode(aFail.GetMessageString());
3788 //Make a Python command
3790 GEOM::TPythonDump(aProximityFuncCoarse, /*append=*/true) << "value = p.coarseProximity()";
3793 GEOMImpl_IProximity aProximity (aProximityFuncCoarse);
3794 return aProximity.GetValue();
3797 //=======================================================================
3798 //function : GetPreciseProximity
3799 //purpose : compute precise proximity
3800 //=======================================================================
3801 Standard_Real GEOMImpl_IMeasureOperations::GetPreciseProximity(Handle(GEOM_Object) theCalculator)
3804 if (theCalculator.IsNull())
3807 Handle(GEOM_Function) aProximityFuncCoarse = theCalculator->GetFunction(1);
3808 Handle(GEOM_Function) aProximityFuncFine = theCalculator->GetFunction(2);
3809 if (aProximityFuncFine.IsNull())
3810 aProximityFuncFine = theCalculator->AddFunction
3811 (GEOMImpl_ShapeProximityDriver::GetID(), PROXIMITY_PRECISE);
3813 //Check if the functions are set correctly
3814 if (aProximityFuncCoarse.IsNull() ||
3815 aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID() ||
3816 aProximityFuncFine.IsNull() ||
3817 aProximityFuncFine->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID())
3820 // perform coarse computation beforehand
3821 GetCoarseProximity(theCalculator, /*doPythonDump=*/false);
3823 // transfer parameters from the coarse to precise calculator
3824 GEOMImpl_IProximity aCoarseProximity (aProximityFuncCoarse);
3825 Handle(GEOM_Function) aShape1, aShape2;
3826 aCoarseProximity.GetShapes(aShape1, aShape2);
3827 if (aShape1.IsNull() || aShape2.IsNull())
3829 gp_Pnt aProxPnt1, aProxPnt2;
3830 Standard_Integer intStatus1, intStatus2;
3831 aCoarseProximity.GetProximityPoints(aProxPnt1, aProxPnt2);
3832 aCoarseProximity.GetStatusOfPoints(intStatus1, intStatus2);
3833 Standard_Real aResultValue = aCoarseProximity.GetValue();
3835 GEOMImpl_IProximity aFineProximity (aProximityFuncFine);
3836 aFineProximity.SetShapes(aShape1, aShape2);
3837 aFineProximity.SetProximityPoints(aProxPnt1, aProxPnt2);
3838 aFineProximity.SetStatusOfPoints(intStatus1, intStatus2);
3839 aFineProximity.SetValue(aResultValue); // in some cases this value cannot be precised
3844 if (!GetSolver()->ComputeFunction(aProximityFuncFine)) {
3845 SetErrorCode("shape proximity driver failed");
3849 catch (Standard_Failure& aFail) {
3850 SetErrorCode(aFail.GetMessageString());
3854 aResultValue = aFineProximity.GetValue();
3855 aFineProximity.GetProximityPoints(aProxPnt1, aProxPnt2);
3857 //Make a Python command
3858 GEOM::TPythonDump(aProximityFuncCoarse, /*append=*/true) << "value = p.preciseProximity()";
3861 return aResultValue;