1 // Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 #pragma warning( disable:4786 )
26 #include <Standard_Stream.hxx>
28 #include <GEOMImpl_IBlocksOperations.hxx>
30 #include <GEOMImpl_Types.hxx>
32 #include <GEOMImpl_BlockDriver.hxx>
33 #include <GEOMImpl_IBlocks.hxx>
34 #include <GEOMImpl_IBlockTrsf.hxx>
35 #include <GEOMImpl_CopyDriver.hxx>
36 #include <GEOMImpl_Block6Explorer.hxx>
37 #include <GEOMImpl_IShapesOperations.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 <Basics_OCCTVersion.hxx>
50 #include "utilities.h"
52 #include <Utils_ExceptHandlers.hxx>
54 #include <TFunction_DriverTable.hxx>
55 #include <TFunction_Driver.hxx>
56 #include <TFunction_Logbook.hxx>
57 #include <TDataStd_Integer.hxx>
58 #include <TDF_Tool.hxx>
60 #include <BRep_Tool.hxx>
61 #include <BRep_Builder.hxx>
62 #include <BRepTools.hxx>
63 #include <BRepTools_WireExplorer.hxx>
64 #include <BRepGProp.hxx>
65 #include <BRepBndLib.hxx>
66 #include <BRepAdaptor_Surface.hxx>
67 #include <BRepClass_FaceClassifier.hxx>
68 #include <BRepClass3d_SolidClassifier.hxx>
69 #include <BRepExtrema_DistShapeShape.hxx>
73 #include <TopoDS_Edge.hxx>
74 #include <TopoDS_Vertex.hxx>
75 #include <TopoDS_Compound.hxx>
76 #include <TopoDS_Iterator.hxx>
78 #include <TopExp_Explorer.hxx>
79 #include <TopTools_MapOfShape.hxx>
80 #include <TopTools_Array1OfShape.hxx>
81 #include <TopTools_IndexedMapOfShape.hxx>
82 #include <TopTools_DataMapOfShapeInteger.hxx>
83 #include <TopTools_ListIteratorOfListOfShape.hxx>
84 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
85 #include <TopTools_DataMapIteratorOfDataMapOfShapeInteger.hxx>
87 #include <Bnd_Box.hxx>
88 #include <GProp_GProps.hxx>
90 #include <Geom_Surface.hxx>
91 #include <ShapeAnalysis_Surface.hxx>
93 #include <TColStd_MapOfInteger.hxx>
94 #include <TColStd_Array1OfReal.hxx>
95 #include <TColStd_Array1OfInteger.hxx>
96 #include <TColStd_Array2OfInteger.hxx>
98 //#include <OSD_Timer.hxx>
100 #include <Precision.hxx>
102 #include <Standard_Failure.hxx>
103 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
105 //=============================================================================
109 //=============================================================================
110 GEOMImpl_IBlocksOperations::GEOMImpl_IBlocksOperations (GEOM_Engine* theEngine, int theDocID)
111 : GEOM_IOperations(theEngine, theDocID)
113 MESSAGE("GEOMImpl_IBlocksOperations::GEOMImpl_IBlocksOperations");
116 //=============================================================================
120 //=============================================================================
121 GEOMImpl_IBlocksOperations::~GEOMImpl_IBlocksOperations()
123 MESSAGE("GEOMImpl_IBlocksOperations::~GEOMImpl_IBlocksOperations");
127 //=============================================================================
131 //=============================================================================
132 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad
133 (Handle(GEOM_Object) theEdge1, Handle(GEOM_Object) theEdge2,
134 Handle(GEOM_Object) theEdge3, Handle(GEOM_Object) theEdge4)
138 if (theEdge1.IsNull() || theEdge2.IsNull() ||
139 theEdge3.IsNull() || theEdge4.IsNull()) return NULL;
141 //Add a new Face object
142 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
144 //Add a new Face function
145 Handle(GEOM_Function) aFunction =
146 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_FOUR_EDGES);
148 //Check if the function is set correctly
149 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
151 GEOMImpl_IBlocks aPI (aFunction);
153 Handle(GEOM_Function) aRef1 = theEdge1->GetLastFunction();
154 Handle(GEOM_Function) aRef2 = theEdge2->GetLastFunction();
155 Handle(GEOM_Function) aRef3 = theEdge3->GetLastFunction();
156 Handle(GEOM_Function) aRef4 = theEdge4->GetLastFunction();
157 if (aRef1.IsNull() || aRef2.IsNull() ||
158 aRef3.IsNull() || aRef4.IsNull()) return NULL;
160 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
161 aShapesSeq->Append(aRef1);
162 aShapesSeq->Append(aRef2);
163 aShapesSeq->Append(aRef3);
164 aShapesSeq->Append(aRef4);
166 aPI.SetShapes(aShapesSeq);
168 //Compute the Face value
170 #if OCC_VERSION_LARGE > 0x06010000
173 if (!GetSolver()->ComputeFunction(aFunction)) {
174 SetErrorCode("Block driver failed to compute a face");
178 catch (Standard_Failure) {
179 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
180 SetErrorCode(aFail->GetMessageString());
184 //Make a Python command
185 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeQuad("
186 << theEdge1 << ", " << theEdge2 << ", " << theEdge3 << ", " << theEdge4 << ")";
192 //=============================================================================
196 //=============================================================================
197 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad2Edges
198 (Handle(GEOM_Object) theEdge1, Handle(GEOM_Object) theEdge2)
202 if (theEdge1.IsNull() || theEdge2.IsNull()) return NULL;
204 //Add a new Face object
205 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
207 //Add a new Face function
208 Handle(GEOM_Function) aFunction =
209 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_TWO_EDGES);
211 //Check if the function is set correctly
212 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
214 GEOMImpl_IBlocks aPI (aFunction);
216 Handle(GEOM_Function) aRef1 = theEdge1->GetLastFunction();
217 Handle(GEOM_Function) aRef2 = theEdge2->GetLastFunction();
218 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
220 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
221 aShapesSeq->Append(aRef1);
222 aShapesSeq->Append(aRef2);
224 aPI.SetShapes(aShapesSeq);
226 //Compute the Face value
228 #if OCC_VERSION_LARGE > 0x06010000
231 if (!GetSolver()->ComputeFunction(aFunction)) {
232 SetErrorCode("Block driver failed to compute a face");
236 catch (Standard_Failure) {
237 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
238 SetErrorCode(aFail->GetMessageString());
242 //Make a Python command
243 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeQuad2Edges("
244 << theEdge1 << ", " << theEdge2 << ")";
250 //=============================================================================
254 //=============================================================================
255 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad4Vertices
256 (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2,
257 Handle(GEOM_Object) thePnt3, Handle(GEOM_Object) thePnt4)
261 if (thePnt1.IsNull() || thePnt2.IsNull() ||
262 thePnt3.IsNull() || thePnt4.IsNull()) return NULL;
264 //Add a new Face object
265 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
267 //Add a new Face function
268 Handle(GEOM_Function) aFunction =
269 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_FOUR_PNT);
271 //Check if the function is set correctly
272 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
274 GEOMImpl_IBlocks aPI (aFunction);
276 Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
277 Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
278 Handle(GEOM_Function) aRef3 = thePnt3->GetLastFunction();
279 Handle(GEOM_Function) aRef4 = thePnt4->GetLastFunction();
280 if (aRef1.IsNull() || aRef2.IsNull() ||
281 aRef3.IsNull() || aRef4.IsNull()) return NULL;
283 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
284 aShapesSeq->Append(aRef1);
285 aShapesSeq->Append(aRef2);
286 aShapesSeq->Append(aRef3);
287 aShapesSeq->Append(aRef4);
289 aPI.SetShapes(aShapesSeq);
291 //Compute the Face value
293 #if OCC_VERSION_LARGE > 0x06010000
296 if (!GetSolver()->ComputeFunction(aFunction)) {
297 SetErrorCode("Block driver failed to compute a face");
301 catch (Standard_Failure) {
302 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
303 SetErrorCode(aFail->GetMessageString());
307 //Make a Python command
308 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeQuad4Vertices("
309 << thePnt1 << ", " << thePnt2 << ", " << thePnt3 << ", " << thePnt4 << ")";
315 //=============================================================================
319 //=============================================================================
320 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeHexa
321 (Handle(GEOM_Object) theFace1, Handle(GEOM_Object) theFace2,
322 Handle(GEOM_Object) theFace3, Handle(GEOM_Object) theFace4,
323 Handle(GEOM_Object) theFace5, Handle(GEOM_Object) theFace6)
327 if (theFace1.IsNull() || theFace2.IsNull() ||
328 theFace3.IsNull() || theFace4.IsNull() ||
329 theFace5.IsNull() || theFace6.IsNull()) return NULL;
331 //Add a new Solid object
332 Handle(GEOM_Object) aBlock = GetEngine()->AddObject(GetDocID(), GEOM_BLOCK);
334 //Add a new Block function
335 Handle(GEOM_Function) aFunction =
336 aBlock->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_SIX_FACES);
338 //Check if the function is set correctly
339 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
341 GEOMImpl_IBlocks aPI (aFunction);
343 Handle(GEOM_Function) aRef1 = theFace1->GetLastFunction();
344 Handle(GEOM_Function) aRef2 = theFace2->GetLastFunction();
345 Handle(GEOM_Function) aRef3 = theFace3->GetLastFunction();
346 Handle(GEOM_Function) aRef4 = theFace4->GetLastFunction();
347 Handle(GEOM_Function) aRef5 = theFace5->GetLastFunction();
348 Handle(GEOM_Function) aRef6 = theFace6->GetLastFunction();
349 if (aRef1.IsNull() || aRef2.IsNull() ||
350 aRef3.IsNull() || aRef4.IsNull() ||
351 aRef5.IsNull() || aRef6.IsNull()) return NULL;
353 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
354 aShapesSeq->Append(aRef1);
355 aShapesSeq->Append(aRef2);
356 aShapesSeq->Append(aRef3);
357 aShapesSeq->Append(aRef4);
358 aShapesSeq->Append(aRef5);
359 aShapesSeq->Append(aRef6);
361 aPI.SetShapes(aShapesSeq);
363 //Compute the Block value
365 #if OCC_VERSION_LARGE > 0x06010000
368 if (!GetSolver()->ComputeFunction(aFunction)) {
369 SetErrorCode("Block driver failed to compute a block");
373 catch (Standard_Failure) {
374 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
375 SetErrorCode(aFail->GetMessageString());
379 //Make a Python command
380 GEOM::TPythonDump(aFunction) << aBlock << " = geompy.MakeHexa("
381 << theFace1 << ", " << theFace2 << ", " << theFace3 << ", "
382 << theFace4 << ", " << theFace5 << ", " << theFace6 << ")";
388 //=============================================================================
392 //=============================================================================
393 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeHexa2Faces
394 (Handle(GEOM_Object) theFace1, Handle(GEOM_Object) theFace2)
398 if (theFace1.IsNull() || theFace2.IsNull()) return NULL;
400 //Add a new Solid object
401 Handle(GEOM_Object) aBlock = GetEngine()->AddObject(GetDocID(), GEOM_BLOCK);
403 //Add a new Block function
404 Handle(GEOM_Function) aFunction =
405 aBlock->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_TWO_FACES);
407 //Check if the function is set correctly
408 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
410 GEOMImpl_IBlocks aPI (aFunction);
412 Handle(GEOM_Function) aRef1 = theFace1->GetLastFunction();
413 Handle(GEOM_Function) aRef2 = theFace2->GetLastFunction();
414 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
416 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
417 aShapesSeq->Append(aRef1);
418 aShapesSeq->Append(aRef2);
420 aPI.SetShapes(aShapesSeq);
422 //Compute the Block value
424 #if OCC_VERSION_LARGE > 0x06010000
427 if (!GetSolver()->ComputeFunction(aFunction)) {
428 SetErrorCode("Block driver failed to compute a block");
432 catch (Standard_Failure) {
433 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
434 SetErrorCode(aFail->GetMessageString());
438 //Make a Python command
439 GEOM::TPythonDump(aFunction) << aBlock << " = geompy.MakeHexa2Faces("
440 << theFace1 << ", " << theFace2 << ")";
446 //=============================================================================
450 //=============================================================================
451 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeBlockCompound
452 (Handle(GEOM_Object) theCompound)
456 if (theCompound.IsNull()) return NULL;
459 Handle(GEOM_Object) aBlockComp = GetEngine()->AddObject(GetDocID(), GEOM_COMPOUND);
461 //Add a new BlocksComp function
462 Handle(GEOM_Function) aFunction =
463 aBlockComp->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_COMPOUND_GLUE);
465 //Check if the function is set correctly
466 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
468 GEOMImpl_IBlocks aPI (aFunction);
470 Handle(GEOM_Function) aRef1 = theCompound->GetLastFunction();
471 if (aRef1.IsNull()) return NULL;
473 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
474 aShapesSeq->Append(aRef1);
476 aPI.SetShapes(aShapesSeq);
478 //Compute the Blocks Compound value
480 #if OCC_VERSION_LARGE > 0x06010000
483 if (!GetSolver()->ComputeFunction(aFunction)) {
484 SetErrorCode("Block driver failed to compute a blocks compound");
488 catch (Standard_Failure) {
489 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
490 SetErrorCode(aFail->GetMessageString());
494 //Make a Python command
495 GEOM::TPythonDump(aFunction) << aBlockComp
496 << " = geompy.MakeBlockCompound(" << theCompound << ")";
502 //=============================================================================
506 //=============================================================================
507 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetPoint
508 (Handle(GEOM_Object) theShape,
509 const Standard_Real theX,
510 const Standard_Real theY,
511 const Standard_Real theZ,
512 const Standard_Real theEpsilon)
517 Handle(GEOM_Object) aResult;
520 if (theShape.IsNull()) return NULL;
522 TopoDS_Shape aBlockOrComp = theShape->GetValue();
523 if (aBlockOrComp.IsNull()) {
524 SetErrorCode("Given shape is null");
528 //Compute the Vertex value
529 gp_Pnt P (theX, theY, theZ);
530 Standard_Real eps = Max(theEpsilon, Precision::Confusion());
533 Standard_Integer isFound = 0;
534 TopTools_MapOfShape mapShape;
535 TopExp_Explorer exp (aBlockOrComp, TopAbs_VERTEX);
537 for (; exp.More(); exp.Next()) {
538 if (mapShape.Add(exp.Current())) {
539 TopoDS_Vertex aVi = TopoDS::Vertex(exp.Current());
540 gp_Pnt aPi = BRep_Tool::Pnt(aVi);
541 if (aPi.Distance(P) < eps) {
549 SetErrorCode("Vertex has not been found");
551 } else if (isFound > 1) {
552 SetErrorCode("Multiple vertices found by the given coordinates and epsilon");
555 TopTools_IndexedMapOfShape anIndices;
556 TopExp::MapShapes(aBlockOrComp, anIndices);
557 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
558 anArray->SetValue(1, anIndices.FindIndex(V));
559 aResult = GetEngine()->AddSubShape(theShape, anArray);
562 //The GetPoint() doesn't change object so no new function is required.
563 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
565 //Make a Python command
566 GEOM::TPythonDump(aFunction, /*append=*/true)
567 << aResult << " = geompy.GetPoint(" << theShape << ", "
568 << theX << ", " << theY << ", " << theZ << ", " << theEpsilon << ")";
574 //=============================================================================
578 //=============================================================================
579 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetVertexNearPoint
580 (Handle(GEOM_Object) theShape,
581 Handle(GEOM_Object) thePoint)
586 Handle(GEOM_Object) aResult;
589 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
591 TopoDS_Shape aBlockOrComp = theShape->GetValue();
592 TopoDS_Shape aPoint = thePoint->GetValue();
593 if (aBlockOrComp.IsNull() || aPoint.IsNull()) {
594 SetErrorCode("Given shape is null");
598 if (aPoint.ShapeType() != TopAbs_VERTEX) {
599 SetErrorCode("Element for vertex identification is not a vertex");
603 TopoDS_Vertex aVert = TopoDS::Vertex(aPoint);
604 gp_Pnt aP = BRep_Tool::Pnt(aVert);
606 // Compute the Vertex value
608 bool isFound = false;
609 Standard_Real aDist = RealLast();
610 TopTools_MapOfShape mapShape;
612 TopExp_Explorer exp (aBlockOrComp, TopAbs_VERTEX);
613 for (; exp.More(); exp.Next()) {
614 if (mapShape.Add(exp.Current())) {
615 TopoDS_Vertex aVi = TopoDS::Vertex(exp.Current());
616 gp_Pnt aPi = BRep_Tool::Pnt(aVi);
617 Standard_Real aDisti = aPi.Distance(aP);
618 if (aDisti < aDist) {
627 SetErrorCode("Vertex has not been found");
631 TopTools_IndexedMapOfShape anIndices;
632 TopExp::MapShapes(aBlockOrComp, anIndices);
633 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
634 anArray->SetValue(1, anIndices.FindIndex(V));
635 aResult = GetEngine()->AddSubShape(theShape, anArray);
637 // The GetPoint() doesn't change object so no new function is required.
638 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
640 // Make a Python command
641 GEOM::TPythonDump(aFunction, /*append=*/true)
642 << aResult << " = geompy.GetVertexNearPoint("
643 << theShape << ", " << thePoint << ")";
649 //=============================================================================
653 //=============================================================================
654 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetEdge
655 (Handle(GEOM_Object) theShape,
656 Handle(GEOM_Object) thePoint1,
657 Handle(GEOM_Object) thePoint2)
662 Handle(GEOM_Object) aResult;
665 if (theShape.IsNull() || thePoint1.IsNull() || thePoint2.IsNull()) return NULL;
667 TopoDS_Shape aBlockOrComp = theShape->GetValue();
668 if (aBlockOrComp.IsNull()) {
669 SetErrorCode("Given shape is null");
673 TopoDS_Shape anArg1 = thePoint1->GetValue();
674 TopoDS_Shape anArg2 = thePoint2->GetValue();
675 if (anArg1.IsNull() || anArg2.IsNull()) {
676 SetErrorCode("Null shape is given as argument");
679 if (anArg1.ShapeType() != TopAbs_VERTEX ||
680 anArg2.ShapeType() != TopAbs_VERTEX) {
681 SetErrorCode("Element for edge identification is not a vertex");
685 //Compute the Edge value
687 #if OCC_VERSION_LARGE > 0x06010000
690 TopTools_IndexedDataMapOfShapeListOfShape MVE;
691 GEOMImpl_Block6Explorer::MapShapesAndAncestors
692 (aBlockOrComp, TopAbs_VERTEX, TopAbs_EDGE, MVE);
695 Standard_Integer ish, ext = MVE.Extent();
697 if (MVE.Contains(anArg1)) {
700 for (ish = 1; ish <= ext; ish++) {
701 TopoDS_Shape aShi = MVE.FindKey(ish);
702 if (BRepTools::Compare(TopoDS::Vertex(anArg1), TopoDS::Vertex(aShi))) {
709 if (MVE.Contains(anArg2)) {
712 for (ish = 1; ish <= ext; ish++) {
713 TopoDS_Shape aShi = MVE.FindKey(ish);
714 if (BRepTools::Compare(TopoDS::Vertex(anArg2), TopoDS::Vertex(aShi))) {
721 if (V1.IsNull() || V2.IsNull()) {
722 SetErrorCode("The given vertex does not belong to the shape");
727 Standard_Integer isFound =
728 GEOMImpl_Block6Explorer::FindEdge(anEdge, V1, V2, MVE, Standard_True);
730 SetErrorCode("The given vertices do not belong to one edge of the given shape");
732 } else if (isFound > 1) {
733 SetErrorCode("Multiple edges found by the given vertices of the shape");
736 TopTools_IndexedMapOfShape anIndices;
737 TopExp::MapShapes(aBlockOrComp, anIndices);
738 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
739 anArray->SetValue(1, anIndices.FindIndex(anEdge));
740 aResult = GetEngine()->AddSubShape(theShape, anArray);
742 } catch (Standard_Failure) {
743 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
744 SetErrorCode(aFail->GetMessageString());
748 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
750 //Make a Python command
751 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetEdge("
752 << theShape << ", " << thePoint1 << ", " << thePoint2 << ")";
758 //=============================================================================
762 //=============================================================================
763 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetEdgeNearPoint
764 (Handle(GEOM_Object) theShape,
765 Handle(GEOM_Object) thePoint)
770 Handle(GEOM_Object) aResult;
773 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
775 TopoDS_Shape aBlockOrComp = theShape->GetValue();
776 if (aBlockOrComp.IsNull()) {
777 SetErrorCode("Given shape is null");
781 TopoDS_Shape anArg = thePoint->GetValue();
782 if (anArg.IsNull()) {
783 SetErrorCode("Null shape is given as argument");
786 if (anArg.ShapeType() != TopAbs_VERTEX) {
787 SetErrorCode("Element for edge identification is not a vertex");
791 //Compute the Edge value
793 #if OCC_VERSION_LARGE > 0x06010000
798 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
800 // 1. Explode blocks on edges
801 TopTools_MapOfShape mapShape;
802 Standard_Integer nbEdges = 0;
803 TopExp_Explorer exp (aBlockOrComp, TopAbs_EDGE);
804 for (; exp.More(); exp.Next()) {
805 if (mapShape.Add(exp.Current())) {
811 SetErrorCode("Given shape contains no edges");
816 Standard_Integer ind = 1;
817 TopTools_Array1OfShape anEdges (1, nbEdges);
818 TColStd_Array1OfReal aDistances (1, nbEdges);
819 for (exp.Init(aBlockOrComp, TopAbs_EDGE); exp.More(); exp.Next()) {
820 if (mapShape.Add(exp.Current())) {
821 TopoDS_Shape anEdge = exp.Current();
822 anEdges(ind) = anEdge;
824 // 2. Classify the point relatively each edge
825 BRepExtrema_DistShapeShape aDistTool (aVert, anEdges(ind));
826 if (!aDistTool.IsDone()) {
827 SetErrorCode("Can not find a distance from the given point to one of edges");
830 aDistances(ind) = aDistTool.Value();
835 // 3. Define edge, having minimum distance to the point
836 Standard_Real nearest = RealLast(), nbFound = 0;
837 Standard_Real prec = Precision::Confusion();
838 for (ind = 1; ind <= nbEdges; ind++) {
839 if (Abs(aDistances(ind) - nearest) < prec) {
841 } else if (aDistances(ind) < nearest) {
842 nearest = aDistances(ind);
843 aShape = anEdges(ind);
849 SetErrorCode("Multiple edges near the given point are found");
851 } else if (nbFound == 0) {
852 SetErrorCode("There are no edges near the given point");
855 TopTools_IndexedMapOfShape anIndices;
856 TopExp::MapShapes(aBlockOrComp, anIndices);
857 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
858 anArray->SetValue(1, anIndices.FindIndex(aShape));
859 aResult = GetEngine()->AddSubShape(theShape, anArray);
862 catch (Standard_Failure) {
863 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
864 SetErrorCode(aFail->GetMessageString());
868 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
870 //Make a Python command
871 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetEdgeNearPoint("
872 << theShape << ", " << thePoint << ")";
878 //=============================================================================
882 //=============================================================================
883 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByPoints
884 (Handle(GEOM_Object) theShape,
885 Handle(GEOM_Object) thePoint1,
886 Handle(GEOM_Object) thePoint2,
887 Handle(GEOM_Object) thePoint3,
888 Handle(GEOM_Object) thePoint4)
893 Handle(GEOM_Object) aResult;
896 if (theShape.IsNull() ||
897 thePoint1.IsNull() || thePoint2.IsNull() ||
898 thePoint3.IsNull() || thePoint4.IsNull()) return NULL;
900 TopoDS_Shape aBlockOrComp = theShape->GetValue();
901 if (aBlockOrComp.IsNull()) {
902 SetErrorCode("Block or compound is null");
906 TopoDS_Shape anArg1 = thePoint1->GetValue();
907 TopoDS_Shape anArg2 = thePoint2->GetValue();
908 TopoDS_Shape anArg3 = thePoint3->GetValue();
909 TopoDS_Shape anArg4 = thePoint4->GetValue();
910 if (anArg1.IsNull() || anArg2.IsNull() ||
911 anArg3.IsNull() || anArg4.IsNull()) {
912 SetErrorCode("Null shape is given as argument");
915 if (anArg1.ShapeType() != TopAbs_VERTEX ||
916 anArg2.ShapeType() != TopAbs_VERTEX ||
917 anArg3.ShapeType() != TopAbs_VERTEX ||
918 anArg4.ShapeType() != TopAbs_VERTEX) {
919 SetErrorCode("Element for face identification is not a vertex");
923 //Compute the Face value
925 #if OCC_VERSION_LARGE > 0x06010000
930 TopTools_IndexedDataMapOfShapeListOfShape MVF;
931 GEOMImpl_Block6Explorer::MapShapesAndAncestors(aBlockOrComp, TopAbs_VERTEX, TopAbs_FACE, MVF);
933 TopoDS_Shape V1,V2,V3,V4;
934 Standard_Integer ish, ext = MVF.Extent();
936 if (MVF.Contains(anArg1)) {
939 for (ish = 1; ish <= ext; ish++) {
940 TopoDS_Shape aShi = MVF.FindKey(ish);
941 if (BRepTools::Compare(TopoDS::Vertex(anArg1), TopoDS::Vertex(aShi))) {
948 if (MVF.Contains(anArg2)) {
951 for (ish = 1; ish <= ext; ish++) {
952 TopoDS_Shape aShi = MVF.FindKey(ish);
953 if (BRepTools::Compare(TopoDS::Vertex(anArg2), TopoDS::Vertex(aShi))) {
960 if (MVF.Contains(anArg3)) {
963 for (ish = 1; ish <= ext; ish++) {
964 TopoDS_Shape aShi = MVF.FindKey(ish);
965 if (BRepTools::Compare(TopoDS::Vertex(anArg3), TopoDS::Vertex(aShi))) {
972 if (MVF.Contains(anArg4)) {
975 for (ish = 1; ish <= ext; ish++) {
976 TopoDS_Shape aShi = MVF.FindKey(ish);
977 if (BRepTools::Compare(TopoDS::Vertex(anArg4), TopoDS::Vertex(aShi))) {
984 if (V1.IsNull() || V2.IsNull() || V3.IsNull() || V4.IsNull()) {
985 SetErrorCode("The given vertex does not belong to the shape");
989 Standard_Integer isFound =
990 GEOMImpl_Block6Explorer::FindFace(aShape, V1, V2, V3, V4, MVF, Standard_True);
992 SetErrorCode("The given vertices do not belong to one face of the given shape");
994 } else if (isFound > 1) {
995 SetErrorCode("The given vertices belong to several faces of the given shape");
998 TopTools_IndexedMapOfShape anIndices;
999 TopExp::MapShapes(aBlockOrComp, anIndices);
1000 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1001 anArray->SetValue(1, anIndices.FindIndex(aShape));
1002 aResult = GetEngine()->AddSubShape(theShape, anArray);
1005 catch (Standard_Failure) {
1006 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1007 SetErrorCode(aFail->GetMessageString());
1011 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1013 //Make a Python command
1014 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByPoints("
1015 << theShape << ", " << thePoint1 << ", " << thePoint2
1016 << ", " << thePoint3 << ", " << thePoint4 << ")";
1022 //=============================================================================
1026 //=============================================================================
1027 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByEdges
1028 (Handle(GEOM_Object) theShape,
1029 Handle(GEOM_Object) theEdge1,
1030 Handle(GEOM_Object) theEdge2)
1035 Handle(GEOM_Object) aResult;
1038 if (theShape.IsNull() || theEdge1.IsNull() || theEdge2.IsNull()) return NULL;
1040 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1041 if (aBlockOrComp.IsNull()) {
1042 SetErrorCode("Block or compound is null");
1046 TopoDS_Shape anArg1 = theEdge1->GetValue();
1047 TopoDS_Shape anArg2 = theEdge2->GetValue();
1048 if (anArg1.IsNull() || anArg2.IsNull()) {
1049 SetErrorCode("Null shape is given as argument");
1052 if (anArg1.ShapeType() != TopAbs_EDGE ||
1053 anArg2.ShapeType() != TopAbs_EDGE) {
1054 SetErrorCode("Element for face identification is not an edge");
1058 //Compute the Face value
1060 #if OCC_VERSION_LARGE > 0x06010000
1063 TopoDS_Shape aShape;
1065 TopTools_IndexedDataMapOfShapeListOfShape MEF;
1066 GEOMImpl_Block6Explorer::MapShapesAndAncestors(aBlockOrComp, TopAbs_EDGE, TopAbs_FACE, MEF);
1069 Standard_Integer ish, ext = MEF.Extent();
1071 if (MEF.Contains(anArg1)) {
1074 for (ish = 1; ish <= ext; ish++) {
1075 TopoDS_Shape aShi = MEF.FindKey(ish);
1076 if (GEOMImpl_Block6Explorer::IsSimilarEdges(anArg1, aShi)) {
1082 if (MEF.Contains(anArg2)) {
1085 for (ish = 1; ish <= ext; ish++) {
1086 TopoDS_Shape aShi = MEF.FindKey(ish);
1087 if (GEOMImpl_Block6Explorer::IsSimilarEdges(anArg2, aShi)) {
1093 if (E1.IsNull() || E2.IsNull()) {
1094 SetErrorCode("The given edge does not belong to the shape");
1098 const TopTools_ListOfShape& aFacesOfE1 = MEF.FindFromKey(E1);
1099 const TopTools_ListOfShape& aFacesOfE2 = MEF.FindFromKey(E2);
1101 Standard_Integer isFound = 0;
1102 TopTools_ListIteratorOfListOfShape anIterF1 (aFacesOfE1);
1103 for (; anIterF1.More(); anIterF1.Next()) {
1105 TopTools_ListIteratorOfListOfShape anIterF2 (aFacesOfE2);
1106 for (; anIterF2.More(); anIterF2.Next()) {
1108 if (anIterF1.Value().IsSame(anIterF2.Value())) {
1111 // Store the face, defined by two edges
1112 aShape = anIterF1.Value();
1117 SetErrorCode("The given edges do not belong to one face of the given shape");
1119 } else if (isFound > 1) {
1120 SetErrorCode("The given edges belong to several faces of the given shape");
1123 TopTools_IndexedMapOfShape anIndices;
1124 TopExp::MapShapes(aBlockOrComp, anIndices);
1125 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1126 anArray->SetValue(1, anIndices.FindIndex(aShape));
1127 aResult = GetEngine()->AddSubShape(theShape, anArray);
1130 catch (Standard_Failure) {
1131 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1132 SetErrorCode(aFail->GetMessageString());
1136 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1138 //Make a Python command
1139 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByEdges("
1140 << theShape << ", " << theEdge1 << ", " << theEdge2 << ")";
1146 //=============================================================================
1150 //=============================================================================
1151 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetOppositeFace
1152 (Handle(GEOM_Object) theShape,
1153 Handle(GEOM_Object) theFace)
1158 Handle(GEOM_Object) aResult;
1161 if (theShape.IsNull() || theFace.IsNull()) return NULL;
1163 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1164 if (aBlockOrComp.IsNull()) {
1165 SetErrorCode("Block is null");
1168 if (aBlockOrComp.ShapeType() != TopAbs_SOLID) {
1169 SetErrorCode("Shape is not a block");
1173 TopoDS_Shape anArg = theFace->GetValue();
1174 if (anArg.IsNull()) {
1175 SetErrorCode("Null shape is given as argument");
1178 if (anArg.ShapeType() != TopAbs_FACE) {
1179 SetErrorCode("Element for face identification is not a face");
1183 //Compute the Face value
1185 #if OCC_VERSION_LARGE > 0x06010000
1188 TopoDS_Shape aShape;
1190 GEOMImpl_Block6Explorer aBlockTool;
1191 aBlockTool.InitByBlockAndFace(aBlockOrComp, anArg);
1192 aShape = aBlockTool.GetFace(2);
1194 TopTools_IndexedMapOfShape anIndices;
1195 TopExp::MapShapes(aBlockOrComp, anIndices);
1196 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1197 anArray->SetValue(1, anIndices.FindIndex(aShape));
1198 aResult = GetEngine()->AddSubShape(theShape, anArray);
1200 catch (Standard_Failure) {
1201 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1202 SetErrorCode(aFail->GetMessageString());
1206 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1208 //Make a Python command
1209 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetOppositeFace("
1210 << theShape << ", " << theFace << ")";
1216 //=============================================================================
1220 //=============================================================================
1221 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceNearPoint
1222 (Handle(GEOM_Object) theShape,
1223 Handle(GEOM_Object) thePoint)
1228 Handle(GEOM_Object) aResult;
1231 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
1233 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1234 if (aBlockOrComp.IsNull()) {
1235 SetErrorCode("Block or compound is null");
1239 TopoDS_Shape anArg = thePoint->GetValue();
1240 if (anArg.IsNull()) {
1241 SetErrorCode("Null shape is given as argument");
1244 if (anArg.ShapeType() != TopAbs_VERTEX) {
1245 SetErrorCode("Element for face identification is not a vertex");
1249 //Compute the Face value
1251 #if OCC_VERSION_LARGE > 0x06010000
1254 TopoDS_Shape aShape;
1256 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
1257 gp_Pnt aPnt = BRep_Tool::Pnt(aVert);
1258 Standard_Real PX, PY, PZ;
1259 aPnt.Coord(PX, PY, PZ);
1261 // 1. Classify the point relatively each face
1262 Standard_Integer nearest = 2, nbFound = 0;
1263 TopTools_DataMapOfShapeInteger mapShapeDist;
1264 TopExp_Explorer exp (aBlockOrComp, TopAbs_FACE);
1265 for (; exp.More(); exp.Next()) {
1266 TopoDS_Shape aFace = exp.Current();
1268 if (!mapShapeDist.IsBound(aFace)) {
1269 Standard_Integer aDistance = 2;
1271 // 1.a. Classify relatively Surface
1272 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aFace));
1273 Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf);
1274 gp_Pnt2d p2dOnSurf = aSurfAna->ValueOfUV(aPnt, Precision::Confusion());
1275 gp_Pnt p3dOnSurf = aSurfAna->Value(p2dOnSurf);
1276 Standard_Real aDist = p3dOnSurf.Distance(aPnt);
1277 if (aDist > Precision::Confusion()) {
1281 // 1.b. Classify relatively the face itself
1282 BRepClass_FaceClassifier FC (TopoDS::Face(aFace), p2dOnSurf, Precision::Confusion());
1283 if (FC.State() == TopAbs_IN) {
1285 } else if (FC.State() == TopAbs_ON) {
1292 if (aDistance < nearest) {
1293 nearest = aDistance;
1297 // A first found face, containing the point inside, will be returned.
1298 // It is the solution, if there are no
1299 // coincident or intersecting faces in the compound.
1300 if (nearest == -1) break;
1302 } else if (aDistance == nearest) {
1307 mapShapeDist.Bind(aFace, aDistance);
1308 } // if (!mapShapeDist.IsBound(aFace))
1311 // 2. Define face, containing the point or having minimum distance to it
1314 // The point is on boundary of some faces and there are
1315 // no faces, having the point inside
1316 SetErrorCode("Multiple faces near the given point are found");
1319 } else if (nearest == 1) {
1320 // The point is outside some faces and there are
1321 // no faces, having the point inside or on boundary.
1322 // We will get a nearest face
1323 Standard_Real bigReal = RealLast();
1324 Standard_Real minDist = bigReal;
1325 TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
1326 for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
1327 if (mapShapeDistIter.Value() == 1) {
1328 TopoDS_Shape aFace = mapShapeDistIter.Key();
1329 Standard_Real aDist = bigReal;
1331 // 2.a. Fast check of distance - if point projection on surface is on face
1332 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aFace));
1333 Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf);
1334 gp_Pnt2d p2dOnSurf = aSurfAna->ValueOfUV(aPnt, Precision::Confusion());
1335 gp_Pnt p3dOnSurf = aSurfAna->Value(p2dOnSurf);
1336 aDist = p3dOnSurf.Distance(aPnt);
1338 BRepClass_FaceClassifier FC (TopoDS::Face(aFace), p2dOnSurf, Precision::Confusion());
1339 if (FC.State() == TopAbs_OUT) {
1340 if (aDist < minDist) {
1341 // 2.b. Slow check - if point projection on surface is outside of face
1342 BRepExtrema_DistShapeShape aDistTool (aVert, aFace);
1343 if (!aDistTool.IsDone()) {
1344 SetErrorCode("Can not find a distance from the given point to one of faces");
1347 aDist = aDistTool.Value();
1353 if (aDist < minDist) {
1359 } else { // nearest == -1
1360 // // The point is inside some faces.
1361 // // We will get a face with nearest center
1362 // Standard_Real minDist = RealLast();
1363 // TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
1364 // for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
1365 // if (mapShapeDistIter.Value() == -1) {
1366 // TopoDS_Shape aFace = mapShapeDistIter.Key();
1367 // GProp_GProps aSystem;
1368 // BRepGProp::SurfaceProperties(aFace, aSystem);
1369 // gp_Pnt aCenterMass = aSystem.CentreOfMass();
1371 // Standard_Real aDist = aCenterMass.Distance(aPnt);
1372 // if (aDist < minDist) {
1379 } // if (nbFound > 1)
1382 SetErrorCode("There are no faces near the given point");
1385 TopTools_IndexedMapOfShape anIndices;
1386 TopExp::MapShapes(aBlockOrComp, anIndices);
1387 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1388 anArray->SetValue(1, anIndices.FindIndex(aShape));
1389 aResult = GetEngine()->AddSubShape(theShape, anArray);
1392 catch (Standard_Failure) {
1393 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1394 SetErrorCode(aFail->GetMessageString());
1398 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1400 //Make a Python command
1401 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceNearPoint("
1402 << theShape << ", " << thePoint << ")";
1408 //=============================================================================
1412 //=============================================================================
1413 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByNormale
1414 (Handle(GEOM_Object) theShape,
1415 Handle(GEOM_Object) theVector)
1420 Handle(GEOM_Object) aResult;
1423 if (theShape.IsNull() || theVector.IsNull()) return NULL;
1425 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1426 if (aBlockOrComp.IsNull()) {
1427 SetErrorCode("Block or compound is null");
1431 TopoDS_Shape anArg = theVector->GetValue();
1432 if (anArg.IsNull()) {
1433 SetErrorCode("Null shape is given as argument");
1436 if (anArg.ShapeType() != TopAbs_EDGE) {
1437 SetErrorCode("Element for normale identification is not an edge");
1441 //Compute the Face value
1443 #if OCC_VERSION_LARGE > 0x06010000
1446 TopoDS_Shape aShape;
1448 TopoDS_Edge anEdge = TopoDS::Edge(anArg);
1449 TopoDS_Vertex V1, V2;
1450 TopExp::Vertices(anEdge, V1, V2, Standard_True);
1451 gp_Pnt P1 = BRep_Tool::Pnt(V1);
1452 gp_Pnt P2 = BRep_Tool::Pnt(V2);
1453 gp_Vec aVec (P1, P2);
1454 if (aVec.Magnitude() < Precision::Confusion()) {
1455 SetErrorCode("Vector with null magnitude is given");
1459 Standard_Real minAngle = RealLast();
1460 TopTools_MapOfShape mapShape;
1461 TopExp_Explorer exp (aBlockOrComp, TopAbs_FACE);
1462 for (; exp.More(); exp.Next()) {
1463 if (mapShape.Add(exp.Current())) {
1464 TopoDS_Face aFace = TopoDS::Face(exp.Current());
1465 BRepAdaptor_Surface SF (aFace);
1467 Standard_Real u, v, x;
1469 // find a point on the surface to get normal direction in
1470 u = SF.FirstUParameter();
1471 x = SF.LastUParameter();
1472 if (Precision::IsInfinite(u)) {
1473 u = (Precision::IsInfinite(x)) ? 0. : x;
1474 } else if (!Precision::IsInfinite(x)) {
1478 v = SF.FirstVParameter();
1479 x = SF.LastVParameter();
1480 if (Precision::IsInfinite(v)) {
1481 v = (Precision::IsInfinite(x)) ? 0. : x;
1482 } else if (!Precision::IsInfinite(x)) {
1486 // compute the normal direction
1488 SF.D1(u,v,P1,Vec1,Vec2);
1489 gp_Vec V = Vec1.Crossed(Vec2);
1491 if (V.Magnitude() < Precision::Confusion()) {
1492 SetErrorCode("Normal vector of a face has null magnitude");
1496 // consider the face orientation
1497 if (aFace.Orientation() == TopAbs_REVERSED ||
1498 aFace.Orientation() == TopAbs_INTERNAL) {
1502 // compute the angle and compare with the minimal one
1503 Standard_Real anAngle = aVec.Angle(V);
1504 if (anAngle < minAngle) {
1511 if (aShape.IsNull()) {
1512 SetErrorCode("Failed to find a face by the given normale");
1515 TopTools_IndexedMapOfShape anIndices;
1516 TopExp::MapShapes(aBlockOrComp, anIndices);
1517 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1518 anArray->SetValue(1, anIndices.FindIndex(aShape));
1519 aResult = GetEngine()->AddSubShape(theShape, anArray);
1522 catch (Standard_Failure) {
1523 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1524 SetErrorCode(aFail->GetMessageString());
1528 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1530 //Make a Python command
1531 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByNormale("
1532 << theShape << ", " << theVector << ")";
1538 //=============================================================================
1540 * GetShapesNearPoint
1542 //=============================================================================
1543 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetShapesNearPoint
1544 (Handle(GEOM_Object) theShape,
1545 Handle(GEOM_Object) thePoint,
1546 const Standard_Integer theShapeType,
1547 const Standard_Real theConstTolerance)
1552 Handle(GEOM_Object) aResult;
1555 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
1557 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1558 if (aBlockOrComp.IsNull()) {
1559 SetErrorCode("Block or compound is null");
1563 TopoDS_Shape anArg = thePoint->GetValue();
1564 if (anArg.IsNull()) {
1565 SetErrorCode("Null shape is given as argument");
1568 if (anArg.ShapeType() != TopAbs_VERTEX) {
1569 SetErrorCode("Element for face identification is not a vertex");
1573 if (theShapeType < TopAbs_SOLID || TopAbs_VERTEX < theShapeType) {
1574 SetErrorCode("Invalid type of result is requested");
1578 Standard_Real theTolerance = theConstTolerance;
1579 if (theTolerance < Precision::Confusion()) {
1580 theTolerance = Precision::Confusion();
1583 // Compute the result
1585 #if OCC_VERSION_LARGE > 0x06010000
1588 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
1590 TopTools_MapOfShape mapShape;
1591 Standard_Integer nbEdges = 0;
1592 TopExp_Explorer exp (aBlockOrComp, TopAbs_ShapeEnum(theShapeType));
1593 for (; exp.More(); exp.Next()) {
1594 if (mapShape.Add(exp.Current())) {
1600 SetErrorCode("Given shape contains no subshapes of requested type");
1604 // Calculate distances and find min
1606 Standard_Integer ind = 1;
1607 Standard_Real aMinDist = RealLast();
1608 TopTools_Array1OfShape anEdges (1, nbEdges);
1609 TColStd_Array1OfReal aDistances (1, nbEdges);
1610 for (exp.Init(aBlockOrComp, TopAbs_ShapeEnum(theShapeType)); exp.More(); exp.Next()) {
1611 if (mapShape.Add(exp.Current())) {
1612 TopoDS_Shape anEdge = exp.Current();
1613 anEdges(ind) = anEdge;
1615 BRepExtrema_DistShapeShape aDistTool (aVert, anEdges(ind));
1616 if (!aDistTool.IsDone()) {
1617 SetErrorCode("Can not find a distance from the given point to one of subshapes");
1620 aDistances(ind) = aDistTool.Value();
1621 if (aDistances(ind) < aMinDist) {
1622 aMinDist = aDistances(ind);
1628 if (aMinDist < RealLast()) {
1629 // Collect subshapes with distance < (aMinDist + theTolerance)
1630 int nbSubShapes = 0;
1631 TopTools_Array1OfShape aNearShapes (1, nbEdges);
1632 for (ind = 1; ind <= nbEdges; ind++) {
1633 if (aDistances(ind) < aMinDist + theTolerance) {
1635 aNearShapes(nbSubShapes) = anEdges(ind);
1640 TopTools_IndexedMapOfShape anIndices;
1641 TopExp::MapShapes(aBlockOrComp, anIndices);
1642 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger (1, nbSubShapes);
1643 for (ind = 1; ind <= nbSubShapes; ind++) {
1644 anArray->SetValue(ind, anIndices.FindIndex(aNearShapes(ind)));
1646 aResult = GetEngine()->AddSubShape(theShape, anArray);
1649 catch (Standard_Failure) {
1650 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1651 SetErrorCode(aFail->GetMessageString());
1655 if (aResult.IsNull())
1658 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1660 //Make a Python command
1661 GEOM::TPythonDump(aFunction)
1662 << aResult << " = geompy.GetShapesNearPoint(" << theShape << ", " << thePoint
1663 << ", " << TopAbs_ShapeEnum(theShapeType) << ", " << theTolerance << ")";
1669 //=============================================================================
1671 * IsCompoundOfBlocks
1673 //=============================================================================
1674 Standard_Boolean GEOMImpl_IBlocksOperations::IsCompoundOfBlocks
1675 (Handle(GEOM_Object) theCompound,
1676 const Standard_Integer theMinNbFaces,
1677 const Standard_Integer theMaxNbFaces,
1678 Standard_Integer& theNbBlocks)
1681 Standard_Boolean isCompOfBlocks = Standard_False;
1684 if (theCompound.IsNull()) return isCompOfBlocks;
1685 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
1688 isCompOfBlocks = Standard_True;
1690 #if OCC_VERSION_LARGE > 0x06010000
1693 TopTools_MapOfShape mapShape;
1694 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
1695 for (; exp.More(); exp.Next()) {
1696 if (mapShape.Add(exp.Current())) {
1697 TopoDS_Shape aSolid = exp.Current();
1699 TopTools_MapOfShape mapFaces;
1700 TopExp_Explorer expF (aSolid, TopAbs_FACE);
1701 Standard_Integer nbFaces = 0;
1702 for (; expF.More(); expF.Next()) {
1703 if (mapFaces.Add(expF.Current())) {
1705 if (nbFaces > theMaxNbFaces) {
1706 isCompOfBlocks = Standard_False;
1711 if (nbFaces < theMinNbFaces || theMaxNbFaces < nbFaces) {
1712 isCompOfBlocks = Standard_False;
1719 catch (Standard_Failure) {
1720 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1721 SetErrorCode(aFail->GetMessageString());
1722 return isCompOfBlocks;
1726 return isCompOfBlocks;
1729 //=============================================================================
1731 * Set of functions, used by CheckCompoundOfBlocks() method
1733 //=============================================================================
1734 void GEOMImpl_IBlocksOperations::AddBlocksFrom (const TopoDS_Shape& theShape,
1735 TopTools_ListOfShape& BLO,
1736 TopTools_ListOfShape& NOT,
1737 TopTools_ListOfShape& EXT)
1739 TopAbs_ShapeEnum aType = theShape.ShapeType();
1741 case TopAbs_COMPOUND:
1742 case TopAbs_COMPSOLID:
1744 TopoDS_Iterator It (theShape);
1745 for (; It.More(); It.Next()) {
1746 AddBlocksFrom(It.Value(), BLO, NOT, EXT);
1752 // Check, if there are seam or degenerated edges
1753 BlockFix_CheckTool aTool;
1754 aTool.SetShape(theShape);
1756 if (aTool.NbPossibleBlocks() > 0) {
1757 EXT.Append(theShape);
1759 // Count faces and edges in each face to recognize blocks
1760 TopTools_MapOfShape mapFaces;
1761 Standard_Integer nbFaces = 0;
1762 Standard_Boolean hasNonQuadr = Standard_False;
1763 TopExp_Explorer expF (theShape, TopAbs_FACE);
1765 for (; expF.More(); expF.Next()) {
1766 if (mapFaces.Add(expF.Current())) {
1768 if (nbFaces > 6) break;
1771 TopoDS_Shape aF = expF.Current();
1772 TopExp_Explorer wires (aF, TopAbs_WIRE);
1773 if (!wires.More()) {
1774 // no wire in the face
1775 hasNonQuadr = Standard_True;
1778 TopoDS_Shape aWire = wires.Current();
1781 // multiple wires in the face
1782 hasNonQuadr = Standard_True;
1786 // Check number of edges in the face
1787 Standard_Integer nbEdges = 0;
1788 TopTools_MapOfShape mapEdges;
1789 TopExp_Explorer expW (aWire, TopAbs_EDGE);
1790 for (; expW.More(); expW.Next()) {
1791 if (mapEdges.Add(expW.Current())) {
1793 if (nbEdges > 4) break;
1797 hasNonQuadr = Standard_True;
1802 if (nbFaces == 6 && !hasNonQuadr) {
1803 BLO.Append(theShape);
1805 NOT.Append(theShape);
1811 NOT.Append(theShape);
1815 void AddBlocksFromOld (const TopoDS_Shape& theShape,
1816 TopTools_ListOfShape& BLO,
1817 TopTools_ListOfShape& NOT,
1818 TopTools_ListOfShape& DEG,
1819 TopTools_ListOfShape& SEA)
1821 TopAbs_ShapeEnum aType = theShape.ShapeType();
1823 case TopAbs_COMPOUND:
1824 case TopAbs_COMPSOLID:
1826 TopoDS_Iterator It (theShape);
1827 for (; It.More(); It.Next()) {
1828 AddBlocksFromOld(It.Value(), BLO, NOT, DEG, SEA);
1834 TopTools_MapOfShape mapFaces;
1835 TopExp_Explorer expF (theShape, TopAbs_FACE);
1836 Standard_Integer nbFaces = 0;
1837 Standard_Boolean hasNonQuadr = Standard_False;
1838 Standard_Boolean hasDegenerated = Standard_False;
1839 Standard_Boolean hasSeam = Standard_False;
1840 for (; expF.More(); expF.Next()) {
1841 if (mapFaces.Add(expF.Current())) {
1843 if (nbFaces > 6) break;
1845 // Check number of edges in the face
1846 Standard_Integer nbEdges = 0;
1847 TopTools_MapOfShape mapEdges;
1850 TopoDS_Shape aF = expF.Current();
1851 TopExp_Explorer wires (aF, TopAbs_WIRE);
1852 if (!wires.More()) {
1853 // no wire in the face
1854 hasNonQuadr = Standard_True;
1857 TopoDS_Shape aWire = wires.Current();
1860 // multiple wires in the face
1861 hasNonQuadr = Standard_True;
1866 BRepTools_WireExplorer aWE (TopoDS::Wire(aWire), TopoDS::Face(aF));
1867 for (; aWE.More(); aWE.Next(), nbEdges++) {
1868 if (BRep_Tool::Degenerated(aWE.Current())) {
1869 // degenerated edge found
1870 hasDegenerated = Standard_True;
1873 if (mapEdges.Contains(aWE.Current())) {
1875 hasSeam = Standard_True;
1878 mapEdges.Add(aWE.Current());
1881 hasNonQuadr = Standard_True;
1886 if (hasDegenerated || hasSeam) {
1887 if (hasDegenerated) {
1888 DEG.Append(theShape);
1891 SEA.Append(theShape);
1893 } else if (hasNonQuadr) {
1894 NOT.Append(theShape);
1896 BLO.Append(theShape);
1899 NOT.Append(theShape);
1904 NOT.Append(theShape);
1908 #define REL_NOT_CONNECTED 0
1910 #define REL_NOT_GLUED 2
1911 #define REL_COLLISION_VV 3
1912 #define REL_COLLISION_FF 4
1913 #define REL_COLLISION_EE 5
1914 #define REL_UNKNOWN 6
1916 Standard_Integer BlocksRelation (const TopoDS_Shape& theBlock1,
1917 const TopoDS_Shape& theBlock2)
1919 // Compare bounding boxes before calling BRepExtrema_DistShapeShape
1920 Standard_Real Xmin1, Ymin1, Zmin1, Xmax1, Ymax1, Zmax1;
1921 Standard_Real Xmin2, Ymin2, Zmin2, Xmax2, Ymax2, Zmax2;
1923 BRepBndLib::Add(theBlock1, B1);
1924 BRepBndLib::Add(theBlock2, B2);
1925 B1.Get(Xmin1, Ymin1, Zmin1, Xmax1, Ymax1, Zmax1);
1926 B2.Get(Xmin2, Ymin2, Zmin2, Xmax2, Ymax2, Zmax2);
1927 if (Xmax2 < Xmin1 || Xmax1 < Xmin2 ||
1928 Ymax2 < Ymin1 || Ymax1 < Ymin2 ||
1929 Zmax2 < Zmin1 || Zmax1 < Zmin2) {
1930 return REL_NOT_CONNECTED;
1933 BRepExtrema_DistShapeShape dst (theBlock1, theBlock2);
1934 if (!dst.IsDone()) {
1938 if (dst.Value() > Precision::Confusion()) {
1939 return REL_NOT_CONNECTED;
1942 if (dst.InnerSolution()) {
1943 return REL_COLLISION_VV;
1946 Standard_Integer nbSol = dst.NbSolution();
1947 Standard_Integer relation = REL_OK;
1948 Standard_Integer nbVerts = 0;
1949 Standard_Integer nbEdges = 0;
1950 Standard_Integer sol = 1;
1951 for (; sol <= nbSol; sol++) {
1952 BRepExtrema_SupportType supp1 = dst.SupportTypeShape1(sol);
1953 BRepExtrema_SupportType supp2 = dst.SupportTypeShape2(sol);
1954 if (supp1 == BRepExtrema_IsVertex && supp2 == BRepExtrema_IsVertex) {
1956 } else if (supp1 == BRepExtrema_IsInFace || supp2 == BRepExtrema_IsInFace) {
1957 return REL_COLLISION_FF;
1958 } else if (supp1 == BRepExtrema_IsOnEdge && supp2 == BRepExtrema_IsOnEdge) {
1960 } else if ((supp1 == BRepExtrema_IsOnEdge && supp2 == BRepExtrema_IsVertex) ||
1961 (supp2 == BRepExtrema_IsOnEdge && supp1 == BRepExtrema_IsVertex)) {
1962 relation = REL_COLLISION_EE;
1967 if (relation != REL_OK) {
1971 TColStd_Array1OfInteger vertSol (1, nbVerts);
1972 TopTools_Array1OfShape V1 (1, nbVerts);
1973 TopTools_Array1OfShape V2 (1, nbVerts);
1974 Standard_Integer ivs = 0;
1975 for (sol = 1; sol <= nbSol; sol++) {
1976 if (dst.SupportTypeShape1(sol) == BRepExtrema_IsVertex &&
1977 dst.SupportTypeShape2(sol) == BRepExtrema_IsVertex) {
1978 TopoDS_Vertex Vcur = TopoDS::Vertex(dst.SupportOnShape1(sol));
1979 // Check, that this vertex is far enough from other solution vertices.
1980 Standard_Integer ii = 1;
1981 for (; ii <= ivs; ii++) {
1982 if (BRepTools::Compare(TopoDS::Vertex(V1(ii)), Vcur)) {
1989 V2(ivs) = dst.SupportOnShape2(sol);
1993 // As we deal only with quadrangles,
1994 // 2, 3 or 4 vertex solutions can be found.
1997 return REL_COLLISION_FF;
1999 return REL_NOT_CONNECTED;
2005 // Check sharing of coincident entities.
2006 if (ivs == 2 || ivs == 3) {
2007 // Map vertices and edges of the blocks
2008 TopTools_IndexedDataMapOfShapeListOfShape MVE1, MVE2;
2009 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2010 (theBlock1, TopAbs_VERTEX, TopAbs_EDGE, MVE1);
2011 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2012 (theBlock2, TopAbs_VERTEX, TopAbs_EDGE, MVE2);
2016 TopoDS_Shape anEdge1, anEdge2;
2017 GEOMImpl_Block6Explorer::FindEdge(anEdge1, V1(1), V1(2), MVE1);
2018 if (anEdge1.IsNull()) return REL_UNKNOWN;
2020 GEOMImpl_Block6Explorer::FindEdge(anEdge2, V2(1), V2(2), MVE2);
2021 if (anEdge2.IsNull()) return REL_UNKNOWN;
2023 if (!anEdge1.IsSame(anEdge2)) return REL_NOT_GLUED;
2025 } else { // ivs == 3
2026 // Find common edges
2027 Standard_Integer e1_v1 = 1;
2028 Standard_Integer e1_v2 = 2;
2029 Standard_Integer e2_v1 = 3;
2030 Standard_Integer e2_v2 = 1;
2032 TopoDS_Shape anEdge11, anEdge12;
2033 GEOMImpl_Block6Explorer::FindEdge(anEdge11, V1(e1_v1), V1(e1_v2), MVE1);
2034 if (anEdge11.IsNull()) {
2037 GEOMImpl_Block6Explorer::FindEdge(anEdge11, V1(e1_v1), V1(e1_v2), MVE1);
2038 if (anEdge11.IsNull()) return REL_UNKNOWN;
2040 GEOMImpl_Block6Explorer::FindEdge(anEdge12, V1(e2_v1), V1(e2_v2), MVE1);
2041 if (anEdge12.IsNull()) {
2043 GEOMImpl_Block6Explorer::FindEdge(anEdge12, V1(e2_v1), V1(e2_v2), MVE1);
2044 if (anEdge12.IsNull()) return REL_UNKNOWN;
2047 TopoDS_Shape anEdge21, anEdge22;
2048 GEOMImpl_Block6Explorer::FindEdge(anEdge21, V2(e1_v1), V2(e1_v2), MVE2);
2049 if (anEdge21.IsNull()) return REL_UNKNOWN;
2050 GEOMImpl_Block6Explorer::FindEdge(anEdge22, V2(e2_v1), V2(e2_v2), MVE2);
2051 if (anEdge22.IsNull()) return REL_UNKNOWN;
2053 // Check of edges coincidence (with some precision) have to be done here
2054 // if (!anEdge11.IsEqual(anEdge21)) return REL_UNKNOWN;
2055 // if (!anEdge12.IsEqual(anEdge22)) return REL_UNKNOWN;
2057 // Check of edges sharing
2058 if (!anEdge11.IsSame(anEdge21)) return REL_NOT_GLUED;
2059 if (!anEdge12.IsSame(anEdge22)) return REL_NOT_GLUED;
2064 // Map vertices and faces of the blocks
2065 TopTools_IndexedDataMapOfShapeListOfShape MVF1, MVF2;
2066 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2067 (theBlock1, TopAbs_VERTEX, TopAbs_FACE, MVF1);
2068 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2069 (theBlock2, TopAbs_VERTEX, TopAbs_FACE, MVF2);
2071 TopoDS_Shape aFace1, aFace2;
2072 GEOMImpl_Block6Explorer::FindFace(aFace1, V1(1), V1(2), V1(3), V1(4), MVF1);
2073 if (aFace1.IsNull()) return REL_UNKNOWN;
2074 GEOMImpl_Block6Explorer::FindFace(aFace2, V2(1), V2(2), V2(3), V2(4), MVF2);
2075 if (aFace2.IsNull()) return REL_UNKNOWN;
2077 // Check of faces coincidence (with some precision) have to be done here
2078 // if (!aFace1.IsEqual(aFace2)) return REL_UNKNOWN;
2080 // Check of faces sharing
2081 if (!aFace1.IsSame(aFace2)) return REL_NOT_GLUED;
2087 void FindConnected (const Standard_Integer theBlockIndex,
2088 const TColStd_Array2OfInteger& theRelations,
2089 TColStd_MapOfInteger& theProcessedMap,
2090 TColStd_MapOfInteger& theConnectedMap)
2092 theConnectedMap.Add(theBlockIndex);
2093 theProcessedMap.Add(theBlockIndex);
2095 Standard_Integer nbBlocks = theRelations.ColLength();
2096 Standard_Integer col = 1;
2097 for (; col <= nbBlocks; col++) {
2098 if (theRelations(theBlockIndex, col) == REL_OK ||
2099 theRelations(theBlockIndex, col) == REL_NOT_GLUED) {
2100 if (!theProcessedMap.Contains(col)) {
2101 FindConnected(col, theRelations, theProcessedMap, theConnectedMap);
2107 Standard_Boolean HasAnyConnection (const Standard_Integer theBlockIndex,
2108 const TColStd_MapOfInteger& theWith,
2109 const TColStd_Array2OfInteger& theRelations,
2110 TColStd_MapOfInteger& theProcessedMap)
2112 theProcessedMap.Add(theBlockIndex);
2114 Standard_Integer nbBlocks = theRelations.ColLength();
2115 Standard_Integer col = 1;
2116 for (; col <= nbBlocks; col++) {
2117 if (theRelations(theBlockIndex, col) != REL_NOT_CONNECTED) {
2118 if (!theProcessedMap.Contains(col)) {
2119 if (theWith.Contains(col))
2120 return Standard_True;
2121 if (HasAnyConnection(col, theWith, theRelations, theProcessedMap))
2122 return Standard_True;
2127 return Standard_False;
2130 //=============================================================================
2132 * CheckCompoundOfBlocksOld
2134 //=============================================================================
2135 Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocksOld
2136 (Handle(GEOM_Object) theCompound,
2137 std::list<BCError>& theErrors)
2141 if (theCompound.IsNull()) return Standard_False;
2142 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2144 Standard_Boolean isCompOfBlocks = Standard_True;
2146 // Map sub-shapes and their indices
2147 TopTools_IndexedMapOfShape anIndices;
2148 TopExp::MapShapes(aBlockOrComp, anIndices);
2150 // 1. Report non-blocks
2151 TopTools_ListOfShape NOT; // Not blocks
2152 TopTools_ListOfShape DEG; // Hexahedral solids, having degenerated edges
2153 TopTools_ListOfShape SEA; // Hexahedral solids, having seam edges
2154 TopTools_ListOfShape BLO; // All blocks from the given compound
2155 AddBlocksFromOld(aBlockOrComp, BLO, NOT, DEG, SEA);
2157 if (NOT.Extent() > 0) {
2158 isCompOfBlocks = Standard_False;
2160 anErr.error = NOT_BLOCK;
2161 TopTools_ListIteratorOfListOfShape it (NOT);
2162 for (; it.More(); it.Next()) {
2163 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
2165 theErrors.push_back(anErr);
2168 if (DEG.Extent() > 0 || SEA.Extent() > 0) {
2169 isCompOfBlocks = Standard_False;
2171 anErr.error = EXTRA_EDGE;
2173 TopTools_ListIteratorOfListOfShape itDEG (DEG);
2174 for (; itDEG.More(); itDEG.Next()) {
2175 anErr.incriminated.push_back(anIndices.FindIndex(itDEG.Value()));
2178 TopTools_ListIteratorOfListOfShape itSEA (SEA);
2179 for (; itSEA.More(); itSEA.Next()) {
2180 anErr.incriminated.push_back(anIndices.FindIndex(itSEA.Value()));
2183 theErrors.push_back(anErr);
2186 Standard_Integer nbBlocks = BLO.Extent();
2187 if (nbBlocks == 0) {
2188 isCompOfBlocks = Standard_False;
2190 return isCompOfBlocks;
2192 if (nbBlocks == 1) {
2194 return isCompOfBlocks;
2197 // Convert list of blocks into array for easy and fast access
2198 Standard_Integer ibl = 1;
2199 TopTools_Array1OfShape aBlocks (1, nbBlocks);
2200 TopTools_ListIteratorOfListOfShape BLOit (BLO);
2201 for (; BLOit.More(); BLOit.Next(), ibl++) {
2202 aBlocks.SetValue(ibl, BLOit.Value());
2205 // 2. Find relations between all blocks,
2206 // report connection errors (NOT_GLUED and INVALID_CONNECTION)
2207 TColStd_Array2OfInteger aRelations (1, nbBlocks, 1, nbBlocks);
2208 aRelations.Init(REL_NOT_CONNECTED);
2210 Standard_Integer row = 1;
2211 for (row = 1; row <= nbBlocks; row++) {
2212 TopoDS_Shape aBlock = aBlocks.Value(row);
2214 Standard_Integer col = row + 1;
2215 for (; col <= nbBlocks; col++) {
2216 Standard_Integer aRel = BlocksRelation(aBlock, aBlocks.Value(col));
2217 if (aRel != REL_NOT_CONNECTED) {
2218 aRelations.SetValue(row, col, aRel);
2219 aRelations.SetValue(col, row, aRel);
2220 if (aRel == REL_NOT_GLUED) {
2221 // report connection error
2222 isCompOfBlocks = Standard_False;
2224 anErr.error = NOT_GLUED;
2225 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row)));
2226 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col)));
2227 theErrors.push_back(anErr);
2228 } else if (aRel == REL_COLLISION_VV ||
2229 aRel == REL_COLLISION_FF ||
2230 aRel == REL_COLLISION_EE ||
2231 aRel == REL_UNKNOWN) {
2232 // report connection error
2233 isCompOfBlocks = Standard_False;
2235 anErr.error = INVALID_CONNECTION;
2236 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row)));
2237 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col)));
2238 theErrors.push_back(anErr);
2245 // 3. Find largest set of connected (good connection or not glued) blocks
2246 TColStd_MapOfInteger aProcessedMap;
2247 TColStd_MapOfInteger aLargestSet;
2248 TColStd_MapOfInteger aCurrentSet;
2249 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2250 if (!aProcessedMap.Contains(ibl)) {
2251 aCurrentSet.Clear();
2252 FindConnected(ibl, aRelations, aProcessedMap, aCurrentSet);
2253 if (aCurrentSet.Extent() > aLargestSet.Extent()) {
2254 aLargestSet = aCurrentSet;
2259 // 4. Report all blocks, isolated from <aLargestSet>
2261 anErr.error = NOT_CONNECTED;
2262 Standard_Boolean hasIsolated = Standard_False;
2263 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2264 if (!aLargestSet.Contains(ibl)) {
2265 aProcessedMap.Clear();
2266 if (!HasAnyConnection(ibl, aLargestSet, aRelations, aProcessedMap)) {
2267 // report connection absence
2268 hasIsolated = Standard_True;
2269 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(ibl)));
2274 isCompOfBlocks = Standard_False;
2275 theErrors.push_back(anErr);
2279 return isCompOfBlocks;
2282 //=============================================================================
2286 //=============================================================================
2287 TCollection_AsciiString GEOMImpl_IBlocksOperations::PrintBCErrors
2288 (Handle(GEOM_Object) theCompound,
2289 const std::list<BCError>& theErrors)
2291 TCollection_AsciiString aDescr;
2293 std::list<BCError>::const_iterator errIt = theErrors.begin();
2295 for (; errIt != theErrors.end(); i++, errIt++) {
2296 BCError errStruct = *errIt;
2298 switch (errStruct.error) {
2300 aDescr += "\n\tNot a Blocks: ";
2303 aDescr += "\n\tHexahedral solids with degenerated and/or seam edges: ";
2305 case INVALID_CONNECTION:
2306 aDescr += "\n\tInvalid connection between two blocks: ";
2309 aDescr += "\n\tBlocks, not connected with main body: ";
2312 aDescr += "\n\tNot glued blocks: ";
2318 std::list<int> sshList = errStruct.incriminated;
2319 std::list<int>::iterator sshIt = sshList.begin();
2321 for (; sshIt != sshList.end(); jj++, sshIt++) {
2324 aDescr += TCollection_AsciiString(*sshIt);
2331 //=============================================================================
2333 * CheckCompoundOfBlocks
2335 //=============================================================================
2336 Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocks
2337 (Handle(GEOM_Object) theCompound,
2338 std::list<BCError>& theErrors)
2342 if (theCompound.IsNull()) return Standard_False;
2343 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2345 Standard_Boolean isCompOfBlocks = Standard_True;
2347 // Map sub-shapes and their indices
2348 TopTools_IndexedMapOfShape anIndices;
2349 TopExp::MapShapes(aBlockOrComp, anIndices);
2351 // 1. Separate blocks from non-blocks
2352 TopTools_ListOfShape NOT; // Not blocks
2353 TopTools_ListOfShape EXT; // Hexahedral solids, having degenerated and/or seam edges
2354 TopTools_ListOfShape BLO; // All blocks from the given compound
2355 AddBlocksFrom(aBlockOrComp, BLO, NOT, EXT);
2357 // Report non-blocks
2358 if (NOT.Extent() > 0) {
2359 isCompOfBlocks = Standard_False;
2361 anErr.error = NOT_BLOCK;
2362 TopTools_ListIteratorOfListOfShape it (NOT);
2363 for (; it.More(); it.Next()) {
2364 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
2366 theErrors.push_back(anErr);
2369 // Report solids, having degenerated and/or seam edges
2370 if (EXT.Extent() > 0) {
2371 isCompOfBlocks = Standard_False;
2373 anErr.error = EXTRA_EDGE;
2374 TopTools_ListIteratorOfListOfShape it (EXT);
2375 for (; it.More(); it.Next()) {
2376 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
2378 theErrors.push_back(anErr);
2381 Standard_Integer nbBlocks = BLO.Extent();
2382 if (nbBlocks == 0) {
2383 isCompOfBlocks = Standard_False;
2385 return isCompOfBlocks;
2387 if (nbBlocks == 1) {
2389 return isCompOfBlocks;
2392 // Prepare data for 2. and 3.
2393 TColStd_Array2OfInteger aRelations (1, nbBlocks, 1, nbBlocks);
2394 aRelations.Init(REL_NOT_CONNECTED);
2396 TopTools_IndexedMapOfShape mapBlocks;
2399 TopoDS_Compound aComp;
2400 BB.MakeCompound(aComp);
2402 TopTools_ListIteratorOfListOfShape BLOit (BLO);
2403 for (; BLOit.More(); BLOit.Next()) {
2404 mapBlocks.Add(BLOit.Value());
2405 BB.Add(aComp, BLOit.Value());
2408 // 2. Find glued blocks (having shared faces)
2409 TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
2410 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2411 (aComp, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
2413 Standard_Integer prevInd = 0, curInd = 0;
2414 Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
2415 for (; ind <= nbFaces; ind++) {
2416 const TopTools_ListOfShape& aGluedBlocks = mapFaceBlocks.FindFromIndex(ind);
2417 if (aGluedBlocks.Extent() > 1) { // Shared face found
2418 TopTools_ListIteratorOfListOfShape aGluedBlocksIt (aGluedBlocks);
2419 TopoDS_Shape prevBlock, curBlock;
2420 for (; aGluedBlocksIt.More(); aGluedBlocksIt.Next()) {
2421 curBlock = aGluedBlocksIt.Value();
2422 if (!prevBlock.IsNull()) {
2423 prevInd = mapBlocks.FindIndex(prevBlock);
2424 curInd = mapBlocks.FindIndex(curBlock);
2425 aRelations.SetValue(prevInd, curInd, REL_OK);
2426 aRelations.SetValue(curInd, prevInd, REL_OK);
2428 prevBlock = curBlock;
2433 // 3. Find not glued blocks
2434 GEOMAlgo_GlueAnalyser aGD;
2436 aGD.SetShape(aComp);
2437 aGD.SetTolerance(Precision::Confusion());
2438 aGD.SetCheckGeometry(Standard_True);
2441 Standard_Integer iErr, iWrn;
2442 iErr = aGD.ErrorStatus();
2444 SetErrorCode("Error in GEOMAlgo_GlueAnalyser");
2445 return isCompOfBlocks;
2447 iWrn = aGD.WarningStatus();
2449 MESSAGE("Warning in GEOMAlgo_GlueAnalyser");
2452 // Report not glued blocks
2453 if (aGD.HasSolidsToGlue()) {
2454 isCompOfBlocks = Standard_False;
2455 Standard_Integer aSx1Ind, aSx2Ind;
2457 const GEOMAlgo_ListOfCoupleOfShapes& aLCS = aGD.SolidsToGlue();
2458 GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS (aLCS);
2459 for (; aItCS.More(); aItCS.Next()) {
2460 const GEOMAlgo_CoupleOfShapes& aCS = aItCS.Value();
2461 const TopoDS_Shape& aSx1 = aCS.Shape1();
2462 const TopoDS_Shape& aSx2 = aCS.Shape2();
2464 aSx1Ind = mapBlocks.FindIndex(aSx1);
2465 aSx2Ind = mapBlocks.FindIndex(aSx2);
2466 aRelations.SetValue(aSx1Ind, aSx2Ind, NOT_GLUED);
2467 aRelations.SetValue(aSx2Ind, aSx1Ind, NOT_GLUED);
2470 anErr.error = NOT_GLUED;
2471 anErr.incriminated.push_back(anIndices.FindIndex(aSx1));
2472 anErr.incriminated.push_back(anIndices.FindIndex(aSx2));
2473 theErrors.push_back(anErr);
2477 // 4. Find largest set of connected (good connection or not glued) blocks
2478 Standard_Integer ibl = 1;
2479 TColStd_MapOfInteger aProcessedMap;
2480 TColStd_MapOfInteger aLargestSet;
2481 TColStd_MapOfInteger aCurrentSet;
2482 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2483 if (!aProcessedMap.Contains(ibl)) {
2484 aCurrentSet.Clear();
2485 FindConnected(ibl, aRelations, aProcessedMap, aCurrentSet);
2486 if (aCurrentSet.Extent() > aLargestSet.Extent()) {
2487 aLargestSet = aCurrentSet;
2492 // 5. Report all blocks, isolated from <aLargestSet>
2494 anErr.error = NOT_CONNECTED;
2495 Standard_Boolean hasIsolated = Standard_False;
2496 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2497 if (!aLargestSet.Contains(ibl)) {
2498 aProcessedMap.Clear();
2499 if (!HasAnyConnection(ibl, aLargestSet, aRelations, aProcessedMap)) {
2500 // report connection absence
2501 hasIsolated = Standard_True;
2502 anErr.incriminated.push_back(anIndices.FindIndex(mapBlocks.FindKey(ibl)));
2507 isCompOfBlocks = Standard_False;
2508 theErrors.push_back(anErr);
2512 return isCompOfBlocks;
2515 //=============================================================================
2519 //=============================================================================
2520 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::RemoveExtraEdges
2521 (Handle(GEOM_Object) theObject,
2522 const Standard_Integer theOptimumNbFaces)
2526 if (theObject.IsNull()) return NULL;
2528 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2529 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be fixed
2531 //Add a new Copy object
2532 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2535 Handle(GEOM_Function) aFunction =
2536 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_REMOVE_EXTRA);
2538 //Check if the function is set correctly
2539 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2541 GEOMImpl_IBlockTrsf aTI (aFunction);
2542 aTI.SetOriginal(aLastFunction);
2543 aTI.SetOptimumNbFaces(theOptimumNbFaces);
2545 //Compute the fixed shape
2547 #if OCC_VERSION_LARGE > 0x06010000
2550 if (!GetSolver()->ComputeFunction(aFunction)) {
2551 SetErrorCode("Block driver failed to remove extra edges of the given shape");
2555 catch (Standard_Failure) {
2556 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2557 SetErrorCode(aFail->GetMessageString());
2561 //Make a Python command
2562 std::string doUnionFaces = (theOptimumNbFaces < 0) ? "False" : "True";
2563 GEOM::TPythonDump(aFunction) << aCopy << " = geompy.RemoveExtraEdges("
2564 << theObject << ", " << doUnionFaces.data() << ")";
2570 //=============================================================================
2574 //=============================================================================
2575 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::CheckAndImprove
2576 (Handle(GEOM_Object) theObject)
2580 if (theObject.IsNull()) return NULL;
2582 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2583 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be fixed
2585 //Add a new Copy object
2586 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2589 Handle(GEOM_Function) aFunction =
2590 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_COMPOUND_IMPROVE);
2592 //Check if the function is set correctly
2593 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2595 GEOMImpl_IBlockTrsf aTI (aFunction);
2596 aTI.SetOriginal(aLastFunction);
2598 // -1 means do not unite faces on common surface (?except case of seam edge between them?)
2599 //aTI.SetOptimumNbFaces(-1);
2600 aTI.SetOptimumNbFaces(6);
2602 //Compute the fixed shape
2604 #if OCC_VERSION_LARGE > 0x06010000
2607 if (!GetSolver()->ComputeFunction(aFunction)) {
2608 SetErrorCode("Block driver failed to improve the given blocks compound");
2612 catch (Standard_Failure) {
2613 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2614 SetErrorCode(aFail->GetMessageString());
2618 //Make a Python command
2619 GEOM::TPythonDump(aFunction) << aCopy
2620 << " = geompy.CheckAndImprove(" << theObject << ")";
2626 //=============================================================================
2628 * ExplodeCompoundOfBlocks
2630 //=============================================================================
2631 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::ExplodeCompoundOfBlocks
2632 (Handle(GEOM_Object) theCompound,
2633 const Standard_Integer theMinNbFaces,
2634 const Standard_Integer theMaxNbFaces)
2638 if (theCompound.IsNull()) return NULL;
2639 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2640 if (aBlockOrComp.IsNull()) return NULL;
2642 Handle(TColStd_HSequenceOfTransient) aBlocks = new TColStd_HSequenceOfTransient;
2643 Handle(GEOM_Object) anObj;
2644 Handle(GEOM_Function) aFunction;
2646 TopTools_MapOfShape mapShape;
2647 TCollection_AsciiString anAsciiList, anEntry;
2650 TopTools_IndexedMapOfShape anIndices;
2651 TopExp::MapShapes(aBlockOrComp, anIndices);
2652 Handle(TColStd_HArray1OfInteger) anArray;
2656 #if OCC_VERSION_LARGE > 0x06010000
2659 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2660 for (; exp.More(); exp.Next()) {
2661 if (mapShape.Add(exp.Current())) {
2662 TopoDS_Shape aSolid = exp.Current();
2664 TopTools_MapOfShape mapFaces;
2665 TopExp_Explorer expF (aSolid, TopAbs_FACE);
2666 Standard_Integer nbFaces = 0;
2667 for (; expF.More(); expF.Next()) {
2668 if (mapFaces.Add(expF.Current())) {
2673 if (theMinNbFaces <= nbFaces && nbFaces <= theMaxNbFaces) {
2674 anArray = new TColStd_HArray1OfInteger(1,1);
2675 anArray->SetValue(1, anIndices.FindIndex(aSolid));
2676 anObj = GetEngine()->AddSubShape(theCompound, anArray);
2677 aBlocks->Append(anObj);
2679 //Make a Python command
2680 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2681 anAsciiList += anEntry + ", ";
2686 catch (Standard_Failure) {
2687 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2688 SetErrorCode(aFail->GetMessageString());
2692 if (aBlocks->IsEmpty()) {
2693 SetErrorCode("There are no specified blocks in the given shape");
2697 anAsciiList.Trunc(anAsciiList.Length() - 2);
2699 //The explode doesn't change object so no new function is required.
2700 aFunction = theCompound->GetLastFunction();
2702 //Make a Python command
2703 GEOM::TPythonDump(aFunction, /*append=*/true)
2704 << "[" << anAsciiList.ToCString() << "] = geompy.MakeBlockExplode("
2705 << theCompound << ", " << theMinNbFaces << ", " << theMaxNbFaces << ")";
2711 //=============================================================================
2715 //=============================================================================
2716 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetBlockNearPoint
2717 (Handle(GEOM_Object) theCompound,
2718 Handle(GEOM_Object) thePoint)
2723 Handle(GEOM_Object) aResult;
2726 if (theCompound.IsNull() || thePoint.IsNull()) return NULL;
2728 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2729 if (aBlockOrComp.IsNull()) {
2730 SetErrorCode("Compound is null");
2733 if (aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
2734 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
2735 SetErrorCode("Shape to find block in is not a compound");
2739 TopoDS_Shape anArg = thePoint->GetValue();
2740 if (anArg.IsNull()) {
2741 SetErrorCode("Point is null");
2744 if (anArg.ShapeType() != TopAbs_VERTEX) {
2745 SetErrorCode("Shape for block identification is not a vertex");
2749 //Compute the Block value
2751 #if OCC_VERSION_LARGE > 0x06010000
2754 TopoDS_Shape aShape;
2756 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
2757 gp_Pnt aPnt = BRep_Tool::Pnt(aVert);
2758 Standard_Real PX, PY, PZ;
2759 aPnt.Coord(PX, PY, PZ);
2761 // 1. Classify the point relatively each block
2762 Standard_Integer nearest = 2, nbFound = 0;
2763 TopTools_DataMapOfShapeInteger mapShapeDist;
2764 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2765 for (; exp.More(); exp.Next()) {
2766 TopoDS_Shape aSolid = exp.Current();
2768 if (!mapShapeDist.IsBound(aSolid)) {
2769 Standard_Integer aDistance = 2;
2771 // 1.a. Classify relatively Bounding box
2772 Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
2774 BRepBndLib::Add(aSolid, BB);
2775 BB.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
2776 if (PX < Xmin || Xmax < PX ||
2777 PY < Ymin || Ymax < PY ||
2778 PZ < Zmin || Zmax < PZ) {
2779 // OUT of bounding box
2782 // 1.b. Classify relatively the solid itself
2783 BRepClass3d_SolidClassifier SC (aSolid, aPnt, Precision::Confusion());
2784 if (SC.State() == TopAbs_IN) {
2786 } else if (SC.State() == TopAbs_ON) {
2793 if (aDistance < nearest) {
2794 nearest = aDistance;
2798 // A first found block, containing the point inside, will be returned.
2799 // It is the solution, if there are no intersecting blocks in the compound.
2800 if (nearest == -1) break;
2802 } else if (aDistance == nearest) {
2807 mapShapeDist.Bind(aSolid, aDistance);
2808 } // if (!mapShapeDist.IsBound(aSolid))
2811 // 2. Define block, containing the point or having minimum distance to it
2814 // The point is on boundary of some blocks and there are
2815 // no blocks, having the point inside their volume
2816 SetErrorCode("Multiple blocks near the given point are found");
2819 } else if (nearest == 1) {
2820 // The point is outside some blocks and there are
2821 // no blocks, having the point inside or on boundary.
2822 // We will get a nearest block
2823 Standard_Real minDist = RealLast();
2824 TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
2825 for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
2826 if (mapShapeDistIter.Value() == 1) {
2827 TopoDS_Shape aSolid = mapShapeDistIter.Key();
2828 BRepExtrema_DistShapeShape aDistTool (aVert, aSolid);
2829 if (!aDistTool.IsDone()) {
2830 SetErrorCode("Can not find a distance from the given point to one of blocks");
2833 Standard_Real aDist = aDistTool.Value();
2834 if (aDist < minDist) {
2840 } else { // nearest == -1
2841 // // The point is inside some blocks.
2842 // // We will get a block with nearest center
2843 // Standard_Real minDist = RealLast();
2844 // TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
2845 // for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
2846 // if (mapShapeDistIter.Value() == -1) {
2847 // TopoDS_Shape aSolid = mapShapeDistIter.Key();
2848 // GProp_GProps aSystem;
2849 // BRepGProp::VolumeProperties(aSolid, aSystem);
2850 // gp_Pnt aCenterMass = aSystem.CentreOfMass();
2852 // Standard_Real aDist = aCenterMass.Distance(aPnt);
2853 // if (aDist < minDist) {
2860 } // if (nbFound > 1)
2863 SetErrorCode("There are no blocks near the given point");
2866 TopTools_IndexedMapOfShape anIndices;
2867 TopExp::MapShapes(aBlockOrComp, anIndices);
2868 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2869 anArray->SetValue(1, anIndices.FindIndex(aShape));
2870 aResult = GetEngine()->AddSubShape(theCompound, anArray);
2873 catch (Standard_Failure) {
2874 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2875 SetErrorCode(aFail->GetMessageString());
2879 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
2881 //Make a Python command
2882 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetBlockNearPoint("
2883 << theCompound << ", " << thePoint << ")";
2889 //=============================================================================
2893 //=============================================================================
2894 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetBlockByParts
2895 (Handle(GEOM_Object) theCompound,
2896 const Handle(TColStd_HSequenceOfTransient)& theParts)
2900 Handle(GEOM_Object) aResult;
2902 if (theCompound.IsNull() || theParts.IsNull()) return NULL;
2903 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2904 if (aBlockOrComp.IsNull()) return NULL;
2907 Standard_Integer argi, aLen = theParts->Length();
2908 TopTools_Array1OfShape anArgs (1, aLen);
2909 TCollection_AsciiString anEntry, aPartsDescr;
2910 for (argi = 1; argi <= aLen; argi++) {
2911 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theParts->Value(argi));
2912 Handle(GEOM_Function) aRef = anObj->GetLastFunction();
2913 if (aRef.IsNull()) return NULL;
2915 TopoDS_Shape anArg = aRef->GetValue();
2916 if (anArg.IsNull()) {
2917 SetErrorCode("Null shape is given as argument");
2920 anArgs(argi) = anArg;
2922 // For Python command
2923 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2924 if (argi > 1) aPartsDescr += ", ";
2925 aPartsDescr += anEntry;
2928 //Compute the Block value
2930 #if OCC_VERSION_LARGE > 0x06010000
2933 // 1. Explode compound on solids
2934 TopTools_MapOfShape mapShape;
2935 Standard_Integer nbSolids = 0;
2936 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2937 for (; exp.More(); exp.Next()) {
2938 if (mapShape.Add(exp.Current())) {
2944 Standard_Integer ind = 1;
2945 TopTools_Array1OfShape aSolids (1, nbSolids);
2946 TColStd_Array1OfInteger aNbParts (1, nbSolids);
2947 for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next(), ind++) {
2948 if (mapShape.Add(exp.Current())) {
2949 TopoDS_Shape aSolid = exp.Current();
2950 aSolids(ind) = aSolid;
2953 // 2. Define quantity of parts, contained in each solid
2954 TopTools_IndexedMapOfShape aSubShapes;
2955 TopExp::MapShapes(aSolid, aSubShapes);
2956 for (argi = 1; argi <= aLen; argi++) {
2957 if (aSubShapes.Contains(anArgs(argi))) {
2964 // 3. Define solid, containing maximum quantity of parts
2965 Standard_Integer maxNb = 0, nbFound = 0;
2966 TopoDS_Shape aShape;
2967 for (ind = 1; ind <= nbSolids; ind++) {
2968 if (aNbParts(ind) > maxNb) {
2969 maxNb = aNbParts(ind);
2970 aShape = aSolids(ind);
2972 } else if (aNbParts(ind) == maxNb) {
2978 SetErrorCode("Multiple blocks, containing maximum quantity of the given parts, are found");
2980 } else if (nbFound == 0) {
2981 SetErrorCode("There are no blocks, containing the given parts");
2984 TopTools_IndexedMapOfShape anIndices;
2985 TopExp::MapShapes(aBlockOrComp, anIndices);
2986 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2987 anArray->SetValue(1, anIndices.FindIndex(aShape));
2988 aResult = GetEngine()->AddSubShape(theCompound, anArray);
2990 } catch (Standard_Failure) {
2991 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2992 SetErrorCode(aFail->GetMessageString());
2996 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
2998 //Make a Python command
2999 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetBlockByParts("
3000 << theCompound << ", [" << aPartsDescr.ToCString() << "])";
3006 //=============================================================================
3010 //=============================================================================
3011 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::GetBlocksByParts
3012 (Handle(GEOM_Object) theCompound,
3013 const Handle(TColStd_HSequenceOfTransient)& theParts)
3017 if (theCompound.IsNull() || theParts.IsNull()) return NULL;
3018 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
3019 if (aBlockOrComp.IsNull()) return NULL;
3021 Handle(TColStd_HSequenceOfTransient) aBlocks = new TColStd_HSequenceOfTransient;
3022 Handle(GEOM_Object) anObj;
3023 Handle(GEOM_Function) aFunction;
3026 Standard_Integer argi, aLen = theParts->Length();
3027 TopTools_Array1OfShape anArgs (1, aLen);
3028 TCollection_AsciiString anEntry, aPartsDescr, anAsciiList;
3030 for (argi = 1; argi <= aLen; argi++) {
3031 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theParts->Value(argi));
3032 Handle(GEOM_Function) aRef = anObj->GetLastFunction();
3033 if (aRef.IsNull()) return NULL;
3035 TopoDS_Shape anArg = aRef->GetValue();
3036 if (anArg.IsNull()) {
3037 SetErrorCode("Null shape is given as argument");
3040 anArgs(argi) = anArg;
3042 // For Python command
3043 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
3044 aPartsDescr += anEntry + ", ";
3049 #if OCC_VERSION_LARGE > 0x06010000
3052 TopTools_MapOfShape mapShape;
3053 Standard_Integer nbSolids = 0;
3054 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
3055 for (; exp.More(); exp.Next()) {
3056 if (mapShape.Add(exp.Current())) {
3062 Standard_Integer ind = 1;
3063 TopTools_Array1OfShape aSolids (1, nbSolids);
3064 TColStd_Array1OfInteger aNbParts (1, nbSolids);
3065 for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next(), ind++) {
3066 if (mapShape.Add(exp.Current())) {
3067 TopoDS_Shape aSolid = exp.Current();
3068 aSolids(ind) = aSolid;
3071 // 2. Define quantity of parts, contained in each solid
3072 TopTools_IndexedMapOfShape aSubShapes;
3073 TopExp::MapShapes(aSolid, aSubShapes);
3074 for (argi = 1; argi <= aLen; argi++) {
3075 if (aSubShapes.Contains(anArgs(argi))) {
3082 // 3. Define solid, containing maximum quantity of parts
3083 Standard_Integer maxNb = 0, nbFound = 0;
3084 for (ind = 1; ind <= nbSolids; ind++) {
3085 if (aNbParts(ind) > maxNb) {
3086 maxNb = aNbParts(ind);
3088 } else if (aNbParts(ind) == maxNb) {
3094 SetErrorCode("There are no blocks, containing the given parts");
3099 TopTools_IndexedMapOfShape anIndices;
3100 TopExp::MapShapes(aBlockOrComp, anIndices);
3101 Handle(TColStd_HArray1OfInteger) anArray;
3103 for (ind = 1; ind <= nbSolids; ind++) {
3104 if (aNbParts(ind) == maxNb) {
3105 anArray = new TColStd_HArray1OfInteger(1,1);
3106 anArray->SetValue(1, anIndices.FindIndex(aSolids(ind)));
3107 anObj = GetEngine()->AddSubShape(theCompound, anArray);
3108 aBlocks->Append(anObj);
3110 // For Python command
3111 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
3112 anAsciiList += anEntry + ", ";
3113 if (aFunction.IsNull())
3114 aFunction = anObj->GetLastFunction();
3118 catch (Standard_Failure) {
3119 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3120 SetErrorCode(aFail->GetMessageString());
3124 //Make a Python command
3125 aPartsDescr.Trunc(aPartsDescr.Length() - 2);
3126 anAsciiList.Trunc(anAsciiList.Length() - 2);
3128 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3129 << "] = geompy.GetBlocksByParts(" << theCompound
3130 << ", [" << aPartsDescr.ToCString() << "])";
3136 //=============================================================================
3138 * MakeMultiTransformation1D
3140 //=============================================================================
3141 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeMultiTransformation1D
3142 (Handle(GEOM_Object) theObject,
3143 const Standard_Integer theDirFace1,
3144 const Standard_Integer theDirFace2,
3145 const Standard_Integer theNbTimes)
3149 if (theObject.IsNull()) return NULL;
3151 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
3152 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be moved
3154 //Add a new Copy object
3155 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
3157 //Add a translate function
3158 Handle(GEOM_Function) aFunction =
3159 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_MULTI_TRANSFORM_1D);
3161 //Check if the function is set correctly
3162 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
3164 GEOMImpl_IBlockTrsf aTI (aFunction);
3165 aTI.SetOriginal(aLastFunction);
3166 aTI.SetFace1U(theDirFace1);
3167 aTI.SetFace2U(theDirFace2);
3168 aTI.SetNbIterU(theNbTimes);
3170 //Compute the transformation
3172 #if OCC_VERSION_LARGE > 0x06010000
3175 if (!GetSolver()->ComputeFunction(aFunction)) {
3176 SetErrorCode("Block driver failed to make multi-transformation");
3180 catch (Standard_Failure) {
3181 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3182 SetErrorCode(aFail->GetMessageString());
3186 //Make a Python command
3187 GEOM::TPythonDump(aFunction) << aCopy << " = geompy.MakeMultiTransformation1D("
3188 << theObject << ", " << theDirFace1 << ", " << theDirFace2 << ", " << theNbTimes << ")";
3194 //=============================================================================
3196 * MakeMultiTransformation2D
3198 //=============================================================================
3199 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeMultiTransformation2D
3200 (Handle(GEOM_Object) theObject,
3201 const Standard_Integer theDirFace1U,
3202 const Standard_Integer theDirFace2U,
3203 const Standard_Integer theNbTimesU,
3204 const Standard_Integer theDirFace1V,
3205 const Standard_Integer theDirFace2V,
3206 const Standard_Integer theNbTimesV)
3210 if (theObject.IsNull()) return NULL;
3212 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
3213 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be moved
3215 //Add a new Copy object
3216 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
3218 //Add a translate function
3219 Handle(GEOM_Function) aFunction =
3220 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_MULTI_TRANSFORM_2D);
3222 //Check if the function is set correctly
3223 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
3225 GEOMImpl_IBlockTrsf aTI (aFunction);
3226 aTI.SetOriginal(aLastFunction);
3227 aTI.SetFace1U(theDirFace1U);
3228 aTI.SetFace2U(theDirFace2U);
3229 aTI.SetNbIterU(theNbTimesU);
3230 aTI.SetFace1V(theDirFace1V);
3231 aTI.SetFace2V(theDirFace2V);
3232 aTI.SetNbIterV(theNbTimesV);
3234 //Compute the transformation
3236 #if OCC_VERSION_LARGE > 0x06010000
3239 if (!GetSolver()->ComputeFunction(aFunction)) {
3240 SetErrorCode("Block driver failed to make multi-transformation");
3244 catch (Standard_Failure) {
3245 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3246 SetErrorCode(aFail->GetMessageString());
3250 //Make a Python command
3251 GEOM::TPythonDump(aFunction) << aCopy << " = geompy.MakeMultiTransformation2D("
3252 << theObject << ", " << theDirFace1U << ", " << theDirFace2U << ", " << theNbTimesU
3253 << ", " << theDirFace1V << ", " << theDirFace2V << ", " << theNbTimesV << ")";
3259 //=============================================================================
3263 //=============================================================================
3264 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::Propagate
3265 (Handle(GEOM_Object) theShape)
3269 if (theShape.IsNull()) return NULL;
3271 TopoDS_Shape aShape = theShape->GetValue();
3272 if (aShape.IsNull()) return NULL;
3274 TopTools_IndexedMapOfShape anIndices;
3275 TopExp::MapShapes(aShape, anIndices);
3277 TopTools_IndexedDataMapOfShapeListOfShape MEW;
3278 GEOMImpl_Block6Explorer::MapShapesAndAncestors
3279 (aShape, TopAbs_EDGE, TopAbs_WIRE, MEW);
3280 Standard_Integer ie, nbEdges = MEW.Extent();
3283 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
3285 TopTools_MapOfShape mapAcceptedEdges;
3286 TCollection_AsciiString aListRes, anEntry;
3288 // Sort shapes in current chain (Mantis issue 21053)
3289 TopTools_DataMapOfShapeListOfShape aMapChains;
3290 TopTools_ListOfShape aFirstInChains;
3292 for (ie = 1; ie <= nbEdges; ie++) {
3293 TopoDS_Shape curE = MEW.FindKey(ie);
3295 if (mapAcceptedEdges.Contains(curE)) continue;
3298 TopTools_ListOfShape currentChain;
3299 TopTools_ListOfShape listPrevEdges;
3301 currentChain.Append(curE);
3302 listPrevEdges.Append(curE);
3303 mapAcceptedEdges.Add(curE);
3305 // Collect all edges pass by pass
3306 while (listPrevEdges.Extent() > 0) {
3307 // List of edges, added to chain on this cycle pass
3308 TopTools_ListOfShape listCurEdges;
3310 // Find the next portion of edges
3311 TopTools_ListIteratorOfListOfShape itE (listPrevEdges);
3312 for (; itE.More(); itE.Next()) {
3313 TopoDS_Shape anE = itE.Value();
3315 // Iterate on faces, having edge <anE>
3316 TopTools_ListIteratorOfListOfShape itW (MEW.FindFromKey(anE));
3317 for (; itW.More(); itW.Next()) {
3318 TopoDS_Shape aW = itW.Value();
3319 TopoDS_Shape anOppE;
3321 BRepTools_WireExplorer aWE (TopoDS::Wire(aW));
3322 Standard_Integer nb = 1, found = 0;
3323 TopTools_Array1OfShape anEdges (1,4);
3324 for (; aWE.More(); aWE.Next(), nb++) {
3329 anEdges(nb) = aWE.Current();
3330 if (anEdges(nb).IsSame(anE)) found = nb;
3333 if (nb == 5 && found > 0) {
3334 // Quadrangle face found, get an opposite edge
3335 Standard_Integer opp = found + 2;
3336 if (opp > 4) opp -= 4;
3337 anOppE = anEdges(opp);
3339 if (!mapAcceptedEdges.Contains(anOppE)) {
3340 // Add found edge to the chain
3341 currentChain.Append(anOppE);
3342 listCurEdges.Append(anOppE);
3343 mapAcceptedEdges.Add(anOppE);
3345 } // if (nb == 5 && found > 0)
3346 } // for (; itF.More(); itF.Next())
3347 } // for (; itE.More(); itE.Next())
3349 listPrevEdges = listCurEdges;
3350 } // while (listPrevEdges.Extent() > 0)
3352 // Sort shapes in current chain (Mantis issue 21053)
3353 GEOMImpl_IShapesOperations::SortShapes(currentChain, Standard_False);
3354 aFirstInChains.Append(currentChain.First());
3355 aMapChains.Bind(currentChain.First(), currentChain);
3358 // Sort chains (Mantis issue 21053)
3359 GEOMImpl_IShapesOperations::SortShapes(aFirstInChains, Standard_False);
3361 // Store sorted chains in the document
3362 TopTools_ListIteratorOfListOfShape aChainsIt (aFirstInChains);
3363 for (; aChainsIt.More(); aChainsIt.Next()) {
3364 TopoDS_Shape aFirstInChain = aChainsIt.Value();
3365 const TopTools_ListOfShape& currentChain = aMapChains.Find(aFirstInChain);
3367 // Store the chain in the document
3368 Handle(TColStd_HArray1OfInteger) anArray =
3369 new TColStd_HArray1OfInteger (1, currentChain.Extent());
3371 // Fill array of sub-shape indices
3372 TopTools_ListIteratorOfListOfShape itSub (currentChain);
3373 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
3374 int id = anIndices.FindIndex(itSub.Value());
3375 anArray->SetValue(index, id);
3378 // Add a new group object
3379 Handle(GEOM_Object) aChain = GetEngine()->AddSubShape(theShape, anArray);
3382 aChain->SetType(GEOM_GROUP);
3384 // Set a sub shape type
3385 TDF_Label aFreeLabel = aChain->GetFreeLabel();
3386 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)TopAbs_EDGE);
3388 // Add the chain to the result
3389 aSeq->Append(aChain);
3391 //Make a Python command
3392 TDF_Tool::Entry(aChain->GetEntry(), anEntry);
3393 aListRes += anEntry + ", ";
3396 if (aSeq->IsEmpty()) {
3397 SetErrorCode("There are no quadrangle faces in the shape");
3401 aListRes.Trunc(aListRes.Length() - 2);
3403 // The Propagation doesn't change object so no new function is required.
3404 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
3406 // Make a Python command
3407 GEOM::TPythonDump(aFunction, /*append=*/true)
3408 << "[" << aListRes.ToCString() << "] = geompy.Propagate(" << theShape << ")";