1 // Copyright (C) 2007-2012 CEA/DEN, EDF R&D, 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.
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 #pragma warning( disable:4786 )
26 #include <Standard_Stream.hxx>
28 #include <GEOMImpl_IBlocksOperations.hxx>
30 #include <GEOMImpl_Types.hxx>
32 #include <GEOMImpl_BlockDriver.hxx>
33 #include <GEOMImpl_IBlocks.hxx>
34 #include <GEOMImpl_IBlockTrsf.hxx>
35 #include <GEOMImpl_CopyDriver.hxx>
36 #include <GEOMImpl_Block6Explorer.hxx>
38 #include <GEOMUtils.hxx>
40 #include <GEOM_Function.hxx>
41 #include <GEOM_PythonDump.hxx>
43 #include <GEOMAlgo_GlueAnalyser.hxx>
44 #include <GEOMAlgo_CoupleOfShapes.hxx>
45 #include <GEOMAlgo_ListOfCoupleOfShapes.hxx>
46 #include <GEOMAlgo_ListIteratorOfListOfCoupleOfShapes.hxx>
47 #include <BlockFix_CheckTool.hxx>
49 #include <Basics_OCCTVersion.hxx>
51 #include "utilities.h"
53 #include <Utils_ExceptHandlers.hxx>
55 #include <TFunction_DriverTable.hxx>
56 #include <TFunction_Driver.hxx>
57 #include <TFunction_Logbook.hxx>
58 #include <TDataStd_Integer.hxx>
59 #include <TDF_Tool.hxx>
61 #include <BRep_Tool.hxx>
62 #include <BRep_Builder.hxx>
63 #include <BRepTools.hxx>
64 #include <BRepTools_WireExplorer.hxx>
65 #include <BRepGProp.hxx>
66 #include <BRepBndLib.hxx>
67 #include <BRepAdaptor_Surface.hxx>
68 #include <BRepClass_FaceClassifier.hxx>
69 #include <BRepClass3d_SolidClassifier.hxx>
70 #include <BRepExtrema_DistShapeShape.hxx>
74 #include <TopoDS_Edge.hxx>
75 #include <TopoDS_Vertex.hxx>
76 #include <TopoDS_Compound.hxx>
77 #include <TopoDS_Iterator.hxx>
79 #include <TopExp_Explorer.hxx>
80 #include <TopTools_MapOfShape.hxx>
81 #include <TopTools_Array1OfShape.hxx>
82 #include <TopTools_IndexedMapOfShape.hxx>
83 #include <TopTools_DataMapOfShapeInteger.hxx>
84 #include <TopTools_ListIteratorOfListOfShape.hxx>
85 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
86 #include <TopTools_DataMapIteratorOfDataMapOfShapeInteger.hxx>
88 #include <Bnd_Box.hxx>
89 #include <GProp_GProps.hxx>
91 #include <Geom_Surface.hxx>
92 #include <ShapeAnalysis_Surface.hxx>
94 #include <TColStd_MapOfInteger.hxx>
95 #include <TColStd_Array1OfReal.hxx>
96 #include <TColStd_Array1OfInteger.hxx>
97 #include <TColStd_Array2OfInteger.hxx>
99 //#include <OSD_Timer.hxx>
101 #include <Precision.hxx>
103 #include <Standard_Failure.hxx>
104 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
106 //=============================================================================
110 //=============================================================================
111 GEOMImpl_IBlocksOperations::GEOMImpl_IBlocksOperations (GEOM_Engine* theEngine, int theDocID)
112 : GEOM_IOperations(theEngine, theDocID)
114 MESSAGE("GEOMImpl_IBlocksOperations::GEOMImpl_IBlocksOperations");
117 //=============================================================================
121 //=============================================================================
122 GEOMImpl_IBlocksOperations::~GEOMImpl_IBlocksOperations()
124 MESSAGE("GEOMImpl_IBlocksOperations::~GEOMImpl_IBlocksOperations");
128 //=============================================================================
132 //=============================================================================
133 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad
134 (Handle(GEOM_Object) theEdge1, Handle(GEOM_Object) theEdge2,
135 Handle(GEOM_Object) theEdge3, Handle(GEOM_Object) theEdge4)
139 if (theEdge1.IsNull() || theEdge2.IsNull() ||
140 theEdge3.IsNull() || theEdge4.IsNull()) return NULL;
142 //Add a new Face object
143 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
145 //Add a new Face function
146 Handle(GEOM_Function) aFunction =
147 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_FOUR_EDGES);
149 //Check if the function is set correctly
150 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
152 GEOMImpl_IBlocks aPI (aFunction);
154 Handle(GEOM_Function) aRef1 = theEdge1->GetLastFunction();
155 Handle(GEOM_Function) aRef2 = theEdge2->GetLastFunction();
156 Handle(GEOM_Function) aRef3 = theEdge3->GetLastFunction();
157 Handle(GEOM_Function) aRef4 = theEdge4->GetLastFunction();
158 if (aRef1.IsNull() || aRef2.IsNull() ||
159 aRef3.IsNull() || aRef4.IsNull()) return NULL;
161 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
162 aShapesSeq->Append(aRef1);
163 aShapesSeq->Append(aRef2);
164 aShapesSeq->Append(aRef3);
165 aShapesSeq->Append(aRef4);
167 aPI.SetShapes(aShapesSeq);
169 //Compute the Face value
171 #if OCC_VERSION_LARGE > 0x06010000
174 if (!GetSolver()->ComputeFunction(aFunction)) {
175 SetErrorCode("Block driver failed to compute a face");
179 catch (Standard_Failure) {
180 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
181 SetErrorCode(aFail->GetMessageString());
185 //Make a Python command
186 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeQuad("
187 << theEdge1 << ", " << theEdge2 << ", " << theEdge3 << ", " << theEdge4 << ")";
193 //=============================================================================
197 //=============================================================================
198 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad2Edges
199 (Handle(GEOM_Object) theEdge1, Handle(GEOM_Object) theEdge2)
203 if (theEdge1.IsNull() || theEdge2.IsNull()) return NULL;
205 //Add a new Face object
206 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
208 //Add a new Face function
209 Handle(GEOM_Function) aFunction =
210 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_TWO_EDGES);
212 //Check if the function is set correctly
213 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
215 GEOMImpl_IBlocks aPI (aFunction);
217 Handle(GEOM_Function) aRef1 = theEdge1->GetLastFunction();
218 Handle(GEOM_Function) aRef2 = theEdge2->GetLastFunction();
219 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
221 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
222 aShapesSeq->Append(aRef1);
223 aShapesSeq->Append(aRef2);
225 aPI.SetShapes(aShapesSeq);
227 //Compute the Face value
229 #if OCC_VERSION_LARGE > 0x06010000
232 if (!GetSolver()->ComputeFunction(aFunction)) {
233 SetErrorCode("Block driver failed to compute a face");
237 catch (Standard_Failure) {
238 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
239 SetErrorCode(aFail->GetMessageString());
243 //Make a Python command
244 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeQuad2Edges("
245 << theEdge1 << ", " << theEdge2 << ")";
251 //=============================================================================
255 //=============================================================================
256 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad4Vertices
257 (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2,
258 Handle(GEOM_Object) thePnt3, Handle(GEOM_Object) thePnt4)
262 if (thePnt1.IsNull() || thePnt2.IsNull() ||
263 thePnt3.IsNull() || thePnt4.IsNull()) return NULL;
265 //Add a new Face object
266 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
268 //Add a new Face function
269 Handle(GEOM_Function) aFunction =
270 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_FOUR_PNT);
272 //Check if the function is set correctly
273 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
275 GEOMImpl_IBlocks aPI (aFunction);
277 Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
278 Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
279 Handle(GEOM_Function) aRef3 = thePnt3->GetLastFunction();
280 Handle(GEOM_Function) aRef4 = thePnt4->GetLastFunction();
281 if (aRef1.IsNull() || aRef2.IsNull() ||
282 aRef3.IsNull() || aRef4.IsNull()) return NULL;
284 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
285 aShapesSeq->Append(aRef1);
286 aShapesSeq->Append(aRef2);
287 aShapesSeq->Append(aRef3);
288 aShapesSeq->Append(aRef4);
290 aPI.SetShapes(aShapesSeq);
292 //Compute the Face value
294 #if OCC_VERSION_LARGE > 0x06010000
297 if (!GetSolver()->ComputeFunction(aFunction)) {
298 SetErrorCode("Block driver failed to compute a face");
302 catch (Standard_Failure) {
303 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
304 SetErrorCode(aFail->GetMessageString());
308 //Make a Python command
309 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeQuad4Vertices("
310 << thePnt1 << ", " << thePnt2 << ", " << thePnt3 << ", " << thePnt4 << ")";
316 //=============================================================================
320 //=============================================================================
321 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeHexa
322 (Handle(GEOM_Object) theFace1, Handle(GEOM_Object) theFace2,
323 Handle(GEOM_Object) theFace3, Handle(GEOM_Object) theFace4,
324 Handle(GEOM_Object) theFace5, Handle(GEOM_Object) theFace6)
328 if (theFace1.IsNull() || theFace2.IsNull() ||
329 theFace3.IsNull() || theFace4.IsNull() ||
330 theFace5.IsNull() || theFace6.IsNull()) return NULL;
332 //Add a new Solid object
333 Handle(GEOM_Object) aBlock = GetEngine()->AddObject(GetDocID(), GEOM_BLOCK);
335 //Add a new Block function
336 Handle(GEOM_Function) aFunction =
337 aBlock->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_SIX_FACES);
339 //Check if the function is set correctly
340 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
342 GEOMImpl_IBlocks aPI (aFunction);
344 Handle(GEOM_Function) aRef1 = theFace1->GetLastFunction();
345 Handle(GEOM_Function) aRef2 = theFace2->GetLastFunction();
346 Handle(GEOM_Function) aRef3 = theFace3->GetLastFunction();
347 Handle(GEOM_Function) aRef4 = theFace4->GetLastFunction();
348 Handle(GEOM_Function) aRef5 = theFace5->GetLastFunction();
349 Handle(GEOM_Function) aRef6 = theFace6->GetLastFunction();
350 if (aRef1.IsNull() || aRef2.IsNull() ||
351 aRef3.IsNull() || aRef4.IsNull() ||
352 aRef5.IsNull() || aRef6.IsNull()) return NULL;
354 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
355 aShapesSeq->Append(aRef1);
356 aShapesSeq->Append(aRef2);
357 aShapesSeq->Append(aRef3);
358 aShapesSeq->Append(aRef4);
359 aShapesSeq->Append(aRef5);
360 aShapesSeq->Append(aRef6);
362 aPI.SetShapes(aShapesSeq);
364 //Compute the Block value
366 #if OCC_VERSION_LARGE > 0x06010000
369 if (!GetSolver()->ComputeFunction(aFunction)) {
370 SetErrorCode("Block driver failed to compute a block");
374 catch (Standard_Failure) {
375 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
376 SetErrorCode(aFail->GetMessageString());
380 //Make a Python command
381 GEOM::TPythonDump(aFunction) << aBlock << " = geompy.MakeHexa("
382 << theFace1 << ", " << theFace2 << ", " << theFace3 << ", "
383 << theFace4 << ", " << theFace5 << ", " << theFace6 << ")";
389 //=============================================================================
393 //=============================================================================
394 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeHexa2Faces
395 (Handle(GEOM_Object) theFace1, Handle(GEOM_Object) theFace2)
399 if (theFace1.IsNull() || theFace2.IsNull()) return NULL;
401 //Add a new Solid object
402 Handle(GEOM_Object) aBlock = GetEngine()->AddObject(GetDocID(), GEOM_BLOCK);
404 //Add a new Block function
405 Handle(GEOM_Function) aFunction =
406 aBlock->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_TWO_FACES);
408 //Check if the function is set correctly
409 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
411 GEOMImpl_IBlocks aPI (aFunction);
413 Handle(GEOM_Function) aRef1 = theFace1->GetLastFunction();
414 Handle(GEOM_Function) aRef2 = theFace2->GetLastFunction();
415 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
417 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
418 aShapesSeq->Append(aRef1);
419 aShapesSeq->Append(aRef2);
421 aPI.SetShapes(aShapesSeq);
423 //Compute the Block value
425 #if OCC_VERSION_LARGE > 0x06010000
428 if (!GetSolver()->ComputeFunction(aFunction)) {
429 SetErrorCode("Block driver failed to compute a block");
433 catch (Standard_Failure) {
434 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
435 SetErrorCode(aFail->GetMessageString());
439 //Make a Python command
440 GEOM::TPythonDump(aFunction) << aBlock << " = geompy.MakeHexa2Faces("
441 << theFace1 << ", " << theFace2 << ")";
447 //=============================================================================
451 //=============================================================================
452 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeBlockCompound
453 (Handle(GEOM_Object) theCompound)
457 if (theCompound.IsNull()) return NULL;
460 Handle(GEOM_Object) aBlockComp = GetEngine()->AddObject(GetDocID(), GEOM_COMPOUND);
462 //Add a new BlocksComp function
463 Handle(GEOM_Function) aFunction =
464 aBlockComp->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_COMPOUND_GLUE);
466 //Check if the function is set correctly
467 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
469 GEOMImpl_IBlocks aPI (aFunction);
471 Handle(GEOM_Function) aRef1 = theCompound->GetLastFunction();
472 if (aRef1.IsNull()) return NULL;
474 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
475 aShapesSeq->Append(aRef1);
477 aPI.SetShapes(aShapesSeq);
479 //Compute the Blocks Compound value
481 #if OCC_VERSION_LARGE > 0x06010000
484 if (!GetSolver()->ComputeFunction(aFunction)) {
485 SetErrorCode("Block driver failed to compute a blocks compound");
489 catch (Standard_Failure) {
490 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
491 SetErrorCode(aFail->GetMessageString());
495 //Make a Python command
496 GEOM::TPythonDump(aFunction) << aBlockComp
497 << " = geompy.MakeBlockCompound(" << theCompound << ")";
503 //=============================================================================
507 //=============================================================================
508 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetPoint
509 (Handle(GEOM_Object) theShape,
510 const Standard_Real theX,
511 const Standard_Real theY,
512 const Standard_Real theZ,
513 const Standard_Real theEpsilon)
518 Handle(GEOM_Object) aResult;
521 if (theShape.IsNull()) return NULL;
523 TopoDS_Shape aBlockOrComp = theShape->GetValue();
524 if (aBlockOrComp.IsNull()) {
525 SetErrorCode("Given shape is null");
529 //Compute the Vertex value
530 gp_Pnt P (theX, theY, theZ);
531 Standard_Real eps = Max(theEpsilon, Precision::Confusion());
534 Standard_Integer isFound = 0;
535 TopTools_MapOfShape mapShape;
536 TopExp_Explorer exp (aBlockOrComp, TopAbs_VERTEX);
538 for (; exp.More(); exp.Next()) {
539 if (mapShape.Add(exp.Current())) {
540 TopoDS_Vertex aVi = TopoDS::Vertex(exp.Current());
541 gp_Pnt aPi = BRep_Tool::Pnt(aVi);
542 if (aPi.Distance(P) < eps) {
550 SetErrorCode("Vertex has not been found");
552 } else if (isFound > 1) {
553 SetErrorCode("Multiple vertices found by the given coordinates and epsilon");
556 TopTools_IndexedMapOfShape anIndices;
557 TopExp::MapShapes(aBlockOrComp, anIndices);
558 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
559 anArray->SetValue(1, anIndices.FindIndex(V));
560 aResult = GetEngine()->AddSubShape(theShape, anArray);
563 //The GetPoint() doesn't change object so no new function is required.
564 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
566 //Make a Python command
567 GEOM::TPythonDump(aFunction, /*append=*/true)
568 << aResult << " = geompy.GetPoint(" << theShape << ", "
569 << theX << ", " << theY << ", " << theZ << ", " << theEpsilon << ")";
575 //=============================================================================
579 //=============================================================================
580 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetVertexNearPoint
581 (Handle(GEOM_Object) theShape,
582 Handle(GEOM_Object) thePoint)
587 Handle(GEOM_Object) aResult;
590 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
592 TopoDS_Shape aBlockOrComp = theShape->GetValue();
593 TopoDS_Shape aPoint = thePoint->GetValue();
594 if (aBlockOrComp.IsNull() || aPoint.IsNull()) {
595 SetErrorCode("Given shape is null");
599 if (aPoint.ShapeType() != TopAbs_VERTEX) {
600 SetErrorCode("Element for vertex identification is not a vertex");
604 TopoDS_Vertex aVert = TopoDS::Vertex(aPoint);
605 gp_Pnt aP = BRep_Tool::Pnt(aVert);
607 // Compute the Vertex value
609 bool isFound = false;
610 Standard_Real aDist = RealLast();
611 TopTools_MapOfShape mapShape;
613 TopExp_Explorer exp (aBlockOrComp, TopAbs_VERTEX);
614 for (; exp.More(); exp.Next()) {
615 if (mapShape.Add(exp.Current())) {
616 TopoDS_Vertex aVi = TopoDS::Vertex(exp.Current());
617 gp_Pnt aPi = BRep_Tool::Pnt(aVi);
618 Standard_Real aDisti = aPi.Distance(aP);
619 if (aDisti < aDist) {
628 SetErrorCode("Vertex has not been found");
632 TopTools_IndexedMapOfShape anIndices;
633 TopExp::MapShapes(aBlockOrComp, anIndices);
634 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
635 anArray->SetValue(1, anIndices.FindIndex(V));
636 aResult = GetEngine()->AddSubShape(theShape, anArray);
638 // The GetPoint() doesn't change object so no new function is required.
639 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
641 // Make a Python command
642 GEOM::TPythonDump(aFunction, /*append=*/true)
643 << aResult << " = geompy.GetVertexNearPoint("
644 << theShape << ", " << thePoint << ")";
650 //=============================================================================
654 //=============================================================================
655 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetEdge
656 (Handle(GEOM_Object) theShape,
657 Handle(GEOM_Object) thePoint1,
658 Handle(GEOM_Object) thePoint2)
663 Handle(GEOM_Object) aResult;
666 if (theShape.IsNull() || thePoint1.IsNull() || thePoint2.IsNull()) return NULL;
668 TopoDS_Shape aBlockOrComp = theShape->GetValue();
669 if (aBlockOrComp.IsNull()) {
670 SetErrorCode("Given shape is null");
674 TopoDS_Shape anArg1 = thePoint1->GetValue();
675 TopoDS_Shape anArg2 = thePoint2->GetValue();
676 if (anArg1.IsNull() || anArg2.IsNull()) {
677 SetErrorCode("Null shape is given as argument");
680 if (anArg1.ShapeType() != TopAbs_VERTEX ||
681 anArg2.ShapeType() != TopAbs_VERTEX) {
682 SetErrorCode("Element for edge identification is not a vertex");
686 //Compute the Edge value
688 #if OCC_VERSION_LARGE > 0x06010000
691 TopTools_IndexedDataMapOfShapeListOfShape MVE;
692 GEOMImpl_Block6Explorer::MapShapesAndAncestors
693 (aBlockOrComp, TopAbs_VERTEX, TopAbs_EDGE, MVE);
696 Standard_Integer ish, ext = MVE.Extent();
698 if (MVE.Contains(anArg1)) {
701 for (ish = 1; ish <= ext; ish++) {
702 TopoDS_Shape aShi = MVE.FindKey(ish);
703 if (BRepTools::Compare(TopoDS::Vertex(anArg1), TopoDS::Vertex(aShi))) {
710 if (MVE.Contains(anArg2)) {
713 for (ish = 1; ish <= ext; ish++) {
714 TopoDS_Shape aShi = MVE.FindKey(ish);
715 if (BRepTools::Compare(TopoDS::Vertex(anArg2), TopoDS::Vertex(aShi))) {
722 if (V1.IsNull() || V2.IsNull()) {
723 SetErrorCode("The given vertex does not belong to the shape");
728 Standard_Integer isFound =
729 GEOMImpl_Block6Explorer::FindEdge(anEdge, V1, V2, MVE, Standard_True);
731 SetErrorCode("The given vertices do not belong to one edge of the given shape");
733 } else if (isFound > 1) {
734 SetErrorCode("Multiple edges found by the given vertices of the shape");
737 TopTools_IndexedMapOfShape anIndices;
738 TopExp::MapShapes(aBlockOrComp, anIndices);
739 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
740 anArray->SetValue(1, anIndices.FindIndex(anEdge));
741 aResult = GetEngine()->AddSubShape(theShape, anArray);
743 } catch (Standard_Failure) {
744 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
745 SetErrorCode(aFail->GetMessageString());
749 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
751 //Make a Python command
752 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetEdge("
753 << theShape << ", " << thePoint1 << ", " << thePoint2 << ")";
759 //=============================================================================
763 //=============================================================================
764 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetEdgeNearPoint
765 (Handle(GEOM_Object) theShape,
766 Handle(GEOM_Object) thePoint)
771 Handle(GEOM_Object) aResult;
774 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
776 TopoDS_Shape aBlockOrComp = theShape->GetValue();
777 if (aBlockOrComp.IsNull()) {
778 SetErrorCode("Given shape is null");
782 TopoDS_Shape anArg = thePoint->GetValue();
783 if (anArg.IsNull()) {
784 SetErrorCode("Null shape is given as argument");
787 if (anArg.ShapeType() != TopAbs_VERTEX) {
788 SetErrorCode("Element for edge identification is not a vertex");
792 //Compute the Edge value
794 #if OCC_VERSION_LARGE > 0x06010000
797 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
798 TopoDS_Shape aShape = GEOMUtils::GetEdgeNearPoint(aBlockOrComp, aVert);
800 TopTools_IndexedMapOfShape anIndices;
801 TopExp::MapShapes(aBlockOrComp, anIndices);
802 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
803 anArray->SetValue(1, anIndices.FindIndex(aShape));
804 aResult = GetEngine()->AddSubShape(theShape, anArray);
806 catch (Standard_Failure) {
807 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
808 SetErrorCode(aFail->GetMessageString());
812 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
814 //Make a Python command
815 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetEdgeNearPoint("
816 << theShape << ", " << thePoint << ")";
822 //=============================================================================
826 //=============================================================================
827 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByPoints
828 (Handle(GEOM_Object) theShape,
829 Handle(GEOM_Object) thePoint1,
830 Handle(GEOM_Object) thePoint2,
831 Handle(GEOM_Object) thePoint3,
832 Handle(GEOM_Object) thePoint4)
837 Handle(GEOM_Object) aResult;
840 if (theShape.IsNull() ||
841 thePoint1.IsNull() || thePoint2.IsNull() ||
842 thePoint3.IsNull() || thePoint4.IsNull()) return NULL;
844 TopoDS_Shape aBlockOrComp = theShape->GetValue();
845 if (aBlockOrComp.IsNull()) {
846 SetErrorCode("Block or compound is null");
850 TopoDS_Shape anArg1 = thePoint1->GetValue();
851 TopoDS_Shape anArg2 = thePoint2->GetValue();
852 TopoDS_Shape anArg3 = thePoint3->GetValue();
853 TopoDS_Shape anArg4 = thePoint4->GetValue();
854 if (anArg1.IsNull() || anArg2.IsNull() ||
855 anArg3.IsNull() || anArg4.IsNull()) {
856 SetErrorCode("Null shape is given as argument");
859 if (anArg1.ShapeType() != TopAbs_VERTEX ||
860 anArg2.ShapeType() != TopAbs_VERTEX ||
861 anArg3.ShapeType() != TopAbs_VERTEX ||
862 anArg4.ShapeType() != TopAbs_VERTEX) {
863 SetErrorCode("Element for face identification is not a vertex");
867 //Compute the Face value
869 #if OCC_VERSION_LARGE > 0x06010000
874 TopTools_IndexedDataMapOfShapeListOfShape MVF;
875 GEOMImpl_Block6Explorer::MapShapesAndAncestors(aBlockOrComp, TopAbs_VERTEX, TopAbs_FACE, MVF);
877 TopoDS_Shape V1,V2,V3,V4;
878 Standard_Integer ish, ext = MVF.Extent();
880 if (MVF.Contains(anArg1)) {
883 for (ish = 1; ish <= ext; ish++) {
884 TopoDS_Shape aShi = MVF.FindKey(ish);
885 if (BRepTools::Compare(TopoDS::Vertex(anArg1), TopoDS::Vertex(aShi))) {
892 if (MVF.Contains(anArg2)) {
895 for (ish = 1; ish <= ext; ish++) {
896 TopoDS_Shape aShi = MVF.FindKey(ish);
897 if (BRepTools::Compare(TopoDS::Vertex(anArg2), TopoDS::Vertex(aShi))) {
904 if (MVF.Contains(anArg3)) {
907 for (ish = 1; ish <= ext; ish++) {
908 TopoDS_Shape aShi = MVF.FindKey(ish);
909 if (BRepTools::Compare(TopoDS::Vertex(anArg3), TopoDS::Vertex(aShi))) {
916 if (MVF.Contains(anArg4)) {
919 for (ish = 1; ish <= ext; ish++) {
920 TopoDS_Shape aShi = MVF.FindKey(ish);
921 if (BRepTools::Compare(TopoDS::Vertex(anArg4), TopoDS::Vertex(aShi))) {
928 if (V1.IsNull() || V2.IsNull() || V3.IsNull() || V4.IsNull()) {
929 SetErrorCode("The given vertex does not belong to the shape");
933 Standard_Integer isFound =
934 GEOMImpl_Block6Explorer::FindFace(aShape, V1, V2, V3, V4, MVF, Standard_True);
936 SetErrorCode("The given vertices do not belong to one face of the given shape");
938 } else if (isFound > 1) {
939 SetErrorCode("The given vertices belong to several faces of the given shape");
942 TopTools_IndexedMapOfShape anIndices;
943 TopExp::MapShapes(aBlockOrComp, anIndices);
944 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
945 anArray->SetValue(1, anIndices.FindIndex(aShape));
946 aResult = GetEngine()->AddSubShape(theShape, anArray);
949 catch (Standard_Failure) {
950 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
951 SetErrorCode(aFail->GetMessageString());
955 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
957 //Make a Python command
958 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByPoints("
959 << theShape << ", " << thePoint1 << ", " << thePoint2
960 << ", " << thePoint3 << ", " << thePoint4 << ")";
966 //=============================================================================
970 //=============================================================================
971 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByEdges
972 (Handle(GEOM_Object) theShape,
973 Handle(GEOM_Object) theEdge1,
974 Handle(GEOM_Object) theEdge2)
979 Handle(GEOM_Object) aResult;
982 if (theShape.IsNull() || theEdge1.IsNull() || theEdge2.IsNull()) return NULL;
984 TopoDS_Shape aBlockOrComp = theShape->GetValue();
985 if (aBlockOrComp.IsNull()) {
986 SetErrorCode("Block or compound is null");
990 TopoDS_Shape anArg1 = theEdge1->GetValue();
991 TopoDS_Shape anArg2 = theEdge2->GetValue();
992 if (anArg1.IsNull() || anArg2.IsNull()) {
993 SetErrorCode("Null shape is given as argument");
996 if (anArg1.ShapeType() != TopAbs_EDGE ||
997 anArg2.ShapeType() != TopAbs_EDGE) {
998 SetErrorCode("Element for face identification is not an edge");
1002 //Compute the Face value
1004 #if OCC_VERSION_LARGE > 0x06010000
1007 TopoDS_Shape aShape;
1009 TopTools_IndexedDataMapOfShapeListOfShape MEF;
1010 GEOMImpl_Block6Explorer::MapShapesAndAncestors(aBlockOrComp, TopAbs_EDGE, TopAbs_FACE, MEF);
1013 Standard_Integer ish, ext = MEF.Extent();
1015 if (MEF.Contains(anArg1)) {
1018 for (ish = 1; ish <= ext; ish++) {
1019 TopoDS_Shape aShi = MEF.FindKey(ish);
1020 if (GEOMImpl_Block6Explorer::IsSimilarEdges(anArg1, aShi)) {
1026 if (MEF.Contains(anArg2)) {
1029 for (ish = 1; ish <= ext; ish++) {
1030 TopoDS_Shape aShi = MEF.FindKey(ish);
1031 if (GEOMImpl_Block6Explorer::IsSimilarEdges(anArg2, aShi)) {
1037 if (E1.IsNull() || E2.IsNull()) {
1038 SetErrorCode("The given edge does not belong to the shape");
1042 const TopTools_ListOfShape& aFacesOfE1 = MEF.FindFromKey(E1);
1043 const TopTools_ListOfShape& aFacesOfE2 = MEF.FindFromKey(E2);
1045 Standard_Integer isFound = 0;
1046 TopTools_ListIteratorOfListOfShape anIterF1 (aFacesOfE1);
1047 for (; anIterF1.More(); anIterF1.Next()) {
1049 TopTools_ListIteratorOfListOfShape anIterF2 (aFacesOfE2);
1050 for (; anIterF2.More(); anIterF2.Next()) {
1052 if (anIterF1.Value().IsSame(anIterF2.Value())) {
1055 // Store the face, defined by two edges
1056 aShape = anIterF1.Value();
1061 SetErrorCode("The given edges do not belong to one face of the given shape");
1063 } else if (isFound > 1) {
1064 SetErrorCode("The given edges belong to several faces of the given shape");
1067 TopTools_IndexedMapOfShape anIndices;
1068 TopExp::MapShapes(aBlockOrComp, anIndices);
1069 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1070 anArray->SetValue(1, anIndices.FindIndex(aShape));
1071 aResult = GetEngine()->AddSubShape(theShape, anArray);
1074 catch (Standard_Failure) {
1075 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1076 SetErrorCode(aFail->GetMessageString());
1080 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1082 //Make a Python command
1083 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByEdges("
1084 << theShape << ", " << theEdge1 << ", " << theEdge2 << ")";
1090 //=============================================================================
1094 //=============================================================================
1095 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetOppositeFace
1096 (Handle(GEOM_Object) theShape,
1097 Handle(GEOM_Object) theFace)
1102 Handle(GEOM_Object) aResult;
1105 if (theShape.IsNull() || theFace.IsNull()) return NULL;
1107 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1108 if (aBlockOrComp.IsNull()) {
1109 SetErrorCode("Block is null");
1112 if (aBlockOrComp.ShapeType() != TopAbs_SOLID) {
1113 SetErrorCode("Shape is not a block");
1117 TopoDS_Shape anArg = theFace->GetValue();
1118 if (anArg.IsNull()) {
1119 SetErrorCode("Null shape is given as argument");
1122 if (anArg.ShapeType() != TopAbs_FACE) {
1123 SetErrorCode("Element for face identification is not a face");
1127 //Compute the Face value
1129 #if OCC_VERSION_LARGE > 0x06010000
1132 TopoDS_Shape aShape;
1134 GEOMImpl_Block6Explorer aBlockTool;
1135 aBlockTool.InitByBlockAndFace(aBlockOrComp, anArg);
1136 aShape = aBlockTool.GetFace(2);
1138 TopTools_IndexedMapOfShape anIndices;
1139 TopExp::MapShapes(aBlockOrComp, anIndices);
1140 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1141 anArray->SetValue(1, anIndices.FindIndex(aShape));
1142 aResult = GetEngine()->AddSubShape(theShape, anArray);
1144 catch (Standard_Failure) {
1145 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1146 SetErrorCode(aFail->GetMessageString());
1150 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1152 //Make a Python command
1153 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetOppositeFace("
1154 << theShape << ", " << theFace << ")";
1160 //=============================================================================
1164 //=============================================================================
1165 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceNearPoint
1166 (Handle(GEOM_Object) theShape,
1167 Handle(GEOM_Object) thePoint)
1172 Handle(GEOM_Object) aResult;
1175 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
1177 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1178 if (aBlockOrComp.IsNull()) {
1179 SetErrorCode("Block or compound is null");
1183 TopoDS_Shape anArg = thePoint->GetValue();
1184 if (anArg.IsNull()) {
1185 SetErrorCode("Null shape is given as argument");
1188 if (anArg.ShapeType() != TopAbs_VERTEX) {
1189 SetErrorCode("Element for face identification is not a vertex");
1193 //Compute the Face value
1195 #if OCC_VERSION_LARGE > 0x06010000
1198 TopoDS_Shape aShape;
1200 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
1201 gp_Pnt aPnt = BRep_Tool::Pnt(aVert);
1202 Standard_Real PX, PY, PZ;
1203 aPnt.Coord(PX, PY, PZ);
1205 // 1. Classify the point relatively each face
1206 Standard_Integer nearest = 2, nbFound = 0;
1207 TopTools_DataMapOfShapeInteger mapShapeDist;
1208 TopExp_Explorer exp (aBlockOrComp, TopAbs_FACE);
1209 for (; exp.More(); exp.Next()) {
1210 TopoDS_Shape aFace = exp.Current();
1212 if (!mapShapeDist.IsBound(aFace)) {
1213 Standard_Integer aDistance = 2;
1215 // 1.a. Classify relatively Surface
1216 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aFace));
1217 Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf);
1218 gp_Pnt2d p2dOnSurf = aSurfAna->ValueOfUV(aPnt, Precision::Confusion());
1219 gp_Pnt p3dOnSurf = aSurfAna->Value(p2dOnSurf);
1220 Standard_Real aDist = p3dOnSurf.Distance(aPnt);
1221 if (aDist > Precision::Confusion()) {
1225 // 1.b. Classify relatively the face itself
1226 BRepClass_FaceClassifier FC (TopoDS::Face(aFace), p2dOnSurf, Precision::Confusion());
1227 if (FC.State() == TopAbs_IN) {
1229 } else if (FC.State() == TopAbs_ON) {
1236 if (aDistance < nearest) {
1237 nearest = aDistance;
1241 // A first found face, containing the point inside, will be returned.
1242 // It is the solution, if there are no
1243 // coincident or intersecting faces in the compound.
1244 if (nearest == -1) break;
1246 } else if (aDistance == nearest) {
1251 mapShapeDist.Bind(aFace, aDistance);
1252 } // if (!mapShapeDist.IsBound(aFace))
1255 // 2. Define face, containing the point or having minimum distance to it
1258 // The point is on boundary of some faces and there are
1259 // no faces, having the point inside
1260 SetErrorCode("Multiple faces near the given point are found");
1263 } else if (nearest == 1) {
1264 // The point is outside some faces and there are
1265 // no faces, having the point inside or on boundary.
1266 // We will get a nearest face
1267 Standard_Real bigReal = RealLast();
1268 Standard_Real minDist = bigReal;
1269 TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
1270 for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
1271 if (mapShapeDistIter.Value() == 1) {
1272 TopoDS_Shape aFace = mapShapeDistIter.Key();
1273 Standard_Real aDist = bigReal;
1275 // 2.a. Fast check of distance - if point projection on surface is on face
1276 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aFace));
1277 Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf);
1278 gp_Pnt2d p2dOnSurf = aSurfAna->ValueOfUV(aPnt, Precision::Confusion());
1279 gp_Pnt p3dOnSurf = aSurfAna->Value(p2dOnSurf);
1280 aDist = p3dOnSurf.Distance(aPnt);
1282 BRepClass_FaceClassifier FC (TopoDS::Face(aFace), p2dOnSurf, Precision::Confusion());
1283 if (FC.State() == TopAbs_OUT) {
1284 if (aDist < minDist) {
1285 // 2.b. Slow check - if point projection on surface is outside of face
1286 BRepExtrema_DistShapeShape aDistTool (aVert, aFace);
1287 if (!aDistTool.IsDone()) {
1288 SetErrorCode("Can not find a distance from the given point to one of faces");
1291 aDist = aDistTool.Value();
1297 if (aDist < minDist) {
1303 } else { // nearest == -1
1304 // // The point is inside some faces.
1305 // // We will get a face with nearest center
1306 // Standard_Real minDist = RealLast();
1307 // TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
1308 // for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
1309 // if (mapShapeDistIter.Value() == -1) {
1310 // TopoDS_Shape aFace = mapShapeDistIter.Key();
1311 // GProp_GProps aSystem;
1312 // BRepGProp::SurfaceProperties(aFace, aSystem);
1313 // gp_Pnt aCenterMass = aSystem.CentreOfMass();
1315 // Standard_Real aDist = aCenterMass.Distance(aPnt);
1316 // if (aDist < minDist) {
1323 } // if (nbFound > 1)
1326 SetErrorCode("There are no faces near the given point");
1329 TopTools_IndexedMapOfShape anIndices;
1330 TopExp::MapShapes(aBlockOrComp, anIndices);
1331 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1332 anArray->SetValue(1, anIndices.FindIndex(aShape));
1333 aResult = GetEngine()->AddSubShape(theShape, anArray);
1336 catch (Standard_Failure) {
1337 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1338 SetErrorCode(aFail->GetMessageString());
1342 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1344 //Make a Python command
1345 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceNearPoint("
1346 << theShape << ", " << thePoint << ")";
1352 //=============================================================================
1356 //=============================================================================
1357 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByNormale
1358 (Handle(GEOM_Object) theShape,
1359 Handle(GEOM_Object) theVector)
1364 Handle(GEOM_Object) aResult;
1367 if (theShape.IsNull() || theVector.IsNull()) return NULL;
1369 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1370 if (aBlockOrComp.IsNull()) {
1371 SetErrorCode("Block or compound is null");
1375 TopoDS_Shape anArg = theVector->GetValue();
1376 if (anArg.IsNull()) {
1377 SetErrorCode("Null shape is given as argument");
1380 if (anArg.ShapeType() != TopAbs_EDGE) {
1381 SetErrorCode("Element for normale identification is not an edge");
1385 //Compute the Face value
1387 #if OCC_VERSION_LARGE > 0x06010000
1390 TopoDS_Shape aShape;
1392 TopoDS_Edge anEdge = TopoDS::Edge(anArg);
1393 TopoDS_Vertex V1, V2;
1394 TopExp::Vertices(anEdge, V1, V2, Standard_True);
1395 gp_Pnt P1 = BRep_Tool::Pnt(V1);
1396 gp_Pnt P2 = BRep_Tool::Pnt(V2);
1397 gp_Vec aVec (P1, P2);
1398 if (aVec.Magnitude() < Precision::Confusion()) {
1399 SetErrorCode("Vector with null magnitude is given");
1403 Standard_Real minAngle = RealLast();
1404 TopTools_MapOfShape mapShape;
1405 TopExp_Explorer exp (aBlockOrComp, TopAbs_FACE);
1406 for (; exp.More(); exp.Next()) {
1407 if (mapShape.Add(exp.Current())) {
1408 TopoDS_Face aFace = TopoDS::Face(exp.Current());
1409 BRepAdaptor_Surface SF (aFace);
1411 Standard_Real u, v, x;
1413 // find a point on the surface to get normal direction in
1414 u = SF.FirstUParameter();
1415 x = SF.LastUParameter();
1416 if (Precision::IsInfinite(u)) {
1417 u = (Precision::IsInfinite(x)) ? 0. : x;
1418 } else if (!Precision::IsInfinite(x)) {
1422 v = SF.FirstVParameter();
1423 x = SF.LastVParameter();
1424 if (Precision::IsInfinite(v)) {
1425 v = (Precision::IsInfinite(x)) ? 0. : x;
1426 } else if (!Precision::IsInfinite(x)) {
1430 // compute the normal direction
1432 SF.D1(u,v,P1,Vec1,Vec2);
1433 gp_Vec V = Vec1.Crossed(Vec2);
1435 if (V.Magnitude() < Precision::Confusion()) {
1436 SetErrorCode("Normal vector of a face has null magnitude");
1440 // consider the face orientation
1441 if (aFace.Orientation() == TopAbs_REVERSED ||
1442 aFace.Orientation() == TopAbs_INTERNAL) {
1446 // compute the angle and compare with the minimal one
1447 Standard_Real anAngle = aVec.Angle(V);
1448 if (anAngle < minAngle) {
1455 if (aShape.IsNull()) {
1456 SetErrorCode("Failed to find a face by the given normale");
1459 TopTools_IndexedMapOfShape anIndices;
1460 TopExp::MapShapes(aBlockOrComp, anIndices);
1461 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1462 anArray->SetValue(1, anIndices.FindIndex(aShape));
1463 aResult = GetEngine()->AddSubShape(theShape, anArray);
1466 catch (Standard_Failure) {
1467 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1468 SetErrorCode(aFail->GetMessageString());
1472 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1474 //Make a Python command
1475 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByNormale("
1476 << theShape << ", " << theVector << ")";
1482 //=============================================================================
1484 * GetShapesNearPoint
1486 //=============================================================================
1487 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetShapesNearPoint
1488 (Handle(GEOM_Object) theShape,
1489 Handle(GEOM_Object) thePoint,
1490 const Standard_Integer theShapeType,
1491 const Standard_Real theConstTolerance)
1496 Handle(GEOM_Object) aResult;
1499 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
1501 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1502 if (aBlockOrComp.IsNull()) {
1503 SetErrorCode("Block or compound is null");
1507 TopoDS_Shape anArg = thePoint->GetValue();
1508 if (anArg.IsNull()) {
1509 SetErrorCode("Null shape is given as argument");
1512 if (anArg.ShapeType() != TopAbs_VERTEX) {
1513 SetErrorCode("Element for face identification is not a vertex");
1517 if (theShapeType < TopAbs_SOLID || TopAbs_VERTEX < theShapeType) {
1518 SetErrorCode("Invalid type of result is requested");
1522 Standard_Real theTolerance = theConstTolerance;
1523 if (theTolerance < Precision::Confusion()) {
1524 theTolerance = Precision::Confusion();
1527 // Compute the result
1529 #if OCC_VERSION_LARGE > 0x06010000
1532 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
1534 TopTools_MapOfShape mapShape;
1535 Standard_Integer nbEdges = 0;
1536 TopExp_Explorer exp (aBlockOrComp, TopAbs_ShapeEnum(theShapeType));
1537 for (; exp.More(); exp.Next()) {
1538 if (mapShape.Add(exp.Current())) {
1544 SetErrorCode("Given shape contains no sub-shapes of requested type");
1548 // Calculate distances and find min
1550 Standard_Integer ind = 1;
1551 Standard_Real aMinDist = RealLast();
1552 TopTools_Array1OfShape anEdges (1, nbEdges);
1553 TColStd_Array1OfReal aDistances (1, nbEdges);
1554 for (exp.Init(aBlockOrComp, TopAbs_ShapeEnum(theShapeType)); exp.More(); exp.Next()) {
1555 if (mapShape.Add(exp.Current())) {
1556 TopoDS_Shape anEdge = exp.Current();
1557 anEdges(ind) = anEdge;
1559 BRepExtrema_DistShapeShape aDistTool (aVert, anEdges(ind));
1560 if (!aDistTool.IsDone()) {
1561 SetErrorCode("Can not find a distance from the given point to one of sub-shapes");
1564 aDistances(ind) = aDistTool.Value();
1565 if (aDistances(ind) < aMinDist) {
1566 aMinDist = aDistances(ind);
1572 if (aMinDist < RealLast()) {
1573 // Collect sub-shapes with distance < (aMinDist + theTolerance)
1574 int nbSubShapes = 0;
1575 TopTools_Array1OfShape aNearShapes (1, nbEdges);
1576 for (ind = 1; ind <= nbEdges; ind++) {
1577 if (aDistances(ind) < aMinDist + theTolerance) {
1579 aNearShapes(nbSubShapes) = anEdges(ind);
1584 TopTools_IndexedMapOfShape anIndices;
1585 TopExp::MapShapes(aBlockOrComp, anIndices);
1586 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger (1, nbSubShapes);
1587 for (ind = 1; ind <= nbSubShapes; ind++) {
1588 anArray->SetValue(ind, anIndices.FindIndex(aNearShapes(ind)));
1590 aResult = GetEngine()->AddSubShape(theShape, anArray);
1593 catch (Standard_Failure) {
1594 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1595 SetErrorCode(aFail->GetMessageString());
1599 if (aResult.IsNull())
1602 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1604 //Make a Python command
1605 GEOM::TPythonDump(aFunction)
1606 << aResult << " = geompy.GetShapesNearPoint(" << theShape << ", " << thePoint
1607 << ", " << TopAbs_ShapeEnum(theShapeType) << ", " << theTolerance << ")";
1613 //=============================================================================
1615 * IsCompoundOfBlocks
1617 //=============================================================================
1618 Standard_Boolean GEOMImpl_IBlocksOperations::IsCompoundOfBlocks
1619 (Handle(GEOM_Object) theCompound,
1620 const Standard_Integer theMinNbFaces,
1621 const Standard_Integer theMaxNbFaces,
1622 Standard_Integer& theNbBlocks)
1625 Standard_Boolean isCompOfBlocks = Standard_False;
1628 if (theCompound.IsNull()) return isCompOfBlocks;
1629 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
1632 isCompOfBlocks = Standard_True;
1634 #if OCC_VERSION_LARGE > 0x06010000
1637 TopTools_MapOfShape mapShape;
1638 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
1639 for (; exp.More(); exp.Next()) {
1640 if (mapShape.Add(exp.Current())) {
1641 TopoDS_Shape aSolid = exp.Current();
1643 TopTools_MapOfShape mapFaces;
1644 TopExp_Explorer expF (aSolid, TopAbs_FACE);
1645 Standard_Integer nbFaces = 0;
1646 for (; expF.More(); expF.Next()) {
1647 if (mapFaces.Add(expF.Current())) {
1649 if (nbFaces > theMaxNbFaces) {
1650 isCompOfBlocks = Standard_False;
1655 if (nbFaces < theMinNbFaces || theMaxNbFaces < nbFaces) {
1656 isCompOfBlocks = Standard_False;
1663 catch (Standard_Failure) {
1664 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1665 SetErrorCode(aFail->GetMessageString());
1666 return isCompOfBlocks;
1670 return isCompOfBlocks;
1673 //=============================================================================
1675 * Set of functions, used by CheckCompoundOfBlocks() method
1677 //=============================================================================
1678 void GEOMImpl_IBlocksOperations::AddBlocksFrom (const TopoDS_Shape& theShape,
1679 TopTools_ListOfShape& BLO,
1680 TopTools_ListOfShape& NOT,
1681 TopTools_ListOfShape& EXT,
1682 TopTools_ListOfShape& NOQ)
1684 TopAbs_ShapeEnum aType = theShape.ShapeType();
1686 case TopAbs_COMPOUND:
1687 case TopAbs_COMPSOLID:
1689 TopoDS_Iterator It (theShape);
1690 for (; It.More(); It.Next()) {
1691 AddBlocksFrom(It.Value(), BLO, NOT, EXT, NOQ);
1697 // Check, if there are seam or degenerated edges
1698 BlockFix_CheckTool aTool;
1699 aTool.SetShape(theShape);
1701 if (aTool.NbPossibleBlocks() > 0) {
1702 EXT.Append(theShape);
1704 // Count faces and edges in each face to recognize blocks
1705 TopTools_MapOfShape mapFaces;
1706 Standard_Integer nbFaces = 0;
1707 Standard_Boolean hasNonQuadr = Standard_False;
1708 TopExp_Explorer expF (theShape, TopAbs_FACE);
1710 for (; expF.More(); expF.Next()) {
1711 if (mapFaces.Add(expF.Current())) {
1713 //0021483//if (nbFaces > 6) break;
1716 TopoDS_Shape aF = expF.Current();
1717 TopExp_Explorer wires (aF, TopAbs_WIRE);
1718 if (!wires.More()) {
1719 // no wire in the face
1720 hasNonQuadr = Standard_True;
1721 NOQ.Append(aF);//0021483
1725 TopoDS_Shape aWire = wires.Current();
1728 // multiple wires in the face
1729 hasNonQuadr = Standard_True;
1730 NOQ.Append(aF);//0021483
1735 // Check number of edges in the face
1736 Standard_Integer nbEdges = 0;
1737 TopTools_MapOfShape mapEdges;
1738 TopExp_Explorer expW (aWire, TopAbs_EDGE);
1739 for (; expW.More(); expW.Next()) {
1740 if (mapEdges.Add(expW.Current())) {
1742 if (nbEdges > 4) break;
1746 hasNonQuadr = Standard_True;
1747 NOQ.Append(aF);//0021483
1752 if (nbFaces == 6 && !hasNonQuadr) {
1753 BLO.Append(theShape);
1755 NOT.Append(theShape);
1760 case TopAbs_SHELL: //0021483
1761 case TopAbs_FACE: //0021483
1763 // Count edges in each face
1764 TopTools_MapOfShape mapFaces;
1765 TopExp_Explorer expF (theShape, TopAbs_FACE);
1766 for (; expF.More(); expF.Next()) {
1767 if (mapFaces.Add(expF.Current())) {
1769 TopoDS_Shape aF = expF.Current();
1770 TopExp_Explorer wires (aF, TopAbs_WIRE);
1771 if (!wires.More()) {
1772 // no wire in the face
1773 NOQ.Append(aF);//0021483
1776 TopoDS_Shape aWire = wires.Current();
1779 // multiple wires in the face
1780 NOQ.Append(aF);//0021483
1784 // Check number of edges in the face
1785 Standard_Integer nbEdges = 0;
1786 TopTools_MapOfShape mapEdges;
1787 TopExp_Explorer expW (aWire, TopAbs_EDGE);
1788 for (; expW.More(); expW.Next()) {
1789 if (mapEdges.Add(expW.Current())) {
1791 if (nbEdges > 4) break;
1795 NOQ.Append(aF);//0021483
1802 NOT.Append(theShape);
1806 void AddBlocksFromOld (const TopoDS_Shape& theShape,
1807 TopTools_ListOfShape& BLO,
1808 TopTools_ListOfShape& NOT,
1809 TopTools_ListOfShape& DEG,
1810 TopTools_ListOfShape& SEA)
1812 TopAbs_ShapeEnum aType = theShape.ShapeType();
1814 case TopAbs_COMPOUND:
1815 case TopAbs_COMPSOLID:
1817 TopoDS_Iterator It (theShape);
1818 for (; It.More(); It.Next()) {
1819 AddBlocksFromOld(It.Value(), BLO, NOT, DEG, SEA);
1825 TopTools_MapOfShape mapFaces;
1826 TopExp_Explorer expF (theShape, TopAbs_FACE);
1827 Standard_Integer nbFaces = 0;
1828 Standard_Boolean hasNonQuadr = Standard_False;
1829 Standard_Boolean hasDegenerated = Standard_False;
1830 Standard_Boolean hasSeam = Standard_False;
1831 for (; expF.More(); expF.Next()) {
1832 if (mapFaces.Add(expF.Current())) {
1834 if (nbFaces > 6) break;
1836 // Check number of edges in the face
1837 Standard_Integer nbEdges = 0;
1838 TopTools_MapOfShape mapEdges;
1841 TopoDS_Shape aF = expF.Current();
1842 TopExp_Explorer wires (aF, TopAbs_WIRE);
1843 if (!wires.More()) {
1844 // no wire in the face
1845 hasNonQuadr = Standard_True;
1848 TopoDS_Shape aWire = wires.Current();
1851 // multiple wires in the face
1852 hasNonQuadr = Standard_True;
1857 BRepTools_WireExplorer aWE (TopoDS::Wire(aWire), TopoDS::Face(aF));
1858 for (; aWE.More(); aWE.Next(), nbEdges++) {
1859 if (BRep_Tool::Degenerated(aWE.Current())) {
1860 // degenerated edge found
1861 hasDegenerated = Standard_True;
1864 if (mapEdges.Contains(aWE.Current())) {
1866 hasSeam = Standard_True;
1869 mapEdges.Add(aWE.Current());
1872 hasNonQuadr = Standard_True;
1877 if (hasDegenerated || hasSeam) {
1878 if (hasDegenerated) {
1879 DEG.Append(theShape);
1882 SEA.Append(theShape);
1884 } else if (hasNonQuadr) {
1885 NOT.Append(theShape);
1887 BLO.Append(theShape);
1890 NOT.Append(theShape);
1895 NOT.Append(theShape);
1899 #define REL_NOT_CONNECTED 0
1901 #define REL_NOT_GLUED 2
1902 #define REL_COLLISION_VV 3
1903 #define REL_COLLISION_FF 4
1904 #define REL_COLLISION_EE 5
1905 #define REL_UNKNOWN 6
1907 Standard_Integer BlocksRelation (const TopoDS_Shape& theBlock1,
1908 const TopoDS_Shape& theBlock2)
1910 // Compare bounding boxes before calling BRepExtrema_DistShapeShape
1911 Standard_Real Xmin1, Ymin1, Zmin1, Xmax1, Ymax1, Zmax1;
1912 Standard_Real Xmin2, Ymin2, Zmin2, Xmax2, Ymax2, Zmax2;
1914 BRepBndLib::Add(theBlock1, B1);
1915 BRepBndLib::Add(theBlock2, B2);
1916 B1.Get(Xmin1, Ymin1, Zmin1, Xmax1, Ymax1, Zmax1);
1917 B2.Get(Xmin2, Ymin2, Zmin2, Xmax2, Ymax2, Zmax2);
1918 if (Xmax2 < Xmin1 || Xmax1 < Xmin2 ||
1919 Ymax2 < Ymin1 || Ymax1 < Ymin2 ||
1920 Zmax2 < Zmin1 || Zmax1 < Zmin2) {
1921 return REL_NOT_CONNECTED;
1924 BRepExtrema_DistShapeShape dst (theBlock1, theBlock2);
1925 if (!dst.IsDone()) {
1929 if (dst.Value() > Precision::Confusion()) {
1930 return REL_NOT_CONNECTED;
1933 if (dst.InnerSolution()) {
1934 return REL_COLLISION_VV;
1937 Standard_Integer nbSol = dst.NbSolution();
1938 Standard_Integer relation = REL_OK;
1939 Standard_Integer nbVerts = 0;
1940 Standard_Integer nbEdges = 0;
1941 Standard_Integer sol = 1;
1942 for (; sol <= nbSol; sol++) {
1943 BRepExtrema_SupportType supp1 = dst.SupportTypeShape1(sol);
1944 BRepExtrema_SupportType supp2 = dst.SupportTypeShape2(sol);
1945 if (supp1 == BRepExtrema_IsVertex && supp2 == BRepExtrema_IsVertex) {
1947 } else if (supp1 == BRepExtrema_IsInFace || supp2 == BRepExtrema_IsInFace) {
1948 return REL_COLLISION_FF;
1949 } else if (supp1 == BRepExtrema_IsOnEdge && supp2 == BRepExtrema_IsOnEdge) {
1951 } else if ((supp1 == BRepExtrema_IsOnEdge && supp2 == BRepExtrema_IsVertex) ||
1952 (supp2 == BRepExtrema_IsOnEdge && supp1 == BRepExtrema_IsVertex)) {
1953 relation = REL_COLLISION_EE;
1958 if (relation != REL_OK) {
1962 TColStd_Array1OfInteger vertSol (1, nbVerts);
1963 TopTools_Array1OfShape V1 (1, nbVerts);
1964 TopTools_Array1OfShape V2 (1, nbVerts);
1965 Standard_Integer ivs = 0;
1966 for (sol = 1; sol <= nbSol; sol++) {
1967 if (dst.SupportTypeShape1(sol) == BRepExtrema_IsVertex &&
1968 dst.SupportTypeShape2(sol) == BRepExtrema_IsVertex) {
1969 TopoDS_Vertex Vcur = TopoDS::Vertex(dst.SupportOnShape1(sol));
1970 // Check, that this vertex is far enough from other solution vertices.
1971 Standard_Integer ii = 1;
1972 for (; ii <= ivs; ii++) {
1973 if (BRepTools::Compare(TopoDS::Vertex(V1(ii)), Vcur)) {
1980 V2(ivs) = dst.SupportOnShape2(sol);
1984 // As we deal only with quadrangles,
1985 // 2, 3 or 4 vertex solutions can be found.
1988 return REL_COLLISION_FF;
1990 return REL_NOT_CONNECTED;
1996 // Check sharing of coincident entities.
1997 if (ivs == 2 || ivs == 3) {
1998 // Map vertices and edges of the blocks
1999 TopTools_IndexedDataMapOfShapeListOfShape MVE1, MVE2;
2000 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2001 (theBlock1, TopAbs_VERTEX, TopAbs_EDGE, MVE1);
2002 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2003 (theBlock2, TopAbs_VERTEX, TopAbs_EDGE, MVE2);
2007 TopoDS_Shape anEdge1, anEdge2;
2008 GEOMImpl_Block6Explorer::FindEdge(anEdge1, V1(1), V1(2), MVE1);
2009 if (anEdge1.IsNull()) return REL_UNKNOWN;
2011 GEOMImpl_Block6Explorer::FindEdge(anEdge2, V2(1), V2(2), MVE2);
2012 if (anEdge2.IsNull()) return REL_UNKNOWN;
2014 if (!anEdge1.IsSame(anEdge2)) return REL_NOT_GLUED;
2016 } else { // ivs == 3
2017 // Find common edges
2018 Standard_Integer e1_v1 = 1;
2019 Standard_Integer e1_v2 = 2;
2020 Standard_Integer e2_v1 = 3;
2021 Standard_Integer e2_v2 = 1;
2023 TopoDS_Shape anEdge11, anEdge12;
2024 GEOMImpl_Block6Explorer::FindEdge(anEdge11, V1(e1_v1), V1(e1_v2), MVE1);
2025 if (anEdge11.IsNull()) {
2028 GEOMImpl_Block6Explorer::FindEdge(anEdge11, V1(e1_v1), V1(e1_v2), MVE1);
2029 if (anEdge11.IsNull()) return REL_UNKNOWN;
2031 GEOMImpl_Block6Explorer::FindEdge(anEdge12, V1(e2_v1), V1(e2_v2), MVE1);
2032 if (anEdge12.IsNull()) {
2034 GEOMImpl_Block6Explorer::FindEdge(anEdge12, V1(e2_v1), V1(e2_v2), MVE1);
2035 if (anEdge12.IsNull()) return REL_UNKNOWN;
2038 TopoDS_Shape anEdge21, anEdge22;
2039 GEOMImpl_Block6Explorer::FindEdge(anEdge21, V2(e1_v1), V2(e1_v2), MVE2);
2040 if (anEdge21.IsNull()) return REL_UNKNOWN;
2041 GEOMImpl_Block6Explorer::FindEdge(anEdge22, V2(e2_v1), V2(e2_v2), MVE2);
2042 if (anEdge22.IsNull()) return REL_UNKNOWN;
2044 // Check of edges coincidence (with some precision) have to be done here
2045 // if (!anEdge11.IsEqual(anEdge21)) return REL_UNKNOWN;
2046 // if (!anEdge12.IsEqual(anEdge22)) return REL_UNKNOWN;
2048 // Check of edges sharing
2049 if (!anEdge11.IsSame(anEdge21)) return REL_NOT_GLUED;
2050 if (!anEdge12.IsSame(anEdge22)) return REL_NOT_GLUED;
2055 // Map vertices and faces of the blocks
2056 TopTools_IndexedDataMapOfShapeListOfShape MVF1, MVF2;
2057 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2058 (theBlock1, TopAbs_VERTEX, TopAbs_FACE, MVF1);
2059 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2060 (theBlock2, TopAbs_VERTEX, TopAbs_FACE, MVF2);
2062 TopoDS_Shape aFace1, aFace2;
2063 GEOMImpl_Block6Explorer::FindFace(aFace1, V1(1), V1(2), V1(3), V1(4), MVF1);
2064 if (aFace1.IsNull()) return REL_UNKNOWN;
2065 GEOMImpl_Block6Explorer::FindFace(aFace2, V2(1), V2(2), V2(3), V2(4), MVF2);
2066 if (aFace2.IsNull()) return REL_UNKNOWN;
2068 // Check of faces coincidence (with some precision) have to be done here
2069 // if (!aFace1.IsEqual(aFace2)) return REL_UNKNOWN;
2071 // Check of faces sharing
2072 if (!aFace1.IsSame(aFace2)) return REL_NOT_GLUED;
2078 void FindConnected (const Standard_Integer theBlockIndex,
2079 const TColStd_Array2OfInteger& theRelations,
2080 TColStd_MapOfInteger& theProcessedMap,
2081 TColStd_MapOfInteger& theConnectedMap)
2083 theConnectedMap.Add(theBlockIndex);
2084 theProcessedMap.Add(theBlockIndex);
2086 Standard_Integer nbBlocks = theRelations.ColLength();
2087 Standard_Integer col = 1;
2088 for (; col <= nbBlocks; col++) {
2089 if (theRelations(theBlockIndex, col) == REL_OK ||
2090 theRelations(theBlockIndex, col) == REL_NOT_GLUED) {
2091 if (!theProcessedMap.Contains(col)) {
2092 FindConnected(col, theRelations, theProcessedMap, theConnectedMap);
2098 Standard_Boolean HasAnyConnection (const Standard_Integer theBlockIndex,
2099 const TColStd_MapOfInteger& theWith,
2100 const TColStd_Array2OfInteger& theRelations,
2101 TColStd_MapOfInteger& theProcessedMap)
2103 theProcessedMap.Add(theBlockIndex);
2105 Standard_Integer nbBlocks = theRelations.ColLength();
2106 Standard_Integer col = 1;
2107 for (; col <= nbBlocks; col++) {
2108 if (theRelations(theBlockIndex, col) != REL_NOT_CONNECTED) {
2109 if (!theProcessedMap.Contains(col)) {
2110 if (theWith.Contains(col))
2111 return Standard_True;
2112 if (HasAnyConnection(col, theWith, theRelations, theProcessedMap))
2113 return Standard_True;
2118 return Standard_False;
2121 //=============================================================================
2123 * CheckCompoundOfBlocksOld
2125 //=============================================================================
2126 Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocksOld
2127 (Handle(GEOM_Object) theCompound,
2128 std::list<BCError>& theErrors)
2132 if (theCompound.IsNull()) return Standard_False;
2133 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2135 Standard_Boolean isCompOfBlocks = Standard_True;
2137 // Map sub-shapes and their indices
2138 TopTools_IndexedMapOfShape anIndices;
2139 TopExp::MapShapes(aBlockOrComp, anIndices);
2141 // 1. Report non-blocks
2142 TopTools_ListOfShape NOT; // Not blocks
2143 TopTools_ListOfShape DEG; // Hexahedral solids, having degenerated edges
2144 TopTools_ListOfShape SEA; // Hexahedral solids, having seam edges
2145 TopTools_ListOfShape BLO; // All blocks from the given compound
2146 AddBlocksFromOld(aBlockOrComp, BLO, NOT, DEG, SEA);
2148 if (NOT.Extent() > 0) {
2149 isCompOfBlocks = Standard_False;
2151 anErr.error = NOT_BLOCK;
2152 TopTools_ListIteratorOfListOfShape it (NOT);
2153 for (; it.More(); it.Next()) {
2154 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
2156 theErrors.push_back(anErr);
2159 if (DEG.Extent() > 0 || SEA.Extent() > 0) {
2160 isCompOfBlocks = Standard_False;
2162 anErr.error = EXTRA_EDGE;
2164 TopTools_ListIteratorOfListOfShape itDEG (DEG);
2165 for (; itDEG.More(); itDEG.Next()) {
2166 anErr.incriminated.push_back(anIndices.FindIndex(itDEG.Value()));
2169 TopTools_ListIteratorOfListOfShape itSEA (SEA);
2170 for (; itSEA.More(); itSEA.Next()) {
2171 anErr.incriminated.push_back(anIndices.FindIndex(itSEA.Value()));
2174 theErrors.push_back(anErr);
2177 Standard_Integer nbBlocks = BLO.Extent();
2178 if (nbBlocks == 0) {
2179 isCompOfBlocks = Standard_False;
2181 return isCompOfBlocks;
2183 if (nbBlocks == 1) {
2185 return isCompOfBlocks;
2188 // Convert list of blocks into array for easy and fast access
2189 Standard_Integer ibl = 1;
2190 TopTools_Array1OfShape aBlocks (1, nbBlocks);
2191 TopTools_ListIteratorOfListOfShape BLOit (BLO);
2192 for (; BLOit.More(); BLOit.Next(), ibl++) {
2193 aBlocks.SetValue(ibl, BLOit.Value());
2196 // 2. Find relations between all blocks,
2197 // report connection errors (NOT_GLUED and INVALID_CONNECTION)
2198 TColStd_Array2OfInteger aRelations (1, nbBlocks, 1, nbBlocks);
2199 aRelations.Init(REL_NOT_CONNECTED);
2201 Standard_Integer row = 1;
2202 for (row = 1; row <= nbBlocks; row++) {
2203 TopoDS_Shape aBlock = aBlocks.Value(row);
2205 Standard_Integer col = row + 1;
2206 for (; col <= nbBlocks; col++) {
2207 Standard_Integer aRel = BlocksRelation(aBlock, aBlocks.Value(col));
2208 if (aRel != REL_NOT_CONNECTED) {
2209 aRelations.SetValue(row, col, aRel);
2210 aRelations.SetValue(col, row, aRel);
2211 if (aRel == REL_NOT_GLUED) {
2212 // report connection error
2213 isCompOfBlocks = Standard_False;
2215 anErr.error = NOT_GLUED;
2216 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row)));
2217 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col)));
2218 theErrors.push_back(anErr);
2219 } else if (aRel == REL_COLLISION_VV ||
2220 aRel == REL_COLLISION_FF ||
2221 aRel == REL_COLLISION_EE ||
2222 aRel == REL_UNKNOWN) {
2223 // report connection error
2224 isCompOfBlocks = Standard_False;
2226 anErr.error = INVALID_CONNECTION;
2227 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row)));
2228 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col)));
2229 theErrors.push_back(anErr);
2236 // 3. Find largest set of connected (good connection or not glued) blocks
2237 TColStd_MapOfInteger aProcessedMap;
2238 TColStd_MapOfInteger aLargestSet;
2239 TColStd_MapOfInteger aCurrentSet;
2240 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2241 if (!aProcessedMap.Contains(ibl)) {
2242 aCurrentSet.Clear();
2243 FindConnected(ibl, aRelations, aProcessedMap, aCurrentSet);
2244 if (aCurrentSet.Extent() > aLargestSet.Extent()) {
2245 aLargestSet = aCurrentSet;
2250 // 4. Report all blocks, isolated from <aLargestSet>
2252 anErr.error = NOT_CONNECTED;
2253 Standard_Boolean hasIsolated = Standard_False;
2254 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2255 if (!aLargestSet.Contains(ibl)) {
2256 aProcessedMap.Clear();
2257 if (!HasAnyConnection(ibl, aLargestSet, aRelations, aProcessedMap)) {
2258 // report connection absence
2259 hasIsolated = Standard_True;
2260 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(ibl)));
2265 isCompOfBlocks = Standard_False;
2266 theErrors.push_back(anErr);
2270 return isCompOfBlocks;
2273 //=============================================================================
2277 //=============================================================================
2278 TCollection_AsciiString GEOMImpl_IBlocksOperations::PrintBCErrors
2279 (Handle(GEOM_Object) theCompound,
2280 const std::list<BCError>& theErrors)
2282 TCollection_AsciiString aDescr;
2284 std::list<BCError>::const_iterator errIt = theErrors.begin();
2286 for (; errIt != theErrors.end(); i++, errIt++) {
2287 BCError errStruct = *errIt;
2289 switch (errStruct.error) {
2291 aDescr += "\n\tNot a Blocks: ";
2294 aDescr += "\n\tHexahedral solids with degenerated and/or seam edges: ";
2296 case INVALID_CONNECTION:
2297 aDescr += "\n\tInvalid connection between two blocks: ";
2300 aDescr += "\n\tBlocks, not connected with main body: ";
2303 aDescr += "\n\tNot glued blocks: ";
2309 std::list<int> sshList = errStruct.incriminated;
2310 std::list<int>::iterator sshIt = sshList.begin();
2312 for (; sshIt != sshList.end(); jj++, sshIt++) {
2315 aDescr += TCollection_AsciiString(*sshIt);
2322 //=============================================================================
2324 * CheckCompoundOfBlocks
2326 //=============================================================================
2327 Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocks
2328 (Handle(GEOM_Object) theCompound,
2329 std::list<BCError>& theErrors)
2333 if (theCompound.IsNull()) return Standard_False;
2334 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2336 Standard_Boolean isCompOfBlocks = Standard_True;
2338 // Map sub-shapes and their indices
2339 TopTools_IndexedMapOfShape anIndices;
2340 TopExp::MapShapes(aBlockOrComp, anIndices);
2342 // 1. Separate blocks from non-blocks
2343 TopTools_ListOfShape NOT; // Not blocks
2344 TopTools_ListOfShape EXT; // Hexahedral solids, having degenerated and/or seam edges
2345 TopTools_ListOfShape BLO; // All blocks from the given compound
2346 TopTools_ListOfShape NOQ; // All non-quadrangular faces
2347 AddBlocksFrom(aBlockOrComp, BLO, NOT, EXT, NOQ);
2349 // Report non-blocks
2350 if (NOT.Extent() > 0) {
2351 isCompOfBlocks = Standard_False;
2353 anErr.error = NOT_BLOCK;
2354 TopTools_ListIteratorOfListOfShape it (NOT);
2355 for (; it.More(); it.Next()) {
2356 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
2358 theErrors.push_back(anErr);
2361 // Report solids, having degenerated and/or seam edges
2362 if (EXT.Extent() > 0) {
2363 isCompOfBlocks = Standard_False;
2365 anErr.error = EXTRA_EDGE;
2366 TopTools_ListIteratorOfListOfShape it (EXT);
2367 for (; it.More(); it.Next()) {
2368 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
2370 theErrors.push_back(anErr);
2373 Standard_Integer nbBlocks = BLO.Extent();
2374 if (nbBlocks == 0) {
2375 isCompOfBlocks = Standard_False;
2377 return isCompOfBlocks;
2379 if (nbBlocks == 1) {
2381 return isCompOfBlocks;
2384 // Prepare data for 2. and 3.
2385 TColStd_Array2OfInteger aRelations (1, nbBlocks, 1, nbBlocks);
2386 aRelations.Init(REL_NOT_CONNECTED);
2388 TopTools_IndexedMapOfShape mapBlocks;
2391 TopoDS_Compound aComp;
2392 BB.MakeCompound(aComp);
2394 TopTools_ListIteratorOfListOfShape BLOit (BLO);
2395 for (; BLOit.More(); BLOit.Next()) {
2396 mapBlocks.Add(BLOit.Value());
2397 BB.Add(aComp, BLOit.Value());
2400 // 2. Find glued blocks (having shared faces)
2401 TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
2402 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2403 (aComp, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
2405 Standard_Integer prevInd = 0, curInd = 0;
2406 Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
2407 for (; ind <= nbFaces; ind++) {
2408 const TopTools_ListOfShape& aGluedBlocks = mapFaceBlocks.FindFromIndex(ind);
2409 if (aGluedBlocks.Extent() > 1) { // Shared face found
2410 TopTools_ListIteratorOfListOfShape aGluedBlocksIt (aGluedBlocks);
2411 TopoDS_Shape prevBlock, curBlock;
2412 for (; aGluedBlocksIt.More(); aGluedBlocksIt.Next()) {
2413 curBlock = aGluedBlocksIt.Value();
2414 if (!prevBlock.IsNull()) {
2415 prevInd = mapBlocks.FindIndex(prevBlock);
2416 curInd = mapBlocks.FindIndex(curBlock);
2417 aRelations.SetValue(prevInd, curInd, REL_OK);
2418 aRelations.SetValue(curInd, prevInd, REL_OK);
2420 prevBlock = curBlock;
2425 // 3. Find not glued blocks
2426 GEOMAlgo_GlueAnalyser aGD;
2428 aGD.SetShape(aComp);
2429 aGD.SetTolerance(Precision::Confusion());
2430 aGD.SetCheckGeometry(Standard_True);
2433 Standard_Integer iErr, iWrn;
2434 iErr = aGD.ErrorStatus();
2436 SetErrorCode("Error in GEOMAlgo_GlueAnalyser");
2437 return isCompOfBlocks;
2439 iWrn = aGD.WarningStatus();
2441 MESSAGE("Warning in GEOMAlgo_GlueAnalyser");
2444 // Report not glued blocks
2445 if (aGD.HasSolidsToGlue()) {
2446 isCompOfBlocks = Standard_False;
2447 Standard_Integer aSx1Ind, aSx2Ind;
2449 const GEOMAlgo_ListOfCoupleOfShapes& aLCS = aGD.SolidsToGlue();
2450 GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS (aLCS);
2451 for (; aItCS.More(); aItCS.Next()) {
2452 const GEOMAlgo_CoupleOfShapes& aCS = aItCS.Value();
2453 const TopoDS_Shape& aSx1 = aCS.Shape1();
2454 const TopoDS_Shape& aSx2 = aCS.Shape2();
2456 aSx1Ind = mapBlocks.FindIndex(aSx1);
2457 aSx2Ind = mapBlocks.FindIndex(aSx2);
2458 aRelations.SetValue(aSx1Ind, aSx2Ind, NOT_GLUED);
2459 aRelations.SetValue(aSx2Ind, aSx1Ind, NOT_GLUED);
2462 anErr.error = NOT_GLUED;
2463 anErr.incriminated.push_back(anIndices.FindIndex(aSx1));
2464 anErr.incriminated.push_back(anIndices.FindIndex(aSx2));
2465 theErrors.push_back(anErr);
2469 // 4. Find largest set of connected (good connection or not glued) blocks
2470 Standard_Integer ibl = 1;
2471 TColStd_MapOfInteger aProcessedMap;
2472 TColStd_MapOfInteger aLargestSet;
2473 TColStd_MapOfInteger aCurrentSet;
2474 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2475 if (!aProcessedMap.Contains(ibl)) {
2476 aCurrentSet.Clear();
2477 FindConnected(ibl, aRelations, aProcessedMap, aCurrentSet);
2478 if (aCurrentSet.Extent() > aLargestSet.Extent()) {
2479 aLargestSet = aCurrentSet;
2484 // 5. Report all blocks, isolated from <aLargestSet>
2486 anErr.error = NOT_CONNECTED;
2487 Standard_Boolean hasIsolated = Standard_False;
2488 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2489 if (!aLargestSet.Contains(ibl)) {
2490 aProcessedMap.Clear();
2491 if (!HasAnyConnection(ibl, aLargestSet, aRelations, aProcessedMap)) {
2492 // report connection absence
2493 hasIsolated = Standard_True;
2494 anErr.incriminated.push_back(anIndices.FindIndex(mapBlocks.FindKey(ibl)));
2499 isCompOfBlocks = Standard_False;
2500 theErrors.push_back(anErr);
2504 return isCompOfBlocks;
2507 //=============================================================================
2511 //=============================================================================
2512 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetNonBlocks
2513 (Handle(GEOM_Object) theShape,
2514 Handle(GEOM_Object)& theNonQuads)
2518 if (theShape.IsNull()) return NULL;
2519 TopoDS_Shape aShape = theShape->GetValue();
2521 // Separate blocks from non-blocks
2522 TopTools_ListOfShape BLO; // All blocks from the given compound
2523 TopTools_ListOfShape NOT; // Not blocks
2524 TopTools_ListOfShape EXT; // Hexahedral solids, having degenerated and/or seam edges
2525 TopTools_ListOfShape NOQ; // All non-quadrangular faces
2526 AddBlocksFrom(aShape, BLO, NOT, EXT, NOQ);
2528 if (NOT.IsEmpty() && EXT.IsEmpty() && NOQ.IsEmpty()) {
2529 SetErrorCode("NOT_FOUND_ANY");
2533 // Map sub-shapes and their indices
2534 TopTools_IndexedMapOfShape anIndices;
2535 TopExp::MapShapes(aShape, anIndices);
2538 Handle(GEOM_Object) aNonBlocks;
2539 if (NOT.Extent() > 0 || EXT.Extent() > 0) {
2540 Handle(TColStd_HArray1OfInteger) anArray =
2541 new TColStd_HArray1OfInteger (1, NOT.Extent() + EXT.Extent());
2542 Standard_Integer ii = 1;
2543 TopTools_ListIteratorOfListOfShape it1 (NOT);
2544 for (; it1.More(); it1.Next(), ii++) {
2545 anArray->SetValue(ii, anIndices.FindIndex(it1.Value()));
2547 TopTools_ListIteratorOfListOfShape it2 (EXT);
2548 for (; it2.More(); it2.Next(), ii++) {
2549 anArray->SetValue(ii, anIndices.FindIndex(it2.Value()));
2552 aNonBlocks = GetEngine()->AddSubShape(theShape, anArray);
2553 if (aNonBlocks.IsNull()) {
2554 SetErrorCode("Error in algorithm: result found, but cannot be returned.");
2557 aNonBlocks->SetType(GEOM_GROUP);
2558 TDF_Label aFreeLabel = aNonBlocks->GetFreeLabel();
2559 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)TopAbs_SOLID);
2563 if (NOQ.Extent() > 0) {
2564 Handle(TColStd_HArray1OfInteger) anArray =
2565 new TColStd_HArray1OfInteger (1, NOQ.Extent());
2566 Standard_Integer ii = 1;
2567 TopTools_ListIteratorOfListOfShape it1 (NOQ);
2568 for (; it1.More(); it1.Next(), ii++) {
2569 anArray->SetValue(ii, anIndices.FindIndex(it1.Value()));
2572 theNonQuads = GetEngine()->AddSubShape(theShape, anArray);
2573 if (theNonQuads.IsNull()) {
2574 SetErrorCode("Error in algorithm: result found, but cannot be returned.");
2577 theNonQuads->SetType(GEOM_GROUP);
2578 TDF_Label aFreeLabel = theNonQuads->GetFreeLabel();
2579 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)TopAbs_FACE);
2582 //Make a Python command
2583 Handle(GEOM_Function) aMainShape = theShape->GetLastFunction();
2584 GEOM::TPythonDump pd (aMainShape, /*append=*/true);
2586 if (aNonBlocks.IsNull())
2587 pd << "no_bad_solids";
2591 if (theNonQuads.IsNull())
2592 pd << "no_bad_faces";
2595 pd << ") = geompy.GetNonBlocks(" << theShape << ")";
2601 //=============================================================================
2605 //=============================================================================
2606 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::RemoveExtraEdges
2607 (Handle(GEOM_Object) theObject,
2608 const Standard_Integer theOptimumNbFaces)
2612 if (theObject.IsNull()) return NULL;
2614 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2615 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be fixed
2617 //Add a new Copy object
2618 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2621 Handle(GEOM_Function) aFunction =
2622 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_REMOVE_EXTRA);
2624 //Check if the function is set correctly
2625 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2627 GEOMImpl_IBlockTrsf aTI (aFunction);
2628 aTI.SetOriginal(aLastFunction);
2629 aTI.SetOptimumNbFaces(theOptimumNbFaces);
2631 //Compute the fixed shape
2633 #if OCC_VERSION_LARGE > 0x06010000
2636 if (!GetSolver()->ComputeFunction(aFunction)) {
2637 SetErrorCode("Block driver failed to remove extra edges of the given shape");
2641 catch (Standard_Failure) {
2642 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2643 SetErrorCode(aFail->GetMessageString());
2647 //Make a Python command
2648 std::string doUnionFaces = (theOptimumNbFaces < 0) ? "False" : "True";
2649 GEOM::TPythonDump(aFunction) << aCopy << " = geompy.RemoveExtraEdges("
2650 << theObject << ", " << doUnionFaces.data() << ")";
2656 //=============================================================================
2660 //=============================================================================
2661 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::CheckAndImprove
2662 (Handle(GEOM_Object) theObject)
2666 if (theObject.IsNull()) return NULL;
2668 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2669 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be fixed
2671 //Add a new Copy object
2672 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2675 Handle(GEOM_Function) aFunction =
2676 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_COMPOUND_IMPROVE);
2678 //Check if the function is set correctly
2679 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2681 GEOMImpl_IBlockTrsf aTI (aFunction);
2682 aTI.SetOriginal(aLastFunction);
2684 // -1 means do not unite faces on common surface (?except case of seam edge between them?)
2685 //aTI.SetOptimumNbFaces(-1);
2686 aTI.SetOptimumNbFaces(6);
2688 //Compute the fixed shape
2690 #if OCC_VERSION_LARGE > 0x06010000
2693 if (!GetSolver()->ComputeFunction(aFunction)) {
2694 SetErrorCode("Block driver failed to improve the given blocks compound");
2698 catch (Standard_Failure) {
2699 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2700 SetErrorCode(aFail->GetMessageString());
2704 //Make a Python command
2705 GEOM::TPythonDump(aFunction) << aCopy
2706 << " = geompy.CheckAndImprove(" << theObject << ")";
2712 //=============================================================================
2714 * ExplodeCompoundOfBlocks
2716 //=============================================================================
2717 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::ExplodeCompoundOfBlocks
2718 (Handle(GEOM_Object) theCompound,
2719 const Standard_Integer theMinNbFaces,
2720 const Standard_Integer theMaxNbFaces)
2724 if (theCompound.IsNull()) return NULL;
2725 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2726 if (aBlockOrComp.IsNull()) return NULL;
2728 Handle(TColStd_HSequenceOfTransient) aBlocks = new TColStd_HSequenceOfTransient;
2729 Handle(GEOM_Object) anObj;
2730 Handle(GEOM_Function) aFunction;
2732 TopTools_MapOfShape mapShape;
2733 TCollection_AsciiString anAsciiList, anEntry;
2736 TopTools_IndexedMapOfShape anIndices;
2737 TopExp::MapShapes(aBlockOrComp, anIndices);
2738 Handle(TColStd_HArray1OfInteger) anArray;
2742 #if OCC_VERSION_LARGE > 0x06010000
2745 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2746 for (; exp.More(); exp.Next()) {
2747 if (mapShape.Add(exp.Current())) {
2748 TopoDS_Shape aSolid = exp.Current();
2750 TopTools_MapOfShape mapFaces;
2751 TopExp_Explorer expF (aSolid, TopAbs_FACE);
2752 Standard_Integer nbFaces = 0;
2753 for (; expF.More(); expF.Next()) {
2754 if (mapFaces.Add(expF.Current())) {
2759 if (theMinNbFaces <= nbFaces && nbFaces <= theMaxNbFaces) {
2760 anArray = new TColStd_HArray1OfInteger(1,1);
2761 anArray->SetValue(1, anIndices.FindIndex(aSolid));
2762 anObj = GetEngine()->AddSubShape(theCompound, anArray);
2763 aBlocks->Append(anObj);
2765 //Make a Python command
2766 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2767 anAsciiList += anEntry + ", ";
2772 catch (Standard_Failure) {
2773 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2774 SetErrorCode(aFail->GetMessageString());
2778 if (aBlocks->IsEmpty()) {
2779 SetErrorCode("There are no specified blocks in the given shape");
2783 anAsciiList.Trunc(anAsciiList.Length() - 2);
2785 //The explode doesn't change object so no new function is required.
2786 aFunction = theCompound->GetLastFunction();
2788 //Make a Python command
2789 GEOM::TPythonDump(aFunction, /*append=*/true)
2790 << "[" << anAsciiList.ToCString() << "] = geompy.MakeBlockExplode("
2791 << theCompound << ", " << theMinNbFaces << ", " << theMaxNbFaces << ")";
2797 //=============================================================================
2801 //=============================================================================
2802 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetBlockNearPoint
2803 (Handle(GEOM_Object) theCompound,
2804 Handle(GEOM_Object) thePoint)
2809 Handle(GEOM_Object) aResult;
2812 if (theCompound.IsNull() || thePoint.IsNull()) return NULL;
2814 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2815 if (aBlockOrComp.IsNull()) {
2816 SetErrorCode("Compound is null");
2819 if (aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
2820 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
2821 SetErrorCode("Shape to find block in is not a compound");
2825 TopoDS_Shape anArg = thePoint->GetValue();
2826 if (anArg.IsNull()) {
2827 SetErrorCode("Point is null");
2830 if (anArg.ShapeType() != TopAbs_VERTEX) {
2831 SetErrorCode("Shape for block identification is not a vertex");
2835 //Compute the Block value
2837 #if OCC_VERSION_LARGE > 0x06010000
2840 TopoDS_Shape aShape;
2842 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
2843 gp_Pnt aPnt = BRep_Tool::Pnt(aVert);
2844 Standard_Real PX, PY, PZ;
2845 aPnt.Coord(PX, PY, PZ);
2847 // 1. Classify the point relatively each block
2848 Standard_Integer nearest = 2, nbFound = 0;
2849 TopTools_DataMapOfShapeInteger mapShapeDist;
2850 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2851 for (; exp.More(); exp.Next()) {
2852 TopoDS_Shape aSolid = exp.Current();
2854 if (!mapShapeDist.IsBound(aSolid)) {
2855 Standard_Integer aDistance = 2;
2857 // 1.a. Classify relatively Bounding box
2858 Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
2860 BRepBndLib::Add(aSolid, BB);
2861 BB.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
2862 if (PX < Xmin || Xmax < PX ||
2863 PY < Ymin || Ymax < PY ||
2864 PZ < Zmin || Zmax < PZ) {
2865 // OUT of bounding box
2868 // 1.b. Classify relatively the solid itself
2869 BRepClass3d_SolidClassifier SC (aSolid, aPnt, Precision::Confusion());
2870 if (SC.State() == TopAbs_IN) {
2872 } else if (SC.State() == TopAbs_ON) {
2879 if (aDistance < nearest) {
2880 nearest = aDistance;
2884 // A first found block, containing the point inside, will be returned.
2885 // It is the solution, if there are no intersecting blocks in the compound.
2886 if (nearest == -1) break;
2888 } else if (aDistance == nearest) {
2893 mapShapeDist.Bind(aSolid, aDistance);
2894 } // if (!mapShapeDist.IsBound(aSolid))
2897 // 2. Define block, containing the point or having minimum distance to it
2900 // The point is on boundary of some blocks and there are
2901 // no blocks, having the point inside their volume
2902 SetErrorCode("Multiple blocks near the given point are found");
2905 } else if (nearest == 1) {
2906 // The point is outside some blocks and there are
2907 // no blocks, having the point inside or on boundary.
2908 // We will get a nearest block
2909 Standard_Real minDist = RealLast();
2910 TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
2911 for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
2912 if (mapShapeDistIter.Value() == 1) {
2913 TopoDS_Shape aSolid = mapShapeDistIter.Key();
2914 BRepExtrema_DistShapeShape aDistTool (aVert, aSolid);
2915 if (!aDistTool.IsDone()) {
2916 SetErrorCode("Can not find a distance from the given point to one of blocks");
2919 Standard_Real aDist = aDistTool.Value();
2920 if (aDist < minDist) {
2926 } else { // nearest == -1
2927 // // The point is inside some blocks.
2928 // // We will get a block with nearest center
2929 // Standard_Real minDist = RealLast();
2930 // TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
2931 // for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
2932 // if (mapShapeDistIter.Value() == -1) {
2933 // TopoDS_Shape aSolid = mapShapeDistIter.Key();
2934 // GProp_GProps aSystem;
2935 // BRepGProp::VolumeProperties(aSolid, aSystem);
2936 // gp_Pnt aCenterMass = aSystem.CentreOfMass();
2938 // Standard_Real aDist = aCenterMass.Distance(aPnt);
2939 // if (aDist < minDist) {
2946 } // if (nbFound > 1)
2949 SetErrorCode("There are no blocks near the given point");
2952 TopTools_IndexedMapOfShape anIndices;
2953 TopExp::MapShapes(aBlockOrComp, anIndices);
2954 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2955 anArray->SetValue(1, anIndices.FindIndex(aShape));
2956 aResult = GetEngine()->AddSubShape(theCompound, anArray);
2959 catch (Standard_Failure) {
2960 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2961 SetErrorCode(aFail->GetMessageString());
2965 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
2967 //Make a Python command
2968 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetBlockNearPoint("
2969 << theCompound << ", " << thePoint << ")";
2975 //=============================================================================
2979 //=============================================================================
2980 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetBlockByParts
2981 (Handle(GEOM_Object) theCompound,
2982 const Handle(TColStd_HSequenceOfTransient)& theParts)
2986 Handle(GEOM_Object) aResult;
2988 if (theCompound.IsNull() || theParts.IsNull()) return NULL;
2989 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2990 if (aBlockOrComp.IsNull()) return NULL;
2993 Standard_Integer argi, aLen = theParts->Length();
2994 TopTools_Array1OfShape anArgs (1, aLen);
2995 TCollection_AsciiString anEntry, aPartsDescr;
2996 for (argi = 1; argi <= aLen; argi++) {
2997 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theParts->Value(argi));
2998 Handle(GEOM_Function) aRef = anObj->GetLastFunction();
2999 if (aRef.IsNull()) return NULL;
3001 TopoDS_Shape anArg = aRef->GetValue();
3002 if (anArg.IsNull()) {
3003 SetErrorCode("Null shape is given as argument");
3006 anArgs(argi) = anArg;
3008 // For Python command
3009 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
3010 if (argi > 1) aPartsDescr += ", ";
3011 aPartsDescr += anEntry;
3014 //Compute the Block value
3016 #if OCC_VERSION_LARGE > 0x06010000
3019 // 1. Explode compound on solids
3020 TopTools_MapOfShape mapShape;
3021 Standard_Integer nbSolids = 0;
3022 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
3023 for (; exp.More(); exp.Next()) {
3024 if (mapShape.Add(exp.Current())) {
3030 Standard_Integer ind = 1;
3031 TopTools_Array1OfShape aSolids (1, nbSolids);
3032 TColStd_Array1OfInteger aNbParts (1, nbSolids);
3033 for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next(), ind++) {
3034 if (mapShape.Add(exp.Current())) {
3035 TopoDS_Shape aSolid = exp.Current();
3036 aSolids(ind) = aSolid;
3039 // 2. Define quantity of parts, contained in each solid
3040 TopTools_IndexedMapOfShape aSubShapes;
3041 TopExp::MapShapes(aSolid, aSubShapes);
3042 for (argi = 1; argi <= aLen; argi++) {
3043 if (aSubShapes.Contains(anArgs(argi))) {
3050 // 3. Define solid, containing maximum quantity of parts
3051 Standard_Integer maxNb = 0, nbFound = 0;
3052 TopoDS_Shape aShape;
3053 for (ind = 1; ind <= nbSolids; ind++) {
3054 if (aNbParts(ind) > maxNb) {
3055 maxNb = aNbParts(ind);
3056 aShape = aSolids(ind);
3058 } else if (aNbParts(ind) == maxNb) {
3064 SetErrorCode("Multiple blocks, containing maximum quantity of the given parts, are found");
3066 } else if (nbFound == 0) {
3067 SetErrorCode("There are no blocks, containing the given parts");
3070 TopTools_IndexedMapOfShape anIndices;
3071 TopExp::MapShapes(aBlockOrComp, anIndices);
3072 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
3073 anArray->SetValue(1, anIndices.FindIndex(aShape));
3074 aResult = GetEngine()->AddSubShape(theCompound, anArray);
3076 } catch (Standard_Failure) {
3077 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3078 SetErrorCode(aFail->GetMessageString());
3082 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
3084 //Make a Python command
3085 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetBlockByParts("
3086 << theCompound << ", [" << aPartsDescr.ToCString() << "])";
3092 //=============================================================================
3096 //=============================================================================
3097 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::GetBlocksByParts
3098 (Handle(GEOM_Object) theCompound,
3099 const Handle(TColStd_HSequenceOfTransient)& theParts)
3103 if (theCompound.IsNull() || theParts.IsNull()) return NULL;
3104 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
3105 if (aBlockOrComp.IsNull()) return NULL;
3107 Handle(TColStd_HSequenceOfTransient) aBlocks = new TColStd_HSequenceOfTransient;
3108 Handle(GEOM_Object) anObj;
3109 Handle(GEOM_Function) aFunction;
3112 Standard_Integer argi, aLen = theParts->Length();
3113 TopTools_Array1OfShape anArgs (1, aLen);
3114 TCollection_AsciiString anEntry, aPartsDescr, anAsciiList;
3116 for (argi = 1; argi <= aLen; argi++) {
3117 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theParts->Value(argi));
3118 Handle(GEOM_Function) aRef = anObj->GetLastFunction();
3119 if (aRef.IsNull()) return NULL;
3121 TopoDS_Shape anArg = aRef->GetValue();
3122 if (anArg.IsNull()) {
3123 SetErrorCode("Null shape is given as argument");
3126 anArgs(argi) = anArg;
3128 // For Python command
3129 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
3130 aPartsDescr += anEntry + ", ";
3135 #if OCC_VERSION_LARGE > 0x06010000
3138 TopTools_MapOfShape mapShape;
3139 Standard_Integer nbSolids = 0;
3140 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
3141 for (; exp.More(); exp.Next()) {
3142 if (mapShape.Add(exp.Current())) {
3148 Standard_Integer ind = 1;
3149 TopTools_Array1OfShape aSolids (1, nbSolids);
3150 TColStd_Array1OfInteger aNbParts (1, nbSolids);
3151 for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next(), ind++) {
3152 if (mapShape.Add(exp.Current())) {
3153 TopoDS_Shape aSolid = exp.Current();
3154 aSolids(ind) = aSolid;
3157 // 2. Define quantity of parts, contained in each solid
3158 TopTools_IndexedMapOfShape aSubShapes;
3159 TopExp::MapShapes(aSolid, aSubShapes);
3160 for (argi = 1; argi <= aLen; argi++) {
3161 if (aSubShapes.Contains(anArgs(argi))) {
3168 // 3. Define solid, containing maximum quantity of parts
3169 Standard_Integer maxNb = 0, nbFound = 0;
3170 for (ind = 1; ind <= nbSolids; ind++) {
3171 if (aNbParts(ind) > maxNb) {
3172 maxNb = aNbParts(ind);
3174 } else if (aNbParts(ind) == maxNb) {
3180 SetErrorCode("There are no blocks, containing the given parts");
3185 TopTools_IndexedMapOfShape anIndices;
3186 TopExp::MapShapes(aBlockOrComp, anIndices);
3187 Handle(TColStd_HArray1OfInteger) anArray;
3189 for (ind = 1; ind <= nbSolids; ind++) {
3190 if (aNbParts(ind) == maxNb) {
3191 anArray = new TColStd_HArray1OfInteger(1,1);
3192 anArray->SetValue(1, anIndices.FindIndex(aSolids(ind)));
3193 anObj = GetEngine()->AddSubShape(theCompound, anArray);
3194 aBlocks->Append(anObj);
3196 // For Python command
3197 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
3198 anAsciiList += anEntry + ", ";
3199 if (aFunction.IsNull())
3200 aFunction = anObj->GetLastFunction();
3204 catch (Standard_Failure) {
3205 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3206 SetErrorCode(aFail->GetMessageString());
3210 //Make a Python command
3211 aPartsDescr.Trunc(aPartsDescr.Length() - 2);
3212 anAsciiList.Trunc(anAsciiList.Length() - 2);
3214 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3215 << "] = geompy.GetBlocksByParts(" << theCompound
3216 << ", [" << aPartsDescr.ToCString() << "])";
3222 //=============================================================================
3224 * MakeMultiTransformation1D
3226 //=============================================================================
3227 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeMultiTransformation1D
3228 (Handle(GEOM_Object) theObject,
3229 const Standard_Integer theDirFace1,
3230 const Standard_Integer theDirFace2,
3231 const Standard_Integer theNbTimes)
3235 if (theObject.IsNull()) return NULL;
3237 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
3238 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be moved
3240 //Add a new Copy object
3241 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
3243 //Add a translate function
3244 Handle(GEOM_Function) aFunction =
3245 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_MULTI_TRANSFORM_1D);
3247 //Check if the function is set correctly
3248 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
3250 GEOMImpl_IBlockTrsf aTI (aFunction);
3251 aTI.SetOriginal(aLastFunction);
3252 aTI.SetFace1U(theDirFace1);
3253 aTI.SetFace2U(theDirFace2);
3254 aTI.SetNbIterU(theNbTimes);
3256 //Compute the transformation
3258 #if OCC_VERSION_LARGE > 0x06010000
3261 if (!GetSolver()->ComputeFunction(aFunction)) {
3262 SetErrorCode("Block driver failed to make multi-transformation");
3266 catch (Standard_Failure) {
3267 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3268 SetErrorCode(aFail->GetMessageString());
3272 //Make a Python command
3273 GEOM::TPythonDump(aFunction) << aCopy << " = geompy.MakeMultiTransformation1D("
3274 << theObject << ", " << theDirFace1 << ", " << theDirFace2 << ", " << theNbTimes << ")";
3280 //=============================================================================
3282 * MakeMultiTransformation2D
3284 //=============================================================================
3285 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeMultiTransformation2D
3286 (Handle(GEOM_Object) theObject,
3287 const Standard_Integer theDirFace1U,
3288 const Standard_Integer theDirFace2U,
3289 const Standard_Integer theNbTimesU,
3290 const Standard_Integer theDirFace1V,
3291 const Standard_Integer theDirFace2V,
3292 const Standard_Integer theNbTimesV)
3296 if (theObject.IsNull()) return NULL;
3298 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
3299 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be moved
3301 //Add a new Copy object
3302 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
3304 //Add a translate function
3305 Handle(GEOM_Function) aFunction =
3306 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_MULTI_TRANSFORM_2D);
3308 //Check if the function is set correctly
3309 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
3311 GEOMImpl_IBlockTrsf aTI (aFunction);
3312 aTI.SetOriginal(aLastFunction);
3313 aTI.SetFace1U(theDirFace1U);
3314 aTI.SetFace2U(theDirFace2U);
3315 aTI.SetNbIterU(theNbTimesU);
3316 aTI.SetFace1V(theDirFace1V);
3317 aTI.SetFace2V(theDirFace2V);
3318 aTI.SetNbIterV(theNbTimesV);
3320 //Compute the transformation
3322 #if OCC_VERSION_LARGE > 0x06010000
3325 if (!GetSolver()->ComputeFunction(aFunction)) {
3326 SetErrorCode("Block driver failed to make multi-transformation");
3330 catch (Standard_Failure) {
3331 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3332 SetErrorCode(aFail->GetMessageString());
3336 //Make a Python command
3337 GEOM::TPythonDump(aFunction) << aCopy << " = geompy.MakeMultiTransformation2D("
3338 << theObject << ", " << theDirFace1U << ", " << theDirFace2U << ", " << theNbTimesU
3339 << ", " << theDirFace1V << ", " << theDirFace2V << ", " << theNbTimesV << ")";
3345 //=============================================================================
3349 //=============================================================================
3350 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::Propagate
3351 (Handle(GEOM_Object) theShape)
3355 if (theShape.IsNull()) return NULL;
3357 TopoDS_Shape aShape = theShape->GetValue();
3358 if (aShape.IsNull()) return NULL;
3360 TopTools_IndexedMapOfShape anIndices;
3361 TopExp::MapShapes(aShape, anIndices);
3363 TopTools_IndexedDataMapOfShapeListOfShape MEW;
3364 GEOMImpl_Block6Explorer::MapShapesAndAncestors
3365 (aShape, TopAbs_EDGE, TopAbs_WIRE, MEW);
3366 Standard_Integer ie, nbEdges = MEW.Extent();
3369 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
3371 TopTools_MapOfShape mapAcceptedEdges;
3372 TCollection_AsciiString aListRes, anEntry;
3374 // Sort shapes in current chain (Mantis issue 21053)
3375 TopTools_DataMapOfShapeListOfShape aMapChains;
3376 TopTools_ListOfShape aFirstInChains;
3378 for (ie = 1; ie <= nbEdges; ie++) {
3379 TopoDS_Shape curE = MEW.FindKey(ie);
3381 if (mapAcceptedEdges.Contains(curE)) continue;
3384 TopTools_ListOfShape currentChain;
3385 TopTools_ListOfShape listPrevEdges;
3387 currentChain.Append(curE);
3388 listPrevEdges.Append(curE);
3389 mapAcceptedEdges.Add(curE);
3391 // Collect all edges pass by pass
3392 while (listPrevEdges.Extent() > 0) {
3393 // List of edges, added to chain on this cycle pass
3394 TopTools_ListOfShape listCurEdges;
3396 // Find the next portion of edges
3397 TopTools_ListIteratorOfListOfShape itE (listPrevEdges);
3398 for (; itE.More(); itE.Next()) {
3399 TopoDS_Shape anE = itE.Value();
3401 // Iterate on faces, having edge <anE>
3402 TopTools_ListIteratorOfListOfShape itW (MEW.FindFromKey(anE));
3403 for (; itW.More(); itW.Next()) {
3404 TopoDS_Shape aW = itW.Value();
3405 TopoDS_Shape anOppE;
3407 BRepTools_WireExplorer aWE (TopoDS::Wire(aW));
3408 Standard_Integer nb = 1, found = 0;
3409 TopTools_Array1OfShape anEdges (1,4);
3410 for (; aWE.More(); aWE.Next(), nb++) {
3415 anEdges(nb) = aWE.Current();
3416 if (anEdges(nb).IsSame(anE)) found = nb;
3419 if (nb == 5 && found > 0) {
3420 // Quadrangle face found, get an opposite edge
3421 Standard_Integer opp = found + 2;
3422 if (opp > 4) opp -= 4;
3423 anOppE = anEdges(opp);
3425 if (!mapAcceptedEdges.Contains(anOppE)) {
3426 // Add found edge to the chain
3427 currentChain.Append(anOppE);
3428 listCurEdges.Append(anOppE);
3429 mapAcceptedEdges.Add(anOppE);
3431 } // if (nb == 5 && found > 0)
3432 } // for (; itF.More(); itF.Next())
3433 } // for (; itE.More(); itE.Next())
3435 listPrevEdges = listCurEdges;
3436 } // while (listPrevEdges.Extent() > 0)
3438 // Sort shapes in current chain (Mantis issue 21053)
3439 GEOMUtils::SortShapes(currentChain, Standard_False);
3440 aFirstInChains.Append(currentChain.First());
3441 aMapChains.Bind(currentChain.First(), currentChain);
3444 // Sort chains (Mantis issue 21053)
3445 GEOMUtils::SortShapes(aFirstInChains, Standard_False);
3447 // Store sorted chains in the document
3448 TopTools_ListIteratorOfListOfShape aChainsIt (aFirstInChains);
3449 for (; aChainsIt.More(); aChainsIt.Next()) {
3450 TopoDS_Shape aFirstInChain = aChainsIt.Value();
3451 const TopTools_ListOfShape& currentChain = aMapChains.Find(aFirstInChain);
3453 // Store the chain in the document
3454 Handle(TColStd_HArray1OfInteger) anArray =
3455 new TColStd_HArray1OfInteger (1, currentChain.Extent());
3457 // Fill array of sub-shape indices
3458 TopTools_ListIteratorOfListOfShape itSub (currentChain);
3459 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
3460 int id = anIndices.FindIndex(itSub.Value());
3461 anArray->SetValue(index, id);
3464 // Add a new group object
3465 Handle(GEOM_Object) aChain = GetEngine()->AddSubShape(theShape, anArray);
3468 aChain->SetType(GEOM_GROUP);
3470 // Set a sub-shape type
3471 TDF_Label aFreeLabel = aChain->GetFreeLabel();
3472 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)TopAbs_EDGE);
3474 // Add the chain to the result
3475 aSeq->Append(aChain);
3477 //Make a Python command
3478 TDF_Tool::Entry(aChain->GetEntry(), anEntry);
3479 aListRes += anEntry + ", ";
3482 if (aSeq->IsEmpty()) {
3483 SetErrorCode("There are no quadrangle faces in the shape");
3487 aListRes.Trunc(aListRes.Length() - 2);
3489 // The Propagation doesn't change object so no new function is required.
3490 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
3492 // Make a Python command
3493 GEOM::TPythonDump(aFunction, /*append=*/true)
3494 << "[" << aListRes.ToCString() << "] = geompy.Propagate(" << theShape << ")";