1 // Copyright (C) 2007-2010 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
24 #pragma warning( disable:4786 )
27 #include <Standard_Stream.hxx>
29 #include <GEOMImpl_IBlocksOperations.hxx>
31 #include <GEOMImpl_Types.hxx>
33 #include <GEOMImpl_BlockDriver.hxx>
34 #include <GEOMImpl_IBlocks.hxx>
35 #include <GEOMImpl_IBlockTrsf.hxx>
36 #include <GEOMImpl_CopyDriver.hxx>
37 #include <GEOMImpl_Block6Explorer.hxx>
39 #include <GEOM_Function.hxx>
40 #include <GEOM_PythonDump.hxx>
42 #include <GEOMAlgo_GlueAnalyser.hxx>
43 #include <GEOMAlgo_CoupleOfShapes.hxx>
44 #include <GEOMAlgo_ListOfCoupleOfShapes.hxx>
45 #include <GEOMAlgo_ListIteratorOfListOfCoupleOfShapes.hxx>
46 #include <BlockFix_CheckTool.hxx>
48 #include "utilities.h"
50 #include <Utils_ExceptHandlers.hxx>
52 #include <TFunction_DriverTable.hxx>
53 #include <TFunction_Driver.hxx>
54 #include <TFunction_Logbook.hxx>
55 #include <TDataStd_Integer.hxx>
56 #include <TDF_Tool.hxx>
58 #include <BRep_Tool.hxx>
59 #include <BRep_Builder.hxx>
60 #include <BRepTools.hxx>
61 #include <BRepTools_WireExplorer.hxx>
62 #include <BRepGProp.hxx>
63 #include <BRepBndLib.hxx>
64 #include <BRepAdaptor_Surface.hxx>
65 #include <BRepClass_FaceClassifier.hxx>
66 #include <BRepClass3d_SolidClassifier.hxx>
67 #include <BRepExtrema_DistShapeShape.hxx>
71 #include <TopoDS_Edge.hxx>
72 #include <TopoDS_Vertex.hxx>
73 #include <TopoDS_Compound.hxx>
74 #include <TopoDS_Iterator.hxx>
76 #include <TopExp_Explorer.hxx>
77 #include <TopTools_MapOfShape.hxx>
78 #include <TopTools_Array1OfShape.hxx>
79 #include <TopTools_IndexedMapOfShape.hxx>
80 #include <TopTools_DataMapOfShapeInteger.hxx>
81 #include <TopTools_ListIteratorOfListOfShape.hxx>
82 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
83 #include <TopTools_DataMapIteratorOfDataMapOfShapeInteger.hxx>
85 #include <Bnd_Box.hxx>
86 #include <GProp_GProps.hxx>
88 #include <Geom_Surface.hxx>
89 #include <ShapeAnalysis_Surface.hxx>
91 #include <TColStd_MapOfInteger.hxx>
92 #include <TColStd_Array1OfReal.hxx>
93 #include <TColStd_Array1OfInteger.hxx>
94 #include <TColStd_Array2OfInteger.hxx>
96 //#include <OSD_Timer.hxx>
98 #include <Precision.hxx>
100 #include <Standard_Failure.hxx>
101 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
103 //=============================================================================
107 //=============================================================================
108 GEOMImpl_IBlocksOperations::GEOMImpl_IBlocksOperations (GEOM_Engine* theEngine, int theDocID)
109 : GEOM_IOperations(theEngine, theDocID)
111 MESSAGE("GEOMImpl_IBlocksOperations::GEOMImpl_IBlocksOperations");
114 //=============================================================================
118 //=============================================================================
119 GEOMImpl_IBlocksOperations::~GEOMImpl_IBlocksOperations()
121 MESSAGE("GEOMImpl_IBlocksOperations::~GEOMImpl_IBlocksOperations");
125 //=============================================================================
129 //=============================================================================
130 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad
131 (Handle(GEOM_Object) theEdge1, Handle(GEOM_Object) theEdge2,
132 Handle(GEOM_Object) theEdge3, Handle(GEOM_Object) theEdge4)
136 if (theEdge1.IsNull() || theEdge2.IsNull() ||
137 theEdge3.IsNull() || theEdge4.IsNull()) return NULL;
139 //Add a new Face object
140 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
142 //Add a new Face function
143 Handle(GEOM_Function) aFunction =
144 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_FOUR_EDGES);
146 //Check if the function is set correctly
147 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
149 GEOMImpl_IBlocks aPI (aFunction);
151 Handle(GEOM_Function) aRef1 = theEdge1->GetLastFunction();
152 Handle(GEOM_Function) aRef2 = theEdge2->GetLastFunction();
153 Handle(GEOM_Function) aRef3 = theEdge3->GetLastFunction();
154 Handle(GEOM_Function) aRef4 = theEdge4->GetLastFunction();
155 if (aRef1.IsNull() || aRef2.IsNull() ||
156 aRef3.IsNull() || aRef4.IsNull()) return NULL;
158 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
159 aShapesSeq->Append(aRef1);
160 aShapesSeq->Append(aRef2);
161 aShapesSeq->Append(aRef3);
162 aShapesSeq->Append(aRef4);
164 aPI.SetShapes(aShapesSeq);
166 //Compute the Face value
168 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
171 if (!GetSolver()->ComputeFunction(aFunction)) {
172 SetErrorCode("Block driver failed to compute a face");
176 catch (Standard_Failure) {
177 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
178 SetErrorCode(aFail->GetMessageString());
182 //Make a Python command
183 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeQuad("
184 << theEdge1 << ", " << theEdge2 << ", " << theEdge3 << ", " << theEdge4 << ")";
190 //=============================================================================
194 //=============================================================================
195 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad2Edges
196 (Handle(GEOM_Object) theEdge1, Handle(GEOM_Object) theEdge2)
200 if (theEdge1.IsNull() || theEdge2.IsNull()) return NULL;
202 //Add a new Face object
203 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
205 //Add a new Face function
206 Handle(GEOM_Function) aFunction =
207 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_TWO_EDGES);
209 //Check if the function is set correctly
210 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
212 GEOMImpl_IBlocks aPI (aFunction);
214 Handle(GEOM_Function) aRef1 = theEdge1->GetLastFunction();
215 Handle(GEOM_Function) aRef2 = theEdge2->GetLastFunction();
216 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
218 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
219 aShapesSeq->Append(aRef1);
220 aShapesSeq->Append(aRef2);
222 aPI.SetShapes(aShapesSeq);
224 //Compute the Face value
226 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
229 if (!GetSolver()->ComputeFunction(aFunction)) {
230 SetErrorCode("Block driver failed to compute a face");
234 catch (Standard_Failure) {
235 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
236 SetErrorCode(aFail->GetMessageString());
240 //Make a Python command
241 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeQuad2Edges("
242 << theEdge1 << ", " << theEdge2 << ")";
248 //=============================================================================
252 //=============================================================================
253 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad4Vertices
254 (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2,
255 Handle(GEOM_Object) thePnt3, Handle(GEOM_Object) thePnt4)
259 if (thePnt1.IsNull() || thePnt2.IsNull() ||
260 thePnt3.IsNull() || thePnt4.IsNull()) return NULL;
262 //Add a new Face object
263 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
265 //Add a new Face function
266 Handle(GEOM_Function) aFunction =
267 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_FOUR_PNT);
269 //Check if the function is set correctly
270 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
272 GEOMImpl_IBlocks aPI (aFunction);
274 Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
275 Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
276 Handle(GEOM_Function) aRef3 = thePnt3->GetLastFunction();
277 Handle(GEOM_Function) aRef4 = thePnt4->GetLastFunction();
278 if (aRef1.IsNull() || aRef2.IsNull() ||
279 aRef3.IsNull() || aRef4.IsNull()) return NULL;
281 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
282 aShapesSeq->Append(aRef1);
283 aShapesSeq->Append(aRef2);
284 aShapesSeq->Append(aRef3);
285 aShapesSeq->Append(aRef4);
287 aPI.SetShapes(aShapesSeq);
289 //Compute the Face value
291 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
294 if (!GetSolver()->ComputeFunction(aFunction)) {
295 SetErrorCode("Block driver failed to compute a face");
299 catch (Standard_Failure) {
300 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
301 SetErrorCode(aFail->GetMessageString());
305 //Make a Python command
306 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeQuad4Vertices("
307 << thePnt1 << ", " << thePnt2 << ", " << thePnt3 << ", " << thePnt4 << ")";
313 //=============================================================================
317 //=============================================================================
318 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeHexa
319 (Handle(GEOM_Object) theFace1, Handle(GEOM_Object) theFace2,
320 Handle(GEOM_Object) theFace3, Handle(GEOM_Object) theFace4,
321 Handle(GEOM_Object) theFace5, Handle(GEOM_Object) theFace6)
325 if (theFace1.IsNull() || theFace2.IsNull() ||
326 theFace3.IsNull() || theFace4.IsNull() ||
327 theFace5.IsNull() || theFace6.IsNull()) return NULL;
329 //Add a new Solid object
330 Handle(GEOM_Object) aBlock = GetEngine()->AddObject(GetDocID(), GEOM_BLOCK);
332 //Add a new Block function
333 Handle(GEOM_Function) aFunction =
334 aBlock->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_SIX_FACES);
336 //Check if the function is set correctly
337 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
339 GEOMImpl_IBlocks aPI (aFunction);
341 Handle(GEOM_Function) aRef1 = theFace1->GetLastFunction();
342 Handle(GEOM_Function) aRef2 = theFace2->GetLastFunction();
343 Handle(GEOM_Function) aRef3 = theFace3->GetLastFunction();
344 Handle(GEOM_Function) aRef4 = theFace4->GetLastFunction();
345 Handle(GEOM_Function) aRef5 = theFace5->GetLastFunction();
346 Handle(GEOM_Function) aRef6 = theFace6->GetLastFunction();
347 if (aRef1.IsNull() || aRef2.IsNull() ||
348 aRef3.IsNull() || aRef4.IsNull() ||
349 aRef5.IsNull() || aRef6.IsNull()) return NULL;
351 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
352 aShapesSeq->Append(aRef1);
353 aShapesSeq->Append(aRef2);
354 aShapesSeq->Append(aRef3);
355 aShapesSeq->Append(aRef4);
356 aShapesSeq->Append(aRef5);
357 aShapesSeq->Append(aRef6);
359 aPI.SetShapes(aShapesSeq);
361 //Compute the Block value
363 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
366 if (!GetSolver()->ComputeFunction(aFunction)) {
367 SetErrorCode("Block driver failed to compute a block");
371 catch (Standard_Failure) {
372 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
373 SetErrorCode(aFail->GetMessageString());
377 //Make a Python command
378 GEOM::TPythonDump(aFunction) << aBlock << " = geompy.MakeHexa("
379 << theFace1 << ", " << theFace2 << ", " << theFace3 << ", "
380 << theFace4 << ", " << theFace5 << ", " << theFace6 << ")";
386 //=============================================================================
390 //=============================================================================
391 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeHexa2Faces
392 (Handle(GEOM_Object) theFace1, Handle(GEOM_Object) theFace2)
396 if (theFace1.IsNull() || theFace2.IsNull()) return NULL;
398 //Add a new Solid object
399 Handle(GEOM_Object) aBlock = GetEngine()->AddObject(GetDocID(), GEOM_BLOCK);
401 //Add a new Block function
402 Handle(GEOM_Function) aFunction =
403 aBlock->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_TWO_FACES);
405 //Check if the function is set correctly
406 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
408 GEOMImpl_IBlocks aPI (aFunction);
410 Handle(GEOM_Function) aRef1 = theFace1->GetLastFunction();
411 Handle(GEOM_Function) aRef2 = theFace2->GetLastFunction();
412 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
414 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
415 aShapesSeq->Append(aRef1);
416 aShapesSeq->Append(aRef2);
418 aPI.SetShapes(aShapesSeq);
420 //Compute the Block value
422 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
425 if (!GetSolver()->ComputeFunction(aFunction)) {
426 SetErrorCode("Block driver failed to compute a block");
430 catch (Standard_Failure) {
431 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
432 SetErrorCode(aFail->GetMessageString());
436 //Make a Python command
437 GEOM::TPythonDump(aFunction) << aBlock << " = geompy.MakeHexa2Faces("
438 << theFace1 << ", " << theFace2 << ")";
444 //=============================================================================
448 //=============================================================================
449 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeBlockCompound
450 (Handle(GEOM_Object) theCompound)
454 if (theCompound.IsNull()) return NULL;
457 Handle(GEOM_Object) aBlockComp = GetEngine()->AddObject(GetDocID(), GEOM_COMPOUND);
459 //Add a new BlocksComp function
460 Handle(GEOM_Function) aFunction =
461 aBlockComp->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_COMPOUND_GLUE);
463 //Check if the function is set correctly
464 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
466 GEOMImpl_IBlocks aPI (aFunction);
468 Handle(GEOM_Function) aRef1 = theCompound->GetLastFunction();
469 if (aRef1.IsNull()) return NULL;
471 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
472 aShapesSeq->Append(aRef1);
474 aPI.SetShapes(aShapesSeq);
476 //Compute the Blocks Compound value
478 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
481 if (!GetSolver()->ComputeFunction(aFunction)) {
482 SetErrorCode("Block driver failed to compute a blocks compound");
486 catch (Standard_Failure) {
487 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
488 SetErrorCode(aFail->GetMessageString());
492 //Make a Python command
493 GEOM::TPythonDump(aFunction) << aBlockComp
494 << " = geompy.MakeBlockCompound(" << theCompound << ")";
500 //=============================================================================
504 //=============================================================================
505 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetPoint
506 (Handle(GEOM_Object) theShape,
507 const Standard_Real theX,
508 const Standard_Real theY,
509 const Standard_Real theZ,
510 const Standard_Real theEpsilon)
515 Handle(GEOM_Object) aResult;
518 if (theShape.IsNull()) return NULL;
520 TopoDS_Shape aBlockOrComp = theShape->GetValue();
521 if (aBlockOrComp.IsNull()) {
522 SetErrorCode("Given shape is null");
526 //Compute the Vertex value
527 gp_Pnt P (theX, theY, theZ);
528 Standard_Real eps = Max(theEpsilon, Precision::Confusion());
531 Standard_Integer isFound = 0;
532 TopTools_MapOfShape mapShape;
533 TopExp_Explorer exp (aBlockOrComp, TopAbs_VERTEX);
535 for (; exp.More(); exp.Next()) {
536 if (mapShape.Add(exp.Current())) {
537 TopoDS_Vertex aVi = TopoDS::Vertex(exp.Current());
538 gp_Pnt aPi = BRep_Tool::Pnt(aVi);
539 if (aPi.Distance(P) < eps) {
547 SetErrorCode("Vertex has not been found");
549 } else if (isFound > 1) {
550 SetErrorCode("Multiple vertices found by the given coordinates and epsilon");
553 TopTools_IndexedMapOfShape anIndices;
554 TopExp::MapShapes(aBlockOrComp, anIndices);
555 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
556 anArray->SetValue(1, anIndices.FindIndex(V));
557 aResult = GetEngine()->AddSubShape(theShape, anArray);
560 //The GetPoint() doesn't change object so no new function is required.
561 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
563 //Make a Python command
564 GEOM::TPythonDump(aFunction, /*append=*/true)
565 << aResult << " = geompy.GetPoint(" << theShape << ", "
566 << theX << ", " << theY << ", " << theZ << ", " << theEpsilon << ")";
572 //=============================================================================
576 //=============================================================================
577 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetVertexNearPoint
578 (Handle(GEOM_Object) theShape,
579 Handle(GEOM_Object) thePoint)
584 Handle(GEOM_Object) aResult;
587 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
589 TopoDS_Shape aBlockOrComp = theShape->GetValue();
590 TopoDS_Shape aPoint = thePoint->GetValue();
591 if (aBlockOrComp.IsNull() || aPoint.IsNull()) {
592 SetErrorCode("Given shape is null");
596 if (aPoint.ShapeType() != TopAbs_VERTEX) {
597 SetErrorCode("Element for vertex identification is not a vertex");
601 TopoDS_Vertex aVert = TopoDS::Vertex(aPoint);
602 gp_Pnt aP = BRep_Tool::Pnt(aVert);
604 // Compute the Vertex value
606 bool isFound = false;
607 Standard_Real aDist = RealLast();
608 TopTools_MapOfShape mapShape;
610 TopExp_Explorer exp (aBlockOrComp, TopAbs_VERTEX);
611 for (; exp.More(); exp.Next()) {
612 if (mapShape.Add(exp.Current())) {
613 TopoDS_Vertex aVi = TopoDS::Vertex(exp.Current());
614 gp_Pnt aPi = BRep_Tool::Pnt(aVi);
615 Standard_Real aDisti = aPi.Distance(aP);
616 if (aDisti < aDist) {
625 SetErrorCode("Vertex has not been found");
629 TopTools_IndexedMapOfShape anIndices;
630 TopExp::MapShapes(aBlockOrComp, anIndices);
631 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
632 anArray->SetValue(1, anIndices.FindIndex(V));
633 aResult = GetEngine()->AddSubShape(theShape, anArray);
635 // The GetPoint() doesn't change object so no new function is required.
636 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
638 // Make a Python command
639 GEOM::TPythonDump(aFunction, /*append=*/true)
640 << aResult << " = geompy.GetVertexNearPoint("
641 << theShape << ", " << thePoint << ")";
647 //=============================================================================
651 //=============================================================================
652 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetEdge
653 (Handle(GEOM_Object) theShape,
654 Handle(GEOM_Object) thePoint1,
655 Handle(GEOM_Object) thePoint2)
660 Handle(GEOM_Object) aResult;
663 if (theShape.IsNull() || thePoint1.IsNull() || thePoint2.IsNull()) return NULL;
665 TopoDS_Shape aBlockOrComp = theShape->GetValue();
666 if (aBlockOrComp.IsNull()) {
667 SetErrorCode("Given shape is null");
671 TopoDS_Shape anArg1 = thePoint1->GetValue();
672 TopoDS_Shape anArg2 = thePoint2->GetValue();
673 if (anArg1.IsNull() || anArg2.IsNull()) {
674 SetErrorCode("Null shape is given as argument");
677 if (anArg1.ShapeType() != TopAbs_VERTEX ||
678 anArg2.ShapeType() != TopAbs_VERTEX) {
679 SetErrorCode("Element for edge identification is not a vertex");
683 //Compute the Edge value
685 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
688 TopTools_IndexedDataMapOfShapeListOfShape MVE;
689 GEOMImpl_Block6Explorer::MapShapesAndAncestors
690 (aBlockOrComp, TopAbs_VERTEX, TopAbs_EDGE, MVE);
693 Standard_Integer ish, ext = MVE.Extent();
695 if (MVE.Contains(anArg1)) {
698 for (ish = 1; ish <= ext; ish++) {
699 TopoDS_Shape aShi = MVE.FindKey(ish);
700 if (BRepTools::Compare(TopoDS::Vertex(anArg1), TopoDS::Vertex(aShi))) {
707 if (MVE.Contains(anArg2)) {
710 for (ish = 1; ish <= ext; ish++) {
711 TopoDS_Shape aShi = MVE.FindKey(ish);
712 if (BRepTools::Compare(TopoDS::Vertex(anArg2), TopoDS::Vertex(aShi))) {
719 if (V1.IsNull() || V2.IsNull()) {
720 SetErrorCode("The given vertex does not belong to the shape");
725 Standard_Integer isFound =
726 GEOMImpl_Block6Explorer::FindEdge(anEdge, V1, V2, MVE, Standard_True);
728 SetErrorCode("The given vertices do not belong to one edge of the given shape");
730 } else if (isFound > 1) {
731 SetErrorCode("Multiple edges found by the given vertices of the shape");
734 TopTools_IndexedMapOfShape anIndices;
735 TopExp::MapShapes(aBlockOrComp, anIndices);
736 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
737 anArray->SetValue(1, anIndices.FindIndex(anEdge));
738 aResult = GetEngine()->AddSubShape(theShape, anArray);
740 } catch (Standard_Failure) {
741 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
742 SetErrorCode(aFail->GetMessageString());
746 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
748 //Make a Python command
749 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetEdge("
750 << theShape << ", " << thePoint1 << ", " << thePoint2 << ")";
756 //=============================================================================
760 //=============================================================================
761 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetEdgeNearPoint
762 (Handle(GEOM_Object) theShape,
763 Handle(GEOM_Object) thePoint)
768 Handle(GEOM_Object) aResult;
771 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
773 TopoDS_Shape aBlockOrComp = theShape->GetValue();
774 if (aBlockOrComp.IsNull()) {
775 SetErrorCode("Given shape is null");
779 TopoDS_Shape anArg = thePoint->GetValue();
780 if (anArg.IsNull()) {
781 SetErrorCode("Null shape is given as argument");
784 if (anArg.ShapeType() != TopAbs_VERTEX) {
785 SetErrorCode("Element for edge identification is not a vertex");
789 //Compute the Edge value
791 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
796 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
798 // 1. Explode blocks on edges
799 TopTools_MapOfShape mapShape;
800 Standard_Integer nbEdges = 0;
801 TopExp_Explorer exp (aBlockOrComp, TopAbs_EDGE);
802 for (; exp.More(); exp.Next()) {
803 if (mapShape.Add(exp.Current())) {
809 SetErrorCode("Given shape contains no edges");
814 Standard_Integer ind = 1;
815 TopTools_Array1OfShape anEdges (1, nbEdges);
816 TColStd_Array1OfReal aDistances (1, nbEdges);
817 for (exp.Init(aBlockOrComp, TopAbs_EDGE); exp.More(); exp.Next()) {
818 if (mapShape.Add(exp.Current())) {
819 TopoDS_Shape anEdge = exp.Current();
820 anEdges(ind) = anEdge;
822 // 2. Classify the point relatively each edge
823 BRepExtrema_DistShapeShape aDistTool (aVert, anEdges(ind));
824 if (!aDistTool.IsDone()) {
825 SetErrorCode("Can not find a distance from the given point to one of edges");
828 aDistances(ind) = aDistTool.Value();
833 // 3. Define edge, having minimum distance to the point
834 Standard_Real nearest = RealLast(), nbFound = 0;
835 Standard_Real prec = Precision::Confusion();
836 for (ind = 1; ind <= nbEdges; ind++) {
837 if (Abs(aDistances(ind) - nearest) < prec) {
839 } else if (aDistances(ind) < nearest) {
840 nearest = aDistances(ind);
841 aShape = anEdges(ind);
847 SetErrorCode("Multiple edges near the given point are found");
849 } else if (nbFound == 0) {
850 SetErrorCode("There are no edges near the given point");
853 TopTools_IndexedMapOfShape anIndices;
854 TopExp::MapShapes(aBlockOrComp, anIndices);
855 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
856 anArray->SetValue(1, anIndices.FindIndex(aShape));
857 aResult = GetEngine()->AddSubShape(theShape, anArray);
860 catch (Standard_Failure) {
861 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
862 SetErrorCode(aFail->GetMessageString());
866 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
868 //Make a Python command
869 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetEdgeNearPoint("
870 << theShape << ", " << thePoint << ")";
876 //=============================================================================
880 //=============================================================================
881 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByPoints
882 (Handle(GEOM_Object) theShape,
883 Handle(GEOM_Object) thePoint1,
884 Handle(GEOM_Object) thePoint2,
885 Handle(GEOM_Object) thePoint3,
886 Handle(GEOM_Object) thePoint4)
891 Handle(GEOM_Object) aResult;
894 if (theShape.IsNull() ||
895 thePoint1.IsNull() || thePoint2.IsNull() ||
896 thePoint3.IsNull() || thePoint4.IsNull()) return NULL;
898 TopoDS_Shape aBlockOrComp = theShape->GetValue();
899 if (aBlockOrComp.IsNull()) {
900 SetErrorCode("Block or compound is null");
904 TopoDS_Shape anArg1 = thePoint1->GetValue();
905 TopoDS_Shape anArg2 = thePoint2->GetValue();
906 TopoDS_Shape anArg3 = thePoint3->GetValue();
907 TopoDS_Shape anArg4 = thePoint4->GetValue();
908 if (anArg1.IsNull() || anArg2.IsNull() ||
909 anArg3.IsNull() || anArg4.IsNull()) {
910 SetErrorCode("Null shape is given as argument");
913 if (anArg1.ShapeType() != TopAbs_VERTEX ||
914 anArg2.ShapeType() != TopAbs_VERTEX ||
915 anArg3.ShapeType() != TopAbs_VERTEX ||
916 anArg4.ShapeType() != TopAbs_VERTEX) {
917 SetErrorCode("Element for face identification is not a vertex");
921 //Compute the Face value
923 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
928 TopTools_IndexedDataMapOfShapeListOfShape MVF;
929 GEOMImpl_Block6Explorer::MapShapesAndAncestors(aBlockOrComp, TopAbs_VERTEX, TopAbs_FACE, MVF);
931 TopoDS_Shape V1,V2,V3,V4;
932 Standard_Integer ish, ext = MVF.Extent();
934 if (MVF.Contains(anArg1)) {
937 for (ish = 1; ish <= ext; ish++) {
938 TopoDS_Shape aShi = MVF.FindKey(ish);
939 if (BRepTools::Compare(TopoDS::Vertex(anArg1), TopoDS::Vertex(aShi))) {
946 if (MVF.Contains(anArg2)) {
949 for (ish = 1; ish <= ext; ish++) {
950 TopoDS_Shape aShi = MVF.FindKey(ish);
951 if (BRepTools::Compare(TopoDS::Vertex(anArg2), TopoDS::Vertex(aShi))) {
958 if (MVF.Contains(anArg3)) {
961 for (ish = 1; ish <= ext; ish++) {
962 TopoDS_Shape aShi = MVF.FindKey(ish);
963 if (BRepTools::Compare(TopoDS::Vertex(anArg3), TopoDS::Vertex(aShi))) {
970 if (MVF.Contains(anArg4)) {
973 for (ish = 1; ish <= ext; ish++) {
974 TopoDS_Shape aShi = MVF.FindKey(ish);
975 if (BRepTools::Compare(TopoDS::Vertex(anArg4), TopoDS::Vertex(aShi))) {
982 if (V1.IsNull() || V2.IsNull() || V3.IsNull() || V4.IsNull()) {
983 SetErrorCode("The given vertex does not belong to the shape");
987 Standard_Integer isFound =
988 GEOMImpl_Block6Explorer::FindFace(aShape, V1, V2, V3, V4, MVF, Standard_True);
990 SetErrorCode("The given vertices do not belong to one face of the given shape");
992 } else if (isFound > 1) {
993 SetErrorCode("The given vertices belong to several faces of the given shape");
996 TopTools_IndexedMapOfShape anIndices;
997 TopExp::MapShapes(aBlockOrComp, anIndices);
998 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
999 anArray->SetValue(1, anIndices.FindIndex(aShape));
1000 aResult = GetEngine()->AddSubShape(theShape, anArray);
1003 catch (Standard_Failure) {
1004 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1005 SetErrorCode(aFail->GetMessageString());
1009 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1011 //Make a Python command
1012 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByPoints("
1013 << theShape << ", " << thePoint1 << ", " << thePoint2
1014 << ", " << thePoint3 << ", " << thePoint4 << ")";
1020 //=============================================================================
1024 //=============================================================================
1025 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByEdges
1026 (Handle(GEOM_Object) theShape,
1027 Handle(GEOM_Object) theEdge1,
1028 Handle(GEOM_Object) theEdge2)
1033 Handle(GEOM_Object) aResult;
1036 if (theShape.IsNull() || theEdge1.IsNull() || theEdge2.IsNull()) return NULL;
1038 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1039 if (aBlockOrComp.IsNull()) {
1040 SetErrorCode("Block or compound is null");
1044 TopoDS_Shape anArg1 = theEdge1->GetValue();
1045 TopoDS_Shape anArg2 = theEdge2->GetValue();
1046 if (anArg1.IsNull() || anArg2.IsNull()) {
1047 SetErrorCode("Null shape is given as argument");
1050 if (anArg1.ShapeType() != TopAbs_EDGE ||
1051 anArg2.ShapeType() != TopAbs_EDGE) {
1052 SetErrorCode("Element for face identification is not an edge");
1056 //Compute the Face value
1058 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1061 TopoDS_Shape aShape;
1063 TopTools_IndexedDataMapOfShapeListOfShape MEF;
1064 GEOMImpl_Block6Explorer::MapShapesAndAncestors(aBlockOrComp, TopAbs_EDGE, TopAbs_FACE, MEF);
1067 Standard_Integer ish, ext = MEF.Extent();
1069 if (MEF.Contains(anArg1)) {
1072 for (ish = 1; ish <= ext; ish++) {
1073 TopoDS_Shape aShi = MEF.FindKey(ish);
1074 if (GEOMImpl_Block6Explorer::IsSimilarEdges(anArg1, aShi)) {
1080 if (MEF.Contains(anArg2)) {
1083 for (ish = 1; ish <= ext; ish++) {
1084 TopoDS_Shape aShi = MEF.FindKey(ish);
1085 if (GEOMImpl_Block6Explorer::IsSimilarEdges(anArg2, aShi)) {
1091 if (E1.IsNull() || E2.IsNull()) {
1092 SetErrorCode("The given edge does not belong to the shape");
1096 const TopTools_ListOfShape& aFacesOfE1 = MEF.FindFromKey(E1);
1097 const TopTools_ListOfShape& aFacesOfE2 = MEF.FindFromKey(E2);
1099 Standard_Integer isFound = 0;
1100 TopTools_ListIteratorOfListOfShape anIterF1 (aFacesOfE1);
1101 for (; anIterF1.More(); anIterF1.Next()) {
1103 TopTools_ListIteratorOfListOfShape anIterF2 (aFacesOfE2);
1104 for (; anIterF2.More(); anIterF2.Next()) {
1106 if (anIterF1.Value().IsSame(anIterF2.Value())) {
1109 // Store the face, defined by two edges
1110 aShape = anIterF1.Value();
1115 SetErrorCode("The given edges do not belong to one face of the given shape");
1117 } else if (isFound > 1) {
1118 SetErrorCode("The given edges belong to several faces of the given shape");
1121 TopTools_IndexedMapOfShape anIndices;
1122 TopExp::MapShapes(aBlockOrComp, anIndices);
1123 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1124 anArray->SetValue(1, anIndices.FindIndex(aShape));
1125 aResult = GetEngine()->AddSubShape(theShape, anArray);
1128 catch (Standard_Failure) {
1129 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1130 SetErrorCode(aFail->GetMessageString());
1134 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1136 //Make a Python command
1137 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByEdges("
1138 << theShape << ", " << theEdge1 << ", " << theEdge2 << ")";
1144 //=============================================================================
1148 //=============================================================================
1149 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetOppositeFace
1150 (Handle(GEOM_Object) theShape,
1151 Handle(GEOM_Object) theFace)
1156 Handle(GEOM_Object) aResult;
1159 if (theShape.IsNull() || theFace.IsNull()) return NULL;
1161 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1162 if (aBlockOrComp.IsNull()) {
1163 SetErrorCode("Block is null");
1166 if (aBlockOrComp.ShapeType() != TopAbs_SOLID) {
1167 SetErrorCode("Shape is not a block");
1171 TopoDS_Shape anArg = theFace->GetValue();
1172 if (anArg.IsNull()) {
1173 SetErrorCode("Null shape is given as argument");
1176 if (anArg.ShapeType() != TopAbs_FACE) {
1177 SetErrorCode("Element for face identification is not a face");
1181 //Compute the Face value
1183 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1186 TopoDS_Shape aShape;
1188 GEOMImpl_Block6Explorer aBlockTool;
1189 aBlockTool.InitByBlockAndFace(aBlockOrComp, anArg);
1190 aShape = aBlockTool.GetFace(2);
1192 TopTools_IndexedMapOfShape anIndices;
1193 TopExp::MapShapes(aBlockOrComp, anIndices);
1194 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1195 anArray->SetValue(1, anIndices.FindIndex(aShape));
1196 aResult = GetEngine()->AddSubShape(theShape, anArray);
1198 catch (Standard_Failure) {
1199 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1200 SetErrorCode(aFail->GetMessageString());
1204 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1206 //Make a Python command
1207 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetOppositeFace("
1208 << theShape << ", " << theFace << ")";
1214 //=============================================================================
1218 //=============================================================================
1219 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceNearPoint
1220 (Handle(GEOM_Object) theShape,
1221 Handle(GEOM_Object) thePoint)
1226 Handle(GEOM_Object) aResult;
1229 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
1231 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1232 if (aBlockOrComp.IsNull()) {
1233 SetErrorCode("Block or compound is null");
1237 TopoDS_Shape anArg = thePoint->GetValue();
1238 if (anArg.IsNull()) {
1239 SetErrorCode("Null shape is given as argument");
1242 if (anArg.ShapeType() != TopAbs_VERTEX) {
1243 SetErrorCode("Element for face identification is not a vertex");
1247 //Compute the Face value
1249 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1252 TopoDS_Shape aShape;
1254 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
1255 gp_Pnt aPnt = BRep_Tool::Pnt(aVert);
1256 Standard_Real PX, PY, PZ;
1257 aPnt.Coord(PX, PY, PZ);
1259 // 1. Classify the point relatively each face
1260 Standard_Integer nearest = 2, nbFound = 0;
1261 TopTools_DataMapOfShapeInteger mapShapeDist;
1262 TopExp_Explorer exp (aBlockOrComp, TopAbs_FACE);
1263 for (; exp.More(); exp.Next()) {
1264 TopoDS_Shape aFace = exp.Current();
1266 if (!mapShapeDist.IsBound(aFace)) {
1267 Standard_Integer aDistance = 2;
1269 // 1.a. Classify relatively Surface
1270 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aFace));
1271 Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf);
1272 gp_Pnt2d p2dOnSurf = aSurfAna->ValueOfUV(aPnt, Precision::Confusion());
1273 gp_Pnt p3dOnSurf = aSurfAna->Value(p2dOnSurf);
1274 Standard_Real aDist = p3dOnSurf.Distance(aPnt);
1275 if (aDist > Precision::Confusion()) {
1279 // 1.b. Classify relatively the face itself
1280 BRepClass_FaceClassifier FC (TopoDS::Face(aFace), p2dOnSurf, Precision::Confusion());
1281 if (FC.State() == TopAbs_IN) {
1283 } else if (FC.State() == TopAbs_ON) {
1290 if (aDistance < nearest) {
1291 nearest = aDistance;
1295 // A first found face, containing the point inside, will be returned.
1296 // It is the solution, if there are no
1297 // coincident or intersecting faces in the compound.
1298 if (nearest == -1) break;
1300 } else if (aDistance == nearest) {
1305 mapShapeDist.Bind(aFace, aDistance);
1306 } // if (!mapShapeDist.IsBound(aFace))
1309 // 2. Define face, containing the point or having minimum distance to it
1312 // The point is on boundary of some faces and there are
1313 // no faces, having the point inside
1314 SetErrorCode("Multiple faces near the given point are found");
1317 } else if (nearest == 1) {
1318 // The point is outside some faces and there are
1319 // no faces, having the point inside or on boundary.
1320 // We will get a nearest face
1321 Standard_Real bigReal = RealLast();
1322 Standard_Real minDist = bigReal;
1323 TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
1324 for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
1325 if (mapShapeDistIter.Value() == 1) {
1326 TopoDS_Shape aFace = mapShapeDistIter.Key();
1327 Standard_Real aDist = bigReal;
1329 // 2.a. Fast check of distance - if point projection on surface is on face
1330 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aFace));
1331 Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf);
1332 gp_Pnt2d p2dOnSurf = aSurfAna->ValueOfUV(aPnt, Precision::Confusion());
1333 gp_Pnt p3dOnSurf = aSurfAna->Value(p2dOnSurf);
1334 aDist = p3dOnSurf.Distance(aPnt);
1336 BRepClass_FaceClassifier FC (TopoDS::Face(aFace), p2dOnSurf, Precision::Confusion());
1337 if (FC.State() == TopAbs_OUT) {
1338 if (aDist < minDist) {
1339 // 2.b. Slow check - if point projection on surface is outside of face
1340 BRepExtrema_DistShapeShape aDistTool (aVert, aFace);
1341 if (!aDistTool.IsDone()) {
1342 SetErrorCode("Can not find a distance from the given point to one of faces");
1345 aDist = aDistTool.Value();
1351 if (aDist < minDist) {
1357 } else { // nearest == -1
1358 // // The point is inside some faces.
1359 // // We will get a face with nearest center
1360 // Standard_Real minDist = RealLast();
1361 // TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
1362 // for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
1363 // if (mapShapeDistIter.Value() == -1) {
1364 // TopoDS_Shape aFace = mapShapeDistIter.Key();
1365 // GProp_GProps aSystem;
1366 // BRepGProp::SurfaceProperties(aFace, aSystem);
1367 // gp_Pnt aCenterMass = aSystem.CentreOfMass();
1369 // Standard_Real aDist = aCenterMass.Distance(aPnt);
1370 // if (aDist < minDist) {
1377 } // if (nbFound > 1)
1380 SetErrorCode("There are no faces near the given point");
1383 TopTools_IndexedMapOfShape anIndices;
1384 TopExp::MapShapes(aBlockOrComp, anIndices);
1385 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1386 anArray->SetValue(1, anIndices.FindIndex(aShape));
1387 aResult = GetEngine()->AddSubShape(theShape, anArray);
1390 catch (Standard_Failure) {
1391 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1392 SetErrorCode(aFail->GetMessageString());
1396 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1398 //Make a Python command
1399 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceNearPoint("
1400 << theShape << ", " << thePoint << ")";
1406 //=============================================================================
1410 //=============================================================================
1411 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByNormale
1412 (Handle(GEOM_Object) theShape,
1413 Handle(GEOM_Object) theVector)
1418 Handle(GEOM_Object) aResult;
1421 if (theShape.IsNull() || theVector.IsNull()) return NULL;
1423 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1424 if (aBlockOrComp.IsNull()) {
1425 SetErrorCode("Block or compound is null");
1429 TopoDS_Shape anArg = theVector->GetValue();
1430 if (anArg.IsNull()) {
1431 SetErrorCode("Null shape is given as argument");
1434 if (anArg.ShapeType() != TopAbs_EDGE) {
1435 SetErrorCode("Element for normale identification is not an edge");
1439 //Compute the Face value
1441 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1444 TopoDS_Shape aShape;
1446 TopoDS_Edge anEdge = TopoDS::Edge(anArg);
1447 TopoDS_Vertex V1, V2;
1448 TopExp::Vertices(anEdge, V1, V2, Standard_True);
1449 gp_Pnt P1 = BRep_Tool::Pnt(V1);
1450 gp_Pnt P2 = BRep_Tool::Pnt(V2);
1451 gp_Vec aVec (P1, P2);
1452 if (aVec.Magnitude() < Precision::Confusion()) {
1453 SetErrorCode("Vector with null magnitude is given");
1457 Standard_Real minAngle = RealLast();
1458 TopTools_MapOfShape mapShape;
1459 TopExp_Explorer exp (aBlockOrComp, TopAbs_FACE);
1460 for (; exp.More(); exp.Next()) {
1461 if (mapShape.Add(exp.Current())) {
1462 TopoDS_Face aFace = TopoDS::Face(exp.Current());
1463 BRepAdaptor_Surface SF (aFace);
1465 Standard_Real u, v, x;
1467 // find a point on the surface to get normal direction in
1468 u = SF.FirstUParameter();
1469 x = SF.LastUParameter();
1470 if (Precision::IsInfinite(u)) {
1471 u = (Precision::IsInfinite(x)) ? 0. : x;
1472 } else if (!Precision::IsInfinite(x)) {
1476 v = SF.FirstVParameter();
1477 x = SF.LastVParameter();
1478 if (Precision::IsInfinite(v)) {
1479 v = (Precision::IsInfinite(x)) ? 0. : x;
1480 } else if (!Precision::IsInfinite(x)) {
1484 // compute the normal direction
1486 SF.D1(u,v,P1,Vec1,Vec2);
1487 gp_Vec V = Vec1.Crossed(Vec2);
1489 if (V.Magnitude() < Precision::Confusion()) {
1490 SetErrorCode("Normal vector of a face has null magnitude");
1494 // consider the face orientation
1495 if (aFace.Orientation() == TopAbs_REVERSED ||
1496 aFace.Orientation() == TopAbs_INTERNAL) {
1500 // compute the angle and compare with the minimal one
1501 Standard_Real anAngle = aVec.Angle(V);
1502 if (anAngle < minAngle) {
1509 if (aShape.IsNull()) {
1510 SetErrorCode("Failed to find a face by the given normale");
1513 TopTools_IndexedMapOfShape anIndices;
1514 TopExp::MapShapes(aBlockOrComp, anIndices);
1515 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1516 anArray->SetValue(1, anIndices.FindIndex(aShape));
1517 aResult = GetEngine()->AddSubShape(theShape, anArray);
1520 catch (Standard_Failure) {
1521 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1522 SetErrorCode(aFail->GetMessageString());
1526 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1528 //Make a Python command
1529 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByNormale("
1530 << theShape << ", " << theVector << ")";
1536 //=============================================================================
1538 * GetShapesNearPoint
1540 //=============================================================================
1541 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetShapesNearPoint
1542 (Handle(GEOM_Object) theShape,
1543 Handle(GEOM_Object) thePoint,
1544 const Standard_Integer theShapeType,
1545 const Standard_Real theConstTolerance)
1550 Handle(GEOM_Object) aResult;
1553 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
1555 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1556 if (aBlockOrComp.IsNull()) {
1557 SetErrorCode("Block or compound is null");
1561 TopoDS_Shape anArg = thePoint->GetValue();
1562 if (anArg.IsNull()) {
1563 SetErrorCode("Null shape is given as argument");
1566 if (anArg.ShapeType() != TopAbs_VERTEX) {
1567 SetErrorCode("Element for face identification is not a vertex");
1571 if (theShapeType < TopAbs_SOLID || TopAbs_VERTEX < theShapeType) {
1572 SetErrorCode("Invalid type of result is requested");
1576 Standard_Real theTolerance = theConstTolerance;
1577 if (theTolerance < Precision::Confusion()) {
1578 theTolerance = Precision::Confusion();
1581 // Compute the result
1583 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1586 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
1588 TopTools_MapOfShape mapShape;
1589 Standard_Integer nbEdges = 0;
1590 TopExp_Explorer exp (aBlockOrComp, TopAbs_ShapeEnum(theShapeType));
1591 for (; exp.More(); exp.Next()) {
1592 if (mapShape.Add(exp.Current())) {
1598 SetErrorCode("Given shape contains no subshapes of requested type");
1602 // Calculate distances and find min
1604 Standard_Integer ind = 1;
1605 Standard_Real aMinDist = RealLast();
1606 TopTools_Array1OfShape anEdges (1, nbEdges);
1607 TColStd_Array1OfReal aDistances (1, nbEdges);
1608 for (exp.Init(aBlockOrComp, TopAbs_ShapeEnum(theShapeType)); exp.More(); exp.Next()) {
1609 if (mapShape.Add(exp.Current())) {
1610 TopoDS_Shape anEdge = exp.Current();
1611 anEdges(ind) = anEdge;
1613 BRepExtrema_DistShapeShape aDistTool (aVert, anEdges(ind));
1614 if (!aDistTool.IsDone()) {
1615 SetErrorCode("Can not find a distance from the given point to one of subshapes");
1618 aDistances(ind) = aDistTool.Value();
1619 if (aDistances(ind) < aMinDist) {
1620 aMinDist = aDistances(ind);
1626 if (aMinDist < RealLast()) {
1627 // Collect subshapes with distance < (aMinDist + theTolerance)
1628 int nbSubShapes = 0;
1629 TopTools_Array1OfShape aNearShapes (1, nbEdges);
1630 for (ind = 1; ind <= nbEdges; ind++) {
1631 if (aDistances(ind) < aMinDist + theTolerance) {
1633 aNearShapes(nbSubShapes) = anEdges(ind);
1638 TopTools_IndexedMapOfShape anIndices;
1639 TopExp::MapShapes(aBlockOrComp, anIndices);
1640 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger (1, nbSubShapes);
1641 for (ind = 1; ind <= nbSubShapes; ind++) {
1642 anArray->SetValue(ind, anIndices.FindIndex(aNearShapes(ind)));
1644 aResult = GetEngine()->AddSubShape(theShape, anArray);
1647 catch (Standard_Failure) {
1648 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1649 SetErrorCode(aFail->GetMessageString());
1653 if (aResult.IsNull())
1656 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1658 //Make a Python command
1659 GEOM::TPythonDump(aFunction)
1660 << aResult << " = geompy.GetShapesNearPoint(" << theShape << ", " << thePoint
1661 << ", " << TopAbs_ShapeEnum(theShapeType) << ", " << theTolerance << ")";
1667 //=============================================================================
1669 * IsCompoundOfBlocks
1671 //=============================================================================
1672 Standard_Boolean GEOMImpl_IBlocksOperations::IsCompoundOfBlocks
1673 (Handle(GEOM_Object) theCompound,
1674 const Standard_Integer theMinNbFaces,
1675 const Standard_Integer theMaxNbFaces,
1676 Standard_Integer& theNbBlocks)
1679 Standard_Boolean isCompOfBlocks = Standard_False;
1682 if (theCompound.IsNull()) return isCompOfBlocks;
1683 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
1686 isCompOfBlocks = Standard_True;
1688 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1691 TopTools_MapOfShape mapShape;
1692 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
1693 for (; exp.More(); exp.Next()) {
1694 if (mapShape.Add(exp.Current())) {
1695 TopoDS_Shape aSolid = exp.Current();
1697 TopTools_MapOfShape mapFaces;
1698 TopExp_Explorer expF (aSolid, TopAbs_FACE);
1699 Standard_Integer nbFaces = 0;
1700 for (; expF.More(); expF.Next()) {
1701 if (mapFaces.Add(expF.Current())) {
1703 if (nbFaces > theMaxNbFaces) {
1704 isCompOfBlocks = Standard_False;
1709 if (nbFaces < theMinNbFaces || theMaxNbFaces < nbFaces) {
1710 isCompOfBlocks = Standard_False;
1717 catch (Standard_Failure) {
1718 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1719 SetErrorCode(aFail->GetMessageString());
1720 return isCompOfBlocks;
1724 return isCompOfBlocks;
1727 //=============================================================================
1729 * Set of functions, used by CheckCompoundOfBlocks() method
1731 //=============================================================================
1732 void GEOMImpl_IBlocksOperations::AddBlocksFrom (const TopoDS_Shape& theShape,
1733 TopTools_ListOfShape& BLO,
1734 TopTools_ListOfShape& NOT,
1735 TopTools_ListOfShape& EXT)
1737 TopAbs_ShapeEnum aType = theShape.ShapeType();
1739 case TopAbs_COMPOUND:
1740 case TopAbs_COMPSOLID:
1742 TopoDS_Iterator It (theShape);
1743 for (; It.More(); It.Next()) {
1744 AddBlocksFrom(It.Value(), BLO, NOT, EXT);
1750 // Check, if there are seam or degenerated edges
1751 BlockFix_CheckTool aTool;
1752 aTool.SetShape(theShape);
1754 if (aTool.NbPossibleBlocks() > 0) {
1755 EXT.Append(theShape);
1757 // Count faces and edges in each face to recognize blocks
1758 TopTools_MapOfShape mapFaces;
1759 Standard_Integer nbFaces = 0;
1760 Standard_Boolean hasNonQuadr = Standard_False;
1761 TopExp_Explorer expF (theShape, TopAbs_FACE);
1763 for (; expF.More(); expF.Next()) {
1764 if (mapFaces.Add(expF.Current())) {
1766 if (nbFaces > 6) break;
1769 TopoDS_Shape aF = expF.Current();
1770 TopExp_Explorer wires (aF, TopAbs_WIRE);
1771 if (!wires.More()) {
1772 // no wire in the face
1773 hasNonQuadr = Standard_True;
1776 TopoDS_Shape aWire = wires.Current();
1779 // multiple wires in the face
1780 hasNonQuadr = Standard_True;
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 hasNonQuadr = Standard_True;
1800 if (nbFaces == 6 && !hasNonQuadr) {
1801 BLO.Append(theShape);
1803 NOT.Append(theShape);
1809 NOT.Append(theShape);
1813 void AddBlocksFromOld (const TopoDS_Shape& theShape,
1814 TopTools_ListOfShape& BLO,
1815 TopTools_ListOfShape& NOT,
1816 TopTools_ListOfShape& DEG,
1817 TopTools_ListOfShape& SEA)
1819 TopAbs_ShapeEnum aType = theShape.ShapeType();
1821 case TopAbs_COMPOUND:
1822 case TopAbs_COMPSOLID:
1824 TopoDS_Iterator It (theShape);
1825 for (; It.More(); It.Next()) {
1826 AddBlocksFromOld(It.Value(), BLO, NOT, DEG, SEA);
1832 TopTools_MapOfShape mapFaces;
1833 TopExp_Explorer expF (theShape, TopAbs_FACE);
1834 Standard_Integer nbFaces = 0;
1835 Standard_Boolean hasNonQuadr = Standard_False;
1836 Standard_Boolean hasDegenerated = Standard_False;
1837 Standard_Boolean hasSeam = Standard_False;
1838 for (; expF.More(); expF.Next()) {
1839 if (mapFaces.Add(expF.Current())) {
1841 if (nbFaces > 6) break;
1843 // Check number of edges in the face
1844 Standard_Integer nbEdges = 0;
1845 TopTools_MapOfShape mapEdges;
1848 TopoDS_Shape aF = expF.Current();
1849 TopExp_Explorer wires (aF, TopAbs_WIRE);
1850 if (!wires.More()) {
1851 // no wire in the face
1852 hasNonQuadr = Standard_True;
1855 TopoDS_Shape aWire = wires.Current();
1858 // multiple wires in the face
1859 hasNonQuadr = Standard_True;
1864 BRepTools_WireExplorer aWE (TopoDS::Wire(aWire), TopoDS::Face(aF));
1865 for (; aWE.More(); aWE.Next(), nbEdges++) {
1866 if (BRep_Tool::Degenerated(aWE.Current())) {
1867 // degenerated edge found
1868 hasDegenerated = Standard_True;
1871 if (mapEdges.Contains(aWE.Current())) {
1873 hasSeam = Standard_True;
1876 mapEdges.Add(aWE.Current());
1879 hasNonQuadr = Standard_True;
1884 if (hasDegenerated || hasSeam) {
1885 if (hasDegenerated) {
1886 DEG.Append(theShape);
1889 SEA.Append(theShape);
1891 } else if (hasNonQuadr) {
1892 NOT.Append(theShape);
1894 BLO.Append(theShape);
1897 NOT.Append(theShape);
1902 NOT.Append(theShape);
1906 #define REL_NOT_CONNECTED 0
1908 #define REL_NOT_GLUED 2
1909 #define REL_COLLISION_VV 3
1910 #define REL_COLLISION_FF 4
1911 #define REL_COLLISION_EE 5
1912 #define REL_UNKNOWN 6
1914 Standard_Integer BlocksRelation (const TopoDS_Shape& theBlock1,
1915 const TopoDS_Shape& theBlock2)
1917 // Compare bounding boxes before calling BRepExtrema_DistShapeShape
1918 Standard_Real Xmin1, Ymin1, Zmin1, Xmax1, Ymax1, Zmax1;
1919 Standard_Real Xmin2, Ymin2, Zmin2, Xmax2, Ymax2, Zmax2;
1921 BRepBndLib::Add(theBlock1, B1);
1922 BRepBndLib::Add(theBlock2, B2);
1923 B1.Get(Xmin1, Ymin1, Zmin1, Xmax1, Ymax1, Zmax1);
1924 B2.Get(Xmin2, Ymin2, Zmin2, Xmax2, Ymax2, Zmax2);
1925 if (Xmax2 < Xmin1 || Xmax1 < Xmin2 ||
1926 Ymax2 < Ymin1 || Ymax1 < Ymin2 ||
1927 Zmax2 < Zmin1 || Zmax1 < Zmin2) {
1928 return REL_NOT_CONNECTED;
1931 BRepExtrema_DistShapeShape dst (theBlock1, theBlock2);
1932 if (!dst.IsDone()) {
1936 if (dst.Value() > Precision::Confusion()) {
1937 return REL_NOT_CONNECTED;
1940 if (dst.InnerSolution()) {
1941 return REL_COLLISION_VV;
1944 Standard_Integer nbSol = dst.NbSolution();
1945 Standard_Integer relation = REL_OK;
1946 Standard_Integer nbVerts = 0;
1947 Standard_Integer nbEdges = 0;
1948 Standard_Integer sol = 1;
1949 for (; sol <= nbSol; sol++) {
1950 BRepExtrema_SupportType supp1 = dst.SupportTypeShape1(sol);
1951 BRepExtrema_SupportType supp2 = dst.SupportTypeShape2(sol);
1952 if (supp1 == BRepExtrema_IsVertex && supp2 == BRepExtrema_IsVertex) {
1954 } else if (supp1 == BRepExtrema_IsInFace || supp2 == BRepExtrema_IsInFace) {
1955 return REL_COLLISION_FF;
1956 } else if (supp1 == BRepExtrema_IsOnEdge && supp2 == BRepExtrema_IsOnEdge) {
1958 } else if ((supp1 == BRepExtrema_IsOnEdge && supp2 == BRepExtrema_IsVertex) ||
1959 (supp2 == BRepExtrema_IsOnEdge && supp1 == BRepExtrema_IsVertex)) {
1960 relation = REL_COLLISION_EE;
1965 if (relation != REL_OK) {
1969 TColStd_Array1OfInteger vertSol (1, nbVerts);
1970 TopTools_Array1OfShape V1 (1, nbVerts);
1971 TopTools_Array1OfShape V2 (1, nbVerts);
1972 Standard_Integer ivs = 0;
1973 for (sol = 1; sol <= nbSol; sol++) {
1974 if (dst.SupportTypeShape1(sol) == BRepExtrema_IsVertex &&
1975 dst.SupportTypeShape2(sol) == BRepExtrema_IsVertex) {
1976 TopoDS_Vertex Vcur = TopoDS::Vertex(dst.SupportOnShape1(sol));
1977 // Check, that this vertex is far enough from other solution vertices.
1978 Standard_Integer ii = 1;
1979 for (; ii <= ivs; ii++) {
1980 if (BRepTools::Compare(TopoDS::Vertex(V1(ii)), Vcur)) {
1987 V2(ivs) = dst.SupportOnShape2(sol);
1991 // As we deal only with quadrangles,
1992 // 2, 3 or 4 vertex solutions can be found.
1995 return REL_COLLISION_FF;
1997 return REL_NOT_CONNECTED;
2003 // Check sharing of coincident entities.
2004 if (ivs == 2 || ivs == 3) {
2005 // Map vertices and edges of the blocks
2006 TopTools_IndexedDataMapOfShapeListOfShape MVE1, MVE2;
2007 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2008 (theBlock1, TopAbs_VERTEX, TopAbs_EDGE, MVE1);
2009 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2010 (theBlock2, TopAbs_VERTEX, TopAbs_EDGE, MVE2);
2014 TopoDS_Shape anEdge1, anEdge2;
2015 GEOMImpl_Block6Explorer::FindEdge(anEdge1, V1(1), V1(2), MVE1);
2016 if (anEdge1.IsNull()) return REL_UNKNOWN;
2018 GEOMImpl_Block6Explorer::FindEdge(anEdge2, V2(1), V2(2), MVE2);
2019 if (anEdge2.IsNull()) return REL_UNKNOWN;
2021 if (!anEdge1.IsSame(anEdge2)) return REL_NOT_GLUED;
2023 } else { // ivs == 3
2024 // Find common edges
2025 Standard_Integer e1_v1 = 1;
2026 Standard_Integer e1_v2 = 2;
2027 Standard_Integer e2_v1 = 3;
2028 Standard_Integer e2_v2 = 1;
2030 TopoDS_Shape anEdge11, anEdge12;
2031 GEOMImpl_Block6Explorer::FindEdge(anEdge11, V1(e1_v1), V1(e1_v2), MVE1);
2032 if (anEdge11.IsNull()) {
2035 GEOMImpl_Block6Explorer::FindEdge(anEdge11, V1(e1_v1), V1(e1_v2), MVE1);
2036 if (anEdge11.IsNull()) return REL_UNKNOWN;
2038 GEOMImpl_Block6Explorer::FindEdge(anEdge12, V1(e2_v1), V1(e2_v2), MVE1);
2039 if (anEdge12.IsNull()) {
2041 GEOMImpl_Block6Explorer::FindEdge(anEdge12, V1(e2_v1), V1(e2_v2), MVE1);
2042 if (anEdge12.IsNull()) return REL_UNKNOWN;
2045 TopoDS_Shape anEdge21, anEdge22;
2046 GEOMImpl_Block6Explorer::FindEdge(anEdge21, V2(e1_v1), V2(e1_v2), MVE2);
2047 if (anEdge21.IsNull()) return REL_UNKNOWN;
2048 GEOMImpl_Block6Explorer::FindEdge(anEdge22, V2(e2_v1), V2(e2_v2), MVE2);
2049 if (anEdge22.IsNull()) return REL_UNKNOWN;
2051 // Check of edges coincidence (with some precision) have to be done here
2052 // if (!anEdge11.IsEqual(anEdge21)) return REL_UNKNOWN;
2053 // if (!anEdge12.IsEqual(anEdge22)) return REL_UNKNOWN;
2055 // Check of edges sharing
2056 if (!anEdge11.IsSame(anEdge21)) return REL_NOT_GLUED;
2057 if (!anEdge12.IsSame(anEdge22)) return REL_NOT_GLUED;
2062 // Map vertices and faces of the blocks
2063 TopTools_IndexedDataMapOfShapeListOfShape MVF1, MVF2;
2064 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2065 (theBlock1, TopAbs_VERTEX, TopAbs_FACE, MVF1);
2066 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2067 (theBlock2, TopAbs_VERTEX, TopAbs_FACE, MVF2);
2069 TopoDS_Shape aFace1, aFace2;
2070 GEOMImpl_Block6Explorer::FindFace(aFace1, V1(1), V1(2), V1(3), V1(4), MVF1);
2071 if (aFace1.IsNull()) return REL_UNKNOWN;
2072 GEOMImpl_Block6Explorer::FindFace(aFace2, V2(1), V2(2), V2(3), V2(4), MVF2);
2073 if (aFace2.IsNull()) return REL_UNKNOWN;
2075 // Check of faces coincidence (with some precision) have to be done here
2076 // if (!aFace1.IsEqual(aFace2)) return REL_UNKNOWN;
2078 // Check of faces sharing
2079 if (!aFace1.IsSame(aFace2)) return REL_NOT_GLUED;
2085 void FindConnected (const Standard_Integer theBlockIndex,
2086 const TColStd_Array2OfInteger& theRelations,
2087 TColStd_MapOfInteger& theProcessedMap,
2088 TColStd_MapOfInteger& theConnectedMap)
2090 theConnectedMap.Add(theBlockIndex);
2091 theProcessedMap.Add(theBlockIndex);
2093 Standard_Integer nbBlocks = theRelations.ColLength();
2094 Standard_Integer col = 1;
2095 for (; col <= nbBlocks; col++) {
2096 if (theRelations(theBlockIndex, col) == REL_OK ||
2097 theRelations(theBlockIndex, col) == REL_NOT_GLUED) {
2098 if (!theProcessedMap.Contains(col)) {
2099 FindConnected(col, theRelations, theProcessedMap, theConnectedMap);
2105 Standard_Boolean HasAnyConnection (const Standard_Integer theBlockIndex,
2106 const TColStd_MapOfInteger& theWith,
2107 const TColStd_Array2OfInteger& theRelations,
2108 TColStd_MapOfInteger& theProcessedMap)
2110 theProcessedMap.Add(theBlockIndex);
2112 Standard_Integer nbBlocks = theRelations.ColLength();
2113 Standard_Integer col = 1;
2114 for (; col <= nbBlocks; col++) {
2115 if (theRelations(theBlockIndex, col) != REL_NOT_CONNECTED) {
2116 if (!theProcessedMap.Contains(col)) {
2117 if (theWith.Contains(col))
2118 return Standard_True;
2119 if (HasAnyConnection(col, theWith, theRelations, theProcessedMap))
2120 return Standard_True;
2125 return Standard_False;
2128 //=============================================================================
2130 * CheckCompoundOfBlocksOld
2132 //=============================================================================
2133 Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocksOld
2134 (Handle(GEOM_Object) theCompound,
2135 std::list<BCError>& theErrors)
2139 if (theCompound.IsNull()) return Standard_False;
2140 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2142 Standard_Boolean isCompOfBlocks = Standard_True;
2144 // Map sub-shapes and their indices
2145 TopTools_IndexedMapOfShape anIndices;
2146 TopExp::MapShapes(aBlockOrComp, anIndices);
2148 // 1. Report non-blocks
2149 TopTools_ListOfShape NOT; // Not blocks
2150 TopTools_ListOfShape DEG; // Hexahedral solids, having degenerated edges
2151 TopTools_ListOfShape SEA; // Hexahedral solids, having seam edges
2152 TopTools_ListOfShape BLO; // All blocks from the given compound
2153 AddBlocksFromOld(aBlockOrComp, BLO, NOT, DEG, SEA);
2155 if (NOT.Extent() > 0) {
2156 isCompOfBlocks = Standard_False;
2158 anErr.error = NOT_BLOCK;
2159 TopTools_ListIteratorOfListOfShape it (NOT);
2160 for (; it.More(); it.Next()) {
2161 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
2163 theErrors.push_back(anErr);
2166 if (DEG.Extent() > 0 || SEA.Extent() > 0) {
2167 isCompOfBlocks = Standard_False;
2169 anErr.error = EXTRA_EDGE;
2171 TopTools_ListIteratorOfListOfShape itDEG (DEG);
2172 for (; itDEG.More(); itDEG.Next()) {
2173 anErr.incriminated.push_back(anIndices.FindIndex(itDEG.Value()));
2176 TopTools_ListIteratorOfListOfShape itSEA (SEA);
2177 for (; itSEA.More(); itSEA.Next()) {
2178 anErr.incriminated.push_back(anIndices.FindIndex(itSEA.Value()));
2181 theErrors.push_back(anErr);
2184 Standard_Integer nbBlocks = BLO.Extent();
2185 if (nbBlocks == 0) {
2186 isCompOfBlocks = Standard_False;
2188 return isCompOfBlocks;
2190 if (nbBlocks == 1) {
2192 return isCompOfBlocks;
2195 // Convert list of blocks into array for easy and fast access
2196 Standard_Integer ibl = 1;
2197 TopTools_Array1OfShape aBlocks (1, nbBlocks);
2198 TopTools_ListIteratorOfListOfShape BLOit (BLO);
2199 for (; BLOit.More(); BLOit.Next(), ibl++) {
2200 aBlocks.SetValue(ibl, BLOit.Value());
2203 // 2. Find relations between all blocks,
2204 // report connection errors (NOT_GLUED and INVALID_CONNECTION)
2205 TColStd_Array2OfInteger aRelations (1, nbBlocks, 1, nbBlocks);
2206 aRelations.Init(REL_NOT_CONNECTED);
2208 Standard_Integer row = 1;
2209 for (row = 1; row <= nbBlocks; row++) {
2210 TopoDS_Shape aBlock = aBlocks.Value(row);
2212 Standard_Integer col = row + 1;
2213 for (; col <= nbBlocks; col++) {
2214 Standard_Integer aRel = BlocksRelation(aBlock, aBlocks.Value(col));
2215 if (aRel != REL_NOT_CONNECTED) {
2216 aRelations.SetValue(row, col, aRel);
2217 aRelations.SetValue(col, row, aRel);
2218 if (aRel == REL_NOT_GLUED) {
2219 // report connection error
2220 isCompOfBlocks = Standard_False;
2222 anErr.error = NOT_GLUED;
2223 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row)));
2224 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col)));
2225 theErrors.push_back(anErr);
2226 } else if (aRel == REL_COLLISION_VV ||
2227 aRel == REL_COLLISION_FF ||
2228 aRel == REL_COLLISION_EE ||
2229 aRel == REL_UNKNOWN) {
2230 // report connection error
2231 isCompOfBlocks = Standard_False;
2233 anErr.error = INVALID_CONNECTION;
2234 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row)));
2235 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col)));
2236 theErrors.push_back(anErr);
2243 // 3. Find largest set of connected (good connection or not glued) blocks
2244 TColStd_MapOfInteger aProcessedMap;
2245 TColStd_MapOfInteger aLargestSet;
2246 TColStd_MapOfInteger aCurrentSet;
2247 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2248 if (!aProcessedMap.Contains(ibl)) {
2249 aCurrentSet.Clear();
2250 FindConnected(ibl, aRelations, aProcessedMap, aCurrentSet);
2251 if (aCurrentSet.Extent() > aLargestSet.Extent()) {
2252 aLargestSet = aCurrentSet;
2257 // 4. Report all blocks, isolated from <aLargestSet>
2259 anErr.error = NOT_CONNECTED;
2260 Standard_Boolean hasIsolated = Standard_False;
2261 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2262 if (!aLargestSet.Contains(ibl)) {
2263 aProcessedMap.Clear();
2264 if (!HasAnyConnection(ibl, aLargestSet, aRelations, aProcessedMap)) {
2265 // report connection absence
2266 hasIsolated = Standard_True;
2267 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(ibl)));
2272 isCompOfBlocks = Standard_False;
2273 theErrors.push_back(anErr);
2277 return isCompOfBlocks;
2280 //=============================================================================
2284 //=============================================================================
2285 TCollection_AsciiString GEOMImpl_IBlocksOperations::PrintBCErrors
2286 (Handle(GEOM_Object) theCompound,
2287 const std::list<BCError>& theErrors)
2289 TCollection_AsciiString aDescr;
2291 std::list<BCError>::const_iterator errIt = theErrors.begin();
2293 for (; errIt != theErrors.end(); i++, errIt++) {
2294 BCError errStruct = *errIt;
2296 switch (errStruct.error) {
2298 aDescr += "\n\tNot a Blocks: ";
2301 aDescr += "\n\tHexahedral solids with degenerated and/or seam edges: ";
2303 case INVALID_CONNECTION:
2304 aDescr += "\n\tInvalid connection between two blocks: ";
2307 aDescr += "\n\tBlocks, not connected with main body: ";
2310 aDescr += "\n\tNot glued blocks: ";
2316 std::list<int> sshList = errStruct.incriminated;
2317 std::list<int>::iterator sshIt = sshList.begin();
2319 for (; sshIt != sshList.end(); jj++, sshIt++) {
2322 aDescr += TCollection_AsciiString(*sshIt);
2329 //=============================================================================
2331 * CheckCompoundOfBlocks
2333 //=============================================================================
2334 Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocks
2335 (Handle(GEOM_Object) theCompound,
2336 std::list<BCError>& theErrors)
2340 if (theCompound.IsNull()) return Standard_False;
2341 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2343 Standard_Boolean isCompOfBlocks = Standard_True;
2345 // Map sub-shapes and their indices
2346 TopTools_IndexedMapOfShape anIndices;
2347 TopExp::MapShapes(aBlockOrComp, anIndices);
2349 // 1. Separate blocks from non-blocks
2350 TopTools_ListOfShape NOT; // Not blocks
2351 TopTools_ListOfShape EXT; // Hexahedral solids, having degenerated and/or seam edges
2352 TopTools_ListOfShape BLO; // All blocks from the given compound
2353 AddBlocksFrom(aBlockOrComp, BLO, NOT, EXT);
2355 // Report non-blocks
2356 if (NOT.Extent() > 0) {
2357 isCompOfBlocks = Standard_False;
2359 anErr.error = NOT_BLOCK;
2360 TopTools_ListIteratorOfListOfShape it (NOT);
2361 for (; it.More(); it.Next()) {
2362 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
2364 theErrors.push_back(anErr);
2367 // Report solids, having degenerated and/or seam edges
2368 if (EXT.Extent() > 0) {
2369 isCompOfBlocks = Standard_False;
2371 anErr.error = EXTRA_EDGE;
2372 TopTools_ListIteratorOfListOfShape it (EXT);
2373 for (; it.More(); it.Next()) {
2374 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
2376 theErrors.push_back(anErr);
2379 Standard_Integer nbBlocks = BLO.Extent();
2380 if (nbBlocks == 0) {
2381 isCompOfBlocks = Standard_False;
2383 return isCompOfBlocks;
2385 if (nbBlocks == 1) {
2387 return isCompOfBlocks;
2390 // Prepare data for 2. and 3.
2391 TColStd_Array2OfInteger aRelations (1, nbBlocks, 1, nbBlocks);
2392 aRelations.Init(REL_NOT_CONNECTED);
2394 TopTools_IndexedMapOfShape mapBlocks;
2397 TopoDS_Compound aComp;
2398 BB.MakeCompound(aComp);
2400 TopTools_ListIteratorOfListOfShape BLOit (BLO);
2401 for (; BLOit.More(); BLOit.Next()) {
2402 mapBlocks.Add(BLOit.Value());
2403 BB.Add(aComp, BLOit.Value());
2406 // 2. Find glued blocks (having shared faces)
2407 TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
2408 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2409 (aComp, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
2411 Standard_Integer prevInd = 0, curInd = 0;
2412 Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
2413 for (; ind <= nbFaces; ind++) {
2414 const TopTools_ListOfShape& aGluedBlocks = mapFaceBlocks.FindFromIndex(ind);
2415 if (aGluedBlocks.Extent() > 1) { // Shared face found
2416 TopTools_ListIteratorOfListOfShape aGluedBlocksIt (aGluedBlocks);
2417 TopoDS_Shape prevBlock, curBlock;
2418 for (; aGluedBlocksIt.More(); aGluedBlocksIt.Next()) {
2419 curBlock = aGluedBlocksIt.Value();
2420 if (!prevBlock.IsNull()) {
2421 prevInd = mapBlocks.FindIndex(prevBlock);
2422 curInd = mapBlocks.FindIndex(curBlock);
2423 aRelations.SetValue(prevInd, curInd, REL_OK);
2424 aRelations.SetValue(curInd, prevInd, REL_OK);
2426 prevBlock = curBlock;
2431 // 3. Find not glued blocks
2432 GEOMAlgo_GlueAnalyser aGD;
2434 aGD.SetShape(aComp);
2435 aGD.SetTolerance(Precision::Confusion());
2436 aGD.SetCheckGeometry(Standard_True);
2439 Standard_Integer iErr, iWrn;
2440 iErr = aGD.ErrorStatus();
2442 SetErrorCode("Error in GEOMAlgo_GlueAnalyser");
2443 return isCompOfBlocks;
2445 iWrn = aGD.WarningStatus();
2447 MESSAGE("Warning in GEOMAlgo_GlueAnalyser");
2450 // Report not glued blocks
2451 if (aGD.HasSolidsToGlue()) {
2452 isCompOfBlocks = Standard_False;
2453 Standard_Integer aSx1Ind, aSx2Ind;
2455 const GEOMAlgo_ListOfCoupleOfShapes& aLCS = aGD.SolidsToGlue();
2456 GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS (aLCS);
2457 for (; aItCS.More(); aItCS.Next()) {
2458 const GEOMAlgo_CoupleOfShapes& aCS = aItCS.Value();
2459 const TopoDS_Shape& aSx1 = aCS.Shape1();
2460 const TopoDS_Shape& aSx2 = aCS.Shape2();
2462 aSx1Ind = mapBlocks.FindIndex(aSx1);
2463 aSx2Ind = mapBlocks.FindIndex(aSx2);
2464 aRelations.SetValue(aSx1Ind, aSx2Ind, NOT_GLUED);
2465 aRelations.SetValue(aSx2Ind, aSx1Ind, NOT_GLUED);
2468 anErr.error = NOT_GLUED;
2469 anErr.incriminated.push_back(anIndices.FindIndex(aSx1));
2470 anErr.incriminated.push_back(anIndices.FindIndex(aSx2));
2471 theErrors.push_back(anErr);
2475 // 4. Find largest set of connected (good connection or not glued) blocks
2476 Standard_Integer ibl = 1;
2477 TColStd_MapOfInteger aProcessedMap;
2478 TColStd_MapOfInteger aLargestSet;
2479 TColStd_MapOfInteger aCurrentSet;
2480 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2481 if (!aProcessedMap.Contains(ibl)) {
2482 aCurrentSet.Clear();
2483 FindConnected(ibl, aRelations, aProcessedMap, aCurrentSet);
2484 if (aCurrentSet.Extent() > aLargestSet.Extent()) {
2485 aLargestSet = aCurrentSet;
2490 // 5. Report all blocks, isolated from <aLargestSet>
2492 anErr.error = NOT_CONNECTED;
2493 Standard_Boolean hasIsolated = Standard_False;
2494 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2495 if (!aLargestSet.Contains(ibl)) {
2496 aProcessedMap.Clear();
2497 if (!HasAnyConnection(ibl, aLargestSet, aRelations, aProcessedMap)) {
2498 // report connection absence
2499 hasIsolated = Standard_True;
2500 anErr.incriminated.push_back(anIndices.FindIndex(mapBlocks.FindKey(ibl)));
2505 isCompOfBlocks = Standard_False;
2506 theErrors.push_back(anErr);
2510 return isCompOfBlocks;
2513 //=============================================================================
2517 //=============================================================================
2518 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::RemoveExtraEdges
2519 (Handle(GEOM_Object) theObject,
2520 const Standard_Integer theOptimumNbFaces)
2524 if (theObject.IsNull()) return NULL;
2526 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2527 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be fixed
2529 //Add a new Copy object
2530 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2533 Handle(GEOM_Function) aFunction =
2534 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_REMOVE_EXTRA);
2536 //Check if the function is set correctly
2537 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2539 GEOMImpl_IBlockTrsf aTI (aFunction);
2540 aTI.SetOriginal(aLastFunction);
2541 aTI.SetOptimumNbFaces(theOptimumNbFaces);
2543 //Compute the fixed shape
2545 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
2548 if (!GetSolver()->ComputeFunction(aFunction)) {
2549 SetErrorCode("Block driver failed to remove extra edges of the given shape");
2553 catch (Standard_Failure) {
2554 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2555 SetErrorCode(aFail->GetMessageString());
2559 //Make a Python command
2560 std::string doUnionFaces = (theOptimumNbFaces < 0) ? "False" : "True";
2561 GEOM::TPythonDump(aFunction) << aCopy << " = geompy.RemoveExtraEdges("
2562 << theObject << ", " << doUnionFaces.data() << ")";
2568 //=============================================================================
2572 //=============================================================================
2573 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::CheckAndImprove
2574 (Handle(GEOM_Object) theObject)
2578 if (theObject.IsNull()) return NULL;
2580 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2581 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be fixed
2583 //Add a new Copy object
2584 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2587 Handle(GEOM_Function) aFunction =
2588 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_COMPOUND_IMPROVE);
2590 //Check if the function is set correctly
2591 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2593 GEOMImpl_IBlockTrsf aTI (aFunction);
2594 aTI.SetOriginal(aLastFunction);
2596 // -1 means do not unite faces on common surface (?except case of seam edge between them?)
2597 //aTI.SetOptimumNbFaces(-1);
2598 aTI.SetOptimumNbFaces(6);
2600 //Compute the fixed shape
2602 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
2605 if (!GetSolver()->ComputeFunction(aFunction)) {
2606 SetErrorCode("Block driver failed to improve the given blocks compound");
2610 catch (Standard_Failure) {
2611 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2612 SetErrorCode(aFail->GetMessageString());
2616 //Make a Python command
2617 GEOM::TPythonDump(aFunction) << aCopy
2618 << " = geompy.CheckAndImprove(" << theObject << ")";
2624 //=============================================================================
2626 * ExplodeCompoundOfBlocks
2628 //=============================================================================
2629 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::ExplodeCompoundOfBlocks
2630 (Handle(GEOM_Object) theCompound,
2631 const Standard_Integer theMinNbFaces,
2632 const Standard_Integer theMaxNbFaces)
2636 if (theCompound.IsNull()) return NULL;
2637 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2638 if (aBlockOrComp.IsNull()) return NULL;
2640 Handle(TColStd_HSequenceOfTransient) aBlocks = new TColStd_HSequenceOfTransient;
2641 Handle(GEOM_Object) anObj;
2642 Handle(GEOM_Function) aFunction;
2644 TopTools_MapOfShape mapShape;
2645 TCollection_AsciiString anAsciiList, anEntry;
2648 TopTools_IndexedMapOfShape anIndices;
2649 TopExp::MapShapes(aBlockOrComp, anIndices);
2650 Handle(TColStd_HArray1OfInteger) anArray;
2654 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
2657 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2658 for (; exp.More(); exp.Next()) {
2659 if (mapShape.Add(exp.Current())) {
2660 TopoDS_Shape aSolid = exp.Current();
2662 TopTools_MapOfShape mapFaces;
2663 TopExp_Explorer expF (aSolid, TopAbs_FACE);
2664 Standard_Integer nbFaces = 0;
2665 for (; expF.More(); expF.Next()) {
2666 if (mapFaces.Add(expF.Current())) {
2671 if (theMinNbFaces <= nbFaces && nbFaces <= theMaxNbFaces) {
2672 anArray = new TColStd_HArray1OfInteger(1,1);
2673 anArray->SetValue(1, anIndices.FindIndex(aSolid));
2674 anObj = GetEngine()->AddSubShape(theCompound, anArray);
2675 aBlocks->Append(anObj);
2677 //Make a Python command
2678 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2679 anAsciiList += anEntry + ", ";
2684 catch (Standard_Failure) {
2685 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2686 SetErrorCode(aFail->GetMessageString());
2690 if (aBlocks->IsEmpty()) {
2691 SetErrorCode("There are no specified blocks in the given shape");
2695 anAsciiList.Trunc(anAsciiList.Length() - 2);
2697 //The explode doesn't change object so no new function is required.
2698 aFunction = theCompound->GetLastFunction();
2700 //Make a Python command
2701 GEOM::TPythonDump(aFunction, /*append=*/true)
2702 << "[" << anAsciiList.ToCString() << "] = geompy.MakeBlockExplode("
2703 << theCompound << ", " << theMinNbFaces << ", " << theMaxNbFaces << ")";
2709 //=============================================================================
2713 //=============================================================================
2714 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetBlockNearPoint
2715 (Handle(GEOM_Object) theCompound,
2716 Handle(GEOM_Object) thePoint)
2721 Handle(GEOM_Object) aResult;
2724 if (theCompound.IsNull() || thePoint.IsNull()) return NULL;
2726 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2727 if (aBlockOrComp.IsNull()) {
2728 SetErrorCode("Compound is null");
2731 if (aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
2732 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
2733 SetErrorCode("Shape to find block in is not a compound");
2737 TopoDS_Shape anArg = thePoint->GetValue();
2738 if (anArg.IsNull()) {
2739 SetErrorCode("Point is null");
2742 if (anArg.ShapeType() != TopAbs_VERTEX) {
2743 SetErrorCode("Shape for block identification is not a vertex");
2747 //Compute the Block value
2749 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
2752 TopoDS_Shape aShape;
2754 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
2755 gp_Pnt aPnt = BRep_Tool::Pnt(aVert);
2756 Standard_Real PX, PY, PZ;
2757 aPnt.Coord(PX, PY, PZ);
2759 // 1. Classify the point relatively each block
2760 Standard_Integer nearest = 2, nbFound = 0;
2761 TopTools_DataMapOfShapeInteger mapShapeDist;
2762 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2763 for (; exp.More(); exp.Next()) {
2764 TopoDS_Shape aSolid = exp.Current();
2766 if (!mapShapeDist.IsBound(aSolid)) {
2767 Standard_Integer aDistance = 2;
2769 // 1.a. Classify relatively Bounding box
2770 Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
2772 BRepBndLib::Add(aSolid, BB);
2773 BB.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
2774 if (PX < Xmin || Xmax < PX ||
2775 PY < Ymin || Ymax < PY ||
2776 PZ < Zmin || Zmax < PZ) {
2777 // OUT of bounding box
2780 // 1.b. Classify relatively the solid itself
2781 BRepClass3d_SolidClassifier SC (aSolid, aPnt, Precision::Confusion());
2782 if (SC.State() == TopAbs_IN) {
2784 } else if (SC.State() == TopAbs_ON) {
2791 if (aDistance < nearest) {
2792 nearest = aDistance;
2796 // A first found block, containing the point inside, will be returned.
2797 // It is the solution, if there are no intersecting blocks in the compound.
2798 if (nearest == -1) break;
2800 } else if (aDistance == nearest) {
2805 mapShapeDist.Bind(aSolid, aDistance);
2806 } // if (!mapShapeDist.IsBound(aSolid))
2809 // 2. Define block, containing the point or having minimum distance to it
2812 // The point is on boundary of some blocks and there are
2813 // no blocks, having the point inside their volume
2814 SetErrorCode("Multiple blocks near the given point are found");
2817 } else if (nearest == 1) {
2818 // The point is outside some blocks and there are
2819 // no blocks, having the point inside or on boundary.
2820 // We will get a nearest block
2821 Standard_Real minDist = RealLast();
2822 TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
2823 for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
2824 if (mapShapeDistIter.Value() == 1) {
2825 TopoDS_Shape aSolid = mapShapeDistIter.Key();
2826 BRepExtrema_DistShapeShape aDistTool (aVert, aSolid);
2827 if (!aDistTool.IsDone()) {
2828 SetErrorCode("Can not find a distance from the given point to one of blocks");
2831 Standard_Real aDist = aDistTool.Value();
2832 if (aDist < minDist) {
2838 } else { // nearest == -1
2839 // // The point is inside some blocks.
2840 // // We will get a block with nearest center
2841 // Standard_Real minDist = RealLast();
2842 // TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
2843 // for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
2844 // if (mapShapeDistIter.Value() == -1) {
2845 // TopoDS_Shape aSolid = mapShapeDistIter.Key();
2846 // GProp_GProps aSystem;
2847 // BRepGProp::VolumeProperties(aSolid, aSystem);
2848 // gp_Pnt aCenterMass = aSystem.CentreOfMass();
2850 // Standard_Real aDist = aCenterMass.Distance(aPnt);
2851 // if (aDist < minDist) {
2858 } // if (nbFound > 1)
2861 SetErrorCode("There are no blocks near the given point");
2864 TopTools_IndexedMapOfShape anIndices;
2865 TopExp::MapShapes(aBlockOrComp, anIndices);
2866 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2867 anArray->SetValue(1, anIndices.FindIndex(aShape));
2868 aResult = GetEngine()->AddSubShape(theCompound, anArray);
2871 catch (Standard_Failure) {
2872 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2873 SetErrorCode(aFail->GetMessageString());
2877 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
2879 //Make a Python command
2880 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetBlockNearPoint("
2881 << theCompound << ", " << thePoint << ")";
2887 //=============================================================================
2891 //=============================================================================
2892 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetBlockByParts
2893 (Handle(GEOM_Object) theCompound,
2894 const Handle(TColStd_HSequenceOfTransient)& theParts)
2898 Handle(GEOM_Object) aResult;
2900 if (theCompound.IsNull() || theParts.IsNull()) return NULL;
2901 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2902 if (aBlockOrComp.IsNull()) return NULL;
2905 Standard_Integer argi, aLen = theParts->Length();
2906 TopTools_Array1OfShape anArgs (1, aLen);
2907 TCollection_AsciiString anEntry, aPartsDescr;
2908 for (argi = 1; argi <= aLen; argi++) {
2909 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theParts->Value(argi));
2910 Handle(GEOM_Function) aRef = anObj->GetLastFunction();
2911 if (aRef.IsNull()) return NULL;
2913 TopoDS_Shape anArg = aRef->GetValue();
2914 if (anArg.IsNull()) {
2915 SetErrorCode("Null shape is given as argument");
2918 anArgs(argi) = anArg;
2920 // For Python command
2921 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2922 if (argi > 1) aPartsDescr += ", ";
2923 aPartsDescr += anEntry;
2926 //Compute the Block value
2928 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
2931 // 1. Explode compound on solids
2932 TopTools_MapOfShape mapShape;
2933 Standard_Integer nbSolids = 0;
2934 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2935 for (; exp.More(); exp.Next()) {
2936 if (mapShape.Add(exp.Current())) {
2942 Standard_Integer ind = 1;
2943 TopTools_Array1OfShape aSolids (1, nbSolids);
2944 TColStd_Array1OfInteger aNbParts (1, nbSolids);
2945 for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next(), ind++) {
2946 if (mapShape.Add(exp.Current())) {
2947 TopoDS_Shape aSolid = exp.Current();
2948 aSolids(ind) = aSolid;
2951 // 2. Define quantity of parts, contained in each solid
2952 TopTools_IndexedMapOfShape aSubShapes;
2953 TopExp::MapShapes(aSolid, aSubShapes);
2954 for (argi = 1; argi <= aLen; argi++) {
2955 if (aSubShapes.Contains(anArgs(argi))) {
2962 // 3. Define solid, containing maximum quantity of parts
2963 Standard_Integer maxNb = 0, nbFound = 0;
2964 TopoDS_Shape aShape;
2965 for (ind = 1; ind <= nbSolids; ind++) {
2966 if (aNbParts(ind) > maxNb) {
2967 maxNb = aNbParts(ind);
2968 aShape = aSolids(ind);
2970 } else if (aNbParts(ind) == maxNb) {
2976 SetErrorCode("Multiple blocks, containing maximum quantity of the given parts, are found");
2978 } else if (nbFound == 0) {
2979 SetErrorCode("There are no blocks, containing the given parts");
2982 TopTools_IndexedMapOfShape anIndices;
2983 TopExp::MapShapes(aBlockOrComp, anIndices);
2984 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2985 anArray->SetValue(1, anIndices.FindIndex(aShape));
2986 aResult = GetEngine()->AddSubShape(theCompound, anArray);
2988 } catch (Standard_Failure) {
2989 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2990 SetErrorCode(aFail->GetMessageString());
2994 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
2996 //Make a Python command
2997 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetBlockByParts("
2998 << theCompound << ", [" << aPartsDescr.ToCString() << "])";
3004 //=============================================================================
3008 //=============================================================================
3009 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::GetBlocksByParts
3010 (Handle(GEOM_Object) theCompound,
3011 const Handle(TColStd_HSequenceOfTransient)& theParts)
3015 if (theCompound.IsNull() || theParts.IsNull()) return NULL;
3016 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
3017 if (aBlockOrComp.IsNull()) return NULL;
3019 Handle(TColStd_HSequenceOfTransient) aBlocks = new TColStd_HSequenceOfTransient;
3020 Handle(GEOM_Object) anObj;
3021 Handle(GEOM_Function) aFunction;
3024 Standard_Integer argi, aLen = theParts->Length();
3025 TopTools_Array1OfShape anArgs (1, aLen);
3026 TCollection_AsciiString anEntry, aPartsDescr, anAsciiList;
3028 for (argi = 1; argi <= aLen; argi++) {
3029 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theParts->Value(argi));
3030 Handle(GEOM_Function) aRef = anObj->GetLastFunction();
3031 if (aRef.IsNull()) return NULL;
3033 TopoDS_Shape anArg = aRef->GetValue();
3034 if (anArg.IsNull()) {
3035 SetErrorCode("Null shape is given as argument");
3038 anArgs(argi) = anArg;
3040 // For Python command
3041 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
3042 aPartsDescr += anEntry + ", ";
3047 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
3050 TopTools_MapOfShape mapShape;
3051 Standard_Integer nbSolids = 0;
3052 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
3053 for (; exp.More(); exp.Next()) {
3054 if (mapShape.Add(exp.Current())) {
3060 Standard_Integer ind = 1;
3061 TopTools_Array1OfShape aSolids (1, nbSolids);
3062 TColStd_Array1OfInteger aNbParts (1, nbSolids);
3063 for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next(), ind++) {
3064 if (mapShape.Add(exp.Current())) {
3065 TopoDS_Shape aSolid = exp.Current();
3066 aSolids(ind) = aSolid;
3069 // 2. Define quantity of parts, contained in each solid
3070 TopTools_IndexedMapOfShape aSubShapes;
3071 TopExp::MapShapes(aSolid, aSubShapes);
3072 for (argi = 1; argi <= aLen; argi++) {
3073 if (aSubShapes.Contains(anArgs(argi))) {
3080 // 3. Define solid, containing maximum quantity of parts
3081 Standard_Integer maxNb = 0, nbFound = 0;
3082 for (ind = 1; ind <= nbSolids; ind++) {
3083 if (aNbParts(ind) > maxNb) {
3084 maxNb = aNbParts(ind);
3086 } else if (aNbParts(ind) == maxNb) {
3092 SetErrorCode("There are no blocks, containing the given parts");
3097 TopTools_IndexedMapOfShape anIndices;
3098 TopExp::MapShapes(aBlockOrComp, anIndices);
3099 Handle(TColStd_HArray1OfInteger) anArray;
3101 for (ind = 1; ind <= nbSolids; ind++) {
3102 if (aNbParts(ind) == maxNb) {
3103 anArray = new TColStd_HArray1OfInteger(1,1);
3104 anArray->SetValue(1, anIndices.FindIndex(aSolids(ind)));
3105 anObj = GetEngine()->AddSubShape(theCompound, anArray);
3106 aBlocks->Append(anObj);
3108 // For Python command
3109 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
3110 anAsciiList += anEntry + ", ";
3111 if (aFunction.IsNull())
3112 aFunction = anObj->GetLastFunction();
3116 catch (Standard_Failure) {
3117 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3118 SetErrorCode(aFail->GetMessageString());
3122 //Make a Python command
3123 aPartsDescr.Trunc(aPartsDescr.Length() - 2);
3124 anAsciiList.Trunc(anAsciiList.Length() - 2);
3126 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3127 << "] = geompy.GetBlocksByParts(" << theCompound
3128 << ", [" << aPartsDescr.ToCString() << "])";
3134 //=============================================================================
3136 * MakeMultiTransformation1D
3138 //=============================================================================
3139 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeMultiTransformation1D
3140 (Handle(GEOM_Object) theObject,
3141 const Standard_Integer theDirFace1,
3142 const Standard_Integer theDirFace2,
3143 const Standard_Integer theNbTimes)
3147 if (theObject.IsNull()) return NULL;
3149 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
3150 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be moved
3152 //Add a new Copy object
3153 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
3155 //Add a translate function
3156 Handle(GEOM_Function) aFunction =
3157 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_MULTI_TRANSFORM_1D);
3159 //Check if the function is set correctly
3160 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
3162 GEOMImpl_IBlockTrsf aTI (aFunction);
3163 aTI.SetOriginal(aLastFunction);
3164 aTI.SetFace1U(theDirFace1);
3165 aTI.SetFace2U(theDirFace2);
3166 aTI.SetNbIterU(theNbTimes);
3168 //Compute the transformation
3170 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
3173 if (!GetSolver()->ComputeFunction(aFunction)) {
3174 SetErrorCode("Block driver failed to make multi-transformation");
3178 catch (Standard_Failure) {
3179 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3180 SetErrorCode(aFail->GetMessageString());
3184 //Make a Python command
3185 GEOM::TPythonDump(aFunction) << aCopy << " = geompy.MakeMultiTransformation1D("
3186 << theObject << ", " << theDirFace1 << ", " << theDirFace2 << ", " << theNbTimes << ")";
3192 //=============================================================================
3194 * MakeMultiTransformation2D
3196 //=============================================================================
3197 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeMultiTransformation2D
3198 (Handle(GEOM_Object) theObject,
3199 const Standard_Integer theDirFace1U,
3200 const Standard_Integer theDirFace2U,
3201 const Standard_Integer theNbTimesU,
3202 const Standard_Integer theDirFace1V,
3203 const Standard_Integer theDirFace2V,
3204 const Standard_Integer theNbTimesV)
3208 if (theObject.IsNull()) return NULL;
3210 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
3211 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be moved
3213 //Add a new Copy object
3214 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
3216 //Add a translate function
3217 Handle(GEOM_Function) aFunction =
3218 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_MULTI_TRANSFORM_2D);
3220 //Check if the function is set correctly
3221 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
3223 GEOMImpl_IBlockTrsf aTI (aFunction);
3224 aTI.SetOriginal(aLastFunction);
3225 aTI.SetFace1U(theDirFace1U);
3226 aTI.SetFace2U(theDirFace2U);
3227 aTI.SetNbIterU(theNbTimesU);
3228 aTI.SetFace1V(theDirFace1V);
3229 aTI.SetFace2V(theDirFace2V);
3230 aTI.SetNbIterV(theNbTimesV);
3232 //Compute the transformation
3234 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
3237 if (!GetSolver()->ComputeFunction(aFunction)) {
3238 SetErrorCode("Block driver failed to make multi-transformation");
3242 catch (Standard_Failure) {
3243 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3244 SetErrorCode(aFail->GetMessageString());
3248 //Make a Python command
3249 GEOM::TPythonDump(aFunction) << aCopy << " = geompy.MakeMultiTransformation2D("
3250 << theObject << ", " << theDirFace1U << ", " << theDirFace2U << ", " << theNbTimesU
3251 << ", " << theDirFace1V << ", " << theDirFace2V << ", " << theNbTimesV << ")";
3257 //=============================================================================
3261 //=============================================================================
3262 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::Propagate
3263 (Handle(GEOM_Object) theShape)
3267 if (theShape.IsNull()) return NULL;
3269 TopoDS_Shape aShape = theShape->GetValue();
3270 if (aShape.IsNull()) return NULL;
3272 TopTools_IndexedMapOfShape anIndices;
3273 TopExp::MapShapes(aShape, anIndices);
3275 TopTools_IndexedDataMapOfShapeListOfShape MEW;
3276 GEOMImpl_Block6Explorer::MapShapesAndAncestors
3277 (aShape, TopAbs_EDGE, TopAbs_WIRE, MEW);
3278 Standard_Integer ie, nbEdges = MEW.Extent();
3281 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
3283 TopTools_MapOfShape mapAcceptedEdges;
3284 TCollection_AsciiString aListRes, anEntry;
3286 for (ie = 1; ie <= nbEdges; ie++) {
3287 TopoDS_Shape curE = MEW.FindKey(ie);
3289 if (mapAcceptedEdges.Contains(curE)) continue;
3292 TopTools_ListOfShape currentChain;
3293 TopTools_ListOfShape listPrevEdges;
3295 currentChain.Append(curE);
3296 listPrevEdges.Append(curE);
3297 mapAcceptedEdges.Add(curE);
3299 // Collect all edges pass by pass
3300 while (listPrevEdges.Extent() > 0) {
3301 // List of edges, added to chain on this cycle pass
3302 TopTools_ListOfShape listCurEdges;
3304 // Find the next portion of edges
3305 TopTools_ListIteratorOfListOfShape itE (listPrevEdges);
3306 for (; itE.More(); itE.Next()) {
3307 TopoDS_Shape anE = itE.Value();
3309 // Iterate on faces, having edge <anE>
3310 TopTools_ListIteratorOfListOfShape itW (MEW.FindFromKey(anE));
3311 for (; itW.More(); itW.Next()) {
3312 TopoDS_Shape aW = itW.Value();
3313 TopoDS_Shape anOppE;
3315 BRepTools_WireExplorer aWE (TopoDS::Wire(aW));
3316 Standard_Integer nb = 1, found = 0;
3317 TopTools_Array1OfShape anEdges (1,4);
3318 for (; aWE.More(); aWE.Next(), nb++) {
3323 anEdges(nb) = aWE.Current();
3324 if (anEdges(nb).IsSame(anE)) found = nb;
3327 if (nb == 5 && found > 0) {
3328 // Quadrangle face found, get an opposite edge
3329 Standard_Integer opp = found + 2;
3330 if (opp > 4) opp -= 4;
3331 anOppE = anEdges(opp);
3333 if (!mapAcceptedEdges.Contains(anOppE)) {
3334 // Add found edge to the chain
3335 currentChain.Append(anOppE);
3336 listCurEdges.Append(anOppE);
3337 mapAcceptedEdges.Add(anOppE);
3339 } // if (nb == 5 && found > 0)
3340 } // for (; itF.More(); itF.Next())
3341 } // for (; itE.More(); itE.Next())
3343 listPrevEdges = listCurEdges;
3344 } // while (listPrevEdges.Extent() > 0)
3346 // Store the chain in the document
3347 Handle(TColStd_HArray1OfInteger) anArray =
3348 new TColStd_HArray1OfInteger (1, currentChain.Extent());
3350 // Fill array of sub-shape indices
3351 TopTools_ListIteratorOfListOfShape itSub (currentChain);
3352 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
3353 int id = anIndices.FindIndex(itSub.Value());
3354 anArray->SetValue(index, id);
3357 // Add a new group object
3358 Handle(GEOM_Object) aChain = GetEngine()->AddSubShape(theShape, anArray);
3361 aChain->SetType(GEOM_GROUP);
3363 // Set a sub shape type
3364 TDF_Label aFreeLabel = aChain->GetFreeLabel();
3365 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)TopAbs_EDGE);
3367 // Add the chain to the result
3368 aSeq->Append(aChain);
3370 //Make a Python command
3371 TDF_Tool::Entry(aChain->GetEntry(), anEntry);
3372 aListRes += anEntry + ", ";
3375 if (aSeq->IsEmpty()) {
3376 SetErrorCode("There are no quadrangle faces in the shape");
3380 aListRes.Trunc(aListRes.Length() - 2);
3382 // The Propagation doesn't change object so no new function is required.
3383 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
3385 // Make a Python command
3386 GEOM::TPythonDump(aFunction, /*append=*/true)
3387 << "[" << aListRes.ToCString() << "] = geompy.Propagate(" << theShape << ")";