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.hxx>
77 #include <ShapeAnalysis_Surface.hxx>
79 #include <TopExp_Explorer.hxx>
81 #include <TopoDS_Edge.hxx>
82 #include <TopTools_IndexedMapOfShape.hxx>
83 #include <TopTools_DataMapIteratorOfDataMapOfIntegerListOfShape.hxx>
84 #include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
85 #include <TopTools_ListIteratorOfListOfShape.hxx>
86 #include <TopTools_ListOfShape.hxx>
87 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
91 //=============================================================================
95 //=============================================================================
96 GEOMImpl_IMeasureOperations::GEOMImpl_IMeasureOperations (GEOM_Engine* theEngine)
97 : GEOM_IOperations(theEngine)
99 MESSAGE("GEOMImpl_IMeasureOperations::GEOMImpl_IMeasureOperations");
102 //=============================================================================
106 //=============================================================================
107 GEOMImpl_IMeasureOperations::~GEOMImpl_IMeasureOperations()
109 MESSAGE("GEOMImpl_IMeasureOperations::~GEOMImpl_IMeasureOperations");
112 //=============================================================================
113 /*! Get kind and parameters of the given shape.
115 //=============================================================================
116 GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape
117 (Handle(GEOM_Object) theShape,
118 Handle(TColStd_HSequenceOfInteger)& theIntegers,
119 Handle(TColStd_HSequenceOfReal)& theDoubles)
122 ShapeKind aKind = SK_NO_SHAPE;
124 if (theIntegers.IsNull()) theIntegers = new TColStd_HSequenceOfInteger;
125 else theIntegers->Clear();
127 if (theDoubles.IsNull()) theDoubles = new TColStd_HSequenceOfReal;
128 else theDoubles->Clear();
130 if (theShape.IsNull())
133 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
134 if (aRefShape.IsNull()) return aKind;
136 TopoDS_Shape aShape = aRefShape->GetValue();
137 if (aShape.IsNull()) return aKind;
139 int geom_type = theShape->GetType();
141 // check if it's advanced shape
142 if ( geom_type > USER_TYPE ) {
148 GEOMAlgo_ShapeInfoFiller aSF;
149 aSF.SetShape(aShape);
152 Standard_Integer iErr = aSF.ErrorStatus();
155 SetErrorCode("Error in GEOMAlgo_ShapeInfoFiller");
158 const GEOMAlgo_ShapeInfo& anInfo = aSF.Info();
160 // specific processing for some "advanced" objects
161 switch ( geom_type ) {
163 // local coordinate system
164 // (+) geompy.kind.LCS xc yc zc xx xy xz yx yy yz zx zy zz
166 TopoDS_Face aFace = TopoDS::Face( aShape );
167 Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast( BRep_Tool::Surface( aFace ) );
168 gp_Pnt aC = aPlane->Pln().Location();
169 gp_Ax3 anAx3 = aPlane->Pln().Position();
171 theDoubles->Append(aC.X());
172 theDoubles->Append(aC.Y());
173 theDoubles->Append(aC.Z());
175 gp_Dir aD = anAx3.XDirection();
176 theDoubles->Append(aD.X());
177 theDoubles->Append(aD.Y());
178 theDoubles->Append(aD.Z());
179 aD = anAx3.YDirection();
180 theDoubles->Append(aD.X());
181 theDoubles->Append(aD.Y());
182 theDoubles->Append(aD.Z());
183 aD = anAx3.Direction();
184 theDoubles->Append(aD.X());
185 theDoubles->Append(aD.Y());
186 theDoubles->Append(aD.Z());
193 TopAbs_ShapeEnum aType = anInfo.Type();
196 case TopAbs_COMPOUND:
197 case TopAbs_COMPSOLID:
199 // (+) geompy.kind.COMPOUND nb_solids nb_faces nb_edges nb_vertices
200 // (+) geompy.kind.COMPSOLID nb_solids nb_faces nb_edges nb_vertices
201 // ??? "nb_faces" - all faces or only 'standalone' faces?
202 if (aType == TopAbs_COMPOUND)
205 aKind = SK_COMPSOLID;
207 //theIntegers->Append(anInfo.NbSubShapes(TopAbs_COMPOUND));
208 //theIntegers->Append(anInfo.NbSubShapes(TopAbs_COMPSOLID));
209 theIntegers->Append(anInfo.NbSubShapes(TopAbs_SOLID));
210 theIntegers->Append(anInfo.NbSubShapes(TopAbs_FACE));
211 theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
212 theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
218 // (+) geompy.kind.SHELL geompy.info.closed nb_faces nb_edges nb_vertices
219 // (+) geompy.kind.SHELL geompy.info.unclosed nb_faces nb_edges nb_vertices
222 theIntegers->Append((int)anInfo.KindOfClosed());
224 theIntegers->Append(anInfo.NbSubShapes(TopAbs_FACE));
225 theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
226 theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
232 // (+) geompy.kind.WIRE geompy.info.closed nb_edges nb_vertices
233 // (+) geompy.kind.WIRE geompy.info.unclosed nb_edges nb_vertices
236 theIntegers->Append((int)anInfo.KindOfClosed());
238 theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
239 theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
247 GEOMAlgo_KindOfName aKN = anInfo.KindOfName();
250 case GEOMAlgo_KN_SPHERE:
251 // (+) geompy.kind.SPHERE xc yc zc R
255 gp_Pnt aC = anInfo.Location();
256 theDoubles->Append(aC.X());
257 theDoubles->Append(aC.Y());
258 theDoubles->Append(aC.Z());
260 theDoubles->Append(anInfo.Radius1());
263 case GEOMAlgo_KN_CYLINDER:
264 // (+) geompy.kind.CYLINDER xb yb zb dx dy dz R H
268 gp_Pnt aC = anInfo.Location();
269 theDoubles->Append(aC.X());
270 theDoubles->Append(aC.Y());
271 theDoubles->Append(aC.Z());
273 gp_Ax3 anAx3 = anInfo.Position();
274 gp_Dir aD = anAx3.Direction();
275 theDoubles->Append(aD.X());
276 theDoubles->Append(aD.Y());
277 theDoubles->Append(aD.Z());
279 theDoubles->Append(anInfo.Radius1());
280 theDoubles->Append(anInfo.Height());
283 case GEOMAlgo_KN_BOX:
284 // (+) geompy.kind.BOX xc yc zc ax ay az
288 gp_Pnt aC = anInfo.Location();
289 theDoubles->Append(aC.X());
290 theDoubles->Append(aC.Y());
291 theDoubles->Append(aC.Z());
293 gp_Ax3 anAx3 = anInfo.Position();
294 gp_Dir aD = anAx3.Direction();
295 gp_Dir aX = anAx3.XDirection();
298 if (aD.IsParallel(gp::DZ(), Precision::Angular()) &&
299 aX.IsParallel(gp::DX(), Precision::Angular())) {
300 theDoubles->Append(anInfo.Length()); // ax'
301 theDoubles->Append(anInfo.Width()); // ay'
302 theDoubles->Append(anInfo.Height()); // az'
304 else if (aD.IsParallel(gp::DZ(), Precision::Angular()) &&
305 aX.IsParallel(gp::DY(), Precision::Angular())) {
306 theDoubles->Append(anInfo.Width()); // ay'
307 theDoubles->Append(anInfo.Length()); // ax'
308 theDoubles->Append(anInfo.Height()); // az'
310 else if (aD.IsParallel(gp::DX(), Precision::Angular()) &&
311 aX.IsParallel(gp::DZ(), Precision::Angular())) {
312 theDoubles->Append(anInfo.Height()); // az'
313 theDoubles->Append(anInfo.Width()); // ay'
314 theDoubles->Append(anInfo.Length()); // ax'
316 else if (aD.IsParallel(gp::DX(), Precision::Angular()) &&
317 aX.IsParallel(gp::DY(), Precision::Angular())) {
318 theDoubles->Append(anInfo.Height()); // az'
319 theDoubles->Append(anInfo.Length()); // ax'
320 theDoubles->Append(anInfo.Width()); // ay'
322 else if (aD.IsParallel(gp::DY(), Precision::Angular()) &&
323 aX.IsParallel(gp::DZ(), Precision::Angular())) {
324 theDoubles->Append(anInfo.Width()); // ay'
325 theDoubles->Append(anInfo.Height()); // az'
326 theDoubles->Append(anInfo.Length()); // ax'
328 else if (aD.IsParallel(gp::DY(), Precision::Angular()) &&
329 aX.IsParallel(gp::DX(), Precision::Angular())) {
330 theDoubles->Append(anInfo.Length()); // ax'
331 theDoubles->Append(anInfo.Height()); // az'
332 theDoubles->Append(anInfo.Width()); // ay'
335 // (+) geompy.kind.ROTATED_BOX xo yo zo zx zy zz xx xy xz ax ay az
336 aKind = SK_ROTATED_BOX;
338 // Direction and XDirection
339 theDoubles->Append(aD.X());
340 theDoubles->Append(aD.Y());
341 theDoubles->Append(aD.Z());
343 theDoubles->Append(aX.X());
344 theDoubles->Append(aX.Y());
345 theDoubles->Append(aX.Z());
348 theDoubles->Append(anInfo.Length());
349 theDoubles->Append(anInfo.Width());
350 theDoubles->Append(anInfo.Height());
354 case GEOMAlgo_KN_TORUS:
355 // (+) geompy.kind.TORUS xc yc zc dx dy dz R_1 R_2
359 gp_Pnt aO = anInfo.Location();
360 theDoubles->Append(aO.X());
361 theDoubles->Append(aO.Y());
362 theDoubles->Append(aO.Z());
364 gp_Ax3 anAx3 = anInfo.Position();
365 gp_Dir aD = anAx3.Direction();
366 theDoubles->Append(aD.X());
367 theDoubles->Append(aD.Y());
368 theDoubles->Append(aD.Z());
370 theDoubles->Append(anInfo.Radius1());
371 theDoubles->Append(anInfo.Radius2());
374 case GEOMAlgo_KN_CONE:
375 // (+) geompy.kind.CONE xb yb zb dx dy dz R_1 R_2 H
379 gp_Pnt aO = anInfo.Location();
380 theDoubles->Append(aO.X());
381 theDoubles->Append(aO.Y());
382 theDoubles->Append(aO.Z());
384 gp_Ax3 anAx3 = anInfo.Position();
385 gp_Dir aD = anAx3.Direction();
386 theDoubles->Append(aD.X());
387 theDoubles->Append(aD.Y());
388 theDoubles->Append(aD.Z());
390 theDoubles->Append(anInfo.Radius1());
391 theDoubles->Append(anInfo.Radius2());
392 theDoubles->Append(anInfo.Height());
395 case GEOMAlgo_KN_POLYHEDRON:
396 // (+) geompy.kind.POLYHEDRON nb_faces nb_edges nb_vertices
398 aKind = SK_POLYHEDRON;
400 theIntegers->Append(anInfo.NbSubShapes(TopAbs_FACE));
401 theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
402 theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
406 // (+) geompy.kind.SOLID nb_faces nb_edges nb_vertices
408 theIntegers->Append(anInfo.NbSubShapes(TopAbs_FACE));
409 theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
410 theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
420 GEOMAlgo_KindOfName aKN = anInfo.KindOfName();
422 case GEOMAlgo_KN_SPHERE:
423 // (+) geompy.kind.SPHERE2D xc yc zc R
427 gp_Pnt aC = anInfo.Location();
428 theDoubles->Append(aC.X());
429 theDoubles->Append(aC.Y());
430 theDoubles->Append(aC.Z());
432 theDoubles->Append(anInfo.Radius1());
435 case GEOMAlgo_KN_CYLINDER:
436 // (+) geompy.kind.CYLINDER2D xb yb zb dx dy dz R H
438 aKind = SK_CYLINDER2D;
440 gp_Pnt aO = anInfo.Location();
441 theDoubles->Append(aO.X());
442 theDoubles->Append(aO.Y());
443 theDoubles->Append(aO.Z());
445 gp_Ax3 anAx3 = anInfo.Position();
446 gp_Dir aD = anAx3.Direction();
447 theDoubles->Append(aD.X());
448 theDoubles->Append(aD.Y());
449 theDoubles->Append(aD.Z());
451 theDoubles->Append(anInfo.Radius1());
452 theDoubles->Append(anInfo.Height());
455 case GEOMAlgo_KN_TORUS:
456 // (+) geompy.kind.TORUS2D xc yc zc dx dy dz R_1 R_2
460 gp_Pnt aO = anInfo.Location();
461 theDoubles->Append(aO.X());
462 theDoubles->Append(aO.Y());
463 theDoubles->Append(aO.Z());
465 gp_Ax3 anAx3 = anInfo.Position();
466 gp_Dir aD = anAx3.Direction();
467 theDoubles->Append(aD.X());
468 theDoubles->Append(aD.Y());
469 theDoubles->Append(aD.Z());
471 theDoubles->Append(anInfo.Radius1());
472 theDoubles->Append(anInfo.Radius2());
475 case GEOMAlgo_KN_CONE:
476 // (+) geompy.kind.CONE2D xc yc zc dx dy dz R_1 R_2 H
480 gp_Pnt aO = anInfo.Location();
481 theDoubles->Append(aO.X());
482 theDoubles->Append(aO.Y());
483 theDoubles->Append(aO.Z());
485 gp_Ax3 anAx3 = anInfo.Position();
486 gp_Dir aD = anAx3.Direction();
487 theDoubles->Append(aD.X());
488 theDoubles->Append(aD.Y());
489 theDoubles->Append(aD.Z());
491 theDoubles->Append(anInfo.Radius1());
492 theDoubles->Append(anInfo.Radius2());
493 theDoubles->Append(anInfo.Height());
496 case GEOMAlgo_KN_DISKCIRCLE:
497 // (+) geompy.kind.DISK_CIRCLE xc yc zc dx dy dz R
499 aKind = SK_DISK_CIRCLE;
501 gp_Pnt aC = anInfo.Location();
502 theDoubles->Append(aC.X());
503 theDoubles->Append(aC.Y());
504 theDoubles->Append(aC.Z());
506 gp_Ax3 anAx3 = anInfo.Position();
507 gp_Dir aD = anAx3.Direction();
508 theDoubles->Append(aD.X());
509 theDoubles->Append(aD.Y());
510 theDoubles->Append(aD.Z());
512 theDoubles->Append(anInfo.Radius1());
515 case GEOMAlgo_KN_DISKELLIPSE:
516 // (+) geompy.kind.DISK_ELLIPSE xc yc zc dx dy dz R_1 R_2
518 aKind = SK_DISK_ELLIPSE;
520 gp_Pnt aC = anInfo.Location();
521 theDoubles->Append(aC.X());
522 theDoubles->Append(aC.Y());
523 theDoubles->Append(aC.Z());
525 gp_Ax3 anAx3 = anInfo.Position();
526 gp_Dir aD = anAx3.Direction();
527 theDoubles->Append(aD.X());
528 theDoubles->Append(aD.Y());
529 theDoubles->Append(aD.Z());
531 theDoubles->Append(anInfo.Radius1());
532 theDoubles->Append(anInfo.Radius2());
535 case GEOMAlgo_KN_RECTANGLE:
536 case GEOMAlgo_KN_TRIANGLE:
537 case GEOMAlgo_KN_QUADRANGLE:
538 case GEOMAlgo_KN_POLYGON:
539 // (+) geompy.kind.POLYGON xo yo zo dx dy dz nb_edges nb_vertices
543 gp_Pnt aO = anInfo.Location();
544 theDoubles->Append(aO.X());
545 theDoubles->Append(aO.Y());
546 theDoubles->Append(aO.Z());
548 gp_Ax3 anAx3 = anInfo.Position();
549 gp_Dir aD = anAx3.Direction();
550 theDoubles->Append(aD.X());
551 theDoubles->Append(aD.Y());
552 theDoubles->Append(aD.Z());
554 theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
555 theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
558 case GEOMAlgo_KN_PLANE: // infinite
559 // (+) geompy.kind.PLANE xo yo zo dx dy dz
563 gp_Pnt aC = anInfo.Location();
564 theDoubles->Append(aC.X());
565 theDoubles->Append(aC.Y());
566 theDoubles->Append(aC.Z());
568 gp_Ax3 anAx3 = anInfo.Position();
569 gp_Dir aD = anAx3.Direction();
570 theDoubles->Append(aD.X());
571 theDoubles->Append(aD.Y());
572 theDoubles->Append(aD.Z());
574 if (anInfo.KindOfBounds() != GEOMAlgo_KB_INFINITE)
576 // (+) geompy.kind.PLANAR xo yo zo dx dy dz nb_edges nb_vertices
579 theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
580 theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
585 // ??? geompy.kind.FACE nb_edges nb_vertices _surface_type_id_
586 // (+) geompy.kind.FACE nb_edges nb_vertices
587 theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
588 theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
597 GEOMAlgo_KindOfName aKN = anInfo.KindOfName();
599 case GEOMAlgo_KN_CIRCLE:
601 // (+) geompy.kind.CIRCLE xc yc zc dx dy dz R
604 gp_Pnt aC = anInfo.Location();
605 theDoubles->Append(aC.X());
606 theDoubles->Append(aC.Y());
607 theDoubles->Append(aC.Z());
609 gp_Ax3 anAx3 = anInfo.Position();
610 gp_Dir aD = anAx3.Direction();
611 theDoubles->Append(aD.X());
612 theDoubles->Append(aD.Y());
613 theDoubles->Append(aD.Z());
615 theDoubles->Append(anInfo.Radius1());
618 case GEOMAlgo_KN_ARCCIRCLE:
620 // (+) geompy.kind.ARC_CIRCLE xc yc zc dx dy dz R x1 y1 z1 x2 y2 z2
621 aKind = SK_ARC_CIRCLE;
623 gp_Pnt aC = anInfo.Location();
624 theDoubles->Append(aC.X());
625 theDoubles->Append(aC.Y());
626 theDoubles->Append(aC.Z());
628 gp_Ax3 anAx3 = anInfo.Position();
629 gp_Dir aD = anAx3.Direction();
630 theDoubles->Append(aD.X());
631 theDoubles->Append(aD.Y());
632 theDoubles->Append(aD.Z());
634 theDoubles->Append(anInfo.Radius1());
636 gp_Pnt aP1 = anInfo.Pnt1();
637 theDoubles->Append(aP1.X());
638 theDoubles->Append(aP1.Y());
639 theDoubles->Append(aP1.Z());
641 gp_Pnt aP2 = anInfo.Pnt2();
642 theDoubles->Append(aP2.X());
643 theDoubles->Append(aP2.Y());
644 theDoubles->Append(aP2.Z());
647 case GEOMAlgo_KN_ELLIPSE:
649 // (+) geompy.kind.ELLIPSE xc yc zc dx dy dz R_1 R_2
652 gp_Pnt aC = anInfo.Location();
653 theDoubles->Append(aC.X());
654 theDoubles->Append(aC.Y());
655 theDoubles->Append(aC.Z());
657 gp_Ax3 anAx3 = anInfo.Position();
658 gp_Dir aD = anAx3.Direction();
659 theDoubles->Append(aD.X());
660 theDoubles->Append(aD.Y());
661 theDoubles->Append(aD.Z());
663 theDoubles->Append(anInfo.Radius1());
664 theDoubles->Append(anInfo.Radius2());
667 case GEOMAlgo_KN_ARCELLIPSE:
669 // (+) geompy.kind.ARC_ELLIPSE xc yc zc dx dy dz R_1 R_2 x1 y1 z1 x2 y2 z2
670 aKind = SK_ARC_ELLIPSE;
672 gp_Pnt aC = anInfo.Location();
673 theDoubles->Append(aC.X());
674 theDoubles->Append(aC.Y());
675 theDoubles->Append(aC.Z());
677 gp_Ax3 anAx3 = anInfo.Position();
678 gp_Dir aD = anAx3.Direction();
679 theDoubles->Append(aD.X());
680 theDoubles->Append(aD.Y());
681 theDoubles->Append(aD.Z());
683 theDoubles->Append(anInfo.Radius1());
684 theDoubles->Append(anInfo.Radius2());
686 gp_Pnt aP1 = anInfo.Pnt1();
687 theDoubles->Append(aP1.X());
688 theDoubles->Append(aP1.Y());
689 theDoubles->Append(aP1.Z());
691 gp_Pnt aP2 = anInfo.Pnt2();
692 theDoubles->Append(aP2.X());
693 theDoubles->Append(aP2.Y());
694 theDoubles->Append(aP2.Z());
697 case GEOMAlgo_KN_LINE:
699 // ??? geompy.kind.LINE x1 y1 z1 x2 y2 z2
700 // (+) geompy.kind.LINE x1 y1 z1 dx dy dz
703 gp_Pnt aO = anInfo.Location();
704 theDoubles->Append(aO.X());
705 theDoubles->Append(aO.Y());
706 theDoubles->Append(aO.Z());
708 gp_Dir aD = anInfo.Direction();
709 theDoubles->Append(aD.X());
710 theDoubles->Append(aD.Y());
711 theDoubles->Append(aD.Z());
714 case GEOMAlgo_KN_SEGMENT:
716 // (+) geompy.kind.SEGMENT x1 y1 z1 x2 y2 z2
719 gp_Pnt aP1 = anInfo.Pnt1();
720 theDoubles->Append(aP1.X());
721 theDoubles->Append(aP1.Y());
722 theDoubles->Append(aP1.Z());
724 gp_Pnt aP2 = anInfo.Pnt2();
725 theDoubles->Append(aP2.X());
726 theDoubles->Append(aP2.Y());
727 theDoubles->Append(aP2.Z());
731 // ??? geompy.kind.EDGE nb_vertices _curve_type_id_
732 // (+) geompy.kind.EDGE nb_vertices
733 theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
740 // (+) geompy.kind.VERTEX x y z
743 gp_Pnt aP = anInfo.Location();
744 theDoubles->Append(aP.X());
745 theDoubles->Append(aP.Y());
746 theDoubles->Append(aP.Z());
756 //=============================================================================
760 //=============================================================================
761 void GEOMImpl_IMeasureOperations::GetPosition
762 (Handle(GEOM_Object) theShape,
763 Standard_Real& Ox, Standard_Real& Oy, Standard_Real& Oz,
764 Standard_Real& Zx, Standard_Real& Zy, Standard_Real& Zz,
765 Standard_Real& Xx, Standard_Real& Xy, Standard_Real& Xz)
769 //Set default values: global CS
770 Ox = Oy = Oz = Zx = Zy = Xy = Xz = 0.;
773 if (theShape.IsNull()) return;
775 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
776 if (aRefShape.IsNull()) return;
778 TopoDS_Shape aShape = aRefShape->GetValue();
779 if (aShape.IsNull()) {
780 SetErrorCode("The Objects has NULL Shape");
787 gp_Ax3 anAx3 = GEOMUtils::GetPosition(aShape);
789 gp_Pnt anOri = anAx3.Location();
790 gp_Dir aDirZ = anAx3.Direction();
791 gp_Dir aDirX = anAx3.XDirection();
794 anOri.Coord(Ox, Oy, Oz);
795 aDirZ.Coord(Zx, Zy, Zz);
796 aDirX.Coord(Xx, Xy, Xz);
798 catch (Standard_Failure& aFail) {
799 SetErrorCode(aFail.GetMessageString());
806 //=============================================================================
810 //=============================================================================
811 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetCentreOfMass
812 (Handle(GEOM_Object) theShape)
816 if (theShape.IsNull()) return NULL;
818 //Add a new CentreOfMass object
819 Handle(GEOM_Object) aCDG = GetEngine()->AddObject(GEOM_CDG);
821 //Add a new CentreOfMass function
822 Handle(GEOM_Function) aFunction =
823 aCDG->AddFunction(GEOMImpl_MeasureDriver::GetID(), CDG_MEASURE);
824 if (aFunction.IsNull()) return NULL;
826 //Check if the function is set correctly
827 if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
829 GEOMImpl_IMeasure aCI (aFunction);
831 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
832 if (aRefShape.IsNull()) return NULL;
834 aCI.SetBase(aRefShape);
836 //Compute the CentreOfMass value
839 if (!GetSolver()->ComputeFunction(aFunction)) {
840 SetErrorCode("Measure driver failed to compute centre of mass");
844 catch (Standard_Failure& aFail) {
845 SetErrorCode(aFail.GetMessageString());
849 //Make a Python command
850 GEOM::TPythonDump(aFunction) << aCDG << " = geompy.MakeCDG(" << theShape << ")";
856 //=============================================================================
860 //=============================================================================
861 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetVertexByIndex
862 (Handle(GEOM_Object) theShape,
863 Standard_Integer theIndex,
864 Standard_Boolean theUseOri)
868 if (theShape.IsNull()) return NULL;
870 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
871 if (aRefShape.IsNull()) return NULL;
873 //Add a new Vertex object
874 Handle(GEOM_Object) aVertex = GetEngine()->AddObject(GEOM_POINT);
877 Handle(GEOM_Function) aFunction =
878 aVertex->AddFunction(GEOMImpl_MeasureDriver::GetID(), VERTEX_BY_INDEX);
879 if (aFunction.IsNull()) return NULL;
881 //Check if the function is set correctly
882 if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
884 GEOMImpl_IMeasure aCI (aFunction);
885 aCI.SetBase(aRefShape);
886 aCI.SetIndex(theIndex);
887 aCI.SetUseOri(theUseOri);
892 if (!GetSolver()->ComputeFunction(aFunction)) {
893 SetErrorCode("Vertex by index driver failed.");
897 catch (Standard_Failure& aFail) {
898 SetErrorCode(aFail.GetMessageString());
902 //Make a Python command
903 GEOM::TPythonDump(aFunction) << aVertex << " = geompy.GetVertexByIndex("
912 //=============================================================================
916 //=============================================================================
917 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetNormal
918 (Handle(GEOM_Object) theFace,
919 Handle(GEOM_Object) theOptionalPoint)
923 if (theFace.IsNull()) return NULL;
925 //Add a new Normale object
926 Handle(GEOM_Object) aNorm = GetEngine()->AddObject(GEOM_VECTOR);
928 //Add a new Normale function
929 Handle(GEOM_Function) aFunction =
930 aNorm->AddFunction(GEOMImpl_MeasureDriver::GetID(), VECTOR_FACE_NORMALE);
931 if (aFunction.IsNull()) return NULL;
933 //Check if the function is set correctly
934 if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
936 GEOMImpl_IMeasure aCI (aFunction);
938 Handle(GEOM_Function) aFace = theFace->GetLastFunction();
939 if (aFace.IsNull()) return NULL;
943 if (!theOptionalPoint.IsNull()) {
944 Handle(GEOM_Function) anOptPnt = theOptionalPoint->GetLastFunction();
945 aCI.SetPoint(anOptPnt);
948 //Compute the Normale value
951 if (!GetSolver()->ComputeFunction(aFunction)) {
952 SetErrorCode("Measure driver failed to compute normake of face");
956 catch (Standard_Failure& aFail) {
957 SetErrorCode(aFail.GetMessageString());
961 //Make a Python command
962 GEOM::TPythonDump pd (aFunction);
963 pd << aNorm << " = geompy.GetNormal(" << theFace;
964 if (!theOptionalPoint.IsNull()) {
965 pd << ", " << theOptionalPoint;
973 //=============================================================================
977 //=============================================================================
978 void GEOMImpl_IMeasureOperations::GetBasicProperties (Handle(GEOM_Object) theShape,
979 const Standard_Real theTolerance,
980 Standard_Real& theLength,
981 Standard_Real& theSurfArea,
982 Standard_Real& theVolume)
986 if (theShape.IsNull()) return;
988 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
989 if (aRefShape.IsNull()) return;
991 TopoDS_Shape aShape = aRefShape->GetValue();
992 if (aShape.IsNull()) {
993 SetErrorCode("The Objects has NULL Shape");
997 //Compute the parameters
998 GProp_GProps LProps, SProps;
999 Standard_Real anEps = theTolerance >= 0 ? theTolerance : 1.e-6;
1002 BRepGProp::LinearProperties(aShape, LProps, Standard_True);
1003 theLength = LProps.Mass();
1005 BRepGProp::SurfaceProperties(aShape, SProps, anEps, Standard_True);
1006 theSurfArea = SProps.Mass();
1009 if (aShape.ShapeType() < TopAbs_SHELL) {
1010 for (TopExp_Explorer Exp (aShape, TopAbs_SOLID); Exp.More(); Exp.Next()) {
1011 GProp_GProps VProps;
1012 BRepGProp::VolumeProperties(Exp.Current(), VProps, anEps, Standard_True);
1013 theVolume += VProps.Mass();
1017 catch (Standard_Failure& aFail) {
1018 SetErrorCode(aFail.GetMessageString());
1025 //=============================================================================
1029 //=============================================================================
1030 void GEOMImpl_IMeasureOperations::GetInertia
1031 (Handle(GEOM_Object) theShape,
1032 Standard_Real& I11, Standard_Real& I12, Standard_Real& I13,
1033 Standard_Real& I21, Standard_Real& I22, Standard_Real& I23,
1034 Standard_Real& I31, Standard_Real& I32, Standard_Real& I33,
1035 Standard_Real& Ix , Standard_Real& Iy , Standard_Real& Iz)
1039 if (theShape.IsNull()) return;
1041 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1042 if (aRefShape.IsNull()) return;
1044 TopoDS_Shape aShape = aRefShape->GetValue();
1045 if (aShape.IsNull()) {
1046 SetErrorCode("The Objects has NULL Shape");
1050 //Compute the parameters
1051 GProp_GProps System;
1055 if (aShape.ShapeType() == TopAbs_VERTEX ||
1056 aShape.ShapeType() == TopAbs_EDGE ||
1057 aShape.ShapeType() == TopAbs_WIRE) {
1058 BRepGProp::LinearProperties(aShape, System, Standard_True);
1059 } else if (aShape.ShapeType() == TopAbs_FACE ||
1060 aShape.ShapeType() == TopAbs_SHELL) {
1061 BRepGProp::SurfaceProperties(aShape, System, Standard_True);
1063 BRepGProp::VolumeProperties(aShape, System, Standard_True);
1065 gp_Mat I = System.MatrixOfInertia();
1079 GProp_PrincipalProps Pr = System.PrincipalProperties();
1080 Pr.Moments(Ix,Iy,Iz);
1082 catch (Standard_Failure& aFail) {
1083 SetErrorCode(aFail.GetMessageString());
1090 //=============================================================================
1094 //=============================================================================
1095 void GEOMImpl_IMeasureOperations::GetBoundingBox
1096 (Handle(GEOM_Object) theShape,
1097 const Standard_Boolean precise,
1098 Standard_Real& Xmin, Standard_Real& Xmax,
1099 Standard_Real& Ymin, Standard_Real& Ymax,
1100 Standard_Real& Zmin, Standard_Real& Zmax)
1104 if (theShape.IsNull()) return;
1106 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1107 if (aRefShape.IsNull()) return;
1109 TopoDS_Shape aShape = aRefShape->GetValue();
1110 if (aShape.IsNull()) {
1111 SetErrorCode("The Objects has NULL Shape");
1115 //Compute the parameters
1120 BRepBuilderAPI_Copy aCopyTool (aShape);
1121 if (!aCopyTool.IsDone()) {
1122 SetErrorCode("GetBoundingBox Error: Bad shape detected");
1126 aShape = aCopyTool.Shape();
1128 // remove triangulation to obtain more exact boundaries
1129 BRepTools::Clean(aShape);
1131 BRepBndLib::Add(aShape, B);
1134 if (!GEOMUtils::PreciseBoundingBox(aShape, B)) {
1135 SetErrorCode("GetBoundingBox Error: Bounding box cannot be precised");
1140 B.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
1142 catch (Standard_Failure& aFail) {
1143 SetErrorCode(aFail.GetMessageString());
1150 //=============================================================================
1154 //=============================================================================
1155 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetBoundingBox
1156 (Handle(GEOM_Object) theShape,
1157 const Standard_Boolean precise)
1161 if (theShape.IsNull()) return NULL;
1163 //Add a new BoundingBox object
1164 Handle(GEOM_Object) aBnd = GetEngine()->AddObject(GEOM_BOX);
1166 //Add a new BoundingBox function
1167 const int aType = (precise ? BND_BOX_MEASURE_PRECISE : BND_BOX_MEASURE);
1168 Handle(GEOM_Function) aFunction =
1169 aBnd->AddFunction(GEOMImpl_MeasureDriver::GetID(), aType);
1170 if (aFunction.IsNull()) return NULL;
1172 //Check if the function is set correctly
1173 if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
1175 GEOMImpl_IMeasure aCI (aFunction);
1177 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1178 if (aRefShape.IsNull()) return NULL;
1180 aCI.SetBase(aRefShape);
1182 //Compute the BoundingBox value
1185 if (!GetSolver()->ComputeFunction(aFunction)) {
1186 SetErrorCode("Measure driver failed to compute a bounding box");
1190 catch (Standard_Failure& aFail) {
1191 SetErrorCode(aFail.GetMessageString());
1195 //Make a Python command
1196 GEOM::TPythonDump aPd(aFunction);
1198 aPd << aBnd << " = geompy.MakeBoundingBox(" << theShape;
1210 //=============================================================================
1214 //=============================================================================
1215 void GEOMImpl_IMeasureOperations::GetTolerance
1216 (Handle(GEOM_Object) theShape,
1217 Standard_Real& FaceMin, Standard_Real& FaceMax,
1218 Standard_Real& EdgeMin, Standard_Real& EdgeMax,
1219 Standard_Real& VertMin, Standard_Real& VertMax)
1223 if (theShape.IsNull()) return;
1225 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1226 if (aRefShape.IsNull()) return;
1228 TopoDS_Shape aShape = aRefShape->GetValue();
1229 if (aShape.IsNull()) {
1230 SetErrorCode("The Objects has NULL Shape");
1234 //Compute the parameters
1236 FaceMin = EdgeMin = VertMin = RealLast();
1237 FaceMax = EdgeMax = VertMax = -RealLast();
1241 for (TopExp_Explorer ExF (aShape, TopAbs_FACE); ExF.More(); ExF.Next()) {
1242 TopoDS_Face Face = TopoDS::Face(ExF.Current());
1243 T = BRep_Tool::Tolerance(Face);
1249 for (TopExp_Explorer ExE (aShape, TopAbs_EDGE); ExE.More(); ExE.Next()) {
1250 TopoDS_Edge Edge = TopoDS::Edge(ExE.Current());
1251 T = BRep_Tool::Tolerance(Edge);
1257 for (TopExp_Explorer ExV (aShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
1258 TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current());
1259 T = BRep_Tool::Tolerance(Vertex);
1266 catch (Standard_Failure& aFail) {
1267 SetErrorCode(aFail.GetMessageString());
1274 //=============================================================================
1278 //=============================================================================
1279 bool GEOMImpl_IMeasureOperations::CheckShape (Handle(GEOM_Object) theShape,
1280 const Standard_Boolean theIsCheckGeom,
1281 std::list<ShapeError> &theErrors)
1286 if (theShape.IsNull()) return false;
1288 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1289 if (aRefShape.IsNull()) return false;
1291 TopoDS_Shape aShape = aRefShape->GetValue();
1292 if (aShape.IsNull()) {
1293 SetErrorCode("The Objects has NULL Shape");
1297 //Compute the parameters
1298 bool isValid = false;
1301 BRepCheck_Analyzer ana (aShape, theIsCheckGeom);
1302 if (ana.IsValid()) {
1305 FillErrors(ana, aShape, theErrors);
1308 catch (Standard_Failure& aFail) {
1309 SetErrorCode(aFail.GetMessageString());
1317 //=============================================================================
1321 //=============================================================================
1322 TCollection_AsciiString GEOMImpl_IMeasureOperations::PrintShapeErrors
1323 (Handle(GEOM_Object) theShape,
1324 const std::list<ShapeError> &theErrors)
1326 TCollection_AsciiString aDump;
1328 if (theShape.IsNull()) {
1332 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1334 if (aRefShape.IsNull()) {
1338 TopoDS_Shape aShape = aRefShape->GetValue();
1340 if (aShape.IsNull()) {
1341 SetErrorCode("The Objects has NULL Shape");
1345 if (!theErrors.empty()) {
1346 // The shape is not valid. Prepare errors for dump.
1347 TopTools_IndexedMapOfShape anIndices;
1348 std::list<ShapeError>::const_iterator anIter = theErrors.begin();
1349 Standard_Integer nbv, nbe, nbw, nbf, nbs, nbo;
1350 nbv = nbe = nbw = nbf = nbs = nbo = 0;
1352 // Map sub-shapes and their indices
1353 TopExp::MapShapes(aShape, anIndices);
1355 const Standard_Integer aNbSubShapes = anIndices.Extent();
1356 TColStd_MapOfInteger aMapPbInd;
1358 aDump += " -- The Shape has problems :\n";
1359 aDump += " Check Count\n";
1360 aDump += " ------------------------------------------------\n";
1362 for (; anIter != theErrors.end(); anIter++) {
1363 Standard_Integer aNbShapes = anIter->incriminated.size();
1365 switch(anIter->error) {
1366 case BRepCheck_InvalidPointOnCurve:
1367 aDump += " Invalid Point on Curve ................... ";
1369 case BRepCheck_InvalidPointOnCurveOnSurface:
1370 aDump += " Invalid Point on CurveOnSurface .......... ";
1372 case BRepCheck_InvalidPointOnSurface:
1373 aDump += " Invalid Point on Surface ................. ";
1375 case BRepCheck_No3DCurve:
1376 aDump += " No 3D Curve .............................. ";
1378 case BRepCheck_Multiple3DCurve:
1379 aDump += " Multiple 3D Curve ........................ ";
1381 case BRepCheck_Invalid3DCurve:
1382 aDump += " Invalid 3D Curve ......................... ";
1384 case BRepCheck_NoCurveOnSurface:
1385 aDump += " No Curve on Surface ...................... ";
1387 case BRepCheck_InvalidCurveOnSurface:
1388 aDump += " Invalid Curve on Surface ................. ";
1390 case BRepCheck_InvalidCurveOnClosedSurface:
1391 aDump += " Invalid Curve on closed Surface .......... ";
1393 case BRepCheck_InvalidSameRangeFlag:
1394 aDump += " Invalid SameRange Flag ................... ";
1396 case BRepCheck_InvalidSameParameterFlag:
1397 aDump += " Invalid SameParameter Flag ............... ";
1399 case BRepCheck_InvalidDegeneratedFlag:
1400 aDump += " Invalid Degenerated Flag ................. ";
1402 case BRepCheck_FreeEdge:
1403 aDump += " Free Edge ................................ ";
1405 case BRepCheck_InvalidMultiConnexity:
1406 aDump += " Invalid MultiConnexity ................... ";
1408 case BRepCheck_InvalidRange:
1409 aDump += " Invalid Range ............................ ";
1411 case BRepCheck_EmptyWire:
1412 aDump += " Empty Wire ............................... ";
1414 case BRepCheck_RedundantEdge:
1415 aDump += " Redundant Edge ........................... ";
1417 case BRepCheck_SelfIntersectingWire:
1418 aDump += " Self Intersecting Wire ................... ";
1420 case BRepCheck_NoSurface:
1421 aDump += " No Surface ............................... ";
1423 case BRepCheck_InvalidWire:
1424 aDump += " Invalid Wire ............................. ";
1426 case BRepCheck_RedundantWire:
1427 aDump += " Redundant Wire ........................... ";
1429 case BRepCheck_IntersectingWires:
1430 aDump += " Intersecting Wires ....................... ";
1432 case BRepCheck_InvalidImbricationOfWires:
1433 aDump += " Invalid Imbrication of Wires ............. ";
1435 case BRepCheck_EmptyShell:
1436 aDump += " Empty Shell .............................. ";
1438 case BRepCheck_RedundantFace:
1439 aDump += " Redundant Face ........................... ";
1441 case BRepCheck_UnorientableShape:
1442 aDump += " Unorientable Shape ....................... ";
1444 case BRepCheck_NotClosed:
1445 aDump += " Not Closed ............................... ";
1447 case BRepCheck_NotConnected:
1448 aDump += " Not Connected ............................ ";
1450 case BRepCheck_SubshapeNotInShape:
1451 aDump += " Sub-shape not in Shape ................... ";
1453 case BRepCheck_BadOrientation:
1454 aDump += " Bad Orientation .......................... ";
1456 case BRepCheck_BadOrientationOfSubshape:
1457 aDump += " Bad Orientation of Sub-shape ............. ";
1459 case BRepCheck_InvalidToleranceValue:
1460 aDump += " Invalid Tolerance Value .................. ";
1462 case BRepCheck_CheckFail:
1463 aDump += " Check Shape Failure ...................... ";
1469 aDump += TCollection_AsciiString(aNbShapes) + "\n";
1471 // Count types of shape.
1472 std::list<int>::const_iterator aShIter = anIter->incriminated.begin();
1474 for (; aShIter != anIter->incriminated.end(); aShIter++) {
1475 const Standard_Integer anIndex = *aShIter;
1477 if (anIndex > 0 && anIndex <= aNbSubShapes && aMapPbInd.Add(anIndex)) {
1478 const TopoDS_Shape &aSubShape = anIndices.FindKey(anIndex);
1479 const TopAbs_ShapeEnum aType = aSubShape.ShapeType();
1482 case TopAbs_VERTEX : nbv++; break;
1483 case TopAbs_EDGE : nbe++; break;
1484 case TopAbs_WIRE : nbw++; break;
1485 case TopAbs_FACE : nbf++; break;
1486 case TopAbs_SHELL : nbs++; break;
1487 case TopAbs_SOLID : nbo++; break;
1494 const Standard_Integer aNbFaultyShapes = nbv + nbe + nbw + nbf + nbs + nbo;
1495 aDump += " ------------------------------------------------\n";
1496 aDump += "*** Shapes with problems : ";
1497 aDump += TCollection_AsciiString(aNbFaultyShapes) + "\n";
1500 aDump += "VERTEX : ";
1501 if (nbv < 10) aDump += " ";
1502 aDump += TCollection_AsciiString(nbv) + "\n";
1506 if (nbe < 10) aDump += " ";
1507 aDump += TCollection_AsciiString(nbe) + "\n";
1511 if (nbw < 10) aDump += " ";
1512 aDump += TCollection_AsciiString(nbw) + "\n";
1516 if (nbf < 10) aDump += " ";
1517 aDump += TCollection_AsciiString(nbf) + "\n";
1520 aDump += "SHELL : ";
1521 if (nbs < 10) aDump += " ";
1522 aDump += TCollection_AsciiString(nbs) + "\n";
1525 aDump += "SOLID : ";
1526 if (nbo < 10) aDump += " ";
1527 aDump += TCollection_AsciiString(nbo) + "\n";
1534 //=============================================================================
1536 * CheckSelfIntersections
1538 //=============================================================================
1539 bool GEOMImpl_IMeasureOperations::CheckSelfIntersections
1540 (Handle(GEOM_Object) theShape,
1541 const SICheckLevel theCheckLevel,
1542 Handle(TColStd_HSequenceOfInteger)& theIntersections)
1546 if (theIntersections.IsNull())
1547 theIntersections = new TColStd_HSequenceOfInteger;
1549 theIntersections->Clear();
1551 if (theShape.IsNull())
1554 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1555 if (aRefShape.IsNull()) return false;
1557 TopoDS_Shape aShape = aRefShape->GetValue();
1558 if (aShape.IsNull()) return false;
1561 TopoDS_Shape aScopy;
1563 GEOMAlgo_AlgoTools::CopyShape(aShape, aScopy);
1565 // Map sub-shapes and their indices
1566 TopTools_IndexedMapOfShape anIndices;
1567 TopExp::MapShapes(aScopy, anIndices);
1569 TopTools_ListOfShape aLCS;
1570 aLCS.Append(aScopy);
1572 BOPAlgo_CheckerSI aCSI; // checker of self-interferences
1573 aCSI.SetArguments(aLCS);
1574 aCSI.SetLevelOfCheck(theCheckLevel);
1576 // 1. Launch the checker
1578 Standard_Boolean iErr = aCSI.HasErrors();
1581 Standard_Integer aNbS, n1, n2;
1582 BOPDS_MapIteratorOfMapOfPair aItMPK;
1584 // 2. Take the shapes from DS
1585 const BOPDS_DS& aDS = aCSI.DS();
1586 aNbS=aDS.NbShapes();
1588 // 3. Get the pairs of interfered shapes
1589 const BOPDS_MapOfPair& aMPK=aDS.Interferences();
1590 aItMPK.Initialize(aMPK);
1591 for (; aItMPK.More(); aItMPK.Next()) {
1592 const BOPDS_Pair& aPK=aItMPK.Value();
1593 aPK.Indices(n1, n2);
1595 if (n1 > aNbS || n2 > aNbS){
1596 return false; // Error
1598 const TopoDS_Shape& aS1 = aDS.Shape(n1);
1599 const TopoDS_Shape& aS2 = aDS.Shape(n2);
1601 theIntersections->Append(anIndices.FindIndex(aS1));
1602 theIntersections->Append(anIndices.FindIndex(aS2));
1609 return theIntersections->IsEmpty();
1612 //=============================================================================
1614 * CheckSelfIntersectionsFast
1616 //=============================================================================
1617 bool GEOMImpl_IMeasureOperations::CheckSelfIntersectionsFast
1618 (Handle(GEOM_Object) theShape,
1619 float theDeflection, double theTolerance,
1620 Handle(TColStd_HSequenceOfInteger)& theIntersections)
1624 if (theIntersections.IsNull())
1625 theIntersections = new TColStd_HSequenceOfInteger;
1627 theIntersections->Clear();
1629 if (theShape.IsNull())
1632 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1633 if (aRefShape.IsNull()) return false;
1635 TopoDS_Shape aShape = aRefShape->GetValue();
1636 if (aShape.IsNull()) return false;
1639 TopoDS_Shape aScopy;
1641 GEOMAlgo_AlgoTools::CopyShape(aShape, aScopy);
1642 GEOMUtils::MeshShape(aScopy, theDeflection);
1644 // Map sub-shapes and their indices
1645 TopTools_IndexedMapOfShape anIndices;
1646 TopExp::MapShapes(aScopy, anIndices);
1648 // Checker of fast interferences
1649 BRepExtrema_SelfIntersection aTool(aScopy, (theTolerance <= 0.) ? 0.0 : theTolerance);
1651 // Launch the checker
1654 const BRepExtrema_MapOfIntegerPackedMapOfInteger& intersections = aTool.OverlapElements();
1656 std::set<Standard_Integer> processed;
1658 for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator it(intersections); it.More(); it.Next()) {
1659 Standard_Integer idxLeft = it.Key();
1660 if (processed.count(idxLeft) > 0) continue; // already added
1661 processed.insert(idxLeft);
1662 const TColStd_PackedMapOfInteger& overlaps = it.Value();
1663 for (TColStd_MapIteratorOfPackedMapOfInteger subit(overlaps); subit.More(); subit.Next()) {
1664 Standard_Integer idxRight = subit.Key();
1665 if (processed.count(idxRight) > 0) continue; // already added
1666 const TopoDS_Shape& aS1 = aTool.GetSubShape(idxLeft);
1667 const TopoDS_Shape& aS2 = aTool.GetSubShape(idxRight);
1668 theIntersections->Append(anIndices.FindIndex(aS1));
1669 theIntersections->Append(anIndices.FindIndex(aS2));
1676 return theIntersections->IsEmpty();
1679 //=============================================================================
1683 //=============================================================================
1684 bool GEOMImpl_IMeasureOperations::CheckBOPArguments
1685 (const Handle(GEOM_Object) &theShape)
1689 if (theShape.IsNull()) {
1693 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1695 if (aRefShape.IsNull()) {
1699 TopoDS_Shape aShape = aRefShape->GetValue();
1701 if (aShape.IsNull()) {
1705 //Compute the parameters
1706 bool isValid = GEOMUtils::CheckBOPArguments(aShape);
1713 //=============================================================================
1717 //=============================================================================
1718 bool GEOMImpl_IMeasureOperations::FastIntersect (Handle(GEOM_Object) theShape1, Handle(GEOM_Object) theShape2,
1719 double theTolerance, float theDeflection,
1720 Handle(TColStd_HSequenceOfInteger)& theIntersections1,
1721 Handle(TColStd_HSequenceOfInteger)& theIntersections2)
1724 bool isGood = false;
1726 if (theIntersections1.IsNull())
1727 theIntersections1 = new TColStd_HSequenceOfInteger;
1729 theIntersections1->Clear();
1731 if (theIntersections2.IsNull())
1732 theIntersections2 = new TColStd_HSequenceOfInteger;
1734 theIntersections2->Clear();
1736 if (theShape1.IsNull() || theShape2.IsNull()) {
1737 SetErrorCode("Objects have NULL Shape");
1741 if (theShape1 == theShape2) {
1742 SetErrorCode("Objects are equal");
1745 Handle(GEOM_Function) aRefShape1 = theShape1->GetLastFunction();
1746 Handle(GEOM_Function) aRefShape2 = theShape2->GetLastFunction();
1747 if (aRefShape1.IsNull() || aRefShape2.IsNull()) return isGood;
1749 TopoDS_Shape aShape1 = aRefShape1->GetValue();
1750 TopoDS_Shape aShape2 = aRefShape2->GetValue();
1751 if (aShape1.IsNull() || aShape2.IsNull()) return isGood;
1754 TopoDS_Shape aScopy1, aScopy2;
1755 GEOMAlgo_AlgoTools::CopyShape(aShape1, aScopy1);
1756 GEOMAlgo_AlgoTools::CopyShape(aShape2, aScopy2);
1758 GEOMUtils::MeshShape(aScopy1, theDeflection);
1759 GEOMUtils::MeshShape(aScopy2, theDeflection);
1761 // Map sub-shapes and their indices
1762 TopTools_IndexedMapOfShape anIndices1, anIndices2;
1763 TopExp::MapShapes(aScopy1, anIndices1);
1764 TopExp::MapShapes(aScopy2, anIndices2);
1766 TopTools_ListOfShape aLCS1, aLCS2;
1767 aLCS1.Append(aScopy1); aLCS2.Append(aScopy2);
1769 BRepExtrema_ShapeProximity aBSP; // checker of fast interferences
1770 aBSP.LoadShape1(aScopy1); aBSP.LoadShape2(aScopy2);
1771 aBSP.SetTolerance((theTolerance <= 0.) ? 0.0 : theTolerance);
1773 // 1. Launch the checker
1776 // 2. Get sets of IDs of overlapped faces
1777 for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt1 (aBSP.OverlapSubShapes1()); anIt1.More(); anIt1.Next())
1779 const TopoDS_Shape& aS1 = aBSP.GetSubShape1(anIt1.Key());
1780 theIntersections1->Append(anIndices1.FindIndex(aS1));
1783 for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt2 (aBSP.OverlapSubShapes2()); anIt2.More(); anIt2.Next())
1785 const TopoDS_Shape& aS2 = aBSP.GetSubShape2(anIt2.Key());
1786 theIntersections2->Append(anIndices2.FindIndex(aS2));
1789 isGood = !theIntersections1->IsEmpty() && !theIntersections1->IsEmpty();
1797 //=============================================================================
1801 //=============================================================================
1802 TCollection_AsciiString GEOMImpl_IMeasureOperations::IsGoodForSolid (Handle(GEOM_Object) theShape)
1806 TCollection_AsciiString aRes = "";
1808 if (theShape.IsNull()) {
1809 aRes = "WRN_NULL_OBJECT_OR_SHAPE";
1812 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1813 if (aRefShape.IsNull()) {
1814 aRes = "WRN_NULL_OBJECT_OR_SHAPE";
1817 TopoDS_Shape aShape = aRefShape->GetValue();
1818 if (aShape.IsNull()) {
1819 aRes = "WRN_NULL_OBJECT_OR_SHAPE";
1822 if (aShape.ShapeType() == TopAbs_COMPOUND) {
1823 TopoDS_Iterator It (aShape, Standard_True, Standard_True);
1824 if (It.More()) aShape = It.Value();
1826 if (aShape.ShapeType() == TopAbs_SHELL) {
1827 BRepCheck_Shell chkShell (TopoDS::Shell(aShape));
1828 if (chkShell.Closed() == BRepCheck_NotClosed) {
1829 aRes = "WRN_SHAPE_UNCLOSED";
1833 aRes = "WRN_SHAPE_NOT_SHELL";
1845 //=============================================================================
1849 //=============================================================================
1850 TCollection_AsciiString GEOMImpl_IMeasureOperations::WhatIs (Handle(GEOM_Object) theShape)
1854 TCollection_AsciiString Astr;
1856 if (theShape.IsNull()) return Astr;
1858 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1859 if (aRefShape.IsNull()) return Astr;
1861 TopoDS_Shape aShape = aRefShape->GetValue();
1862 if (aShape.IsNull()) {
1863 SetErrorCode("The Objects has NULL Shape");
1867 //Compute the parameters
1868 if (aShape.ShapeType() == TopAbs_EDGE) {
1869 if (BRep_Tool::Degenerated(TopoDS::Edge(aShape))) {
1870 Astr = Astr + " It is a degenerated edge \n";
1874 Astr = Astr + " Number of sub-shapes : \n";
1878 int iType, nbTypes [TopAbs_SHAPE], nbFlatType [TopAbs_SHAPE];
1879 for (iType = 0; iType < TopAbs_SHAPE; ++iType) {
1881 nbFlatType[iType] = 0;
1883 nbTypes[aShape.ShapeType()]++;
1885 TopTools_MapOfShape aMapOfShape;
1886 aMapOfShape.Add(aShape);
1887 TopTools_ListOfShape aListOfShape;
1888 aListOfShape.Append(aShape);
1890 TopTools_ListIteratorOfListOfShape itL (aListOfShape);
1891 for (; itL.More(); itL.Next()) {
1892 TopoDS_Shape sp = itL.Value();
1893 TopoDS_Iterator it (sp);
1894 for (; it.More(); it.Next()) {
1895 TopoDS_Shape s = it.Value();
1896 if (aMapOfShape.Add(s)) {
1897 aListOfShape.Append(s);
1898 nbTypes[s.ShapeType()]++;
1899 if ((sp.ShapeType() == TopAbs_COMPOUND) || (sp.ShapeType() == TopAbs_COMPSOLID)) {
1900 nbFlatType[s.ShapeType()]++;
1906 Astr = Astr + " VERTEX : " + TCollection_AsciiString(nbTypes[TopAbs_VERTEX]) + "\n";
1907 Astr = Astr + " EDGE : " + TCollection_AsciiString(nbTypes[TopAbs_EDGE]) + "\n";
1908 Astr = Astr + " WIRE : " + TCollection_AsciiString(nbTypes[TopAbs_WIRE]) + "\n";
1909 Astr = Astr + " FACE : " + TCollection_AsciiString(nbTypes[TopAbs_FACE]) + "\n";
1910 Astr = Astr + " SHELL : " + TCollection_AsciiString(nbTypes[TopAbs_SHELL]) + "\n";
1911 Astr = Astr + " SOLID : " + TCollection_AsciiString(nbTypes[TopAbs_SOLID]) + "\n";
1912 Astr = Astr + " COMPSOLID : " + TCollection_AsciiString(nbTypes[TopAbs_COMPSOLID]) + "\n";
1913 Astr = Astr + " COMPOUND : " + TCollection_AsciiString(nbTypes[TopAbs_COMPOUND]) + "\n";
1914 Astr = Astr + " SHAPE : " + TCollection_AsciiString(aMapOfShape.Extent()) + "\n";
1916 if ((aShape.ShapeType() == TopAbs_COMPOUND) || (aShape.ShapeType() == TopAbs_COMPSOLID)){
1917 Astr = Astr + " --------------------- \n Flat content : \n";
1918 if (nbFlatType[TopAbs_VERTEX] > 0)
1919 Astr = Astr + " VERTEX : " + TCollection_AsciiString(nbFlatType[TopAbs_VERTEX]) + "\n";
1920 if (nbFlatType[TopAbs_EDGE] > 0)
1921 Astr = Astr + " EDGE : " + TCollection_AsciiString(nbFlatType[TopAbs_EDGE]) + "\n";
1922 if (nbFlatType[TopAbs_WIRE] > 0)
1923 Astr = Astr + " WIRE : " + TCollection_AsciiString(nbFlatType[TopAbs_WIRE]) + "\n";
1924 if (nbFlatType[TopAbs_FACE] > 0)
1925 Astr = Astr + " FACE : " + TCollection_AsciiString(nbFlatType[TopAbs_FACE]) + "\n";
1926 if (nbFlatType[TopAbs_SHELL] > 0)
1927 Astr = Astr + " SHELL : " + TCollection_AsciiString(nbFlatType[TopAbs_SHELL]) + "\n";
1928 if (nbFlatType[TopAbs_SOLID] > 0)
1929 Astr = Astr + " SOLID : " + TCollection_AsciiString(nbFlatType[TopAbs_SOLID]) + "\n";
1932 catch (Standard_Failure& aFail) {
1933 SetErrorCode(aFail.GetMessageString());
1941 //=============================================================================
1945 //=============================================================================
1947 GEOMImpl_IMeasureOperations::AreCoordsInside(Handle(GEOM_Object) theShape,
1948 const std::vector<double>& coords,
1951 std::vector<bool> isInsideRes;
1952 if (!theShape.IsNull()) {
1953 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1954 if (!aRefShape.IsNull()) {
1955 TopoDS_Shape aShape = aRefShape->GetValue();
1956 if (!aShape.IsNull())
1958 TopTools_IndexedMapOfShape mapShape;
1960 TopExp_Explorer anExp;
1961 for ( anExp.Init( aShape, TopAbs_SOLID ); anExp.More(); anExp.Next() )
1962 mapShape.Add( anExp.Current() );
1963 for ( anExp.Init( aShape, TopAbs_FACE, TopAbs_SOLID ); anExp.More(); anExp.Next() )
1964 mapShape.Add( anExp.Current() );
1965 for ( anExp.Init( aShape, TopAbs_EDGE, TopAbs_FACE ); anExp.More(); anExp.Next() )
1966 mapShape.Add( anExp.Current() );
1967 for ( anExp.Init( aShape, TopAbs_VERTEX, TopAbs_EDGE ); anExp.More(); anExp.Next() )
1968 mapShape.Add( anExp.Current() ); //// ?????????
1970 size_t nb_points = coords.size()/3, nb_points_inside = 0;
1971 isInsideRes.resize( nb_points, false );
1973 for ( int iS = 1; iS <= mapShape.Extent(); ++iS )
1975 if ( nb_points_inside == nb_points )
1977 aShape = mapShape( iS );
1978 switch ( aShape.ShapeType() ) {
1981 BRepClass3d_SolidClassifier SC( TopoDS::Solid( aShape ));
1982 for ( size_t i = 0; i < nb_points; i++)
1984 if ( isInsideRes[ i ]) continue;
1985 gp_Pnt aPnt( coords[3*i], coords[3*i+1], coords[3*i+2] );
1986 SC.Perform( aPnt, tolerance );
1987 isInsideRes[ i ] = (( SC.State() == TopAbs_IN ) || ( SC.State() == TopAbs_ON ));
1988 nb_points_inside += isInsideRes[ i ];
1994 Standard_Real u1,u2,v1,v2;
1995 const TopoDS_Face& face = TopoDS::Face( aShape );
1996 Handle(Geom_Surface) surf = BRep_Tool::Surface( face );
1997 surf->Bounds( u1,u2,v1,v2 );
1998 GeomAPI_ProjectPointOnSurf project;
1999 project.Init(surf, u1,u2, v1,v2, tolerance );
2000 for ( size_t i = 0; i < nb_points; i++)
2002 if ( isInsideRes[ i ]) continue;
2003 gp_Pnt aPnt( coords[3*i], coords[3*i+1], coords[3*i+2] );
2004 project.Perform( aPnt );
2005 if ( project.IsDone() &&
2006 project.NbPoints() > 0 &&
2007 project.LowerDistance() <= tolerance )
2010 project.LowerDistanceParameters(u, v);
2011 gp_Pnt2d uv( u, v );
2012 BRepClass_FaceClassifier FC ( face, uv, tolerance );
2013 isInsideRes[ i ] = (( FC.State() == TopAbs_IN ) || ( FC.State() == TopAbs_ON ));
2014 nb_points_inside += isInsideRes[ i ];
2022 const TopoDS_Edge& edge = TopoDS::Edge( aShape );
2023 Handle(Geom_Curve) curve = BRep_Tool::Curve( edge, f, l );
2024 GeomAPI_ProjectPointOnCurve project;
2025 project.Init( curve, f, l );
2026 for ( size_t i = 0; i < nb_points; i++)
2028 if ( isInsideRes[ i ]) continue;
2029 gp_Pnt aPnt( coords[3*i], coords[3*i+1], coords[3*i+2] );
2030 project.Perform( aPnt );
2031 isInsideRes[ i ] = ( project.NbPoints() > 0 &&
2032 project.LowerDistance() <= tolerance );
2033 nb_points_inside += isInsideRes[ i ];
2039 gp_Pnt aVPnt = BRep_Tool::Pnt( TopoDS::Vertex( aShape ));
2040 for ( size_t i = 0; i < nb_points; i++)
2042 if ( isInsideRes[ i ]) continue;
2043 gp_Pnt aPnt( coords[3*i], coords[3*i+1], coords[3*i+2] );
2044 isInsideRes[ i ] = ( aPnt.SquareDistance( aVPnt ) <= tolerance * tolerance );
2045 nb_points_inside += isInsideRes[ i ];
2050 } // switch ( aShape.ShapeType() )
2058 //=============================================================================
2062 //=============================================================================
2064 GEOMImpl_IMeasureOperations::GetMinDistance (Handle(GEOM_Object) theShape1,
2065 Handle(GEOM_Object) theShape2,
2074 Standard_Real MinDist = 1.e9;
2076 if (theShape1.IsNull() || theShape2.IsNull()) return MinDist;
2078 Handle(GEOM_Function) aRefShape1 = theShape1->GetLastFunction();
2079 Handle(GEOM_Function) aRefShape2 = theShape2->GetLastFunction();
2080 if (aRefShape1.IsNull() || aRefShape2.IsNull()) return MinDist;
2082 TopoDS_Shape aShape1 = aRefShape1->GetValue();
2083 TopoDS_Shape aShape2 = aRefShape2->GetValue();
2084 if (aShape1.IsNull() || aShape2.IsNull()) {
2085 SetErrorCode("One of Objects has NULL Shape");
2089 //Compute the parameters
2093 gp_Pnt aPnt1, aPnt2;
2095 MinDist = GEOMUtils::GetMinDistance(aShape1, aShape2, aPnt1, aPnt2);
2097 if (MinDist >= 0.0) {
2098 aPnt1.Coord(X1, Y1, Z1);
2099 aPnt2.Coord(X2, Y2, Z2);
2104 catch (Standard_Failure& aFail) {
2105 SetErrorCode(aFail.GetMessageString());
2113 //=======================================================================
2115 * Get coordinates of closest points of two shapes
2117 //=======================================================================
2118 Standard_Integer GEOMImpl_IMeasureOperations::ClosestPoints (Handle(GEOM_Object) theShape1,
2119 Handle(GEOM_Object) theShape2,
2120 Handle(TColStd_HSequenceOfReal)& theDoubles)
2123 Standard_Integer nbSolutions = 0;
2125 if (theShape1.IsNull() || theShape2.IsNull()) return nbSolutions;
2127 Handle(GEOM_Function) aRefShape1 = theShape1->GetLastFunction();
2128 Handle(GEOM_Function) aRefShape2 = theShape2->GetLastFunction();
2129 if (aRefShape1.IsNull() || aRefShape2.IsNull()) return nbSolutions;
2131 TopoDS_Shape aShape1 = aRefShape1->GetValue();
2132 TopoDS_Shape aShape2 = aRefShape2->GetValue();
2133 if (aShape1.IsNull() || aShape2.IsNull()) {
2134 SetErrorCode("One of Objects has NULL Shape");
2138 // Compute the extremities
2143 // additional workaround for bugs 19899, 19908 and 19910 from Mantis
2145 double dist = GEOMUtils::GetMinDistanceSingular(aShape1, aShape2, P1s, P2s);
2146 bool singularBetter = dist >= 0;
2148 BRepExtrema_DistShapeShape dst (aShape1, aShape2);
2150 nbSolutions = dst.NbSolution();
2151 if (theDoubles.IsNull()) theDoubles = new TColStd_HSequenceOfReal;
2154 for (int i = 1; i <= nbSolutions; i++) {
2155 P1 = dst.PointOnShape1(i);
2156 P2 = dst.PointOnShape2(i);
2158 theDoubles->Append(P1.X());
2159 theDoubles->Append(P1.Y());
2160 theDoubles->Append(P1.Z());
2161 theDoubles->Append(P2.X());
2162 theDoubles->Append(P2.Y());
2163 theDoubles->Append(P2.Z());
2165 Standard_Real Dist = P1.Distance(P2);
2166 singularBetter = singularBetter && dist < Dist;
2170 if (singularBetter) {
2171 if (theDoubles.IsNull()) theDoubles = new TColStd_HSequenceOfReal;
2172 else theDoubles->Clear();
2176 theDoubles->Append(P1s.X());
2177 theDoubles->Append(P1s.Y());
2178 theDoubles->Append(P1s.Z());
2179 theDoubles->Append(P2s.X());
2180 theDoubles->Append(P2s.Y());
2181 theDoubles->Append(P2s.Z());
2184 catch (Standard_Failure& aFail) {
2185 SetErrorCode(aFail.GetMessageString());
2193 //=======================================================================
2195 * Get coordinates of point
2197 //=======================================================================
2198 void GEOMImpl_IMeasureOperations::PointCoordinates (Handle(GEOM_Object) theShape,
2199 Standard_Real& theX, Standard_Real& theY, Standard_Real& theZ)
2203 if (theShape.IsNull())
2206 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
2207 if (aRefShape.IsNull())
2210 TopoDS_Shape aShape = aRefShape->GetValue();
2211 if (aShape.IsNull() || aShape.ShapeType() != TopAbs_VERTEX)
2213 SetErrorCode( "Shape must be a vertex" );
2219 gp_Pnt aPnt = BRep_Tool::Pnt( TopoDS::Vertex( aShape ) );
2226 catch (Standard_Failure& aFail)
2228 SetErrorCode( aFail.GetMessageString() );
2232 //=======================================================================
2234 * Compute angle (in degrees) between two lines
2236 //=======================================================================
2237 Standard_Real GEOMImpl_IMeasureOperations::GetAngle (Handle(GEOM_Object) theLine1,
2238 Handle(GEOM_Object) theLine2)
2240 if (theLine1->GetType() == GEOM_VECTOR &&
2241 theLine2->GetType() == GEOM_VECTOR)
2242 return GetAngleBtwVectors(theLine1, theLine2);
2246 Standard_Real anAngle = -1.0;
2248 if (theLine1.IsNull() || theLine2.IsNull())
2251 Handle(GEOM_Function) aRefLine1 = theLine1->GetLastFunction();
2252 Handle(GEOM_Function) aRefLine2 = theLine2->GetLastFunction();
2253 if (aRefLine1.IsNull() || aRefLine2.IsNull())
2256 TopoDS_Shape aLine1 = aRefLine1->GetValue();
2257 TopoDS_Shape aLine2 = aRefLine2->GetValue();
2258 if (aLine1.IsNull() || aLine2.IsNull() ||
2259 aLine1.ShapeType() != TopAbs_EDGE ||
2260 aLine2.ShapeType() != TopAbs_EDGE)
2262 SetErrorCode("Two edges must be given");
2268 TopoDS_Edge E1 = TopoDS::Edge(aLine1);
2269 TopoDS_Edge E2 = TopoDS::Edge(aLine2);
2272 Handle(Geom_Curve) C1 = BRep_Tool::Curve(E1,fp,lp);
2273 Handle(Geom_Curve) C2 = BRep_Tool::Curve(E2,fp,lp);
2275 if ( C1.IsNull() || C2.IsNull() ||
2276 !C1->IsKind(STANDARD_TYPE(Geom_Line)) ||
2277 !C2->IsKind(STANDARD_TYPE(Geom_Line)))
2279 SetErrorCode("The edges must be linear");
2283 Handle(Geom_Line) L1 = Handle(Geom_Line)::DownCast(C1);
2284 Handle(Geom_Line) L2 = Handle(Geom_Line)::DownCast(C2);
2286 gp_Lin aLin1 = L1->Lin();
2287 gp_Lin aLin2 = L2->Lin();
2289 anAngle = aLin1.Angle(aLin2);
2290 anAngle *= 180. / M_PI; // convert radians into degrees
2292 if (anAngle > 90.0) {
2293 anAngle = 180.0 - anAngle;
2298 catch (Standard_Failure& aFail)
2300 SetErrorCode(aFail.GetMessageString());
2306 //=======================================================================
2308 * Compute angle (in degrees) between two vectors
2310 //=======================================================================
2311 Standard_Real GEOMImpl_IMeasureOperations::GetAngleBtwVectors (Handle(GEOM_Object) theVec1,
2312 Handle(GEOM_Object) theVec2)
2316 Standard_Real anAngle = -1.0;
2318 if (theVec1.IsNull() || theVec2.IsNull())
2321 if (theVec1->GetType() != GEOM_VECTOR || theVec2->GetType() != GEOM_VECTOR) {
2322 SetErrorCode("Two vectors must be given");
2326 Handle(GEOM_Function) aRefVec1 = theVec1->GetLastFunction();
2327 Handle(GEOM_Function) aRefVec2 = theVec2->GetLastFunction();
2328 if (aRefVec1.IsNull() || aRefVec2.IsNull())
2331 TopoDS_Shape aVec1 = aRefVec1->GetValue();
2332 TopoDS_Shape aVec2 = aRefVec2->GetValue();
2333 if (aVec1.IsNull() || aVec2.IsNull() ||
2334 aVec1.ShapeType() != TopAbs_EDGE ||
2335 aVec2.ShapeType() != TopAbs_EDGE)
2337 SetErrorCode("Two edges must be given");
2343 TopoDS_Edge aE1 = TopoDS::Edge(aVec1);
2344 TopoDS_Edge aE2 = TopoDS::Edge(aVec2);
2346 TopoDS_Vertex aP11, aP12, aP21, aP22;
2347 TopExp::Vertices(aE1, aP11, aP12, Standard_True);
2348 TopExp::Vertices(aE2, aP21, aP22, Standard_True);
2349 if (aP11.IsNull() || aP12.IsNull() || aP21.IsNull() || aP22.IsNull()) {
2350 SetErrorCode("Bad edge given");
2354 gp_Vec aV1 (BRep_Tool::Pnt(aP11), BRep_Tool::Pnt(aP12));
2355 gp_Vec aV2 (BRep_Tool::Pnt(aP21), BRep_Tool::Pnt(aP22)) ;
2357 anAngle = aV1.Angle(aV2);
2358 anAngle *= 180. / M_PI; // convert radians into degrees
2362 catch (Standard_Failure& aFail)
2364 SetErrorCode(aFail.GetMessageString());
2371 //=============================================================================
2375 //=============================================================================
2376 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IMeasureOperations::PatchFace(Handle(GEOM_Object) theShape)
2380 if (theShape.IsNull()) return NULL;
2382 Handle(GEOM_Object) aPatchFace = GetEngine()->AddObject(GEOM_PATCH_FACE);
2383 Handle(GEOM_Function) aFunction = aPatchFace->AddFunction(GEOMImpl_PatchFaceDriver::GetID(), 1);
2384 if (aFunction.IsNull()) return NULL;
2386 //Check if the function is set correctly
2387 if (aFunction->GetDriverGUID() != GEOMImpl_PatchFaceDriver::GetID()) return NULL;
2389 GEOMImpl_IPatchFace aPI(aFunction);
2390 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
2391 if (aRefShape.IsNull()) return NULL;
2393 aPI.SetShape(aRefShape);
2394 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2400 if (!GetSolver()->ComputeFunction(aFunction))
2402 SetErrorCode("patch face driver failed");
2406 // Get result compound and collect all faces into result sequence
2407 TopoDS_Shape aResCompound = aFunction->GetValue();
2408 TopTools_IndexedMapOfShape anIndices;
2409 TopExp::MapShapes(aResCompound, anIndices);
2411 Handle(TColStd_HArray1OfInteger) anArray;
2412 for (TopExp_Explorer anExpW(aResCompound, TopAbs_FACE); anExpW.More(); anExpW.Next())
2414 TopoDS_Shape aValue = anExpW.Value();
2415 anArray = new TColStd_HArray1OfInteger(1, 1);
2416 anArray->SetValue(1, anIndices.FindIndex(aValue));
2418 Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(aPatchFace, anArray);
2419 if (!anObj.IsNull())
2421 aSeq->Append(anObj);
2425 catch (Standard_Failure& aFail)
2427 SetErrorCode(aFail.GetMessageString());
2431 //Make a Python command
2432 GEOM::TPythonDump(aFunction, true)
2433 << "[" << aSeq << "] = geompy.PatchFace(" << theShape << ")";
2439 //=============================================================================
2441 * CurveCurvatureByParam
2443 //=============================================================================
2444 Standard_Real GEOMImpl_IMeasureOperations::CurveCurvatureByParam
2445 (Handle(GEOM_Object) theCurve, Standard_Real& theParam)
2448 Standard_Real aRes = -1.0;
2450 if(theCurve.IsNull()) return aRes;
2452 Handle(GEOM_Function) aRefShape = theCurve->GetLastFunction();
2453 if(aRefShape.IsNull()) return aRes;
2455 TopoDS_Shape aShape = aRefShape->GetValue();
2456 if(aShape.IsNull()) {
2457 SetErrorCode("One of Objects has NULL Shape");
2461 Standard_Real aFP, aLP, aP;
2462 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(TopoDS::Edge(aShape), aFP, aLP);
2463 aP = aFP + (aLP - aFP) * theParam;
2465 if(aCurve.IsNull()) return aRes;
2470 GeomLProp_CLProps Prop = GeomLProp_CLProps
2471 (aCurve, aP, 2, Precision::Confusion());
2472 aRes = fabs(Prop.Curvature());
2475 catch (Standard_Failure& aFail) {
2476 SetErrorCode(aFail.GetMessageString());
2480 if( aRes > Precision::Confusion() )
2489 //=============================================================================
2491 * CurveCurvatureByPoint
2493 //=============================================================================
2494 Standard_Real GEOMImpl_IMeasureOperations::CurveCurvatureByPoint
2495 (Handle(GEOM_Object) theCurve, Handle(GEOM_Object) thePoint)
2498 Standard_Real aRes = -1.0;
2500 if( theCurve.IsNull() || thePoint.IsNull() ) return aRes;
2502 Handle(GEOM_Function) aRefCurve = theCurve->GetLastFunction();
2503 Handle(GEOM_Function) aRefPoint = thePoint->GetLastFunction();
2504 if( aRefCurve.IsNull() || aRefPoint.IsNull() ) return aRes;
2506 TopoDS_Edge anEdge = TopoDS::Edge(aRefCurve->GetValue());
2507 TopoDS_Vertex aPnt = TopoDS::Vertex(aRefPoint->GetValue());
2508 if( anEdge.IsNull() || aPnt.IsNull() ) {
2509 SetErrorCode("One of Objects has NULL Shape");
2513 Standard_Real aFP, aLP;
2514 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFP, aLP);
2515 if(aCurve.IsNull()) return aRes;
2516 gp_Pnt aPoint = BRep_Tool::Pnt(aPnt);
2521 GeomAPI_ProjectPointOnCurve PPCurve(aPoint, aCurve, aFP, aLP);
2522 if(PPCurve.NbPoints()>0) {
2523 GeomLProp_CLProps Prop = GeomLProp_CLProps
2524 (aCurve, PPCurve.LowerDistanceParameter(), 2, Precision::Confusion());
2525 aRes = fabs(Prop.Curvature());
2529 catch (Standard_Failure& aFail) {
2530 SetErrorCode(aFail.GetMessageString());
2534 if( aRes > Precision::Confusion() )
2543 //=============================================================================
2545 * getSurfaceCurvatures
2547 //=============================================================================
2548 Standard_Real GEOMImpl_IMeasureOperations::getSurfaceCurvatures
2549 (const Handle(Geom_Surface)& aSurf,
2550 Standard_Real theUParam,
2551 Standard_Real theVParam,
2552 Standard_Boolean theNeedMaxCurv)
2555 Standard_Real aRes = 1.0;
2557 if (aSurf.IsNull()) return aRes;
2561 GeomLProp_SLProps Prop = GeomLProp_SLProps
2562 (aSurf, theUParam, theVParam, 2, Precision::Confusion());
2563 if(Prop.IsCurvatureDefined()) {
2564 if(Prop.IsUmbilic()) {
2565 //cout<<"is umbilic"<<endl;
2566 aRes = fabs(Prop.MeanCurvature());
2569 //cout<<"is not umbilic"<<endl;
2570 double c1 = fabs(Prop.MaxCurvature());
2571 double c2 = fabs(Prop.MinCurvature());
2580 catch (Standard_Failure& aFail) {
2581 SetErrorCode(aFail.GetMessageString());
2585 if( fabs(aRes) > Precision::Confusion() )
2594 //=============================================================================
2596 * MaxSurfaceCurvatureByParam
2598 //=============================================================================
2599 Standard_Real GEOMImpl_IMeasureOperations::MaxSurfaceCurvatureByParam
2600 (Handle(GEOM_Object) theSurf,
2601 Standard_Real& theUParam,
2602 Standard_Real& theVParam)
2605 Standard_Real aRes = -1.0;
2607 if (theSurf.IsNull()) return aRes;
2609 Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2610 if(aRefShape.IsNull()) return aRes;
2612 TopoDS_Shape aShape = aRefShape->GetValue();
2613 if(aShape.IsNull()) {
2614 SetErrorCode("One of Objects has NULL Shape");
2618 TopoDS_Face F = TopoDS::Face(aShape);
2619 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
2621 //Compute the parameters
2622 Standard_Real U1,U2,V1,V2;
2623 ShapeAnalysis::GetFaceUVBounds(F,U1,U2,V1,V2);
2624 Standard_Real U = U1 + (U2-U1)*theUParam;
2625 Standard_Real V = V1 + (V2-V1)*theVParam;
2627 return getSurfaceCurvatures(aSurf, U, V, true);
2631 //=============================================================================
2633 * MaxSurfaceCurvatureByPoint
2635 //=============================================================================
2636 Standard_Real GEOMImpl_IMeasureOperations::MaxSurfaceCurvatureByPoint
2637 (Handle(GEOM_Object) theSurf, Handle(GEOM_Object) thePoint)
2640 Standard_Real aRes = -1.0;
2642 if( theSurf.IsNull() || thePoint.IsNull() ) return aRes;
2644 Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2645 Handle(GEOM_Function) aRefPoint = thePoint->GetLastFunction();
2646 if( aRefShape.IsNull() || aRefPoint.IsNull() ) return aRes;
2648 TopoDS_Face aFace = TopoDS::Face(aRefShape->GetValue());
2649 TopoDS_Vertex aPnt = TopoDS::Vertex(aRefPoint->GetValue());
2650 if( aFace.IsNull() || aPnt.IsNull() ) {
2651 SetErrorCode("One of Objects has NULL Shape");
2655 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
2656 if(aSurf.IsNull()) return aRes;
2657 gp_Pnt aPoint = BRep_Tool::Pnt(aPnt);
2659 //Compute the parameters
2660 ShapeAnalysis_Surface sas(aSurf);
2661 gp_Pnt2d UV = sas.ValueOfUV(aPoint,Precision::Confusion());
2663 return getSurfaceCurvatures(aSurf, UV.X(), UV.Y(), true);
2667 //=============================================================================
2669 * MinSurfaceCurvatureByParam
2671 //=============================================================================
2672 Standard_Real GEOMImpl_IMeasureOperations::MinSurfaceCurvatureByParam
2673 (Handle(GEOM_Object) theSurf,
2674 Standard_Real& theUParam,
2675 Standard_Real& theVParam)
2678 Standard_Real aRes = -1.0;
2680 if (theSurf.IsNull()) return aRes;
2682 Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2683 if(aRefShape.IsNull()) return aRes;
2685 TopoDS_Shape aShape = aRefShape->GetValue();
2686 if(aShape.IsNull()) {
2687 SetErrorCode("One of Objects has NULL Shape");
2691 TopoDS_Face F = TopoDS::Face(aShape);
2692 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
2694 //Compute the parameters
2695 Standard_Real U1,U2,V1,V2;
2696 ShapeAnalysis::GetFaceUVBounds(F,U1,U2,V1,V2);
2697 Standard_Real U = U1 + (U2-U1)*theUParam;
2698 Standard_Real V = V1 + (V2-V1)*theVParam;
2700 return getSurfaceCurvatures(aSurf, U, V, false);
2704 //=============================================================================
2706 * MinSurfaceCurvatureByPoint
2708 //=============================================================================
2709 Standard_Real GEOMImpl_IMeasureOperations::MinSurfaceCurvatureByPoint
2710 (Handle(GEOM_Object) theSurf, Handle(GEOM_Object) thePoint)
2713 Standard_Real aRes = -1.0;
2715 if( theSurf.IsNull() || thePoint.IsNull() ) return aRes;
2717 Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2718 Handle(GEOM_Function) aRefPoint = thePoint->GetLastFunction();
2719 if( aRefShape.IsNull() || aRefPoint.IsNull() ) return aRes;
2721 TopoDS_Face aFace = TopoDS::Face(aRefShape->GetValue());
2722 TopoDS_Vertex aPnt = TopoDS::Vertex(aRefPoint->GetValue());
2723 if( aFace.IsNull() || aPnt.IsNull() ) {
2724 SetErrorCode("One of Objects has NULL Shape");
2728 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
2729 if(aSurf.IsNull()) return aRes;
2730 gp_Pnt aPoint = BRep_Tool::Pnt(aPnt);
2732 //Compute the parameters
2733 ShapeAnalysis_Surface sas(aSurf);
2734 gp_Pnt2d UV = sas.ValueOfUV(aPoint,Precision::Confusion());
2736 return getSurfaceCurvatures(aSurf, UV.X(), UV.Y(), false);
2739 //=============================================================================
2741 * SurfaceCurvatureByPointAndDirection
2743 //=============================================================================
2744 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::SurfaceCurvatureByPointAndDirection
2745 (Handle(GEOM_Object) theSurf,
2746 Handle(GEOM_Object) thePoint,
2747 Handle(GEOM_Object) theDirection)
2751 if (theSurf.IsNull() || thePoint.IsNull() || theDirection.IsNull()) return NULL;
2753 Handle(GEOM_Function) aSurf = theSurf->GetLastFunction();
2754 Handle(GEOM_Function) aPoint = thePoint->GetLastFunction();
2755 Handle(GEOM_Function) aDirection = theDirection->GetLastFunction();
2756 if (aSurf.IsNull() || aPoint.IsNull() || aDirection.IsNull()) return NULL;
2758 //Add a new CurvatureVector object
2759 //Handle(GEOM_Object) aCV = GetEngine()->AddObject(GEOM_CURVATURE_VEC);
2760 Handle(GEOM_Object) aCV = GetEngine()->AddObject(GEOM_VECTOR);
2762 //Add a new CurvatureVector function
2763 Handle(GEOM_Function) aFunction =
2764 aCV->AddFunction(GEOMImpl_MeasureDriver::GetID(), CURVATURE_VEC_MEASURE);
2765 if (aFunction.IsNull()) return NULL;
2767 //Check if the function is set correctly
2768 if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL;
2770 GEOMImpl_IMeasure aCI (aFunction);
2772 aCI.SetPoint(aPoint);
2773 aCI.SetDirection(aDirection);
2775 //Compute the CurvatureVector
2778 if (!GetSolver()->ComputeFunction(aFunction)) {
2779 SetErrorCode("Measure driver failed to compute a surface curvature");
2783 catch (Standard_Failure& aFail) {
2784 SetErrorCode(aFail.GetMessageString());
2788 //Make a Python command
2789 GEOM::TPythonDump(aFunction) << aCV << " = geompy.CurvatureOnFace(" << theSurf
2790 << ", " << thePoint << ", " << theDirection << ")";
2796 //=============================================================================
2800 //=============================================================================
2801 Handle(TColStd_HArray1OfReal) GEOMImpl_IMeasureOperations::XYZtoUV
2802 (Handle(GEOM_Object) theSurf,
2803 const Handle(TColStd_HArray1OfReal)& theXYZlist,
2808 Handle(TColStd_HArray1OfReal) aRet;
2810 // Check list of coordinates
2811 int nbC = theXYZlist->Length();
2813 if (nbP * 3 != nbC) {
2814 SetErrorCode("Coordinates list length is not divisible by 3");
2819 if (theSurf.IsNull()) {
2820 SetErrorCode("The shape is NULL");
2824 Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2825 if (aRefShape.IsNull()) {
2826 SetErrorCode("The shape is NULL");
2830 TopoDS_Shape aShape = aRefShape->GetValue();
2831 if (aShape.IsNull()) {
2832 SetErrorCode("The shape is NULL");
2836 // The shape can be a face, a shell of one face or a compound with one face
2838 if (aShape.ShapeType() == TopAbs_FACE) {
2839 F = TopoDS::Face(aShape);
2841 else if (aShape.ShapeType() < TopAbs_FACE) {
2842 TopExp_Explorer Exp (aShape, TopAbs_FACE);
2844 F = TopoDS::Face(Exp.Current());
2847 SetErrorCode("There should be only one face");
2853 SetErrorCode("There are no faces");
2858 Standard_Real squareTolerance = BRep_Tool::Tolerance(F);
2859 squareTolerance = squareTolerance * squareTolerance;
2861 // Compute parameters
2862 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
2863 aRet = new TColStd_HArray1OfReal (0, nbP * 2 - 1);
2865 Standard_Real U1,U2, V1,V2;
2866 BRepTools::UVBounds(F, U1, U2, V1, V2);
2867 Standard_Real dU = U2 - U1;
2868 Standard_Real dV = V2 - V1;
2870 int iCLower = theXYZlist->Lower();
2871 for (int iP = 0; iP < nbP; iP++) {
2872 gp_Pnt aP (theXYZlist->Value(iCLower + iP * 3),
2873 theXYZlist->Value(iCLower + iP * 3 + 1),
2874 theXYZlist->Value(iCLower + iP * 3 + 2));
2876 gp_Pnt aPonF = GEOMUtils::ProjectPointOnFace(aP, F, U, V);
2877 if (aP.SquareDistance(aPonF) < squareTolerance) {
2879 // Normalize parameters to be in [0, 1]
2883 aRet->SetValue(iP * 2 , U);
2884 aRet->SetValue(iP * 2 + 1, V);
2887 SetErrorCode("Point too far from face");
2896 //=============================================================================
2900 //=============================================================================
2901 Handle(TColStd_HArray1OfReal) GEOMImpl_IMeasureOperations::UVtoXYZ
2902 (Handle(GEOM_Object) theSurf,
2903 const Handle(TColStd_HArray1OfReal)& theUVlist,
2908 Handle(TColStd_HArray1OfReal) aRet;
2910 // Check list of parameters
2911 int nbC = theUVlist->Length();
2913 if (nbP * 2 != nbC) {
2914 SetErrorCode("Parameters list length is not divisible by 2");
2919 if (theSurf.IsNull()) {
2920 SetErrorCode("The shape is NULL");
2924 Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
2925 if (aRefShape.IsNull()) {
2926 SetErrorCode("The shape is NULL");
2930 TopoDS_Shape aShape = aRefShape->GetValue();
2931 if (aShape.IsNull()) {
2932 SetErrorCode("The shape is NULL");
2936 // The shape can be a face, a shell of one face or a compound with one face
2938 if (aShape.ShapeType() == TopAbs_FACE) {
2939 F = TopoDS::Face(aShape);
2941 else if (aShape.ShapeType() < TopAbs_FACE) {
2942 TopExp_Explorer Exp (aShape, TopAbs_FACE);
2944 F = TopoDS::Face(Exp.Current());
2947 SetErrorCode("There should be only one face");
2953 SetErrorCode("There are no faces");
2958 Standard_Real squareTolerance = BRep_Tool::Tolerance(F);
2959 squareTolerance = squareTolerance * squareTolerance;
2961 // Compute coordinates
2962 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
2963 aRet = new TColStd_HArray1OfReal (0, nbP * 3 - 1);
2965 Standard_Real U1,U2, V1,V2;
2966 BRepTools::UVBounds(F, U1, U2, V1, V2);
2967 Standard_Real dU = U2 - U1;
2968 Standard_Real dV = V2 - V1;
2970 Standard_Real tol = 1.e-4;
2971 Standard_Real pc = Precision::Confusion();
2973 int iCLower = theUVlist->Lower();
2974 for (int iP = 0; iP < nbP; iP++) {
2975 Standard_Real U = theUVlist->Value(iCLower + iP * 2);
2976 Standard_Real V = theUVlist->Value(iCLower + iP * 2 + 1);
2979 // Get real parameters from given normalized ones in [0, 1]
2980 if (!(-pc < U && U < 1 + pc) || !(-pc < V && V < 1 + pc)) {
2981 SetErrorCode("Normalized parameter is out of range [0,1]");
2988 gp_Pnt2d aP2d (U, V);
2990 BRepClass_FaceClassifier aClsf (F, aP2d, tol);
2991 if (aClsf.State() != TopAbs_IN && aClsf.State() != TopAbs_ON) {
2992 SetErrorCode("Given parameters are out of face");
2995 gp_Pnt surfPnt = aSurf->Value(U, V);
2997 aRet->SetValue(iP * 3 , surfPnt.X());
2998 aRet->SetValue(iP * 3 + 1, surfPnt.Y());
2999 aRet->SetValue(iP * 3 + 2, surfPnt.Z());
3006 //=============================================================================
3009 * Find all self-intersected 2D curves.
3010 * \param theChecks list of failed checks, contains type of check and failed shapes
3012 //=============================================================================
3013 std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects>
3014 GEOMImpl_IMeasureOperations::SelfIntersected2D(const std::list<FailedChecks>& theChecks)
3017 MESSAGE("GEOMImpl_IMeasureOperations::selfIntersected2D");
3019 std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects> aSelfInters2D;
3023 for (std::list<FailedChecks>::const_iterator anIter(theChecks.begin());
3024 anIter != theChecks.end(); ++anIter)
3026 if (anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_InvalidCurveOnSurface)
3027 aSelfInters2D.push_back(anIter->FailedShapes);
3030 catch (Standard_Failure& aFail)
3032 SetErrorCode(aFail.GetMessageString());
3033 return aSelfInters2D;
3037 return aSelfInters2D;
3042 static bool checkTypes(const GEOMImpl_IMeasureOperations::CoupleOfObjects& theShapes,
3043 const int theShapeType1,
3044 const int theShapeType2)
3046 if (theShapeType1 == -1 && theShapeType2 == -1)
3049 TopAbs_ShapeEnum aShapeType1 = theShapes.first.IsNull()
3051 : theShapes.first->GetValue().ShapeType();
3052 TopAbs_ShapeEnum aShapeType2 = theShapes.second.IsNull()
3054 : theShapes.second->GetValue().ShapeType();
3056 if (theShapeType1 == -1)
3057 return aShapeType1 == theShapeType2 || aShapeType2 == theShapeType2;
3058 else if (theShapeType2 == -1)
3059 return aShapeType1 == theShapeType1 || aShapeType2 == theShapeType1;
3060 return (aShapeType1 == theShapeType1 && aShapeType2 == theShapeType2) ||
3061 (aShapeType1 == theShapeType2 && aShapeType2 == theShapeType1);
3065 //=============================================================================
3067 * InterferingSubshapes
3068 * Find pairs of interfering sub-shapes, by default all pairs of interfering shapes are returned.
3069 * \param theChecks list of failed checks, contains type of check and failed shapes
3070 * \param theShapeType1 Type of shape.
3071 * \param theShapeType2 Type of shape.
3073 //=============================================================================
3074 std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects>
3075 GEOMImpl_IMeasureOperations::InterferingSubshapes
3076 (const std::list<FailedChecks>& theChecks,
3077 const int theShapeType1,
3078 const int theShapeType2)
3081 MESSAGE("GEOMImpl_IMeasureOperations::interferingSubshapes");
3083 std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects> anInterfer;
3087 for (std::list<FailedChecks>::const_iterator anIter(theChecks.begin());
3088 anIter != theChecks.end(); ++anIter)
3090 if (anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_SelfIntersect &&
3091 checkTypes(anIter->FailedShapes, theShapeType1, theShapeType2))
3092 anInterfer.push_back(anIter->FailedShapes);
3095 catch (Standard_Failure& aFail)
3097 SetErrorCode(aFail.GetMessageString());
3105 //=============================================================================
3108 * Find edges, which are fully covered by tolerances of vertices.
3109 * \param theChecks list of failed checks, contains type of check and failed shapes
3111 //=============================================================================
3112 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IMeasureOperations::SmallEdges(
3113 const std::list<FailedChecks>& theChecks)
3116 MESSAGE("GEOMImpl_IMeasureOperations::smallEdges");
3118 Handle(TColStd_HSequenceOfTransient) aSmallEdges = new TColStd_HSequenceOfTransient;
3122 for (std::list<FailedChecks>::const_iterator anIter(theChecks.begin());
3123 anIter != theChecks.end(); ++anIter)
3125 if (anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_TooSmallEdge)
3126 aSmallEdges->Append(anIter->FailedShapes.first);
3129 catch (Standard_Failure& aFail)
3131 SetErrorCode(aFail.GetMessageString());
3139 //=============================================================================
3142 * find remote objects (sub-shape on a shape).
3143 * \param theShape Shape for check.
3144 * \param theShapeType Type of shape.
3145 * \param theSubShapeType Type of sub-shape.
3146 * \param theTolerance tolerance.
3148 //=============================================================================
3149 std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects>
3150 GEOMImpl_IMeasureOperations::DistantShapes
3151 (const std::list<FailedChecks>& theChecks,
3152 const int theShapeType,
3153 const int theSubShapeType,
3154 double theTolerance)
3157 MESSAGE("GEOMImpl_IMeasureOperations::distantShapes");
3159 std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects> aDistShapes;
3163 for (std::list<FailedChecks>::const_iterator anIter(theChecks.begin());
3164 anIter != theChecks.end(); ++anIter)
3166 Handle(GEOM_Object) aSubShape = anIter->FailedShapes.first;
3167 Handle(GEOM_Object) aShape = anIter->FailedShapes.second;
3168 if ((anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_InvalidCurveOnSurface ||
3169 anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_IncompatibilityOfVertex ||
3170 anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_IncompatibilityOfEdge ||
3171 anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_IncompatibilityOfFace) &&
3172 aShape && (theShapeType == -1 || aShape->GetValue().ShapeType() == theShapeType) &&
3173 aSubShape && (theSubShapeType == -1 || aSubShape->GetValue().ShapeType() == theSubShapeType))
3176 Standard_Real aDist = Precision::Infinite();
3177 if (anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_InvalidCurveOnSurface)
3178 aDist = ComputeTolerance(aSubShape, aShape);
3179 if (aDist > theTolerance)
3180 aDistShapes.push_back(anIter->FailedShapes);
3184 catch (Standard_Failure& aFail)
3186 SetErrorCode(aFail.GetMessageString());
3194 //=============================================================================
3196 * CheckConformityShape
3197 * Perform analyse of shape and find imperfections in the shape.
3198 * \param theShape Shape for analyse.
3200 //=============================================================================
3201 void GEOMImpl_IMeasureOperations::CheckConformityShape(Handle(GEOM_Object) theShape, std::list<FailedChecks>& theChecks)
3204 MESSAGE("GEOMImpl_IMeasureOperations::checkShape");
3206 Handle(GEOM_Object) aConformity = GetEngine()->AddObject(GEOM_CHECKCONFORMITY);
3207 Handle(GEOM_Function) aFunction = aConformity->AddFunction(GEOMImpl_ConformityDriver::GetID(), CONFORMITY_CHECK_SHAPE);
3208 if (aFunction.IsNull()) return;
3210 //Check if the function is set correctly
3211 if (aFunction->GetDriverGUID() != GEOMImpl_ConformityDriver::GetID()) return;
3213 GEOMImpl_IConformity aCI(aFunction);
3215 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
3216 if (aRefShape.IsNull()) return;
3218 aCI.SetShape(aRefShape);
3223 if (!GetSolver()->ComputeFunction(aFunction))
3225 SetErrorCode("Failed: checkShape");
3228 Handle(TColStd_HArray1OfInteger) aTypesChecks = aFunction->GetIntegerArray(CHECKCONFORMITY_RET_TYPES_CHECKS);
3229 Handle(TColStd_HArray2OfInteger) aRes = aCI.GetListOfShapesIndices();
3233 for (Standard_Integer anIndex = 1; anIndex <= aRes->NbRows(); ++anIndex)
3235 std::pair<Handle(GEOM_Object), Handle(GEOM_Object)> aPair;
3236 Handle(TColStd_HArray1OfInteger) anArray;
3237 anArray = new TColStd_HArray1OfInteger(1, 1);
3238 anArray->SetValue(1, aRes->Value(anIndex, 1));
3240 Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray);
3241 if (!anObj.IsNull())
3242 aPair.first = anObj;
3244 anArray = new TColStd_HArray1OfInteger(1, 1);
3245 anArray->SetValue(1, aRes->Value(anIndex, 2));
3247 anObj = GetEngine()->AddSubShape(theShape, anArray);
3248 if (!anObj.IsNull())
3249 aPair.second = anObj;
3250 theChecks.push_back({ aTypesChecks->Value(anIndex), aPair });
3253 catch (Standard_Failure& aFail)
3255 SetErrorCode(aFail.GetMessageString());
3263 //=============================================================================
3266 * Compute possible tolerance for the shape, minimize tolerance of shape as well
3267 * as tolerance of sub-shapes as much as possible
3268 * \param theShape Shape for compute tolerance.
3270 //=============================================================================
3271 double GEOMImpl_IMeasureOperations::UpdateTolerance(Handle(GEOM_Object) theShape)
3274 MESSAGE("GEOMImpl_IMeasureOperations::updateTolerance");
3276 double aResTol = -1;
3277 Handle(GEOM_Object) aConformity = GetEngine()->AddObject(GEOM_CHECKCONFORMITY);
3278 Handle(GEOM_Function) aFunction = aConformity->AddFunction(GEOMImpl_ConformityDriver::GetID(), CONFORMITY_UPDATE_TOL);
3279 if (aFunction.IsNull()) return aResTol;
3281 //Check if the function is set correctly
3282 if (aFunction->GetDriverGUID() != GEOMImpl_ConformityDriver::GetID()) return aResTol;
3284 GEOMImpl_IConformity aCI(aFunction);
3286 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
3287 if (aRefShape.IsNull()) return aResTol;
3289 aCI.SetShape(aRefShape);
3294 if (!GetSolver()->ComputeFunction(aFunction))
3296 SetErrorCode("Failed: updateTolerance");
3299 aResTol = aFunction->GetReal(CHECKCONFORMITY_RET_TOLERANCE);
3301 catch (Standard_Failure& aFail)
3303 SetErrorCode(aFail.GetMessageString());
3311 //=============================================================================
3314 * Compute distance from the edge to the face.
3316 //=============================================================================
3317 double GEOMImpl_IMeasureOperations::ComputeTolerance(Handle(GEOM_Object) theEdge,
3318 Handle(GEOM_Object) theFace)
3320 double aMaxDist = Precision::Infinite();
3321 if (theEdge.IsNull() || theFace.IsNull())
3324 Handle(GEOM_Function) aRefEdge = theEdge->GetLastFunction();
3325 Handle(GEOM_Function) aRefFace = theFace->GetLastFunction();
3326 if (aRefEdge.IsNull() || aRefFace.IsNull())
3329 TopoDS_Edge aEdge = TopoDS::Edge(aRefEdge->GetValue());
3330 TopoDS_Face aFace = TopoDS::Face(aRefFace->GetValue());
3331 if (aEdge.IsNull() || aFace.IsNull())
3334 double aParam = 0.0;
3335 BOPTools_AlgoTools::ComputeTolerance(aFace, aEdge, aMaxDist, aParam);
3339 //=======================================================================
3340 //function : FillErrorsSub
3341 //purpose : Fill the errors list of subshapes on shape.
3342 //=======================================================================
3343 void GEOMImpl_IMeasureOperations::FillErrorsSub
3344 (const BRepCheck_Analyzer &theAna,
3345 const TopoDS_Shape &theShape,
3346 const TopAbs_ShapeEnum theSubType,
3347 TopTools_DataMapOfIntegerListOfShape &theMapErrors) const
3349 TopExp_Explorer anExp(theShape, theSubType);
3350 TopTools_MapOfShape aMapSubShapes;
3352 for (; anExp.More(); anExp.Next()) {
3353 const TopoDS_Shape &aSubShape = anExp.Current();
3355 if (aMapSubShapes.Add(aSubShape)) {
3356 const Handle(BRepCheck_Result) &aRes = theAna.Result(aSubShape);
3358 for (aRes->InitContextIterator();
3359 aRes->MoreShapeInContext();
3360 aRes->NextShapeInContext()) {
3361 if (aRes->ContextualShape().IsSame(theShape)) {
3362 BRepCheck_ListIteratorOfListOfStatus itl(aRes->StatusOnShape());
3364 if (itl.Value() != BRepCheck_NoError) {
3365 // Add all errors for theShape and its sub-shape.
3366 for (;itl.More(); itl.Next()) {
3367 const Standard_Integer aStat = (Standard_Integer)itl.Value();
3369 if (!theMapErrors.IsBound(aStat)) {
3370 TopTools_ListOfShape anEmpty;
3372 theMapErrors.Bind(aStat, anEmpty);
3375 TopTools_ListOfShape &theShapes = theMapErrors.ChangeFind(aStat);
3377 theShapes.Append(aSubShape);
3378 theShapes.Append(theShape);
3389 //=======================================================================
3390 //function : FillErrors
3391 //purpose : Fill the errors list.
3392 //=======================================================================
3393 void GEOMImpl_IMeasureOperations::FillErrors
3394 (const BRepCheck_Analyzer &theAna,
3395 const TopoDS_Shape &theShape,
3396 TopTools_DataMapOfIntegerListOfShape &theMapErrors,
3397 TopTools_MapOfShape &theMapShapes) const
3399 if (theMapShapes.Add(theShape)) {
3400 // Fill errors of child shapes.
3401 for (TopoDS_Iterator iter(theShape); iter.More(); iter.Next()) {
3402 FillErrors(theAna, iter.Value(), theMapErrors, theMapShapes);
3405 // Fill errors of theShape.
3406 const Handle(BRepCheck_Result) &aRes = theAna.Result(theShape);
3408 if (!aRes.IsNull()) {
3409 BRepCheck_ListIteratorOfListOfStatus itl(aRes->Status());
3411 if (itl.Value() != BRepCheck_NoError) {
3412 // Add all errors for theShape.
3413 for (;itl.More(); itl.Next()) {
3414 const Standard_Integer aStat = (Standard_Integer)itl.Value();
3416 if (!theMapErrors.IsBound(aStat)) {
3417 TopTools_ListOfShape anEmpty;
3419 theMapErrors.Bind(aStat, anEmpty);
3422 theMapErrors.ChangeFind(aStat).Append(theShape);
3427 // Add errors of subshapes on theShape.
3428 const TopAbs_ShapeEnum aType = theShape.ShapeType();
3432 FillErrorsSub(theAna, theShape, TopAbs_VERTEX, theMapErrors);
3435 FillErrorsSub(theAna, theShape, TopAbs_WIRE, theMapErrors);
3436 FillErrorsSub(theAna, theShape, TopAbs_EDGE, theMapErrors);
3437 FillErrorsSub(theAna, theShape, TopAbs_VERTEX, theMapErrors);
3440 FillErrorsSub(theAna, theShape, TopAbs_SHELL, theMapErrors);
3448 //=======================================================================
3449 //function : FillErrors
3450 //purpose : Fill the errors list.
3451 //=======================================================================
3452 void GEOMImpl_IMeasureOperations::FillErrors
3453 (const BRepCheck_Analyzer &theAna,
3454 const TopoDS_Shape &theShape,
3455 std::list<ShapeError> &theErrors) const
3457 // Fill the errors map.
3458 TopTools_DataMapOfIntegerListOfShape aMapErrors;
3459 TopTools_MapOfShape aMapShapes;
3461 FillErrors(theAna, theShape, aMapErrors, aMapShapes);
3463 // Map sub-shapes and their indices
3464 TopTools_IndexedMapOfShape anIndices;
3466 TopExp::MapShapes(theShape, anIndices);
3468 TopTools_DataMapIteratorOfDataMapOfIntegerListOfShape aMapIter(aMapErrors);
3470 for (; aMapIter.More(); aMapIter.Next()) {
3473 anError.error = (BRepCheck_Status)aMapIter.Key();
3475 TopTools_ListIteratorOfListOfShape aListIter(aMapIter.Value());
3476 TopTools_MapOfShape aMapUnique;
3478 for (; aListIter.More(); aListIter.Next()) {
3479 const TopoDS_Shape &aShape = aListIter.Value();
3481 if (aMapUnique.Add(aShape)) {
3482 const Standard_Integer anIndex = anIndices.FindIndex(aShape);
3484 anError.incriminated.push_back(anIndex);
3488 if (!anError.incriminated.empty()) {
3489 theErrors.push_back(anError);
3494 //=======================================================================
3495 //function : ShapeProximityCalculator
3496 //purpose : returns an object to compute the proximity value
3497 //=======================================================================
3498 Handle(GEOM_Object) GEOMImpl_IMeasureOperations::ShapeProximityCalculator
3499 (Handle(GEOM_Object) theShape1,
3500 Handle(GEOM_Object) theShape2)
3504 if (theShape1.IsNull() || theShape2.IsNull())
3507 Handle(GEOM_Function) aShapeFunc1 = theShape1->GetLastFunction();
3508 Handle(GEOM_Function) aShapeFunc2 = theShape2->GetLastFunction();
3509 if (aShapeFunc1.IsNull() || aShapeFunc2.IsNull())
3512 Handle(GEOM_Object) aProximityCalc = GetEngine()->AddObject(GEOM_SHAPE_PROXIMITY);
3513 if (aProximityCalc.IsNull())
3516 Handle(GEOM_Function) aProximityFuncCoarse =
3517 aProximityCalc->AddFunction(GEOMImpl_ShapeProximityDriver::GetID(), PROXIMITY_COARSE);
3518 //Check if the function is set correctly
3519 if (aProximityFuncCoarse.IsNull() ||
3520 aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID())
3523 GEOMImpl_IProximity aProximity (aProximityFuncCoarse);
3524 aProximity.SetShapes(aShapeFunc1, aShapeFunc2);
3526 //Make a Python command
3527 GEOM::TPythonDump pd (aProximityFuncCoarse);
3528 pd << "p = geompy.ShapeProximity()\n";
3529 pd << "p.setShapes(" << theShape1 << ", " << theShape2 << ")";
3532 return aProximityCalc;
3535 //=======================================================================
3536 //function : SetShapeSampling
3537 //purpose : set number sample points to compute the coarse proximity
3538 //=======================================================================
3539 void GEOMImpl_IMeasureOperations::SetShapeSampling(Handle(GEOM_Object) theCalculator,
3540 Handle(GEOM_Object) theShape,
3541 const Standard_Integer theNbSamples)
3544 if (theShape.IsNull() ||
3545 theCalculator.IsNull() ||
3546 theCalculator->GetNbFunctions() <= 0 ||
3550 Handle(GEOM_Function) aProximityFuncCoarse = theCalculator->GetFunction(1);
3551 if (aProximityFuncCoarse.IsNull() ||
3552 aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID())
3555 Handle(GEOM_Function) aShapeFunc = theShape->GetLastFunction();
3556 if (aShapeFunc.IsNull())
3559 GEOMImpl_IProximity aProximity(aProximityFuncCoarse);
3560 Handle(GEOM_Function) aShape1, aShape2;
3561 aProximity.GetShapes(aShape1, aShape2);
3562 if (aShape1->GetValue() == aShapeFunc->GetValue())
3563 aProximity.SetNbSamples(PROXIMITY_ARG_SAMPLES1, theNbSamples);
3564 else if (aShape2->GetValue() == aShapeFunc->GetValue())
3565 aProximity.SetNbSamples(PROXIMITY_ARG_SAMPLES2, theNbSamples);
3567 //Make a Python command
3568 GEOM::TPythonDump(aProximityFuncCoarse, /*append=*/true) <<
3569 "p.setSampling(" << theShape << ", " << theNbSamples << ")";
3574 //=======================================================================
3575 //function : GetCoarseProximity
3576 //purpose : compute coarse proximity
3577 //=======================================================================
3578 Standard_Real GEOMImpl_IMeasureOperations::GetCoarseProximity(Handle(GEOM_Object) theCalculator,
3582 if (theCalculator.IsNull())
3585 Handle(GEOM_Function) aProximityFuncCoarse = theCalculator->GetFunction(1);
3586 if (aProximityFuncCoarse.IsNull() ||
3587 aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID() ||
3588 aProximityFuncCoarse->GetType() != PROXIMITY_COARSE)
3592 // We have to recompute the function each time,
3593 // because the number of samples can be changed
3596 if (!GetSolver()->ComputeFunction(aProximityFuncCoarse)) {
3597 SetErrorCode("shape proximity driver failed");
3601 catch (Standard_Failure& aFail) {
3602 SetErrorCode(aFail.GetMessageString());
3606 //Make a Python command
3608 GEOM::TPythonDump(aProximityFuncCoarse, /*append=*/true) << "value = p.coarseProximity()";
3611 GEOMImpl_IProximity aProximity (aProximityFuncCoarse);
3612 return aProximity.GetValue();
3615 //=======================================================================
3616 //function : GetPreciseProximity
3617 //purpose : compute precise proximity
3618 //=======================================================================
3619 Standard_Real GEOMImpl_IMeasureOperations::GetPreciseProximity(Handle(GEOM_Object) theCalculator)
3622 if (theCalculator.IsNull())
3625 Handle(GEOM_Function) aProximityFuncCoarse = theCalculator->GetFunction(1);
3626 Handle(GEOM_Function) aProximityFuncFine = theCalculator->GetFunction(2);
3627 if (aProximityFuncFine.IsNull())
3628 aProximityFuncFine = theCalculator->AddFunction
3629 (GEOMImpl_ShapeProximityDriver::GetID(), PROXIMITY_PRECISE);
3631 //Check if the functions are set correctly
3632 if (aProximityFuncCoarse.IsNull() ||
3633 aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID() ||
3634 aProximityFuncFine.IsNull() ||
3635 aProximityFuncFine->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID())
3638 // perform coarse computation beforehand
3639 GetCoarseProximity(theCalculator, /*doPythonDump=*/false);
3641 // transfer parameters from the coarse to precise calculator
3642 GEOMImpl_IProximity aCoarseProximity (aProximityFuncCoarse);
3643 Handle(GEOM_Function) aShape1, aShape2;
3644 aCoarseProximity.GetShapes(aShape1, aShape2);
3645 if (aShape1.IsNull() || aShape2.IsNull())
3647 gp_Pnt aProxPnt1, aProxPnt2;
3648 Standard_Integer intStatus1, intStatus2;
3649 aCoarseProximity.GetProximityPoints(aProxPnt1, aProxPnt2);
3650 aCoarseProximity.GetStatusOfPoints(intStatus1, intStatus2);
3651 Standard_Real aResultValue = aCoarseProximity.GetValue();
3653 GEOMImpl_IProximity aFineProximity (aProximityFuncFine);
3654 aFineProximity.SetShapes(aShape1, aShape2);
3655 aFineProximity.SetProximityPoints(aProxPnt1, aProxPnt2);
3656 aFineProximity.SetStatusOfPoints(intStatus1, intStatus2);
3657 aFineProximity.SetValue(aResultValue); // in some cases this value cannot be precised
3662 if (!GetSolver()->ComputeFunction(aProximityFuncFine)) {
3663 SetErrorCode("shape proximity driver failed");
3667 catch (Standard_Failure& aFail) {
3668 SetErrorCode(aFail.GetMessageString());
3672 aResultValue = aFineProximity.GetValue();
3673 aFineProximity.GetProximityPoints(aProxPnt1, aProxPnt2);
3675 //Make a Python command
3676 GEOM::TPythonDump(aProximityFuncCoarse, /*append=*/true) << "value = p.preciseProximity()";
3679 return aResultValue;