1 // Copyright (C) 2005 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License.
9 // This library is distributed in the hope that it will be useful
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 #pragma warning( disable:4786 )
24 #include <Standard_Stream.hxx>
26 #include <GEOMImpl_IBlocksOperations.hxx>
28 #include <GEOMImpl_Types.hxx>
30 #include <GEOMImpl_BlockDriver.hxx>
31 #include <GEOMImpl_IBlocks.hxx>
32 #include <GEOMImpl_IBlockTrsf.hxx>
33 #include <GEOMImpl_CopyDriver.hxx>
34 #include <GEOMImpl_Block6Explorer.hxx>
36 #include <GEOM_Function.hxx>
37 #include <GEOM_PythonDump.hxx>
39 #include <GEOMAlgo_GlueAnalyser.hxx>
40 #include <GEOMAlgo_CoupleOfShapes.hxx>
41 #include <GEOMAlgo_ListOfCoupleOfShapes.hxx>
42 #include <GEOMAlgo_ListIteratorOfListOfCoupleOfShapes.hxx>
43 #include <BlockFix_CheckTool.hxx>
45 #include "utilities.h"
47 #include <Utils_ExceptHandlers.hxx>
49 #include <TFunction_DriverTable.hxx>
50 #include <TFunction_Driver.hxx>
51 #include <TFunction_Logbook.hxx>
52 #include <TDataStd_Integer.hxx>
53 #include <TDF_Tool.hxx>
55 #include <BRep_Tool.hxx>
56 #include <BRep_Builder.hxx>
57 #include <BRepTools.hxx>
58 #include <BRepTools_WireExplorer.hxx>
59 #include <BRepGProp.hxx>
60 #include <BRepBndLib.hxx>
61 #include <BRepAdaptor_Surface.hxx>
62 #include <BRepClass_FaceClassifier.hxx>
63 #include <BRepClass3d_SolidClassifier.hxx>
64 #include <BRepExtrema_DistShapeShape.hxx>
68 #include <TopoDS_Edge.hxx>
69 #include <TopoDS_Vertex.hxx>
70 #include <TopoDS_Compound.hxx>
71 #include <TopoDS_Iterator.hxx>
73 #include <TopExp_Explorer.hxx>
74 #include <TopTools_MapOfShape.hxx>
75 #include <TopTools_Array1OfShape.hxx>
76 #include <TopTools_IndexedMapOfShape.hxx>
77 #include <TopTools_DataMapOfShapeInteger.hxx>
78 #include <TopTools_ListIteratorOfListOfShape.hxx>
79 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
80 #include <TopTools_DataMapIteratorOfDataMapOfShapeInteger.hxx>
82 #include <Bnd_Box.hxx>
83 #include <GProp_GProps.hxx>
85 #include <Geom_Surface.hxx>
86 #include <ShapeAnalysis_Surface.hxx>
88 #include <TColStd_MapOfInteger.hxx>
89 #include <TColStd_Array1OfReal.hxx>
90 #include <TColStd_Array1OfInteger.hxx>
91 #include <TColStd_Array2OfInteger.hxx>
93 //#include <OSD_Timer.hxx>
95 #include <Precision.hxx>
97 #include <Standard_Failure.hxx>
98 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
100 //=============================================================================
104 //=============================================================================
105 GEOMImpl_IBlocksOperations::GEOMImpl_IBlocksOperations (GEOM_Engine* theEngine, int theDocID)
106 : GEOM_IOperations(theEngine, theDocID)
108 MESSAGE("GEOMImpl_IBlocksOperations::GEOMImpl_IBlocksOperations");
111 //=============================================================================
115 //=============================================================================
116 GEOMImpl_IBlocksOperations::~GEOMImpl_IBlocksOperations()
118 MESSAGE("GEOMImpl_IBlocksOperations::~GEOMImpl_IBlocksOperations");
122 //=============================================================================
126 //=============================================================================
127 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad
128 (Handle(GEOM_Object) theEdge1, Handle(GEOM_Object) theEdge2,
129 Handle(GEOM_Object) theEdge3, Handle(GEOM_Object) theEdge4)
133 if (theEdge1.IsNull() || theEdge2.IsNull() ||
134 theEdge3.IsNull() || theEdge4.IsNull()) return NULL;
136 //Add a new Face object
137 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
139 //Add a new Face function
140 Handle(GEOM_Function) aFunction =
141 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_FOUR_EDGES);
143 //Check if the function is set correctly
144 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
146 GEOMImpl_IBlocks aPI (aFunction);
148 Handle(GEOM_Function) aRef1 = theEdge1->GetLastFunction();
149 Handle(GEOM_Function) aRef2 = theEdge2->GetLastFunction();
150 Handle(GEOM_Function) aRef3 = theEdge3->GetLastFunction();
151 Handle(GEOM_Function) aRef4 = theEdge4->GetLastFunction();
152 if (aRef1.IsNull() || aRef2.IsNull() ||
153 aRef3.IsNull() || aRef4.IsNull()) return NULL;
155 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
156 aShapesSeq->Append(aRef1);
157 aShapesSeq->Append(aRef2);
158 aShapesSeq->Append(aRef3);
159 aShapesSeq->Append(aRef4);
161 aPI.SetShapes(aShapesSeq);
163 //Compute the Face value
165 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
168 if (!GetSolver()->ComputeFunction(aFunction)) {
169 SetErrorCode("Block driver failed to compute a face");
173 catch (Standard_Failure) {
174 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
175 SetErrorCode(aFail->GetMessageString());
179 //Make a Python command
180 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeQuad("
181 << theEdge1 << ", " << theEdge2 << ", " << theEdge3 << ", " << theEdge4 << ")";
187 //=============================================================================
191 //=============================================================================
192 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad2Edges
193 (Handle(GEOM_Object) theEdge1, Handle(GEOM_Object) theEdge2)
197 if (theEdge1.IsNull() || theEdge2.IsNull()) return NULL;
199 //Add a new Face object
200 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
202 //Add a new Face function
203 Handle(GEOM_Function) aFunction =
204 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_TWO_EDGES);
206 //Check if the function is set correctly
207 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
209 GEOMImpl_IBlocks aPI (aFunction);
211 Handle(GEOM_Function) aRef1 = theEdge1->GetLastFunction();
212 Handle(GEOM_Function) aRef2 = theEdge2->GetLastFunction();
213 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
215 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
216 aShapesSeq->Append(aRef1);
217 aShapesSeq->Append(aRef2);
219 aPI.SetShapes(aShapesSeq);
221 //Compute the Face value
223 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
226 if (!GetSolver()->ComputeFunction(aFunction)) {
227 SetErrorCode("Block driver failed to compute a face");
231 catch (Standard_Failure) {
232 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
233 SetErrorCode(aFail->GetMessageString());
237 //Make a Python command
238 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeQuad2Edges("
239 << theEdge1 << ", " << theEdge2 << ")";
245 //=============================================================================
249 //=============================================================================
250 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad4Vertices
251 (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2,
252 Handle(GEOM_Object) thePnt3, Handle(GEOM_Object) thePnt4)
256 if (thePnt1.IsNull() || thePnt2.IsNull() ||
257 thePnt3.IsNull() || thePnt4.IsNull()) return NULL;
259 //Add a new Face object
260 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
262 //Add a new Face function
263 Handle(GEOM_Function) aFunction =
264 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_FOUR_PNT);
266 //Check if the function is set correctly
267 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
269 GEOMImpl_IBlocks aPI (aFunction);
271 Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
272 Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
273 Handle(GEOM_Function) aRef3 = thePnt3->GetLastFunction();
274 Handle(GEOM_Function) aRef4 = thePnt4->GetLastFunction();
275 if (aRef1.IsNull() || aRef2.IsNull() ||
276 aRef3.IsNull() || aRef4.IsNull()) return NULL;
278 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
279 aShapesSeq->Append(aRef1);
280 aShapesSeq->Append(aRef2);
281 aShapesSeq->Append(aRef3);
282 aShapesSeq->Append(aRef4);
284 aPI.SetShapes(aShapesSeq);
286 //Compute the Face value
288 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
291 if (!GetSolver()->ComputeFunction(aFunction)) {
292 SetErrorCode("Block driver failed to compute a face");
296 catch (Standard_Failure) {
297 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
298 SetErrorCode(aFail->GetMessageString());
302 //Make a Python command
303 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeQuad4Vertices("
304 << thePnt1 << ", " << thePnt2 << ", " << thePnt3 << ", " << thePnt4 << ")";
310 //=============================================================================
314 //=============================================================================
315 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeHexa
316 (Handle(GEOM_Object) theFace1, Handle(GEOM_Object) theFace2,
317 Handle(GEOM_Object) theFace3, Handle(GEOM_Object) theFace4,
318 Handle(GEOM_Object) theFace5, Handle(GEOM_Object) theFace6)
322 if (theFace1.IsNull() || theFace2.IsNull() ||
323 theFace3.IsNull() || theFace4.IsNull() ||
324 theFace5.IsNull() || theFace6.IsNull()) return NULL;
326 //Add a new Solid object
327 Handle(GEOM_Object) aBlock = GetEngine()->AddObject(GetDocID(), GEOM_BLOCK);
329 //Add a new Block function
330 Handle(GEOM_Function) aFunction =
331 aBlock->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_SIX_FACES);
333 //Check if the function is set correctly
334 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
336 GEOMImpl_IBlocks aPI (aFunction);
338 Handle(GEOM_Function) aRef1 = theFace1->GetLastFunction();
339 Handle(GEOM_Function) aRef2 = theFace2->GetLastFunction();
340 Handle(GEOM_Function) aRef3 = theFace3->GetLastFunction();
341 Handle(GEOM_Function) aRef4 = theFace4->GetLastFunction();
342 Handle(GEOM_Function) aRef5 = theFace5->GetLastFunction();
343 Handle(GEOM_Function) aRef6 = theFace6->GetLastFunction();
344 if (aRef1.IsNull() || aRef2.IsNull() ||
345 aRef3.IsNull() || aRef4.IsNull() ||
346 aRef5.IsNull() || aRef6.IsNull()) return NULL;
348 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
349 aShapesSeq->Append(aRef1);
350 aShapesSeq->Append(aRef2);
351 aShapesSeq->Append(aRef3);
352 aShapesSeq->Append(aRef4);
353 aShapesSeq->Append(aRef5);
354 aShapesSeq->Append(aRef6);
356 aPI.SetShapes(aShapesSeq);
358 //Compute the Block value
360 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
363 if (!GetSolver()->ComputeFunction(aFunction)) {
364 SetErrorCode("Block driver failed to compute a block");
368 catch (Standard_Failure) {
369 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
370 SetErrorCode(aFail->GetMessageString());
374 //Make a Python command
375 GEOM::TPythonDump(aFunction) << aBlock << " = geompy.MakeHexa("
376 << theFace1 << ", " << theFace2 << ", " << theFace3 << ", "
377 << theFace4 << ", " << theFace5 << ", " << theFace6 << ")";
383 //=============================================================================
387 //=============================================================================
388 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeHexa2Faces
389 (Handle(GEOM_Object) theFace1, Handle(GEOM_Object) theFace2)
393 if (theFace1.IsNull() || theFace2.IsNull()) return NULL;
395 //Add a new Solid object
396 Handle(GEOM_Object) aBlock = GetEngine()->AddObject(GetDocID(), GEOM_BLOCK);
398 //Add a new Block function
399 Handle(GEOM_Function) aFunction =
400 aBlock->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_TWO_FACES);
402 //Check if the function is set correctly
403 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
405 GEOMImpl_IBlocks aPI (aFunction);
407 Handle(GEOM_Function) aRef1 = theFace1->GetLastFunction();
408 Handle(GEOM_Function) aRef2 = theFace2->GetLastFunction();
409 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
411 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
412 aShapesSeq->Append(aRef1);
413 aShapesSeq->Append(aRef2);
415 aPI.SetShapes(aShapesSeq);
417 //Compute the Block value
419 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
422 if (!GetSolver()->ComputeFunction(aFunction)) {
423 SetErrorCode("Block driver failed to compute a block");
427 catch (Standard_Failure) {
428 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
429 SetErrorCode(aFail->GetMessageString());
433 //Make a Python command
434 GEOM::TPythonDump(aFunction) << aBlock << " = geompy.MakeHexa2Faces("
435 << theFace1 << ", " << theFace2 << ")";
441 //=============================================================================
445 //=============================================================================
446 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeBlockCompound
447 (Handle(GEOM_Object) theCompound)
451 if (theCompound.IsNull()) return NULL;
454 Handle(GEOM_Object) aBlockComp = GetEngine()->AddObject(GetDocID(), GEOM_COMPOUND);
456 //Add a new BlocksComp function
457 Handle(GEOM_Function) aFunction =
458 aBlockComp->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_COMPOUND_GLUE);
460 //Check if the function is set correctly
461 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
463 GEOMImpl_IBlocks aPI (aFunction);
465 Handle(GEOM_Function) aRef1 = theCompound->GetLastFunction();
466 if (aRef1.IsNull()) return NULL;
468 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
469 aShapesSeq->Append(aRef1);
471 aPI.SetShapes(aShapesSeq);
473 //Compute the Blocks Compound value
475 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
478 if (!GetSolver()->ComputeFunction(aFunction)) {
479 SetErrorCode("Block driver failed to compute a blocks compound");
483 catch (Standard_Failure) {
484 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
485 SetErrorCode(aFail->GetMessageString());
489 //Make a Python command
490 GEOM::TPythonDump(aFunction) << aBlockComp
491 << " = geompy.MakeBlockCompound(" << theCompound << ")";
497 //=============================================================================
501 //=============================================================================
502 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetPoint
503 (Handle(GEOM_Object) theShape,
504 const Standard_Real theX,
505 const Standard_Real theY,
506 const Standard_Real theZ,
507 const Standard_Real theEpsilon)
512 Handle(GEOM_Object) aResult;
515 if (theShape.IsNull()) return NULL;
517 TopoDS_Shape aBlockOrComp = theShape->GetValue();
518 if (aBlockOrComp.IsNull()) {
519 SetErrorCode("Given shape is null");
523 //Compute the Vertex value
524 gp_Pnt P (theX, theY, theZ);
525 Standard_Real eps = Max(theEpsilon, Precision::Confusion());
528 Standard_Integer isFound = 0;
529 TopTools_MapOfShape mapShape;
530 TopExp_Explorer exp (aBlockOrComp, TopAbs_VERTEX);
532 for (; exp.More(); exp.Next()) {
533 if (mapShape.Add(exp.Current())) {
534 TopoDS_Vertex aVi = TopoDS::Vertex(exp.Current());
535 gp_Pnt aPi = BRep_Tool::Pnt(aVi);
536 if (aPi.Distance(P) < eps) {
544 SetErrorCode("Vertex has not been found");
546 } else if (isFound > 1) {
547 SetErrorCode("Multiple vertices found by the given coordinates and epsilon");
550 TopTools_IndexedMapOfShape anIndices;
551 TopExp::MapShapes(aBlockOrComp, anIndices);
552 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
553 anArray->SetValue(1, anIndices.FindIndex(V));
554 aResult = GetEngine()->AddSubShape(theShape, anArray);
557 //The GetPoint() doesn't change object so no new function is required.
558 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
560 //Make a Python command
561 GEOM::TPythonDump(aFunction, /*append=*/true)
562 << aResult << " = geompy.GetPoint(" << theShape << ", "
563 << theX << ", " << theY << ", " << theZ << ", " << theEpsilon << ")";
569 //=============================================================================
573 //=============================================================================
574 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetEdge
575 (Handle(GEOM_Object) theShape,
576 Handle(GEOM_Object) thePoint1,
577 Handle(GEOM_Object) thePoint2)
582 Handle(GEOM_Object) aResult;
585 if (theShape.IsNull() || thePoint1.IsNull() || thePoint2.IsNull()) return NULL;
587 TopoDS_Shape aBlockOrComp = theShape->GetValue();
588 if (aBlockOrComp.IsNull()) {
589 SetErrorCode("Given shape is null");
593 TopoDS_Shape anArg1 = thePoint1->GetValue();
594 TopoDS_Shape anArg2 = thePoint2->GetValue();
595 if (anArg1.IsNull() || anArg2.IsNull()) {
596 SetErrorCode("Null shape is given as argument");
599 if (anArg1.ShapeType() != TopAbs_VERTEX ||
600 anArg2.ShapeType() != TopAbs_VERTEX) {
601 SetErrorCode("Element for edge identification is not a vertex");
605 //Compute the Edge value
607 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
610 TopTools_IndexedDataMapOfShapeListOfShape MVE;
611 GEOMImpl_Block6Explorer::MapShapesAndAncestors
612 (aBlockOrComp, TopAbs_VERTEX, TopAbs_EDGE, MVE);
615 Standard_Integer ish, ext = MVE.Extent();
617 if (MVE.Contains(anArg1)) {
620 for (ish = 1; ish <= ext; ish++) {
621 TopoDS_Shape aShi = MVE.FindKey(ish);
622 if (BRepTools::Compare(TopoDS::Vertex(anArg1), TopoDS::Vertex(aShi))) {
629 if (MVE.Contains(anArg2)) {
632 for (ish = 1; ish <= ext; ish++) {
633 TopoDS_Shape aShi = MVE.FindKey(ish);
634 if (BRepTools::Compare(TopoDS::Vertex(anArg2), TopoDS::Vertex(aShi))) {
641 if (V1.IsNull() || V2.IsNull()) {
642 SetErrorCode("The given vertex does not belong to the shape");
647 Standard_Integer isFound =
648 GEOMImpl_Block6Explorer::FindEdge(anEdge, V1, V2, MVE, Standard_True);
650 SetErrorCode("The given vertices do not belong to one edge of the given shape");
652 } else if (isFound > 1) {
653 SetErrorCode("Multiple edges found by the given vertices of the shape");
656 TopTools_IndexedMapOfShape anIndices;
657 TopExp::MapShapes(aBlockOrComp, anIndices);
658 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
659 anArray->SetValue(1, anIndices.FindIndex(anEdge));
660 aResult = GetEngine()->AddSubShape(theShape, anArray);
662 } catch (Standard_Failure) {
663 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
664 SetErrorCode(aFail->GetMessageString());
668 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
670 //Make a Python command
671 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetEdge("
672 << theShape << ", " << thePoint1 << ", " << thePoint2 << ")";
678 //=============================================================================
682 //=============================================================================
683 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetEdgeNearPoint
684 (Handle(GEOM_Object) theShape,
685 Handle(GEOM_Object) thePoint)
690 Handle(GEOM_Object) aResult;
693 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
695 TopoDS_Shape aBlockOrComp = theShape->GetValue();
696 if (aBlockOrComp.IsNull()) {
697 SetErrorCode("Given shape is null");
701 TopoDS_Shape anArg = thePoint->GetValue();
702 if (anArg.IsNull()) {
703 SetErrorCode("Null shape is given as argument");
706 if (anArg.ShapeType() != TopAbs_VERTEX) {
707 SetErrorCode("Element for edge identification is not a vertex");
711 //Compute the Edge value
713 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
718 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
720 // 1. Explode blocks on edges
721 TopTools_MapOfShape mapShape;
722 Standard_Integer nbEdges = 0;
723 TopExp_Explorer exp (aBlockOrComp, TopAbs_EDGE);
724 for (; exp.More(); exp.Next()) {
725 if (mapShape.Add(exp.Current())) {
731 SetErrorCode("Given shape contains no edges");
736 Standard_Integer ind = 1;
737 TopTools_Array1OfShape anEdges (1, nbEdges);
738 TColStd_Array1OfReal aDistances (1, nbEdges);
739 for (exp.Init(aBlockOrComp, TopAbs_EDGE); exp.More(); exp.Next()) {
740 if (mapShape.Add(exp.Current())) {
741 TopoDS_Shape anEdge = exp.Current();
742 anEdges(ind) = anEdge;
744 // 2. Classify the point relatively each edge
745 BRepExtrema_DistShapeShape aDistTool (aVert, anEdges(ind));
746 if (!aDistTool.IsDone()) {
747 SetErrorCode("Can not find a distance from the given point to one of edges");
750 aDistances(ind) = aDistTool.Value();
755 // 3. Define edge, having minimum distance to the point
756 Standard_Real nearest = RealLast(), nbFound = 0;
757 Standard_Real prec = Precision::Confusion();
758 for (ind = 1; ind <= nbEdges; ind++) {
759 if (Abs(aDistances(ind) - nearest) < prec) {
761 } else if (aDistances(ind) < nearest) {
762 nearest = aDistances(ind);
763 aShape = anEdges(ind);
769 SetErrorCode("Multiple edges near the given point are found");
771 } else if (nbFound == 0) {
772 SetErrorCode("There are no edges near the given point");
775 TopTools_IndexedMapOfShape anIndices;
776 TopExp::MapShapes(aBlockOrComp, anIndices);
777 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
778 anArray->SetValue(1, anIndices.FindIndex(aShape));
779 aResult = GetEngine()->AddSubShape(theShape, anArray);
782 catch (Standard_Failure) {
783 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
784 SetErrorCode(aFail->GetMessageString());
788 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
790 //Make a Python command
791 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetEdgeNearPoint("
792 << theShape << ", " << thePoint << ")";
798 //=============================================================================
802 //=============================================================================
803 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByPoints
804 (Handle(GEOM_Object) theShape,
805 Handle(GEOM_Object) thePoint1,
806 Handle(GEOM_Object) thePoint2,
807 Handle(GEOM_Object) thePoint3,
808 Handle(GEOM_Object) thePoint4)
813 Handle(GEOM_Object) aResult;
816 if (theShape.IsNull() ||
817 thePoint1.IsNull() || thePoint2.IsNull() ||
818 thePoint3.IsNull() || thePoint4.IsNull()) return NULL;
820 TopoDS_Shape aBlockOrComp = theShape->GetValue();
821 if (aBlockOrComp.IsNull()) {
822 SetErrorCode("Block or compound is null");
826 TopoDS_Shape anArg1 = thePoint1->GetValue();
827 TopoDS_Shape anArg2 = thePoint2->GetValue();
828 TopoDS_Shape anArg3 = thePoint3->GetValue();
829 TopoDS_Shape anArg4 = thePoint4->GetValue();
830 if (anArg1.IsNull() || anArg2.IsNull() ||
831 anArg3.IsNull() || anArg4.IsNull()) {
832 SetErrorCode("Null shape is given as argument");
835 if (anArg1.ShapeType() != TopAbs_VERTEX ||
836 anArg2.ShapeType() != TopAbs_VERTEX ||
837 anArg3.ShapeType() != TopAbs_VERTEX ||
838 anArg4.ShapeType() != TopAbs_VERTEX) {
839 SetErrorCode("Element for face identification is not a vertex");
843 //Compute the Face value
845 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
850 TopTools_IndexedDataMapOfShapeListOfShape MVF;
851 GEOMImpl_Block6Explorer::MapShapesAndAncestors(aBlockOrComp, TopAbs_VERTEX, TopAbs_FACE, MVF);
853 TopoDS_Shape V1,V2,V3,V4;
854 Standard_Integer ish, ext = MVF.Extent();
856 if (MVF.Contains(anArg1)) {
859 for (ish = 1; ish <= ext; ish++) {
860 TopoDS_Shape aShi = MVF.FindKey(ish);
861 if (BRepTools::Compare(TopoDS::Vertex(anArg1), TopoDS::Vertex(aShi))) {
868 if (MVF.Contains(anArg2)) {
871 for (ish = 1; ish <= ext; ish++) {
872 TopoDS_Shape aShi = MVF.FindKey(ish);
873 if (BRepTools::Compare(TopoDS::Vertex(anArg2), TopoDS::Vertex(aShi))) {
880 if (MVF.Contains(anArg3)) {
883 for (ish = 1; ish <= ext; ish++) {
884 TopoDS_Shape aShi = MVF.FindKey(ish);
885 if (BRepTools::Compare(TopoDS::Vertex(anArg3), TopoDS::Vertex(aShi))) {
892 if (MVF.Contains(anArg4)) {
895 for (ish = 1; ish <= ext; ish++) {
896 TopoDS_Shape aShi = MVF.FindKey(ish);
897 if (BRepTools::Compare(TopoDS::Vertex(anArg4), TopoDS::Vertex(aShi))) {
904 if (V1.IsNull() || V2.IsNull() || V3.IsNull() || V4.IsNull()) {
905 SetErrorCode("The given vertex does not belong to the shape");
909 Standard_Integer isFound =
910 GEOMImpl_Block6Explorer::FindFace(aShape, V1, V2, V3, V4, MVF, Standard_True);
912 SetErrorCode("The given vertices do not belong to one face of the given shape");
914 } else if (isFound > 1) {
915 SetErrorCode("The given vertices belong to several faces of the given shape");
918 TopTools_IndexedMapOfShape anIndices;
919 TopExp::MapShapes(aBlockOrComp, anIndices);
920 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
921 anArray->SetValue(1, anIndices.FindIndex(aShape));
922 aResult = GetEngine()->AddSubShape(theShape, anArray);
925 catch (Standard_Failure) {
926 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
927 SetErrorCode(aFail->GetMessageString());
931 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
933 //Make a Python command
934 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByPoints("
935 << theShape << ", " << thePoint1 << ", " << thePoint2
936 << ", " << thePoint3 << ", " << thePoint4 << ")";
942 //=============================================================================
946 //=============================================================================
947 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByEdges
948 (Handle(GEOM_Object) theShape,
949 Handle(GEOM_Object) theEdge1,
950 Handle(GEOM_Object) theEdge2)
955 Handle(GEOM_Object) aResult;
958 if (theShape.IsNull() || theEdge1.IsNull() || theEdge2.IsNull()) return NULL;
960 TopoDS_Shape aBlockOrComp = theShape->GetValue();
961 if (aBlockOrComp.IsNull()) {
962 SetErrorCode("Block or compound is null");
966 TopoDS_Shape anArg1 = theEdge1->GetValue();
967 TopoDS_Shape anArg2 = theEdge2->GetValue();
968 if (anArg1.IsNull() || anArg2.IsNull()) {
969 SetErrorCode("Null shape is given as argument");
972 if (anArg1.ShapeType() != TopAbs_EDGE ||
973 anArg2.ShapeType() != TopAbs_EDGE) {
974 SetErrorCode("Element for face identification is not an edge");
978 //Compute the Face value
980 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
985 TopTools_IndexedDataMapOfShapeListOfShape MEF;
986 GEOMImpl_Block6Explorer::MapShapesAndAncestors(aBlockOrComp, TopAbs_EDGE, TopAbs_FACE, MEF);
989 Standard_Integer ish, ext = MEF.Extent();
991 if (MEF.Contains(anArg1)) {
994 for (ish = 1; ish <= ext; ish++) {
995 TopoDS_Shape aShi = MEF.FindKey(ish);
996 if (GEOMImpl_Block6Explorer::IsSimilarEdges(anArg1, aShi)) {
1002 if (MEF.Contains(anArg2)) {
1005 for (ish = 1; ish <= ext; ish++) {
1006 TopoDS_Shape aShi = MEF.FindKey(ish);
1007 if (GEOMImpl_Block6Explorer::IsSimilarEdges(anArg2, aShi)) {
1013 if (E1.IsNull() || E2.IsNull()) {
1014 SetErrorCode("The given edge does not belong to the shape");
1018 const TopTools_ListOfShape& aFacesOfE1 = MEF.FindFromKey(E1);
1019 const TopTools_ListOfShape& aFacesOfE2 = MEF.FindFromKey(E2);
1021 Standard_Integer isFound = 0;
1022 TopTools_ListIteratorOfListOfShape anIterF1 (aFacesOfE1);
1023 for (; anIterF1.More(); anIterF1.Next()) {
1025 TopTools_ListIteratorOfListOfShape anIterF2 (aFacesOfE2);
1026 for (; anIterF2.More(); anIterF2.Next()) {
1028 if (anIterF1.Value().IsSame(anIterF2.Value())) {
1031 // Store the face, defined by two edges
1032 aShape = anIterF1.Value();
1037 SetErrorCode("The given edges do not belong to one face of the given shape");
1039 } else if (isFound > 1) {
1040 SetErrorCode("The given edges belong to several faces of the given shape");
1043 TopTools_IndexedMapOfShape anIndices;
1044 TopExp::MapShapes(aBlockOrComp, anIndices);
1045 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1046 anArray->SetValue(1, anIndices.FindIndex(aShape));
1047 aResult = GetEngine()->AddSubShape(theShape, anArray);
1050 catch (Standard_Failure) {
1051 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1052 SetErrorCode(aFail->GetMessageString());
1056 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1058 //Make a Python command
1059 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByEdges("
1060 << theShape << ", " << theEdge1 << ", " << theEdge2 << ")";
1066 //=============================================================================
1070 //=============================================================================
1071 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetOppositeFace
1072 (Handle(GEOM_Object) theShape,
1073 Handle(GEOM_Object) theFace)
1078 Handle(GEOM_Object) aResult;
1081 if (theShape.IsNull() || theFace.IsNull()) return NULL;
1083 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1084 if (aBlockOrComp.IsNull()) {
1085 SetErrorCode("Block is null");
1088 if (aBlockOrComp.ShapeType() != TopAbs_SOLID) {
1089 SetErrorCode("Shape is not a block");
1093 TopoDS_Shape anArg = theFace->GetValue();
1094 if (anArg.IsNull()) {
1095 SetErrorCode("Null shape is given as argument");
1098 if (anArg.ShapeType() != TopAbs_FACE) {
1099 SetErrorCode("Element for face identification is not a face");
1103 //Compute the Face value
1105 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1108 TopoDS_Shape aShape;
1110 GEOMImpl_Block6Explorer aBlockTool;
1111 aBlockTool.InitByBlockAndFace(aBlockOrComp, anArg);
1112 aShape = aBlockTool.GetFace(2);
1114 TopTools_IndexedMapOfShape anIndices;
1115 TopExp::MapShapes(aBlockOrComp, anIndices);
1116 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1117 anArray->SetValue(1, anIndices.FindIndex(aShape));
1118 aResult = GetEngine()->AddSubShape(theShape, anArray);
1120 catch (Standard_Failure) {
1121 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1122 SetErrorCode(aFail->GetMessageString());
1126 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1128 //Make a Python command
1129 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetOppositeFace("
1130 << theShape << ", " << theFace << ")";
1136 //=============================================================================
1140 //=============================================================================
1141 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceNearPoint
1142 (Handle(GEOM_Object) theShape,
1143 Handle(GEOM_Object) thePoint)
1148 Handle(GEOM_Object) aResult;
1151 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
1153 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1154 if (aBlockOrComp.IsNull()) {
1155 SetErrorCode("Block or compound is null");
1159 TopoDS_Shape anArg = thePoint->GetValue();
1160 if (anArg.IsNull()) {
1161 SetErrorCode("Null shape is given as argument");
1164 if (anArg.ShapeType() != TopAbs_VERTEX) {
1165 SetErrorCode("Element for face identification is not a vertex");
1169 //Compute the Face value
1171 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1174 TopoDS_Shape aShape;
1176 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
1177 gp_Pnt aPnt = BRep_Tool::Pnt(aVert);
1178 Standard_Real PX, PY, PZ;
1179 aPnt.Coord(PX, PY, PZ);
1181 // 1. Classify the point relatively each face
1182 Standard_Integer nearest = 2, nbFound = 0;
1183 TopTools_DataMapOfShapeInteger mapShapeDist;
1184 TopExp_Explorer exp (aBlockOrComp, TopAbs_FACE);
1185 for (; exp.More(); exp.Next()) {
1186 TopoDS_Shape aFace = exp.Current();
1188 if (!mapShapeDist.IsBound(aFace)) {
1189 Standard_Integer aDistance = 2;
1191 // 1.a. Classify relatively Surface
1192 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aFace));
1193 Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf);
1194 gp_Pnt2d p2dOnSurf = aSurfAna->ValueOfUV(aPnt, Precision::Confusion());
1195 gp_Pnt p3dOnSurf = aSurfAna->Value(p2dOnSurf);
1196 Standard_Real aDist = p3dOnSurf.Distance(aPnt);
1197 if (aDist > Precision::Confusion()) {
1201 // 1.b. Classify relatively the face itself
1202 BRepClass_FaceClassifier FC (TopoDS::Face(aFace), p2dOnSurf, Precision::Confusion());
1203 if (FC.State() == TopAbs_IN) {
1205 } else if (FC.State() == TopAbs_ON) {
1212 if (aDistance < nearest) {
1213 nearest = aDistance;
1217 // A first found face, containing the point inside, will be returned.
1218 // It is the solution, if there are no
1219 // coincident or intersecting faces in the compound.
1220 if (nearest == -1) break;
1222 } else if (aDistance == nearest) {
1227 mapShapeDist.Bind(aFace, aDistance);
1228 } // if (!mapShapeDist.IsBound(aFace))
1231 // 2. Define face, containing the point or having minimum distance to it
1234 // The point is on boundary of some faces and there are
1235 // no faces, having the point inside
1236 SetErrorCode("Multiple faces near the given point are found");
1239 } else if (nearest == 1) {
1240 // The point is outside some faces and there are
1241 // no faces, having the point inside or on boundary.
1242 // We will get a nearest face
1243 Standard_Real bigReal = RealLast();
1244 Standard_Real minDist = bigReal;
1245 TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
1246 for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
1247 if (mapShapeDistIter.Value() == 1) {
1248 TopoDS_Shape aFace = mapShapeDistIter.Key();
1249 Standard_Real aDist = bigReal;
1251 // 2.a. Fast check of distance - if point projection on surface is on face
1252 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aFace));
1253 Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf);
1254 gp_Pnt2d p2dOnSurf = aSurfAna->ValueOfUV(aPnt, Precision::Confusion());
1255 gp_Pnt p3dOnSurf = aSurfAna->Value(p2dOnSurf);
1256 aDist = p3dOnSurf.Distance(aPnt);
1258 BRepClass_FaceClassifier FC (TopoDS::Face(aFace), p2dOnSurf, Precision::Confusion());
1259 if (FC.State() == TopAbs_OUT) {
1260 if (aDist < minDist) {
1261 // 2.b. Slow check - if point projection on surface is outside of face
1262 BRepExtrema_DistShapeShape aDistTool (aVert, aFace);
1263 if (!aDistTool.IsDone()) {
1264 SetErrorCode("Can not find a distance from the given point to one of faces");
1267 aDist = aDistTool.Value();
1273 if (aDist < minDist) {
1279 } else { // nearest == -1
1280 // // The point is inside some faces.
1281 // // We will get a face with nearest center
1282 // Standard_Real minDist = RealLast();
1283 // TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
1284 // for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
1285 // if (mapShapeDistIter.Value() == -1) {
1286 // TopoDS_Shape aFace = mapShapeDistIter.Key();
1287 // GProp_GProps aSystem;
1288 // BRepGProp::SurfaceProperties(aFace, aSystem);
1289 // gp_Pnt aCenterMass = aSystem.CentreOfMass();
1291 // Standard_Real aDist = aCenterMass.Distance(aPnt);
1292 // if (aDist < minDist) {
1299 } // if (nbFound > 1)
1302 SetErrorCode("There are no faces near the given point");
1305 TopTools_IndexedMapOfShape anIndices;
1306 TopExp::MapShapes(aBlockOrComp, anIndices);
1307 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1308 anArray->SetValue(1, anIndices.FindIndex(aShape));
1309 aResult = GetEngine()->AddSubShape(theShape, anArray);
1312 catch (Standard_Failure) {
1313 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1314 SetErrorCode(aFail->GetMessageString());
1318 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1320 //Make a Python command
1321 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceNearPoint("
1322 << theShape << ", " << thePoint << ")";
1328 //=============================================================================
1332 //=============================================================================
1333 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByNormale
1334 (Handle(GEOM_Object) theShape,
1335 Handle(GEOM_Object) theVector)
1340 Handle(GEOM_Object) aResult;
1343 if (theShape.IsNull() || theVector.IsNull()) return NULL;
1345 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1346 if (aBlockOrComp.IsNull()) {
1347 SetErrorCode("Block or compound is null");
1351 TopoDS_Shape anArg = theVector->GetValue();
1352 if (anArg.IsNull()) {
1353 SetErrorCode("Null shape is given as argument");
1356 if (anArg.ShapeType() != TopAbs_EDGE) {
1357 SetErrorCode("Element for normale identification is not an edge");
1361 //Compute the Face value
1363 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1366 TopoDS_Shape aShape;
1368 TopoDS_Edge anEdge = TopoDS::Edge(anArg);
1369 TopoDS_Vertex V1, V2;
1370 TopExp::Vertices(anEdge, V1, V2, Standard_True);
1371 gp_Pnt P1 = BRep_Tool::Pnt(V1);
1372 gp_Pnt P2 = BRep_Tool::Pnt(V2);
1373 gp_Vec aVec (P1, P2);
1374 if (aVec.Magnitude() < Precision::Confusion()) {
1375 SetErrorCode("Vector with null magnitude is given");
1379 Standard_Real minAngle = RealLast();
1380 TopTools_MapOfShape mapShape;
1381 TopExp_Explorer exp (aBlockOrComp, TopAbs_FACE);
1382 for (; exp.More(); exp.Next()) {
1383 if (mapShape.Add(exp.Current())) {
1384 TopoDS_Face aFace = TopoDS::Face(exp.Current());
1385 BRepAdaptor_Surface SF (aFace);
1387 Standard_Real u, v, x;
1389 // find a point on the surface to get normal direction in
1390 u = SF.FirstUParameter();
1391 x = SF.LastUParameter();
1392 if (Precision::IsInfinite(u)) {
1393 u = (Precision::IsInfinite(x)) ? 0. : x;
1394 } else if (!Precision::IsInfinite(x)) {
1398 v = SF.FirstVParameter();
1399 x = SF.LastVParameter();
1400 if (Precision::IsInfinite(v)) {
1401 v = (Precision::IsInfinite(x)) ? 0. : x;
1402 } else if (!Precision::IsInfinite(x)) {
1406 // compute the normal direction
1408 SF.D1(u,v,P1,Vec1,Vec2);
1409 gp_Vec V = Vec1.Crossed(Vec2);
1411 if (V.Magnitude() < Precision::Confusion()) {
1412 SetErrorCode("Normal vector of a face has null magnitude");
1416 // consider the face orientation
1417 if (aFace.Orientation() == TopAbs_REVERSED ||
1418 aFace.Orientation() == TopAbs_INTERNAL) {
1422 // compute the angle and compare with the minimal one
1423 Standard_Real anAngle = aVec.Angle(V);
1424 if (anAngle < minAngle) {
1431 if (aShape.IsNull()) {
1432 SetErrorCode("Failed to find a face by the given normale");
1435 TopTools_IndexedMapOfShape anIndices;
1436 TopExp::MapShapes(aBlockOrComp, anIndices);
1437 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1438 anArray->SetValue(1, anIndices.FindIndex(aShape));
1439 aResult = GetEngine()->AddSubShape(theShape, anArray);
1442 catch (Standard_Failure) {
1443 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1444 SetErrorCode(aFail->GetMessageString());
1448 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1450 //Make a Python command
1451 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByNormale("
1452 << theShape << ", " << theVector << ")";
1458 //=============================================================================
1460 * IsCompoundOfBlocks
1462 //=============================================================================
1463 Standard_Boolean GEOMImpl_IBlocksOperations::IsCompoundOfBlocks
1464 (Handle(GEOM_Object) theCompound,
1465 const Standard_Integer theMinNbFaces,
1466 const Standard_Integer theMaxNbFaces,
1467 Standard_Integer& theNbBlocks)
1470 Standard_Boolean isCompOfBlocks = Standard_False;
1473 if (theCompound.IsNull()) return isCompOfBlocks;
1474 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
1477 isCompOfBlocks = Standard_True;
1479 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1482 TopTools_MapOfShape mapShape;
1483 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
1484 for (; exp.More(); exp.Next()) {
1485 if (mapShape.Add(exp.Current())) {
1486 TopoDS_Shape aSolid = exp.Current();
1488 TopTools_MapOfShape mapFaces;
1489 TopExp_Explorer expF (aSolid, TopAbs_FACE);
1490 Standard_Integer nbFaces = 0;
1491 for (; expF.More(); expF.Next()) {
1492 if (mapFaces.Add(expF.Current())) {
1494 if (nbFaces > theMaxNbFaces) {
1495 isCompOfBlocks = Standard_False;
1500 if (nbFaces < theMinNbFaces || theMaxNbFaces < nbFaces) {
1501 isCompOfBlocks = Standard_False;
1508 catch (Standard_Failure) {
1509 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1510 SetErrorCode(aFail->GetMessageString());
1511 return isCompOfBlocks;
1515 return isCompOfBlocks;
1518 //=============================================================================
1520 * Set of functions, used by CheckCompoundOfBlocks() method
1522 //=============================================================================
1523 void GEOMImpl_IBlocksOperations::AddBlocksFrom (const TopoDS_Shape& theShape,
1524 TopTools_ListOfShape& BLO,
1525 TopTools_ListOfShape& NOT,
1526 TopTools_ListOfShape& EXT)
1528 TopAbs_ShapeEnum aType = theShape.ShapeType();
1530 case TopAbs_COMPOUND:
1531 case TopAbs_COMPSOLID:
1533 TopoDS_Iterator It (theShape);
1534 for (; It.More(); It.Next()) {
1535 AddBlocksFrom(It.Value(), BLO, NOT, EXT);
1541 // Check, if there are seam or degenerated edges
1542 BlockFix_CheckTool aTool;
1543 aTool.SetShape(theShape);
1545 if (aTool.NbPossibleBlocks() > 0) {
1546 EXT.Append(theShape);
1548 // Count faces and edges in each face to recognize blocks
1549 TopTools_MapOfShape mapFaces;
1550 Standard_Integer nbFaces = 0;
1551 Standard_Boolean hasNonQuadr = Standard_False;
1552 TopExp_Explorer expF (theShape, TopAbs_FACE);
1554 for (; expF.More(); expF.Next()) {
1555 if (mapFaces.Add(expF.Current())) {
1557 if (nbFaces > 6) break;
1560 TopoDS_Shape aF = expF.Current();
1561 TopExp_Explorer wires (aF, TopAbs_WIRE);
1562 if (!wires.More()) {
1563 // no wire in the face
1564 hasNonQuadr = Standard_True;
1567 TopoDS_Shape aWire = wires.Current();
1570 // multiple wires in the face
1571 hasNonQuadr = Standard_True;
1575 // Check number of edges in the face
1576 Standard_Integer nbEdges = 0;
1577 TopTools_MapOfShape mapEdges;
1578 TopExp_Explorer expW (aWire, TopAbs_EDGE);
1579 for (; expW.More(); expW.Next()) {
1580 if (mapEdges.Add(expW.Current())) {
1582 if (nbEdges > 4) break;
1586 hasNonQuadr = Standard_True;
1591 if (nbFaces == 6 && !hasNonQuadr) {
1592 BLO.Append(theShape);
1594 NOT.Append(theShape);
1600 NOT.Append(theShape);
1604 void AddBlocksFromOld (const TopoDS_Shape& theShape,
1605 TopTools_ListOfShape& BLO,
1606 TopTools_ListOfShape& NOT,
1607 TopTools_ListOfShape& DEG,
1608 TopTools_ListOfShape& SEA)
1610 TopAbs_ShapeEnum aType = theShape.ShapeType();
1612 case TopAbs_COMPOUND:
1613 case TopAbs_COMPSOLID:
1615 TopoDS_Iterator It (theShape);
1616 for (; It.More(); It.Next()) {
1617 AddBlocksFromOld(It.Value(), BLO, NOT, DEG, SEA);
1623 TopTools_MapOfShape mapFaces;
1624 TopExp_Explorer expF (theShape, TopAbs_FACE);
1625 Standard_Integer nbFaces = 0;
1626 Standard_Boolean hasNonQuadr = Standard_False;
1627 Standard_Boolean hasDegenerated = Standard_False;
1628 Standard_Boolean hasSeam = Standard_False;
1629 for (; expF.More(); expF.Next()) {
1630 if (mapFaces.Add(expF.Current())) {
1632 if (nbFaces > 6) break;
1634 // Check number of edges in the face
1635 Standard_Integer nbEdges = 0;
1636 TopTools_MapOfShape mapEdges;
1639 TopoDS_Shape aF = expF.Current();
1640 TopExp_Explorer wires (aF, TopAbs_WIRE);
1641 if (!wires.More()) {
1642 // no wire in the face
1643 hasNonQuadr = Standard_True;
1646 TopoDS_Shape aWire = wires.Current();
1649 // multiple wires in the face
1650 hasNonQuadr = Standard_True;
1655 BRepTools_WireExplorer aWE (TopoDS::Wire(aWire), TopoDS::Face(aF));
1656 for (; aWE.More(); aWE.Next(), nbEdges++) {
1657 if (BRep_Tool::Degenerated(aWE.Current())) {
1658 // degenerated edge found
1659 hasDegenerated = Standard_True;
1662 if (mapEdges.Contains(aWE.Current())) {
1664 hasSeam = Standard_True;
1667 mapEdges.Add(aWE.Current());
1670 hasNonQuadr = Standard_True;
1675 if (hasDegenerated || hasSeam) {
1676 if (hasDegenerated) {
1677 DEG.Append(theShape);
1680 SEA.Append(theShape);
1682 } else if (hasNonQuadr) {
1683 NOT.Append(theShape);
1685 BLO.Append(theShape);
1688 NOT.Append(theShape);
1693 NOT.Append(theShape);
1697 #define REL_NOT_CONNECTED 0
1699 #define REL_NOT_GLUED 2
1700 #define REL_COLLISION_VV 3
1701 #define REL_COLLISION_FF 4
1702 #define REL_COLLISION_EE 5
1703 #define REL_UNKNOWN 6
1705 Standard_Integer BlocksRelation (const TopoDS_Shape& theBlock1,
1706 const TopoDS_Shape& theBlock2)
1708 // Compare bounding boxes before calling BRepExtrema_DistShapeShape
1709 Standard_Real Xmin1, Ymin1, Zmin1, Xmax1, Ymax1, Zmax1;
1710 Standard_Real Xmin2, Ymin2, Zmin2, Xmax2, Ymax2, Zmax2;
1712 BRepBndLib::Add(theBlock1, B1);
1713 BRepBndLib::Add(theBlock2, B2);
1714 B1.Get(Xmin1, Ymin1, Zmin1, Xmax1, Ymax1, Zmax1);
1715 B2.Get(Xmin2, Ymin2, Zmin2, Xmax2, Ymax2, Zmax2);
1716 if (Xmax2 < Xmin1 || Xmax1 < Xmin2 ||
1717 Ymax2 < Ymin1 || Ymax1 < Ymin2 ||
1718 Zmax2 < Zmin1 || Zmax1 < Zmin2) {
1719 return REL_NOT_CONNECTED;
1722 BRepExtrema_DistShapeShape dst (theBlock1, theBlock2);
1723 if (!dst.IsDone()) {
1727 if (dst.Value() > Precision::Confusion()) {
1728 return REL_NOT_CONNECTED;
1731 if (dst.InnerSolution()) {
1732 return REL_COLLISION_VV;
1735 Standard_Integer nbSol = dst.NbSolution();
1736 Standard_Integer relation = REL_OK;
1737 Standard_Integer nbVerts = 0;
1738 Standard_Integer nbEdges = 0;
1739 Standard_Integer sol = 1;
1740 for (; sol <= nbSol; sol++) {
1741 BRepExtrema_SupportType supp1 = dst.SupportTypeShape1(sol);
1742 BRepExtrema_SupportType supp2 = dst.SupportTypeShape2(sol);
1743 if (supp1 == BRepExtrema_IsVertex && supp2 == BRepExtrema_IsVertex) {
1745 } else if (supp1 == BRepExtrema_IsInFace || supp2 == BRepExtrema_IsInFace) {
1746 return REL_COLLISION_FF;
1747 } else if (supp1 == BRepExtrema_IsOnEdge && supp2 == BRepExtrema_IsOnEdge) {
1749 } else if ((supp1 == BRepExtrema_IsOnEdge && supp2 == BRepExtrema_IsVertex) ||
1750 (supp2 == BRepExtrema_IsOnEdge && supp1 == BRepExtrema_IsVertex)) {
1751 relation = REL_COLLISION_EE;
1756 if (relation != REL_OK) {
1760 TColStd_Array1OfInteger vertSol (1, nbVerts);
1761 TopTools_Array1OfShape V1 (1, nbVerts);
1762 TopTools_Array1OfShape V2 (1, nbVerts);
1763 Standard_Integer ivs = 0;
1764 for (sol = 1; sol <= nbSol; sol++) {
1765 if (dst.SupportTypeShape1(sol) == BRepExtrema_IsVertex &&
1766 dst.SupportTypeShape2(sol) == BRepExtrema_IsVertex) {
1767 TopoDS_Vertex Vcur = TopoDS::Vertex(dst.SupportOnShape1(sol));
1768 // Check, that this vertex is far enough from other solution vertices.
1769 Standard_Integer ii = 1;
1770 for (; ii <= ivs; ii++) {
1771 if (BRepTools::Compare(TopoDS::Vertex(V1(ii)), Vcur)) {
1778 V2(ivs) = dst.SupportOnShape2(sol);
1782 // As we deal only with quadrangles,
1783 // 2, 3 or 4 vertex solutions can be found.
1786 return REL_COLLISION_FF;
1788 return REL_NOT_CONNECTED;
1794 // Check sharing of coincident entities.
1795 if (ivs == 2 || ivs == 3) {
1796 // Map vertices and edges of the blocks
1797 TopTools_IndexedDataMapOfShapeListOfShape MVE1, MVE2;
1798 GEOMImpl_Block6Explorer::MapShapesAndAncestors
1799 (theBlock1, TopAbs_VERTEX, TopAbs_EDGE, MVE1);
1800 GEOMImpl_Block6Explorer::MapShapesAndAncestors
1801 (theBlock2, TopAbs_VERTEX, TopAbs_EDGE, MVE2);
1805 TopoDS_Shape anEdge1, anEdge2;
1806 GEOMImpl_Block6Explorer::FindEdge(anEdge1, V1(1), V1(2), MVE1);
1807 if (anEdge1.IsNull()) return REL_UNKNOWN;
1809 GEOMImpl_Block6Explorer::FindEdge(anEdge2, V2(1), V2(2), MVE2);
1810 if (anEdge2.IsNull()) return REL_UNKNOWN;
1812 if (!anEdge1.IsSame(anEdge2)) return REL_NOT_GLUED;
1814 } else { // ivs == 3
1815 // Find common edges
1816 Standard_Integer e1_v1 = 1;
1817 Standard_Integer e1_v2 = 2;
1818 Standard_Integer e2_v1 = 3;
1819 Standard_Integer e2_v2 = 1;
1821 TopoDS_Shape anEdge11, anEdge12;
1822 GEOMImpl_Block6Explorer::FindEdge(anEdge11, V1(e1_v1), V1(e1_v2), MVE1);
1823 if (anEdge11.IsNull()) {
1826 GEOMImpl_Block6Explorer::FindEdge(anEdge11, V1(e1_v1), V1(e1_v2), MVE1);
1827 if (anEdge11.IsNull()) return REL_UNKNOWN;
1829 GEOMImpl_Block6Explorer::FindEdge(anEdge12, V1(e2_v1), V1(e2_v2), MVE1);
1830 if (anEdge12.IsNull()) {
1832 GEOMImpl_Block6Explorer::FindEdge(anEdge12, V1(e2_v1), V1(e2_v2), MVE1);
1833 if (anEdge12.IsNull()) return REL_UNKNOWN;
1836 TopoDS_Shape anEdge21, anEdge22;
1837 GEOMImpl_Block6Explorer::FindEdge(anEdge21, V2(e1_v1), V2(e1_v2), MVE2);
1838 if (anEdge21.IsNull()) return REL_UNKNOWN;
1839 GEOMImpl_Block6Explorer::FindEdge(anEdge22, V2(e2_v1), V2(e2_v2), MVE2);
1840 if (anEdge22.IsNull()) return REL_UNKNOWN;
1842 // Check of edges coincidence (with some precision) have to be done here
1843 // if (!anEdge11.IsEqual(anEdge21)) return REL_UNKNOWN;
1844 // if (!anEdge12.IsEqual(anEdge22)) return REL_UNKNOWN;
1846 // Check of edges sharing
1847 if (!anEdge11.IsSame(anEdge21)) return REL_NOT_GLUED;
1848 if (!anEdge12.IsSame(anEdge22)) return REL_NOT_GLUED;
1853 // Map vertices and faces of the blocks
1854 TopTools_IndexedDataMapOfShapeListOfShape MVF1, MVF2;
1855 GEOMImpl_Block6Explorer::MapShapesAndAncestors
1856 (theBlock1, TopAbs_VERTEX, TopAbs_FACE, MVF1);
1857 GEOMImpl_Block6Explorer::MapShapesAndAncestors
1858 (theBlock2, TopAbs_VERTEX, TopAbs_FACE, MVF2);
1860 TopoDS_Shape aFace1, aFace2;
1861 GEOMImpl_Block6Explorer::FindFace(aFace1, V1(1), V1(2), V1(3), V1(4), MVF1);
1862 if (aFace1.IsNull()) return REL_UNKNOWN;
1863 GEOMImpl_Block6Explorer::FindFace(aFace2, V2(1), V2(2), V2(3), V2(4), MVF2);
1864 if (aFace2.IsNull()) return REL_UNKNOWN;
1866 // Check of faces coincidence (with some precision) have to be done here
1867 // if (!aFace1.IsEqual(aFace2)) return REL_UNKNOWN;
1869 // Check of faces sharing
1870 if (!aFace1.IsSame(aFace2)) return REL_NOT_GLUED;
1876 void FindConnected (const Standard_Integer theBlockIndex,
1877 const TColStd_Array2OfInteger& theRelations,
1878 TColStd_MapOfInteger& theProcessedMap,
1879 TColStd_MapOfInteger& theConnectedMap)
1881 theConnectedMap.Add(theBlockIndex);
1882 theProcessedMap.Add(theBlockIndex);
1884 Standard_Integer nbBlocks = theRelations.ColLength();
1885 Standard_Integer col = 1;
1886 for (; col <= nbBlocks; col++) {
1887 if (theRelations(theBlockIndex, col) == REL_OK ||
1888 theRelations(theBlockIndex, col) == REL_NOT_GLUED) {
1889 if (!theProcessedMap.Contains(col)) {
1890 FindConnected(col, theRelations, theProcessedMap, theConnectedMap);
1896 Standard_Boolean HasAnyConnection (const Standard_Integer theBlockIndex,
1897 const TColStd_MapOfInteger& theWith,
1898 const TColStd_Array2OfInteger& theRelations,
1899 TColStd_MapOfInteger& theProcessedMap)
1901 theProcessedMap.Add(theBlockIndex);
1903 Standard_Integer nbBlocks = theRelations.ColLength();
1904 Standard_Integer col = 1;
1905 for (; col <= nbBlocks; col++) {
1906 if (theRelations(theBlockIndex, col) != REL_NOT_CONNECTED) {
1907 if (!theProcessedMap.Contains(col)) {
1908 if (theWith.Contains(col))
1909 return Standard_True;
1910 if (HasAnyConnection(col, theWith, theRelations, theProcessedMap))
1911 return Standard_True;
1916 return Standard_False;
1919 //=============================================================================
1921 * CheckCompoundOfBlocksOld
1923 //=============================================================================
1924 Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocksOld
1925 (Handle(GEOM_Object) theCompound,
1926 list<BCError>& theErrors)
1930 if (theCompound.IsNull()) return Standard_False;
1931 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
1933 Standard_Boolean isCompOfBlocks = Standard_True;
1935 // Map sub-shapes and their indices
1936 TopTools_IndexedMapOfShape anIndices;
1937 TopExp::MapShapes(aBlockOrComp, anIndices);
1939 // 1. Report non-blocks
1940 TopTools_ListOfShape NOT; // Not blocks
1941 TopTools_ListOfShape DEG; // Hexahedral solids, having degenerated edges
1942 TopTools_ListOfShape SEA; // Hexahedral solids, having seam edges
1943 TopTools_ListOfShape BLO; // All blocks from the given compound
1944 AddBlocksFromOld(aBlockOrComp, BLO, NOT, DEG, SEA);
1946 if (NOT.Extent() > 0) {
1947 isCompOfBlocks = Standard_False;
1949 anErr.error = NOT_BLOCK;
1950 TopTools_ListIteratorOfListOfShape it (NOT);
1951 for (; it.More(); it.Next()) {
1952 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
1954 theErrors.push_back(anErr);
1957 if (DEG.Extent() > 0 || SEA.Extent() > 0) {
1958 isCompOfBlocks = Standard_False;
1960 anErr.error = EXTRA_EDGE;
1962 TopTools_ListIteratorOfListOfShape itDEG (DEG);
1963 for (; itDEG.More(); itDEG.Next()) {
1964 anErr.incriminated.push_back(anIndices.FindIndex(itDEG.Value()));
1967 TopTools_ListIteratorOfListOfShape itSEA (SEA);
1968 for (; itSEA.More(); itSEA.Next()) {
1969 anErr.incriminated.push_back(anIndices.FindIndex(itSEA.Value()));
1972 theErrors.push_back(anErr);
1975 Standard_Integer nbBlocks = BLO.Extent();
1976 if (nbBlocks == 0) {
1977 isCompOfBlocks = Standard_False;
1979 return isCompOfBlocks;
1981 if (nbBlocks == 1) {
1983 return isCompOfBlocks;
1986 // Convert list of blocks into array for easy and fast access
1987 Standard_Integer ibl = 1;
1988 TopTools_Array1OfShape aBlocks (1, nbBlocks);
1989 TopTools_ListIteratorOfListOfShape BLOit (BLO);
1990 for (; BLOit.More(); BLOit.Next(), ibl++) {
1991 aBlocks.SetValue(ibl, BLOit.Value());
1994 // 2. Find relations between all blocks,
1995 // report connection errors (NOT_GLUED and INVALID_CONNECTION)
1996 TColStd_Array2OfInteger aRelations (1, nbBlocks, 1, nbBlocks);
1997 aRelations.Init(REL_NOT_CONNECTED);
1999 Standard_Integer row = 1;
2000 for (row = 1; row <= nbBlocks; row++) {
2001 TopoDS_Shape aBlock = aBlocks.Value(row);
2003 Standard_Integer col = row + 1;
2004 for (; col <= nbBlocks; col++) {
2005 Standard_Integer aRel = BlocksRelation(aBlock, aBlocks.Value(col));
2006 if (aRel != REL_NOT_CONNECTED) {
2007 aRelations.SetValue(row, col, aRel);
2008 aRelations.SetValue(col, row, aRel);
2009 if (aRel == REL_NOT_GLUED) {
2010 // report connection error
2011 isCompOfBlocks = Standard_False;
2013 anErr.error = NOT_GLUED;
2014 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row)));
2015 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col)));
2016 theErrors.push_back(anErr);
2017 } else if (aRel == REL_COLLISION_VV ||
2018 aRel == REL_COLLISION_FF ||
2019 aRel == REL_COLLISION_EE ||
2020 aRel == REL_UNKNOWN) {
2021 // report connection error
2022 isCompOfBlocks = Standard_False;
2024 anErr.error = INVALID_CONNECTION;
2025 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row)));
2026 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col)));
2027 theErrors.push_back(anErr);
2034 // 3. Find largest set of connected (good connection or not glued) blocks
2035 TColStd_MapOfInteger aProcessedMap;
2036 TColStd_MapOfInteger aLargestSet;
2037 TColStd_MapOfInteger aCurrentSet;
2038 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2039 if (!aProcessedMap.Contains(ibl)) {
2040 aCurrentSet.Clear();
2041 FindConnected(ibl, aRelations, aProcessedMap, aCurrentSet);
2042 if (aCurrentSet.Extent() > aLargestSet.Extent()) {
2043 aLargestSet = aCurrentSet;
2048 // 4. Report all blocks, isolated from <aLargestSet>
2050 anErr.error = NOT_CONNECTED;
2051 Standard_Boolean hasIsolated = Standard_False;
2052 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2053 if (!aLargestSet.Contains(ibl)) {
2054 aProcessedMap.Clear();
2055 if (!HasAnyConnection(ibl, aLargestSet, aRelations, aProcessedMap)) {
2056 // report connection absence
2057 hasIsolated = Standard_True;
2058 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(ibl)));
2063 isCompOfBlocks = Standard_False;
2064 theErrors.push_back(anErr);
2068 return isCompOfBlocks;
2071 //=============================================================================
2075 //=============================================================================
2076 TCollection_AsciiString GEOMImpl_IBlocksOperations::PrintBCErrors
2077 (Handle(GEOM_Object) theCompound,
2078 const list<BCError>& theErrors)
2080 TCollection_AsciiString aDescr;
2082 list<BCError>::const_iterator errIt = theErrors.begin();
2084 for (; errIt != theErrors.end(); i++, errIt++) {
2085 BCError errStruct = *errIt;
2087 switch (errStruct.error) {
2089 aDescr += "\n\tNot a Blocks: ";
2092 aDescr += "\n\tHexahedral solids with degenerated and/or seam edges: ";
2094 case INVALID_CONNECTION:
2095 aDescr += "\n\tInvalid connection between two blocks: ";
2098 aDescr += "\n\tBlocks, not connected with main body: ";
2101 aDescr += "\n\tNot glued blocks: ";
2107 list<int> sshList = errStruct.incriminated;
2108 list<int>::iterator sshIt = sshList.begin();
2110 for (; sshIt != sshList.end(); jj++, sshIt++) {
2113 aDescr += TCollection_AsciiString(*sshIt);
2120 //=============================================================================
2122 * CheckCompoundOfBlocks
2124 //=============================================================================
2125 Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocks
2126 (Handle(GEOM_Object) theCompound,
2127 list<BCError>& theErrors)
2131 if (theCompound.IsNull()) return Standard_False;
2132 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2134 Standard_Boolean isCompOfBlocks = Standard_True;
2136 // Map sub-shapes and their indices
2137 TopTools_IndexedMapOfShape anIndices;
2138 TopExp::MapShapes(aBlockOrComp, anIndices);
2140 // 1. Separate blocks from non-blocks
2141 TopTools_ListOfShape NOT; // Not blocks
2142 TopTools_ListOfShape EXT; // Hexahedral solids, having degenerated and/or seam edges
2143 TopTools_ListOfShape BLO; // All blocks from the given compound
2144 AddBlocksFrom(aBlockOrComp, BLO, NOT, EXT);
2146 // Report non-blocks
2147 if (NOT.Extent() > 0) {
2148 isCompOfBlocks = Standard_False;
2150 anErr.error = NOT_BLOCK;
2151 TopTools_ListIteratorOfListOfShape it (NOT);
2152 for (; it.More(); it.Next()) {
2153 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
2155 theErrors.push_back(anErr);
2158 // Report solids, having degenerated and/or seam edges
2159 if (EXT.Extent() > 0) {
2160 isCompOfBlocks = Standard_False;
2162 anErr.error = EXTRA_EDGE;
2163 TopTools_ListIteratorOfListOfShape it (EXT);
2164 for (; it.More(); it.Next()) {
2165 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
2167 theErrors.push_back(anErr);
2170 Standard_Integer nbBlocks = BLO.Extent();
2171 if (nbBlocks == 0) {
2172 isCompOfBlocks = Standard_False;
2174 return isCompOfBlocks;
2176 if (nbBlocks == 1) {
2178 return isCompOfBlocks;
2181 // Prepare data for 2. and 3.
2182 TColStd_Array2OfInteger aRelations (1, nbBlocks, 1, nbBlocks);
2183 aRelations.Init(REL_NOT_CONNECTED);
2185 TopTools_IndexedMapOfShape mapBlocks;
2188 TopoDS_Compound aComp;
2189 BB.MakeCompound(aComp);
2191 TopTools_ListIteratorOfListOfShape BLOit (BLO);
2192 for (; BLOit.More(); BLOit.Next()) {
2193 mapBlocks.Add(BLOit.Value());
2194 BB.Add(aComp, BLOit.Value());
2197 // 2. Find glued blocks (having shared faces)
2198 TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
2199 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2200 (aComp, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
2202 Standard_Integer prevInd = 0, curInd = 0;
2203 Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
2204 for (; ind <= nbFaces; ind++) {
2205 const TopTools_ListOfShape& aGluedBlocks = mapFaceBlocks.FindFromIndex(ind);
2206 if (aGluedBlocks.Extent() > 1) { // Shared face found
2207 TopTools_ListIteratorOfListOfShape aGluedBlocksIt (aGluedBlocks);
2208 TopoDS_Shape prevBlock, curBlock;
2209 for (; aGluedBlocksIt.More(); aGluedBlocksIt.Next()) {
2210 curBlock = aGluedBlocksIt.Value();
2211 if (!prevBlock.IsNull()) {
2212 prevInd = mapBlocks.FindIndex(prevBlock);
2213 curInd = mapBlocks.FindIndex(curBlock);
2214 aRelations.SetValue(prevInd, curInd, REL_OK);
2215 aRelations.SetValue(curInd, prevInd, REL_OK);
2217 prevBlock = curBlock;
2222 // 3. Find not glued blocks
2223 GEOMAlgo_GlueAnalyser aGD;
2225 aGD.SetShape(aComp);
2226 aGD.SetTolerance(Precision::Confusion());
2227 aGD.SetCheckGeometry(Standard_True);
2230 Standard_Integer iErr, iWrn;
2231 iErr = aGD.ErrorStatus();
2233 SetErrorCode("Error in GEOMAlgo_GlueAnalyser");
2234 return isCompOfBlocks;
2236 iWrn = aGD.WarningStatus();
2238 MESSAGE("Warning in GEOMAlgo_GlueAnalyser");
2241 // Report not glued blocks
2242 if (aGD.HasSolidsToGlue()) {
2243 isCompOfBlocks = Standard_False;
2244 Standard_Integer aSx1Ind, aSx2Ind;
2246 const GEOMAlgo_ListOfCoupleOfShapes& aLCS = aGD.SolidsToGlue();
2247 GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS (aLCS);
2248 for (; aItCS.More(); aItCS.Next()) {
2249 const GEOMAlgo_CoupleOfShapes& aCS = aItCS.Value();
2250 const TopoDS_Shape& aSx1 = aCS.Shape1();
2251 const TopoDS_Shape& aSx2 = aCS.Shape2();
2253 aSx1Ind = mapBlocks.FindIndex(aSx1);
2254 aSx2Ind = mapBlocks.FindIndex(aSx2);
2255 aRelations.SetValue(aSx1Ind, aSx2Ind, NOT_GLUED);
2256 aRelations.SetValue(aSx2Ind, aSx1Ind, NOT_GLUED);
2259 anErr.error = NOT_GLUED;
2260 anErr.incriminated.push_back(anIndices.FindIndex(aSx1));
2261 anErr.incriminated.push_back(anIndices.FindIndex(aSx2));
2262 theErrors.push_back(anErr);
2266 // 4. Find largest set of connected (good connection or not glued) blocks
2267 Standard_Integer ibl = 1;
2268 TColStd_MapOfInteger aProcessedMap;
2269 TColStd_MapOfInteger aLargestSet;
2270 TColStd_MapOfInteger aCurrentSet;
2271 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2272 if (!aProcessedMap.Contains(ibl)) {
2273 aCurrentSet.Clear();
2274 FindConnected(ibl, aRelations, aProcessedMap, aCurrentSet);
2275 if (aCurrentSet.Extent() > aLargestSet.Extent()) {
2276 aLargestSet = aCurrentSet;
2281 // 5. Report all blocks, isolated from <aLargestSet>
2283 anErr.error = NOT_CONNECTED;
2284 Standard_Boolean hasIsolated = Standard_False;
2285 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2286 if (!aLargestSet.Contains(ibl)) {
2287 aProcessedMap.Clear();
2288 if (!HasAnyConnection(ibl, aLargestSet, aRelations, aProcessedMap)) {
2289 // report connection absence
2290 hasIsolated = Standard_True;
2291 anErr.incriminated.push_back(anIndices.FindIndex(mapBlocks.FindKey(ibl)));
2296 isCompOfBlocks = Standard_False;
2297 theErrors.push_back(anErr);
2301 return isCompOfBlocks;
2304 //=============================================================================
2308 //=============================================================================
2309 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::RemoveExtraEdges
2310 (Handle(GEOM_Object) theObject)
2314 if (theObject.IsNull()) return NULL;
2316 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2317 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be fixed
2319 //Add a new Copy object
2320 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2323 Handle(GEOM_Function) aFunction =
2324 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_REMOVE_EXTRA);
2326 //Check if the function is set correctly
2327 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2329 GEOMImpl_IBlockTrsf aTI (aFunction);
2330 aTI.SetOriginal(aLastFunction);
2332 //Compute the fixed shape
2334 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
2337 if (!GetSolver()->ComputeFunction(aFunction)) {
2338 SetErrorCode("Block driver failed to remove extra edges of the given shape");
2342 catch (Standard_Failure) {
2343 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2344 SetErrorCode(aFail->GetMessageString());
2348 //Make a Python command
2349 GEOM::TPythonDump(aFunction) << aCopy
2350 << " = geompy.RemoveExtraEdges(" << theObject << ")";
2356 //=============================================================================
2360 //=============================================================================
2361 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::CheckAndImprove
2362 (Handle(GEOM_Object) theObject)
2366 if (theObject.IsNull()) return NULL;
2368 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2369 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be fixed
2371 //Add a new Copy object
2372 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2375 Handle(GEOM_Function) aFunction =
2376 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_COMPOUND_IMPROVE);
2378 //Check if the function is set correctly
2379 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2381 GEOMImpl_IBlockTrsf aTI (aFunction);
2382 aTI.SetOriginal(aLastFunction);
2384 //Compute the fixed shape
2386 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
2389 if (!GetSolver()->ComputeFunction(aFunction)) {
2390 SetErrorCode("Block driver failed to improve the given blocks compound");
2394 catch (Standard_Failure) {
2395 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2396 SetErrorCode(aFail->GetMessageString());
2400 //Make a Python command
2401 GEOM::TPythonDump(aFunction) << aCopy
2402 << " = geompy.CheckAndImprove(" << theObject << ")";
2408 //=============================================================================
2410 * ExplodeCompoundOfBlocks
2412 //=============================================================================
2413 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::ExplodeCompoundOfBlocks
2414 (Handle(GEOM_Object) theCompound,
2415 const Standard_Integer theMinNbFaces,
2416 const Standard_Integer theMaxNbFaces)
2420 if (theCompound.IsNull()) return NULL;
2421 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2422 if (aBlockOrComp.IsNull()) return NULL;
2424 Handle(TColStd_HSequenceOfTransient) aBlocks = new TColStd_HSequenceOfTransient;
2425 Handle(GEOM_Object) anObj;
2426 Handle(GEOM_Function) aFunction;
2428 TopTools_MapOfShape mapShape;
2429 TCollection_AsciiString anAsciiList, anEntry;
2432 TopTools_IndexedMapOfShape anIndices;
2433 TopExp::MapShapes(aBlockOrComp, anIndices);
2434 Handle(TColStd_HArray1OfInteger) anArray;
2438 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
2441 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2442 for (; exp.More(); exp.Next()) {
2443 if (mapShape.Add(exp.Current())) {
2444 TopoDS_Shape aSolid = exp.Current();
2446 TopTools_MapOfShape mapFaces;
2447 TopExp_Explorer expF (aSolid, TopAbs_FACE);
2448 Standard_Integer nbFaces = 0;
2449 for (; expF.More(); expF.Next()) {
2450 if (mapFaces.Add(expF.Current())) {
2455 if (theMinNbFaces <= nbFaces && nbFaces <= theMaxNbFaces) {
2456 anArray = new TColStd_HArray1OfInteger(1,1);
2457 anArray->SetValue(1, anIndices.FindIndex(aSolid));
2458 anObj = GetEngine()->AddSubShape(theCompound, anArray);
2459 aBlocks->Append(anObj);
2461 //Make a Python command
2462 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2463 anAsciiList += anEntry + ", ";
2468 catch (Standard_Failure) {
2469 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2470 SetErrorCode(aFail->GetMessageString());
2474 if (aBlocks->IsEmpty()) {
2475 SetErrorCode("There are no specified blocks in the given shape");
2479 anAsciiList.Trunc(anAsciiList.Length() - 2);
2481 //The explode doesn't change object so no new function is required.
2482 aFunction = theCompound->GetLastFunction();
2484 //Make a Python command
2485 GEOM::TPythonDump(aFunction, /*append=*/true)
2486 << "[" << anAsciiList.ToCString() << "] = geompy.MakeBlockExplode("
2487 << theCompound << ", " << theMinNbFaces << ", " << theMaxNbFaces << ")";
2493 //=============================================================================
2497 //=============================================================================
2498 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetBlockNearPoint
2499 (Handle(GEOM_Object) theCompound,
2500 Handle(GEOM_Object) thePoint)
2505 Handle(GEOM_Object) aResult;
2508 if (theCompound.IsNull() || thePoint.IsNull()) return NULL;
2510 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2511 if (aBlockOrComp.IsNull()) {
2512 SetErrorCode("Compound is null");
2515 if (aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
2516 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
2517 SetErrorCode("Shape to find block in is not a compound");
2521 TopoDS_Shape anArg = thePoint->GetValue();
2522 if (anArg.IsNull()) {
2523 SetErrorCode("Point is null");
2526 if (anArg.ShapeType() != TopAbs_VERTEX) {
2527 SetErrorCode("Shape for block identification is not a vertex");
2531 //Compute the Block value
2533 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
2536 TopoDS_Shape aShape;
2538 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
2539 gp_Pnt aPnt = BRep_Tool::Pnt(aVert);
2540 Standard_Real PX, PY, PZ;
2541 aPnt.Coord(PX, PY, PZ);
2543 // 1. Classify the point relatively each block
2544 Standard_Integer nearest = 2, nbFound = 0;
2545 TopTools_DataMapOfShapeInteger mapShapeDist;
2546 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2547 for (; exp.More(); exp.Next()) {
2548 TopoDS_Shape aSolid = exp.Current();
2550 if (!mapShapeDist.IsBound(aSolid)) {
2551 Standard_Integer aDistance = 2;
2553 // 1.a. Classify relatively Bounding box
2554 Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
2556 BRepBndLib::Add(aSolid, BB);
2557 BB.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
2558 if (PX < Xmin || Xmax < PX ||
2559 PY < Ymin || Ymax < PY ||
2560 PZ < Zmin || Zmax < PZ) {
2561 // OUT of bounding box
2564 // 1.b. Classify relatively the solid itself
2565 BRepClass3d_SolidClassifier SC (aSolid, aPnt, Precision::Confusion());
2566 if (SC.State() == TopAbs_IN) {
2568 } else if (SC.State() == TopAbs_ON) {
2575 if (aDistance < nearest) {
2576 nearest = aDistance;
2580 // A first found block, containing the point inside, will be returned.
2581 // It is the solution, if there are no intersecting blocks in the compound.
2582 if (nearest == -1) break;
2584 } else if (aDistance == nearest) {
2589 mapShapeDist.Bind(aSolid, aDistance);
2590 } // if (!mapShapeDist.IsBound(aSolid))
2593 // 2. Define block, containing the point or having minimum distance to it
2596 // The point is on boundary of some blocks and there are
2597 // no blocks, having the point inside their volume
2598 SetErrorCode("Multiple blocks near the given point are found");
2601 } else if (nearest == 1) {
2602 // The point is outside some blocks and there are
2603 // no blocks, having the point inside or on boundary.
2604 // We will get a nearest block
2605 Standard_Real minDist = RealLast();
2606 TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
2607 for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
2608 if (mapShapeDistIter.Value() == 1) {
2609 TopoDS_Shape aSolid = mapShapeDistIter.Key();
2610 BRepExtrema_DistShapeShape aDistTool (aVert, aSolid);
2611 if (!aDistTool.IsDone()) {
2612 SetErrorCode("Can not find a distance from the given point to one of blocks");
2615 Standard_Real aDist = aDistTool.Value();
2616 if (aDist < minDist) {
2622 } else { // nearest == -1
2623 // // The point is inside some blocks.
2624 // // We will get a block with nearest center
2625 // Standard_Real minDist = RealLast();
2626 // TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
2627 // for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
2628 // if (mapShapeDistIter.Value() == -1) {
2629 // TopoDS_Shape aSolid = mapShapeDistIter.Key();
2630 // GProp_GProps aSystem;
2631 // BRepGProp::VolumeProperties(aSolid, aSystem);
2632 // gp_Pnt aCenterMass = aSystem.CentreOfMass();
2634 // Standard_Real aDist = aCenterMass.Distance(aPnt);
2635 // if (aDist < minDist) {
2642 } // if (nbFound > 1)
2645 SetErrorCode("There are no blocks near the given point");
2648 TopTools_IndexedMapOfShape anIndices;
2649 TopExp::MapShapes(aBlockOrComp, anIndices);
2650 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2651 anArray->SetValue(1, anIndices.FindIndex(aShape));
2652 aResult = GetEngine()->AddSubShape(theCompound, anArray);
2655 catch (Standard_Failure) {
2656 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2657 SetErrorCode(aFail->GetMessageString());
2661 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
2663 //Make a Python command
2664 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetBlockNearPoint("
2665 << theCompound << ", " << thePoint << ")";
2671 //=============================================================================
2675 //=============================================================================
2676 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetBlockByParts
2677 (Handle(GEOM_Object) theCompound,
2678 const Handle(TColStd_HSequenceOfTransient)& theParts)
2682 Handle(GEOM_Object) aResult;
2684 if (theCompound.IsNull() || theParts.IsNull()) return NULL;
2685 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2686 if (aBlockOrComp.IsNull()) return NULL;
2689 Standard_Integer argi, aLen = theParts->Length();
2690 TopTools_Array1OfShape anArgs (1, aLen);
2691 TCollection_AsciiString anEntry, aPartsDescr;
2692 for (argi = 1; argi <= aLen; argi++) {
2693 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theParts->Value(argi));
2694 Handle(GEOM_Function) aRef = anObj->GetLastFunction();
2695 if (aRef.IsNull()) return NULL;
2697 TopoDS_Shape anArg = aRef->GetValue();
2698 if (anArg.IsNull()) {
2699 SetErrorCode("Null shape is given as argument");
2702 anArgs(argi) = anArg;
2704 // For Python command
2705 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2706 if (argi > 1) aPartsDescr += ", ";
2707 aPartsDescr += anEntry;
2710 //Compute the Block value
2712 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
2715 // 1. Explode compound on solids
2716 TopTools_MapOfShape mapShape;
2717 Standard_Integer nbSolids = 0;
2718 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2719 for (; exp.More(); exp.Next()) {
2720 if (mapShape.Add(exp.Current())) {
2726 Standard_Integer ind = 1;
2727 TopTools_Array1OfShape aSolids (1, nbSolids);
2728 TColStd_Array1OfInteger aNbParts (1, nbSolids);
2729 for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next(), ind++) {
2730 if (mapShape.Add(exp.Current())) {
2731 TopoDS_Shape aSolid = exp.Current();
2732 aSolids(ind) = aSolid;
2735 // 2. Define quantity of parts, contained in each solid
2736 TopTools_IndexedMapOfShape aSubShapes;
2737 TopExp::MapShapes(aSolid, aSubShapes);
2738 for (argi = 1; argi <= aLen; argi++) {
2739 if (aSubShapes.Contains(anArgs(argi))) {
2746 // 3. Define solid, containing maximum quantity of parts
2747 Standard_Integer maxNb = 0, nbFound = 0;
2748 TopoDS_Shape aShape;
2749 for (ind = 1; ind <= nbSolids; ind++) {
2750 if (aNbParts(ind) > maxNb) {
2751 maxNb = aNbParts(ind);
2752 aShape = aSolids(ind);
2754 } else if (aNbParts(ind) == maxNb) {
2760 SetErrorCode("Multiple blocks, containing maximum quantity of the given parts, are found");
2762 } else if (nbFound == 0) {
2763 SetErrorCode("There are no blocks, containing the given parts");
2766 TopTools_IndexedMapOfShape anIndices;
2767 TopExp::MapShapes(aBlockOrComp, anIndices);
2768 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2769 anArray->SetValue(1, anIndices.FindIndex(aShape));
2770 aResult = GetEngine()->AddSubShape(theCompound, anArray);
2772 } catch (Standard_Failure) {
2773 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2774 SetErrorCode(aFail->GetMessageString());
2778 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
2780 //Make a Python command
2781 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetBlockByParts("
2782 << theCompound << ", [" << aPartsDescr.ToCString() << "])";
2788 //=============================================================================
2792 //=============================================================================
2793 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::GetBlocksByParts
2794 (Handle(GEOM_Object) theCompound,
2795 const Handle(TColStd_HSequenceOfTransient)& theParts)
2799 if (theCompound.IsNull() || theParts.IsNull()) return NULL;
2800 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2801 if (aBlockOrComp.IsNull()) return NULL;
2803 Handle(TColStd_HSequenceOfTransient) aBlocks = new TColStd_HSequenceOfTransient;
2804 Handle(GEOM_Object) anObj;
2805 Handle(GEOM_Function) aFunction;
2808 Standard_Integer argi, aLen = theParts->Length();
2809 TopTools_Array1OfShape anArgs (1, aLen);
2810 TCollection_AsciiString anEntry, aPartsDescr, anAsciiList;
2812 for (argi = 1; argi <= aLen; argi++) {
2813 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theParts->Value(argi));
2814 Handle(GEOM_Function) aRef = anObj->GetLastFunction();
2815 if (aRef.IsNull()) return NULL;
2817 TopoDS_Shape anArg = aRef->GetValue();
2818 if (anArg.IsNull()) {
2819 SetErrorCode("Null shape is given as argument");
2822 anArgs(argi) = anArg;
2824 // For Python command
2825 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2826 aPartsDescr += anEntry + ", ";
2831 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
2834 TopTools_MapOfShape mapShape;
2835 Standard_Integer nbSolids = 0;
2836 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2837 for (; exp.More(); exp.Next()) {
2838 if (mapShape.Add(exp.Current())) {
2844 Standard_Integer ind = 1;
2845 TopTools_Array1OfShape aSolids (1, nbSolids);
2846 TColStd_Array1OfInteger aNbParts (1, nbSolids);
2847 for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next(), ind++) {
2848 if (mapShape.Add(exp.Current())) {
2849 TopoDS_Shape aSolid = exp.Current();
2850 aSolids(ind) = aSolid;
2853 // 2. Define quantity of parts, contained in each solid
2854 TopTools_IndexedMapOfShape aSubShapes;
2855 TopExp::MapShapes(aSolid, aSubShapes);
2856 for (argi = 1; argi <= aLen; argi++) {
2857 if (aSubShapes.Contains(anArgs(argi))) {
2864 // 3. Define solid, containing maximum quantity of parts
2865 Standard_Integer maxNb = 0, nbFound = 0;
2866 for (ind = 1; ind <= nbSolids; ind++) {
2867 if (aNbParts(ind) > maxNb) {
2868 maxNb = aNbParts(ind);
2870 } else if (aNbParts(ind) == maxNb) {
2876 SetErrorCode("There are no blocks, containing the given parts");
2881 TopTools_IndexedMapOfShape anIndices;
2882 TopExp::MapShapes(aBlockOrComp, anIndices);
2883 Handle(TColStd_HArray1OfInteger) anArray;
2885 for (ind = 1; ind <= nbSolids; ind++) {
2886 if (aNbParts(ind) == maxNb) {
2887 anArray = new TColStd_HArray1OfInteger(1,1);
2888 anArray->SetValue(1, anIndices.FindIndex(aSolids(ind)));
2889 anObj = GetEngine()->AddSubShape(theCompound, anArray);
2890 aBlocks->Append(anObj);
2892 // For Python command
2893 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2894 anAsciiList += anEntry + ", ";
2895 if (aFunction.IsNull())
2896 aFunction = anObj->GetLastFunction();
2900 catch (Standard_Failure) {
2901 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2902 SetErrorCode(aFail->GetMessageString());
2906 //Make a Python command
2907 aPartsDescr.Trunc(aPartsDescr.Length() - 2);
2908 anAsciiList.Trunc(anAsciiList.Length() - 2);
2910 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2911 << "] = geompy.GetBlocksByParts(" << theCompound
2912 << ", [" << aPartsDescr.ToCString() << "])";
2918 //=============================================================================
2920 * MakeMultiTransformation1D
2922 //=============================================================================
2923 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeMultiTransformation1D
2924 (Handle(GEOM_Object) theObject,
2925 const Standard_Integer theDirFace1,
2926 const Standard_Integer theDirFace2,
2927 const Standard_Integer theNbTimes)
2931 if (theObject.IsNull()) return NULL;
2933 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2934 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be moved
2936 //Add a new Copy object
2937 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2939 //Add a translate function
2940 Handle(GEOM_Function) aFunction =
2941 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_MULTI_TRANSFORM_1D);
2943 //Check if the function is set correctly
2944 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2946 GEOMImpl_IBlockTrsf aTI (aFunction);
2947 aTI.SetOriginal(aLastFunction);
2948 aTI.SetFace1U(theDirFace1);
2949 aTI.SetFace2U(theDirFace2);
2950 aTI.SetNbIterU(theNbTimes);
2952 //Compute the transformation
2954 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
2957 if (!GetSolver()->ComputeFunction(aFunction)) {
2958 SetErrorCode("Block driver failed to make multi-transformation");
2962 catch (Standard_Failure) {
2963 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2964 SetErrorCode(aFail->GetMessageString());
2968 //Make a Python command
2969 GEOM::TPythonDump(aFunction) << aCopy << " = geompy.MakeMultiTransformation1D("
2970 << theObject << ", " << theDirFace1 << ", " << theDirFace2 << ", " << theNbTimes << ")";
2976 //=============================================================================
2978 * MakeMultiTransformation2D
2980 //=============================================================================
2981 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeMultiTransformation2D
2982 (Handle(GEOM_Object) theObject,
2983 const Standard_Integer theDirFace1U,
2984 const Standard_Integer theDirFace2U,
2985 const Standard_Integer theNbTimesU,
2986 const Standard_Integer theDirFace1V,
2987 const Standard_Integer theDirFace2V,
2988 const Standard_Integer theNbTimesV)
2992 if (theObject.IsNull()) return NULL;
2994 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2995 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be moved
2997 //Add a new Copy object
2998 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
3000 //Add a translate function
3001 Handle(GEOM_Function) aFunction =
3002 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_MULTI_TRANSFORM_2D);
3004 //Check if the function is set correctly
3005 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
3007 GEOMImpl_IBlockTrsf aTI (aFunction);
3008 aTI.SetOriginal(aLastFunction);
3009 aTI.SetFace1U(theDirFace1U);
3010 aTI.SetFace2U(theDirFace2U);
3011 aTI.SetNbIterU(theNbTimesU);
3012 aTI.SetFace1V(theDirFace1V);
3013 aTI.SetFace2V(theDirFace2V);
3014 aTI.SetNbIterV(theNbTimesV);
3016 //Compute the transformation
3018 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
3021 if (!GetSolver()->ComputeFunction(aFunction)) {
3022 SetErrorCode("Block driver failed to make multi-transformation");
3026 catch (Standard_Failure) {
3027 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3028 SetErrorCode(aFail->GetMessageString());
3032 //Make a Python command
3033 GEOM::TPythonDump(aFunction) << aCopy << " = geompy.MakeMultiTransformation2D("
3034 << theObject << ", " << theDirFace1U << ", " << theDirFace2U << ", " << theNbTimesU
3035 << ", " << theDirFace1V << ", " << theDirFace2V << ", " << theNbTimesV << ")";
3041 //=============================================================================
3045 //=============================================================================
3046 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::Propagate
3047 (Handle(GEOM_Object) theShape)
3051 if (theShape.IsNull()) return NULL;
3053 TopoDS_Shape aShape = theShape->GetValue();
3054 if (aShape.IsNull()) return NULL;
3056 TopTools_IndexedMapOfShape anIndices;
3057 TopExp::MapShapes(aShape, anIndices);
3059 TopTools_IndexedDataMapOfShapeListOfShape MEW;
3060 GEOMImpl_Block6Explorer::MapShapesAndAncestors
3061 (aShape, TopAbs_EDGE, TopAbs_WIRE, MEW);
3062 Standard_Integer ie, nbEdges = MEW.Extent();
3065 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
3067 TopTools_MapOfShape mapAcceptedEdges;
3068 TCollection_AsciiString aListRes, anEntry;
3070 for (ie = 1; ie <= nbEdges; ie++) {
3071 TopoDS_Shape curE = MEW.FindKey(ie);
3073 if (mapAcceptedEdges.Contains(curE)) continue;
3076 TopTools_ListOfShape currentChain;
3077 TopTools_ListOfShape listPrevEdges;
3079 currentChain.Append(curE);
3080 listPrevEdges.Append(curE);
3081 mapAcceptedEdges.Add(curE);
3083 // Collect all edges pass by pass
3084 while (listPrevEdges.Extent() > 0) {
3085 // List of edges, added to chain on this cycle pass
3086 TopTools_ListOfShape listCurEdges;
3088 // Find the next portion of edges
3089 TopTools_ListIteratorOfListOfShape itE (listPrevEdges);
3090 for (; itE.More(); itE.Next()) {
3091 TopoDS_Shape anE = itE.Value();
3093 // Iterate on faces, having edge <anE>
3094 TopTools_ListIteratorOfListOfShape itW (MEW.FindFromKey(anE));
3095 for (; itW.More(); itW.Next()) {
3096 TopoDS_Shape aW = itW.Value();
3097 TopoDS_Shape anOppE;
3099 BRepTools_WireExplorer aWE (TopoDS::Wire(aW));
3100 Standard_Integer nb = 1, found = 0;
3101 TopTools_Array1OfShape anEdges (1,4);
3102 for (; aWE.More(); aWE.Next(), nb++) {
3107 anEdges(nb) = aWE.Current();
3108 if (anEdges(nb).IsSame(anE)) found = nb;
3111 if (nb == 5 && found > 0) {
3112 // Quadrangle face found, get an opposite edge
3113 Standard_Integer opp = found + 2;
3114 if (opp > 4) opp -= 4;
3115 anOppE = anEdges(opp);
3117 if (!mapAcceptedEdges.Contains(anOppE)) {
3118 // Add found edge to the chain
3119 currentChain.Append(anOppE);
3120 listCurEdges.Append(anOppE);
3121 mapAcceptedEdges.Add(anOppE);
3123 } // if (nb == 5 && found > 0)
3124 } // for (; itF.More(); itF.Next())
3125 } // for (; itE.More(); itE.Next())
3127 listPrevEdges = listCurEdges;
3128 } // while (listPrevEdges.Extent() > 0)
3130 // Store the chain in the document
3131 Handle(TColStd_HArray1OfInteger) anArray =
3132 new TColStd_HArray1OfInteger (1, currentChain.Extent());
3134 // Fill array of sub-shape indices
3135 TopTools_ListIteratorOfListOfShape itSub (currentChain);
3136 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
3137 int id = anIndices.FindIndex(itSub.Value());
3138 anArray->SetValue(index, id);
3141 // Add a new group object
3142 Handle(GEOM_Object) aChain = GetEngine()->AddSubShape(theShape, anArray);
3145 aChain->SetType(GEOM_GROUP);
3147 // Set a sub shape type
3148 TDF_Label aFreeLabel = aChain->GetFreeLabel();
3149 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)TopAbs_EDGE);
3151 // Add the chain to the result
3152 aSeq->Append(aChain);
3154 //Make a Python command
3155 TDF_Tool::Entry(aChain->GetEntry(), anEntry);
3156 aListRes += anEntry + ", ";
3159 if (aSeq->IsEmpty()) {
3160 SetErrorCode("There are no quadrangle faces in the shape");
3164 aListRes.Trunc(aListRes.Length() - 2);
3166 // The Propagation doesn't change object so no new function is required.
3167 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
3169 // Make a Python command
3170 GEOM::TPythonDump(aFunction, /*append=*/true)
3171 << "[" << aListRes.ToCString() << "] = geompy.Propagate(" << theShape << ")";