1 // Copyright (C) 2005 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License.
9 // This library is distributed in the hope that it will be useful
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 #pragma warning( disable:4786 )
24 #include <Standard_Stream.hxx>
26 #include <GEOMImpl_IBlocksOperations.hxx>
28 #include <GEOMImpl_Types.hxx>
30 #include <GEOMImpl_BlockDriver.hxx>
31 #include <GEOMImpl_IBlocks.hxx>
32 #include <GEOMImpl_IBlockTrsf.hxx>
33 #include <GEOMImpl_CopyDriver.hxx>
34 #include <GEOMImpl_Block6Explorer.hxx>
36 #include <GEOM_Function.hxx>
37 #include <GEOM_PythonDump.hxx>
39 #include <GEOMAlgo_GlueAnalyser.hxx>
40 #include <GEOMAlgo_CoupleOfShapes.hxx>
41 #include <GEOMAlgo_ListOfCoupleOfShapes.hxx>
42 #include <GEOMAlgo_ListIteratorOfListOfCoupleOfShapes.hxx>
43 #include <BlockFix_CheckTool.hxx>
45 #include "utilities.h"
47 #include <Utils_ExceptHandlers.hxx>
49 #include <TFunction_DriverTable.hxx>
50 #include <TFunction_Driver.hxx>
51 #include <TFunction_Logbook.hxx>
52 #include <TDataStd_Integer.hxx>
53 #include <TDF_Tool.hxx>
55 #include <BRep_Tool.hxx>
56 #include <BRep_Builder.hxx>
57 #include <BRepTools.hxx>
58 #include <BRepTools_WireExplorer.hxx>
59 #include <BRepGProp.hxx>
60 #include <BRepBndLib.hxx>
61 #include <BRepAdaptor_Surface.hxx>
62 #include <BRepClass_FaceClassifier.hxx>
63 #include <BRepClass3d_SolidClassifier.hxx>
64 #include <BRepExtrema_DistShapeShape.hxx>
68 #include <TopoDS_Edge.hxx>
69 #include <TopoDS_Vertex.hxx>
70 #include <TopoDS_Compound.hxx>
71 #include <TopoDS_Iterator.hxx>
73 #include <TopExp_Explorer.hxx>
74 #include <TopTools_MapOfShape.hxx>
75 #include <TopTools_Array1OfShape.hxx>
76 #include <TopTools_IndexedMapOfShape.hxx>
77 #include <TopTools_DataMapOfShapeInteger.hxx>
78 #include <TopTools_ListIteratorOfListOfShape.hxx>
79 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
80 #include <TopTools_DataMapIteratorOfDataMapOfShapeInteger.hxx>
82 #include <Bnd_Box.hxx>
83 #include <GProp_GProps.hxx>
85 #include <Geom_Surface.hxx>
86 #include <ShapeAnalysis_Surface.hxx>
88 #include <TColStd_MapOfInteger.hxx>
89 #include <TColStd_Array1OfReal.hxx>
90 #include <TColStd_Array1OfInteger.hxx>
91 #include <TColStd_Array2OfInteger.hxx>
93 //#include <OSD_Timer.hxx>
95 #include <Precision.hxx>
97 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
99 //=============================================================================
103 //=============================================================================
104 GEOMImpl_IBlocksOperations::GEOMImpl_IBlocksOperations (GEOM_Engine* theEngine, int theDocID)
105 : GEOM_IOperations(theEngine, theDocID)
107 MESSAGE("GEOMImpl_IBlocksOperations::GEOMImpl_IBlocksOperations");
110 //=============================================================================
114 //=============================================================================
115 GEOMImpl_IBlocksOperations::~GEOMImpl_IBlocksOperations()
117 MESSAGE("GEOMImpl_IBlocksOperations::~GEOMImpl_IBlocksOperations");
121 //=============================================================================
125 //=============================================================================
126 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad
127 (Handle(GEOM_Object) theEdge1, Handle(GEOM_Object) theEdge2,
128 Handle(GEOM_Object) theEdge3, Handle(GEOM_Object) theEdge4)
132 if (theEdge1.IsNull() || theEdge2.IsNull() ||
133 theEdge3.IsNull() || theEdge4.IsNull()) return NULL;
135 //Add a new Face object
136 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
138 //Add a new Face function
139 Handle(GEOM_Function) aFunction =
140 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_FOUR_EDGES);
142 //Check if the function is set correctly
143 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
145 GEOMImpl_IBlocks aPI (aFunction);
147 Handle(GEOM_Function) aRef1 = theEdge1->GetLastFunction();
148 Handle(GEOM_Function) aRef2 = theEdge2->GetLastFunction();
149 Handle(GEOM_Function) aRef3 = theEdge3->GetLastFunction();
150 Handle(GEOM_Function) aRef4 = theEdge4->GetLastFunction();
151 if (aRef1.IsNull() || aRef2.IsNull() ||
152 aRef3.IsNull() || aRef4.IsNull()) return NULL;
154 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
155 aShapesSeq->Append(aRef1);
156 aShapesSeq->Append(aRef2);
157 aShapesSeq->Append(aRef3);
158 aShapesSeq->Append(aRef4);
160 aPI.SetShapes(aShapesSeq);
162 //Compute the Face value
164 if (!GetSolver()->ComputeFunction(aFunction)) {
165 SetErrorCode("Block driver failed to compute a face");
169 catch (Standard_Failure) {
170 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
171 SetErrorCode(aFail->GetMessageString());
175 //Make a Python command
176 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeQuad("
177 << theEdge1 << ", " << theEdge2 << ", " << theEdge3 << ", " << theEdge4 << ")";
183 //=============================================================================
187 //=============================================================================
188 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad2Edges
189 (Handle(GEOM_Object) theEdge1, Handle(GEOM_Object) theEdge2)
193 if (theEdge1.IsNull() || theEdge2.IsNull()) return NULL;
195 //Add a new Face object
196 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
198 //Add a new Face function
199 Handle(GEOM_Function) aFunction =
200 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_TWO_EDGES);
202 //Check if the function is set correctly
203 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
205 GEOMImpl_IBlocks aPI (aFunction);
207 Handle(GEOM_Function) aRef1 = theEdge1->GetLastFunction();
208 Handle(GEOM_Function) aRef2 = theEdge2->GetLastFunction();
209 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
211 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
212 aShapesSeq->Append(aRef1);
213 aShapesSeq->Append(aRef2);
215 aPI.SetShapes(aShapesSeq);
217 //Compute the Face value
219 if (!GetSolver()->ComputeFunction(aFunction)) {
220 SetErrorCode("Block driver failed to compute a face");
224 catch (Standard_Failure) {
225 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
226 SetErrorCode(aFail->GetMessageString());
230 //Make a Python command
231 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeQuad2Edges("
232 << theEdge1 << ", " << theEdge2 << ")";
238 //=============================================================================
242 //=============================================================================
243 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad4Vertices
244 (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2,
245 Handle(GEOM_Object) thePnt3, Handle(GEOM_Object) thePnt4)
249 if (thePnt1.IsNull() || thePnt2.IsNull() ||
250 thePnt3.IsNull() || thePnt4.IsNull()) return NULL;
252 //Add a new Face object
253 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
255 //Add a new Face function
256 Handle(GEOM_Function) aFunction =
257 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_FOUR_PNT);
259 //Check if the function is set correctly
260 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
262 GEOMImpl_IBlocks aPI (aFunction);
264 Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
265 Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
266 Handle(GEOM_Function) aRef3 = thePnt3->GetLastFunction();
267 Handle(GEOM_Function) aRef4 = thePnt4->GetLastFunction();
268 if (aRef1.IsNull() || aRef2.IsNull() ||
269 aRef3.IsNull() || aRef4.IsNull()) return NULL;
271 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
272 aShapesSeq->Append(aRef1);
273 aShapesSeq->Append(aRef2);
274 aShapesSeq->Append(aRef3);
275 aShapesSeq->Append(aRef4);
277 aPI.SetShapes(aShapesSeq);
279 //Compute the Face value
281 if (!GetSolver()->ComputeFunction(aFunction)) {
282 SetErrorCode("Block driver failed to compute a face");
286 catch (Standard_Failure) {
287 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
288 SetErrorCode(aFail->GetMessageString());
292 //Make a Python command
293 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeQuad4Vertices("
294 << thePnt1 << ", " << thePnt2 << ", " << thePnt3 << ", " << thePnt4 << ")";
300 //=============================================================================
304 //=============================================================================
305 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeHexa
306 (Handle(GEOM_Object) theFace1, Handle(GEOM_Object) theFace2,
307 Handle(GEOM_Object) theFace3, Handle(GEOM_Object) theFace4,
308 Handle(GEOM_Object) theFace5, Handle(GEOM_Object) theFace6)
312 if (theFace1.IsNull() || theFace2.IsNull() ||
313 theFace3.IsNull() || theFace4.IsNull() ||
314 theFace5.IsNull() || theFace6.IsNull()) return NULL;
316 //Add a new Solid object
317 Handle(GEOM_Object) aBlock = GetEngine()->AddObject(GetDocID(), GEOM_BLOCK);
319 //Add a new Block function
320 Handle(GEOM_Function) aFunction =
321 aBlock->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_SIX_FACES);
323 //Check if the function is set correctly
324 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
326 GEOMImpl_IBlocks aPI (aFunction);
328 Handle(GEOM_Function) aRef1 = theFace1->GetLastFunction();
329 Handle(GEOM_Function) aRef2 = theFace2->GetLastFunction();
330 Handle(GEOM_Function) aRef3 = theFace3->GetLastFunction();
331 Handle(GEOM_Function) aRef4 = theFace4->GetLastFunction();
332 Handle(GEOM_Function) aRef5 = theFace5->GetLastFunction();
333 Handle(GEOM_Function) aRef6 = theFace6->GetLastFunction();
334 if (aRef1.IsNull() || aRef2.IsNull() ||
335 aRef3.IsNull() || aRef4.IsNull() ||
336 aRef5.IsNull() || aRef6.IsNull()) return NULL;
338 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
339 aShapesSeq->Append(aRef1);
340 aShapesSeq->Append(aRef2);
341 aShapesSeq->Append(aRef3);
342 aShapesSeq->Append(aRef4);
343 aShapesSeq->Append(aRef5);
344 aShapesSeq->Append(aRef6);
346 aPI.SetShapes(aShapesSeq);
348 //Compute the Block value
350 if (!GetSolver()->ComputeFunction(aFunction)) {
351 SetErrorCode("Block driver failed to compute a block");
355 catch (Standard_Failure) {
356 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
357 SetErrorCode(aFail->GetMessageString());
361 //Make a Python command
362 GEOM::TPythonDump(aFunction) << aBlock << " = geompy.MakeHexa("
363 << theFace1 << ", " << theFace2 << ", " << theFace3 << ", "
364 << theFace4 << ", " << theFace5 << ", " << theFace6 << ")";
370 //=============================================================================
374 //=============================================================================
375 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeHexa2Faces
376 (Handle(GEOM_Object) theFace1, Handle(GEOM_Object) theFace2)
380 if (theFace1.IsNull() || theFace2.IsNull()) return NULL;
382 //Add a new Solid object
383 Handle(GEOM_Object) aBlock = GetEngine()->AddObject(GetDocID(), GEOM_BLOCK);
385 //Add a new Block function
386 Handle(GEOM_Function) aFunction =
387 aBlock->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_TWO_FACES);
389 //Check if the function is set correctly
390 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
392 GEOMImpl_IBlocks aPI (aFunction);
394 Handle(GEOM_Function) aRef1 = theFace1->GetLastFunction();
395 Handle(GEOM_Function) aRef2 = theFace2->GetLastFunction();
396 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
398 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
399 aShapesSeq->Append(aRef1);
400 aShapesSeq->Append(aRef2);
402 aPI.SetShapes(aShapesSeq);
404 //Compute the Block value
406 if (!GetSolver()->ComputeFunction(aFunction)) {
407 SetErrorCode("Block driver failed to compute a block");
411 catch (Standard_Failure) {
412 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
413 SetErrorCode(aFail->GetMessageString());
417 //Make a Python command
418 GEOM::TPythonDump(aFunction) << aBlock << " = geompy.MakeHexa2Faces("
419 << theFace1 << ", " << theFace2 << ")";
425 //=============================================================================
429 //=============================================================================
430 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeBlockCompound
431 (Handle(GEOM_Object) theCompound)
435 if (theCompound.IsNull()) return NULL;
438 Handle(GEOM_Object) aBlockComp = GetEngine()->AddObject(GetDocID(), GEOM_COMPOUND);
440 //Add a new BlocksComp function
441 Handle(GEOM_Function) aFunction =
442 aBlockComp->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_COMPOUND_GLUE);
444 //Check if the function is set correctly
445 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
447 GEOMImpl_IBlocks aPI (aFunction);
449 Handle(GEOM_Function) aRef1 = theCompound->GetLastFunction();
450 if (aRef1.IsNull()) return NULL;
452 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
453 aShapesSeq->Append(aRef1);
455 aPI.SetShapes(aShapesSeq);
457 //Compute the Blocks Compound value
459 if (!GetSolver()->ComputeFunction(aFunction)) {
460 SetErrorCode("Block driver failed to compute a blocks compound");
464 catch (Standard_Failure) {
465 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
466 SetErrorCode(aFail->GetMessageString());
470 //Make a Python command
471 GEOM::TPythonDump(aFunction) << aBlockComp
472 << " = geompy.MakeBlockCompound(" << theCompound << ")";
478 //=============================================================================
482 //=============================================================================
483 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetPoint
484 (Handle(GEOM_Object) theShape,
485 const Standard_Real theX,
486 const Standard_Real theY,
487 const Standard_Real theZ,
488 const Standard_Real theEpsilon)
493 Handle(GEOM_Object) aResult;
496 if (theShape.IsNull()) return NULL;
498 TopoDS_Shape aBlockOrComp = theShape->GetValue();
499 if (aBlockOrComp.IsNull()) {
500 SetErrorCode("Given shape is null");
504 //Compute the Vertex value
505 gp_Pnt P (theX, theY, theZ);
506 Standard_Real eps = Max(theEpsilon, Precision::Confusion());
509 Standard_Integer isFound = 0;
510 TopTools_MapOfShape mapShape;
511 TopExp_Explorer exp (aBlockOrComp, TopAbs_VERTEX);
513 for (; exp.More(); exp.Next()) {
514 if (mapShape.Add(exp.Current())) {
515 TopoDS_Vertex aVi = TopoDS::Vertex(exp.Current());
516 gp_Pnt aPi = BRep_Tool::Pnt(aVi);
517 if (aPi.Distance(P) < eps) {
525 SetErrorCode("Vertex has not been found");
527 } else if (isFound > 1) {
528 SetErrorCode("Multiple vertices found by the given coordinates and epsilon");
531 TopTools_IndexedMapOfShape anIndices;
532 TopExp::MapShapes(aBlockOrComp, anIndices);
533 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
534 anArray->SetValue(1, anIndices.FindIndex(V));
535 aResult = GetEngine()->AddSubShape(theShape, anArray);
538 //The GetPoint() doesn't change object so no new function is required.
539 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
541 //Make a Python command
542 GEOM::TPythonDump(aFunction, /*append=*/true)
543 << aResult << " = geompy.GetPoint(" << theShape << ", "
544 << theX << ", " << theY << ", " << theZ << ", " << theEpsilon << ")";
550 //=============================================================================
554 //=============================================================================
555 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetEdge
556 (Handle(GEOM_Object) theShape,
557 Handle(GEOM_Object) thePoint1,
558 Handle(GEOM_Object) thePoint2)
563 Handle(GEOM_Object) aResult;
566 if (theShape.IsNull() || thePoint1.IsNull() || thePoint2.IsNull()) return NULL;
568 TopoDS_Shape aBlockOrComp = theShape->GetValue();
569 if (aBlockOrComp.IsNull()) {
570 SetErrorCode("Given shape is null");
574 TopoDS_Shape anArg1 = thePoint1->GetValue();
575 TopoDS_Shape anArg2 = thePoint2->GetValue();
576 if (anArg1.IsNull() || anArg2.IsNull()) {
577 SetErrorCode("Null shape is given as argument");
580 if (anArg1.ShapeType() != TopAbs_VERTEX ||
581 anArg2.ShapeType() != TopAbs_VERTEX) {
582 SetErrorCode("Element for edge identification is not a vertex");
586 //Compute the Edge value
588 TopTools_IndexedDataMapOfShapeListOfShape MVE;
589 GEOMImpl_Block6Explorer::MapShapesAndAncestors
590 (aBlockOrComp, TopAbs_VERTEX, TopAbs_EDGE, MVE);
593 Standard_Integer ish, ext = MVE.Extent();
595 if (MVE.Contains(anArg1)) {
598 for (ish = 1; ish <= ext; ish++) {
599 TopoDS_Shape aShi = MVE.FindKey(ish);
600 if (BRepTools::Compare(TopoDS::Vertex(anArg1), TopoDS::Vertex(aShi))) {
607 if (MVE.Contains(anArg2)) {
610 for (ish = 1; ish <= ext; ish++) {
611 TopoDS_Shape aShi = MVE.FindKey(ish);
612 if (BRepTools::Compare(TopoDS::Vertex(anArg2), TopoDS::Vertex(aShi))) {
619 if (V1.IsNull() || V2.IsNull()) {
620 SetErrorCode("The given vertex does not belong to the shape");
625 Standard_Integer isFound =
626 GEOMImpl_Block6Explorer::FindEdge(anEdge, V1, V2, MVE, Standard_True);
628 SetErrorCode("The given vertices do not belong to one edge of the given shape");
630 } else if (isFound > 1) {
631 SetErrorCode("Multiple edges found by the given vertices of the shape");
634 TopTools_IndexedMapOfShape anIndices;
635 TopExp::MapShapes(aBlockOrComp, anIndices);
636 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
637 anArray->SetValue(1, anIndices.FindIndex(anEdge));
638 aResult = GetEngine()->AddSubShape(theShape, anArray);
640 } catch (Standard_Failure) {
641 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
642 SetErrorCode(aFail->GetMessageString());
646 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
648 //Make a Python command
649 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetEdge("
650 << theShape << ", " << thePoint1 << ", " << thePoint2 << ")";
656 //=============================================================================
660 //=============================================================================
661 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetEdgeNearPoint
662 (Handle(GEOM_Object) theShape,
663 Handle(GEOM_Object) thePoint)
668 Handle(GEOM_Object) aResult;
671 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
673 TopoDS_Shape aBlockOrComp = theShape->GetValue();
674 if (aBlockOrComp.IsNull()) {
675 SetErrorCode("Given shape is null");
679 TopoDS_Shape anArg = thePoint->GetValue();
680 if (anArg.IsNull()) {
681 SetErrorCode("Null shape is given as argument");
684 if (anArg.ShapeType() != TopAbs_VERTEX) {
685 SetErrorCode("Element for edge identification is not a vertex");
689 //Compute the Edge value
693 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
695 // 1. Explode blocks on edges
696 TopTools_MapOfShape mapShape;
697 Standard_Integer nbEdges = 0;
698 TopExp_Explorer exp (aBlockOrComp, TopAbs_EDGE);
699 for (; exp.More(); exp.Next()) {
700 if (mapShape.Add(exp.Current())) {
706 SetErrorCode("Given shape contains no edges");
711 Standard_Integer ind = 1;
712 TopTools_Array1OfShape anEdges (1, nbEdges);
713 TColStd_Array1OfReal aDistances (1, nbEdges);
714 for (exp.Init(aBlockOrComp, TopAbs_EDGE); exp.More(); exp.Next()) {
715 if (mapShape.Add(exp.Current())) {
716 TopoDS_Shape anEdge = exp.Current();
717 anEdges(ind) = anEdge;
719 // 2. Classify the point relatively each edge
720 BRepExtrema_DistShapeShape aDistTool (aVert, anEdges(ind));
721 if (!aDistTool.IsDone()) {
722 SetErrorCode("Can not find a distance from the given point to one of edges");
725 aDistances(ind) = aDistTool.Value();
730 // 3. Define edge, having minimum distance to the point
731 Standard_Real nearest = RealLast(), nbFound = 0;
732 Standard_Real prec = Precision::Confusion();
733 for (ind = 1; ind <= nbEdges; ind++) {
734 if (Abs(aDistances(ind) - nearest) < prec) {
736 } else if (aDistances(ind) < nearest) {
737 nearest = aDistances(ind);
738 aShape = anEdges(ind);
744 SetErrorCode("Multiple edges near the given point are found");
746 } else if (nbFound == 0) {
747 SetErrorCode("There are no edges near the given point");
750 TopTools_IndexedMapOfShape anIndices;
751 TopExp::MapShapes(aBlockOrComp, anIndices);
752 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
753 anArray->SetValue(1, anIndices.FindIndex(aShape));
754 aResult = GetEngine()->AddSubShape(theShape, anArray);
757 catch (Standard_Failure) {
758 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
759 SetErrorCode(aFail->GetMessageString());
763 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
765 //Make a Python command
766 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetEdgeNearPoint("
767 << theShape << ", " << thePoint << ")";
773 //=============================================================================
777 //=============================================================================
778 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByPoints
779 (Handle(GEOM_Object) theShape,
780 Handle(GEOM_Object) thePoint1,
781 Handle(GEOM_Object) thePoint2,
782 Handle(GEOM_Object) thePoint3,
783 Handle(GEOM_Object) thePoint4)
788 Handle(GEOM_Object) aResult;
791 if (theShape.IsNull() ||
792 thePoint1.IsNull() || thePoint2.IsNull() ||
793 thePoint3.IsNull() || thePoint4.IsNull()) return NULL;
795 TopoDS_Shape aBlockOrComp = theShape->GetValue();
796 if (aBlockOrComp.IsNull()) {
797 SetErrorCode("Block or compound is null");
801 TopoDS_Shape anArg1 = thePoint1->GetValue();
802 TopoDS_Shape anArg2 = thePoint2->GetValue();
803 TopoDS_Shape anArg3 = thePoint3->GetValue();
804 TopoDS_Shape anArg4 = thePoint4->GetValue();
805 if (anArg1.IsNull() || anArg2.IsNull() ||
806 anArg3.IsNull() || anArg4.IsNull()) {
807 SetErrorCode("Null shape is given as argument");
810 if (anArg1.ShapeType() != TopAbs_VERTEX ||
811 anArg2.ShapeType() != TopAbs_VERTEX ||
812 anArg3.ShapeType() != TopAbs_VERTEX ||
813 anArg4.ShapeType() != TopAbs_VERTEX) {
814 SetErrorCode("Element for face identification is not a vertex");
818 //Compute the Face value
822 TopTools_IndexedDataMapOfShapeListOfShape MVF;
823 GEOMImpl_Block6Explorer::MapShapesAndAncestors(aBlockOrComp, TopAbs_VERTEX, TopAbs_FACE, MVF);
825 TopoDS_Shape V1,V2,V3,V4;
826 Standard_Integer ish, ext = MVF.Extent();
828 if (MVF.Contains(anArg1)) {
831 for (ish = 1; ish <= ext; ish++) {
832 TopoDS_Shape aShi = MVF.FindKey(ish);
833 if (BRepTools::Compare(TopoDS::Vertex(anArg1), TopoDS::Vertex(aShi))) {
840 if (MVF.Contains(anArg2)) {
843 for (ish = 1; ish <= ext; ish++) {
844 TopoDS_Shape aShi = MVF.FindKey(ish);
845 if (BRepTools::Compare(TopoDS::Vertex(anArg2), TopoDS::Vertex(aShi))) {
852 if (MVF.Contains(anArg3)) {
855 for (ish = 1; ish <= ext; ish++) {
856 TopoDS_Shape aShi = MVF.FindKey(ish);
857 if (BRepTools::Compare(TopoDS::Vertex(anArg3), TopoDS::Vertex(aShi))) {
864 if (MVF.Contains(anArg4)) {
867 for (ish = 1; ish <= ext; ish++) {
868 TopoDS_Shape aShi = MVF.FindKey(ish);
869 if (BRepTools::Compare(TopoDS::Vertex(anArg4), TopoDS::Vertex(aShi))) {
876 if (V1.IsNull() || V2.IsNull() || V3.IsNull() || V4.IsNull()) {
877 SetErrorCode("The given vertex does not belong to the shape");
881 Standard_Integer isFound =
882 GEOMImpl_Block6Explorer::FindFace(aShape, V1, V2, V3, V4, MVF, Standard_True);
884 SetErrorCode("The given vertices do not belong to one face of the given shape");
886 } else if (isFound > 1) {
887 SetErrorCode("The given vertices belong to several faces of the given shape");
890 TopTools_IndexedMapOfShape anIndices;
891 TopExp::MapShapes(aBlockOrComp, anIndices);
892 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
893 anArray->SetValue(1, anIndices.FindIndex(aShape));
894 aResult = GetEngine()->AddSubShape(theShape, anArray);
897 catch (Standard_Failure) {
898 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
899 SetErrorCode(aFail->GetMessageString());
903 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
905 //Make a Python command
906 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByPoints("
907 << theShape << ", " << thePoint1 << ", " << thePoint2
908 << ", " << thePoint3 << ", " << thePoint4 << ")";
914 //=============================================================================
918 //=============================================================================
919 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByEdges
920 (Handle(GEOM_Object) theShape,
921 Handle(GEOM_Object) theEdge1,
922 Handle(GEOM_Object) theEdge2)
927 Handle(GEOM_Object) aResult;
930 if (theShape.IsNull() || theEdge1.IsNull() || theEdge2.IsNull()) return NULL;
932 TopoDS_Shape aBlockOrComp = theShape->GetValue();
933 if (aBlockOrComp.IsNull()) {
934 SetErrorCode("Block or compound is null");
937 if (aBlockOrComp.ShapeType() != TopAbs_SOLID &&
938 aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
939 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
940 SetErrorCode("Shape is neither a block, nor a compound of blocks");
944 TopoDS_Shape anArg1 = theEdge1->GetValue();
945 TopoDS_Shape anArg2 = theEdge2->GetValue();
946 if (anArg1.IsNull() || anArg2.IsNull()) {
947 SetErrorCode("Null shape is given as argument");
950 if (anArg1.ShapeType() != TopAbs_EDGE ||
951 anArg2.ShapeType() != TopAbs_EDGE) {
952 SetErrorCode("Element for face identification is not an edge");
956 //Compute the Face value
960 TopTools_IndexedDataMapOfShapeListOfShape MEF;
961 GEOMImpl_Block6Explorer::MapShapesAndAncestors(aBlockOrComp, TopAbs_EDGE, TopAbs_FACE, MEF);
964 Standard_Integer ish, ext = MEF.Extent();
966 if (MEF.Contains(anArg1)) {
969 for (ish = 1; ish <= ext; ish++) {
970 TopoDS_Shape aShi = MEF.FindKey(ish);
971 if (GEOMImpl_Block6Explorer::IsSimilarEdges(anArg1, aShi)) {
977 if (MEF.Contains(anArg2)) {
980 for (ish = 1; ish <= ext; ish++) {
981 TopoDS_Shape aShi = MEF.FindKey(ish);
982 if (GEOMImpl_Block6Explorer::IsSimilarEdges(anArg2, aShi)) {
988 if (E1.IsNull() || E2.IsNull()) {
989 SetErrorCode("The given edge does not belong to the shape");
993 const TopTools_ListOfShape& aFacesOfE1 = MEF.FindFromKey(E1);
994 const TopTools_ListOfShape& aFacesOfE2 = MEF.FindFromKey(E2);
996 Standard_Integer isFound = 0;
997 TopTools_ListIteratorOfListOfShape anIterF1 (aFacesOfE1);
998 for (; anIterF1.More(); anIterF1.Next()) {
1000 TopTools_ListIteratorOfListOfShape anIterF2 (aFacesOfE2);
1001 for (; anIterF2.More(); anIterF2.Next()) {
1003 if (anIterF1.Value().IsSame(anIterF2.Value())) {
1006 // Store the face, defined by two edges
1007 aShape = anIterF1.Value();
1012 SetErrorCode("The given edges do not belong to one face of the given shape");
1014 } else if (isFound > 1) {
1015 SetErrorCode("The given edges belong to several faces of the given shape");
1018 TopTools_IndexedMapOfShape anIndices;
1019 TopExp::MapShapes(aBlockOrComp, anIndices);
1020 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1021 anArray->SetValue(1, anIndices.FindIndex(aShape));
1022 aResult = GetEngine()->AddSubShape(theShape, anArray);
1025 catch (Standard_Failure) {
1026 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1027 SetErrorCode(aFail->GetMessageString());
1031 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1033 //Make a Python command
1034 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByEdges("
1035 << theShape << ", " << theEdge1 << ", " << theEdge2 << ")";
1041 //=============================================================================
1045 //=============================================================================
1046 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetOppositeFace
1047 (Handle(GEOM_Object) theShape,
1048 Handle(GEOM_Object) theFace)
1053 Handle(GEOM_Object) aResult;
1056 if (theShape.IsNull() || theFace.IsNull()) return NULL;
1058 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1059 if (aBlockOrComp.IsNull()) {
1060 SetErrorCode("Block is null");
1063 if (aBlockOrComp.ShapeType() != TopAbs_SOLID) {
1064 SetErrorCode("Shape is not a block");
1068 TopoDS_Shape anArg = theFace->GetValue();
1069 if (anArg.IsNull()) {
1070 SetErrorCode("Null shape is given as argument");
1073 if (anArg.ShapeType() != TopAbs_FACE) {
1074 SetErrorCode("Element for face identification is not a face");
1078 //Compute the Face value
1080 TopoDS_Shape aShape;
1082 GEOMImpl_Block6Explorer aBlockTool;
1083 aBlockTool.InitByBlockAndFace(aBlockOrComp, anArg);
1084 aShape = aBlockTool.GetFace(2);
1086 TopTools_IndexedMapOfShape anIndices;
1087 TopExp::MapShapes(aBlockOrComp, anIndices);
1088 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1089 anArray->SetValue(1, anIndices.FindIndex(aShape));
1090 aResult = GetEngine()->AddSubShape(theShape, anArray);
1092 catch (Standard_Failure) {
1093 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1094 SetErrorCode(aFail->GetMessageString());
1098 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1100 //Make a Python command
1101 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetOppositeFace("
1102 << theShape << ", " << theFace << ")";
1108 //=============================================================================
1112 //=============================================================================
1113 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceNearPoint
1114 (Handle(GEOM_Object) theShape,
1115 Handle(GEOM_Object) thePoint)
1120 Handle(GEOM_Object) aResult;
1123 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
1125 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1126 if (aBlockOrComp.IsNull()) {
1127 SetErrorCode("Block or compound is null");
1130 if (aBlockOrComp.ShapeType() != TopAbs_SOLID &&
1131 aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
1132 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
1133 SetErrorCode("Shape is neither a block, nor a compound of blocks");
1137 TopoDS_Shape anArg = thePoint->GetValue();
1138 if (anArg.IsNull()) {
1139 SetErrorCode("Null shape is given as argument");
1142 if (anArg.ShapeType() != TopAbs_VERTEX) {
1143 SetErrorCode("Element for face identification is not a vertex");
1147 //Compute the Face value
1149 TopoDS_Shape aShape;
1151 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
1152 gp_Pnt aPnt = BRep_Tool::Pnt(aVert);
1153 Standard_Real PX, PY, PZ;
1154 aPnt.Coord(PX, PY, PZ);
1156 // 1. Classify the point relatively each face
1157 Standard_Integer nearest = 2, nbFound = 0;
1158 TopTools_DataMapOfShapeInteger mapShapeDist;
1159 TopExp_Explorer exp (aBlockOrComp, TopAbs_FACE);
1160 for (; exp.More(); exp.Next()) {
1161 TopoDS_Shape aFace = exp.Current();
1163 if (!mapShapeDist.IsBound(aFace)) {
1164 Standard_Integer aDistance = 2;
1166 // 1.a. Classify relatively Surface
1167 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aFace));
1168 Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf);
1169 gp_Pnt2d p2dOnSurf = aSurfAna->ValueOfUV(aPnt, Precision::Confusion());
1170 gp_Pnt p3dOnSurf = aSurfAna->Value(p2dOnSurf);
1171 Standard_Real aDist = p3dOnSurf.Distance(aPnt);
1172 if (aDist > Precision::Confusion()) {
1176 // 1.b. Classify relatively the face itself
1177 BRepClass_FaceClassifier FC (TopoDS::Face(aFace), p2dOnSurf, Precision::Confusion());
1178 if (FC.State() == TopAbs_IN) {
1180 } else if (FC.State() == TopAbs_ON) {
1187 if (aDistance < nearest) {
1188 nearest = aDistance;
1192 // A first found face, containing the point inside, will be returned.
1193 // It is the solution, if there are no
1194 // coincident or intersecting faces in the compound.
1195 if (nearest == -1) break;
1197 } else if (aDistance == nearest) {
1202 mapShapeDist.Bind(aFace, aDistance);
1203 } // if (!mapShapeDist.IsBound(aFace))
1206 // 2. Define face, containing the point or having minimum distance to it
1209 // The point is on boundary of some faces and there are
1210 // no faces, having the point inside
1211 SetErrorCode("Multiple faces near the given point are found");
1214 } else if (nearest == 1) {
1215 // The point is outside some faces and there are
1216 // no faces, having the point inside or on boundary.
1217 // We will get a nearest face
1218 Standard_Real bigReal = RealLast();
1219 Standard_Real minDist = bigReal;
1220 TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
1221 for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
1222 if (mapShapeDistIter.Value() == 1) {
1223 TopoDS_Shape aFace = mapShapeDistIter.Key();
1224 Standard_Real aDist = bigReal;
1226 // 2.a. Fast check of distance - if point projection on surface is on face
1227 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aFace));
1228 Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf);
1229 gp_Pnt2d p2dOnSurf = aSurfAna->ValueOfUV(aPnt, Precision::Confusion());
1230 gp_Pnt p3dOnSurf = aSurfAna->Value(p2dOnSurf);
1231 aDist = p3dOnSurf.Distance(aPnt);
1233 BRepClass_FaceClassifier FC (TopoDS::Face(aFace), p2dOnSurf, Precision::Confusion());
1234 if (FC.State() == TopAbs_OUT) {
1235 if (aDist < minDist) {
1236 // 2.b. Slow check - if point projection on surface is outside of face
1237 BRepExtrema_DistShapeShape aDistTool (aVert, aFace);
1238 if (!aDistTool.IsDone()) {
1239 SetErrorCode("Can not find a distance from the given point to one of faces");
1242 aDist = aDistTool.Value();
1248 if (aDist < minDist) {
1254 } else { // nearest == -1
1255 // // The point is inside some faces.
1256 // // We will get a face with nearest center
1257 // Standard_Real minDist = RealLast();
1258 // TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
1259 // for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
1260 // if (mapShapeDistIter.Value() == -1) {
1261 // TopoDS_Shape aFace = mapShapeDistIter.Key();
1262 // GProp_GProps aSystem;
1263 // BRepGProp::SurfaceProperties(aFace, aSystem);
1264 // gp_Pnt aCenterMass = aSystem.CentreOfMass();
1266 // Standard_Real aDist = aCenterMass.Distance(aPnt);
1267 // if (aDist < minDist) {
1274 } // if (nbFound > 1)
1277 SetErrorCode("There are no faces near the given point");
1280 TopTools_IndexedMapOfShape anIndices;
1281 TopExp::MapShapes(aBlockOrComp, anIndices);
1282 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1283 anArray->SetValue(1, anIndices.FindIndex(aShape));
1284 aResult = GetEngine()->AddSubShape(theShape, anArray);
1287 catch (Standard_Failure) {
1288 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1289 SetErrorCode(aFail->GetMessageString());
1293 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1295 //Make a Python command
1296 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceNearPoint("
1297 << theShape << ", " << thePoint << ")";
1303 //=============================================================================
1307 //=============================================================================
1308 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByNormale
1309 (Handle(GEOM_Object) theShape,
1310 Handle(GEOM_Object) theVector)
1315 Handle(GEOM_Object) aResult;
1318 if (theShape.IsNull() || theVector.IsNull()) return NULL;
1320 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1321 if (aBlockOrComp.IsNull()) {
1322 SetErrorCode("Block or compound is null");
1325 if (aBlockOrComp.ShapeType() != TopAbs_SOLID &&
1326 aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
1327 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
1328 SetErrorCode("Shape is neither a block, nor a compound of blocks");
1332 TopoDS_Shape anArg = theVector->GetValue();
1333 if (anArg.IsNull()) {
1334 SetErrorCode("Null shape is given as argument");
1337 if (anArg.ShapeType() != TopAbs_EDGE) {
1338 SetErrorCode("Element for normale identification is not an edge");
1342 //Compute the Face value
1344 TopoDS_Shape aShape;
1346 TopoDS_Edge anEdge = TopoDS::Edge(anArg);
1347 TopoDS_Vertex V1, V2;
1348 TopExp::Vertices(anEdge, V1, V2, Standard_True);
1349 gp_Pnt P1 = BRep_Tool::Pnt(V1);
1350 gp_Pnt P2 = BRep_Tool::Pnt(V2);
1351 gp_Vec aVec (P1, P2);
1352 if (aVec.Magnitude() < Precision::Confusion()) {
1353 SetErrorCode("Vector with null magnitude is given");
1357 Standard_Real minAngle = RealLast();
1358 TopTools_MapOfShape mapShape;
1359 TopExp_Explorer exp (aBlockOrComp, TopAbs_FACE);
1360 for (; exp.More(); exp.Next()) {
1361 if (mapShape.Add(exp.Current())) {
1362 TopoDS_Face aFace = TopoDS::Face(exp.Current());
1363 BRepAdaptor_Surface SF (aFace);
1365 Standard_Real u, v, x;
1367 // find a point on the surface to get normal direction in
1368 u = SF.FirstUParameter();
1369 x = SF.LastUParameter();
1370 if (Precision::IsInfinite(u)) {
1371 u = (Precision::IsInfinite(x)) ? 0. : x;
1372 } else if (!Precision::IsInfinite(x)) {
1376 v = SF.FirstVParameter();
1377 x = SF.LastVParameter();
1378 if (Precision::IsInfinite(v)) {
1379 v = (Precision::IsInfinite(x)) ? 0. : x;
1380 } else if (!Precision::IsInfinite(x)) {
1384 // compute the normal direction
1386 SF.D1(u,v,P1,Vec1,Vec2);
1387 gp_Vec V = Vec1.Crossed(Vec2);
1389 if (V.Magnitude() < Precision::Confusion()) {
1390 SetErrorCode("Normal vector of a face has null magnitude");
1394 // consider the face orientation
1395 if (aFace.Orientation() == TopAbs_REVERSED ||
1396 aFace.Orientation() == TopAbs_INTERNAL) {
1400 // compute the angle and compare with the minimal one
1401 Standard_Real anAngle = aVec.Angle(V);
1402 if (anAngle < minAngle) {
1409 if (aShape.IsNull()) {
1410 SetErrorCode("Failed to find a face by the given normale");
1413 TopTools_IndexedMapOfShape anIndices;
1414 TopExp::MapShapes(aBlockOrComp, anIndices);
1415 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1416 anArray->SetValue(1, anIndices.FindIndex(aShape));
1417 aResult = GetEngine()->AddSubShape(theShape, anArray);
1420 catch (Standard_Failure) {
1421 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1422 SetErrorCode(aFail->GetMessageString());
1426 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1428 //Make a Python command
1429 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByNormale("
1430 << theShape << ", " << theVector << ")";
1436 //=============================================================================
1438 * IsCompoundOfBlocks
1440 //=============================================================================
1441 Standard_Boolean GEOMImpl_IBlocksOperations::IsCompoundOfBlocks
1442 (Handle(GEOM_Object) theCompound,
1443 const Standard_Integer theMinNbFaces,
1444 const Standard_Integer theMaxNbFaces,
1445 Standard_Integer& theNbBlocks)
1448 Standard_Boolean isCompOfBlocks = Standard_False;
1451 if (theCompound.IsNull()) return isCompOfBlocks;
1452 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
1455 isCompOfBlocks = Standard_True;
1457 TopTools_MapOfShape mapShape;
1458 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
1459 for (; exp.More(); exp.Next()) {
1460 if (mapShape.Add(exp.Current())) {
1461 TopoDS_Shape aSolid = exp.Current();
1463 TopTools_MapOfShape mapFaces;
1464 TopExp_Explorer expF (aSolid, TopAbs_FACE);
1465 Standard_Integer nbFaces = 0;
1466 for (; expF.More(); expF.Next()) {
1467 if (mapFaces.Add(expF.Current())) {
1469 if (nbFaces > theMaxNbFaces) {
1470 isCompOfBlocks = Standard_False;
1475 if (nbFaces < theMinNbFaces || theMaxNbFaces < nbFaces) {
1476 isCompOfBlocks = Standard_False;
1483 catch (Standard_Failure) {
1484 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1485 SetErrorCode(aFail->GetMessageString());
1486 return isCompOfBlocks;
1490 return isCompOfBlocks;
1493 //=============================================================================
1495 * Set of functions, used by CheckCompoundOfBlocks() method
1497 //=============================================================================
1498 void GEOMImpl_IBlocksOperations::AddBlocksFrom (const TopoDS_Shape& theShape,
1499 TopTools_ListOfShape& BLO,
1500 TopTools_ListOfShape& NOT,
1501 TopTools_ListOfShape& EXT)
1503 TopAbs_ShapeEnum aType = theShape.ShapeType();
1505 case TopAbs_COMPOUND:
1506 case TopAbs_COMPSOLID:
1508 TopoDS_Iterator It (theShape);
1509 for (; It.More(); It.Next()) {
1510 AddBlocksFrom(It.Value(), BLO, NOT, EXT);
1516 // Check, if there are seam or degenerated edges
1517 BlockFix_CheckTool aTool;
1518 aTool.SetShape(theShape);
1520 if (aTool.NbPossibleBlocks() > 0) {
1521 EXT.Append(theShape);
1523 // Count faces and edges in each face to recognize blocks
1524 TopTools_MapOfShape mapFaces;
1525 Standard_Integer nbFaces = 0;
1526 Standard_Boolean hasNonQuadr = Standard_False;
1527 TopExp_Explorer expF (theShape, TopAbs_FACE);
1529 for (; expF.More(); expF.Next()) {
1530 if (mapFaces.Add(expF.Current())) {
1532 if (nbFaces > 6) break;
1535 TopoDS_Shape aF = expF.Current();
1536 TopExp_Explorer wires (aF, TopAbs_WIRE);
1537 if (!wires.More()) {
1538 // no wire in the face
1539 hasNonQuadr = Standard_True;
1542 TopoDS_Shape aWire = wires.Current();
1545 // multiple wires in the face
1546 hasNonQuadr = Standard_True;
1550 // Check number of edges in the face
1551 Standard_Integer nbEdges = 0;
1552 TopTools_MapOfShape mapEdges;
1553 TopExp_Explorer expW (aWire, TopAbs_EDGE);
1554 for (; expW.More(); expW.Next()) {
1555 if (mapEdges.Add(expW.Current())) {
1557 if (nbEdges > 4) break;
1561 hasNonQuadr = Standard_True;
1566 if (nbFaces == 6 && !hasNonQuadr) {
1567 BLO.Append(theShape);
1569 NOT.Append(theShape);
1575 NOT.Append(theShape);
1579 void AddBlocksFromOld (const TopoDS_Shape& theShape,
1580 TopTools_ListOfShape& BLO,
1581 TopTools_ListOfShape& NOT,
1582 TopTools_ListOfShape& DEG,
1583 TopTools_ListOfShape& SEA)
1585 TopAbs_ShapeEnum aType = theShape.ShapeType();
1587 case TopAbs_COMPOUND:
1588 case TopAbs_COMPSOLID:
1590 TopoDS_Iterator It (theShape);
1591 for (; It.More(); It.Next()) {
1592 AddBlocksFromOld(It.Value(), BLO, NOT, DEG, SEA);
1598 TopTools_MapOfShape mapFaces;
1599 TopExp_Explorer expF (theShape, TopAbs_FACE);
1600 Standard_Integer nbFaces = 0;
1601 Standard_Boolean hasNonQuadr = Standard_False;
1602 Standard_Boolean hasDegenerated = Standard_False;
1603 Standard_Boolean hasSeam = Standard_False;
1604 for (; expF.More(); expF.Next()) {
1605 if (mapFaces.Add(expF.Current())) {
1607 if (nbFaces > 6) break;
1609 // Check number of edges in the face
1610 Standard_Integer nbEdges = 0;
1611 TopTools_MapOfShape mapEdges;
1614 TopoDS_Shape aF = expF.Current();
1615 TopExp_Explorer wires (aF, TopAbs_WIRE);
1616 if (!wires.More()) {
1617 // no wire in the face
1618 hasNonQuadr = Standard_True;
1621 TopoDS_Shape aWire = wires.Current();
1624 // multiple wires in the face
1625 hasNonQuadr = Standard_True;
1630 BRepTools_WireExplorer aWE (TopoDS::Wire(aWire), TopoDS::Face(aF));
1631 for (; aWE.More(); aWE.Next(), nbEdges++) {
1632 if (BRep_Tool::Degenerated(aWE.Current())) {
1633 // degenerated edge found
1634 hasDegenerated = Standard_True;
1637 if (mapEdges.Contains(aWE.Current())) {
1639 hasSeam = Standard_True;
1642 mapEdges.Add(aWE.Current());
1645 hasNonQuadr = Standard_True;
1650 if (hasDegenerated || hasSeam) {
1651 if (hasDegenerated) {
1652 DEG.Append(theShape);
1655 SEA.Append(theShape);
1657 } else if (hasNonQuadr) {
1658 NOT.Append(theShape);
1660 BLO.Append(theShape);
1663 NOT.Append(theShape);
1668 NOT.Append(theShape);
1672 #define REL_NOT_CONNECTED 0
1674 #define REL_NOT_GLUED 2
1675 #define REL_COLLISION_VV 3
1676 #define REL_COLLISION_FF 4
1677 #define REL_COLLISION_EE 5
1678 #define REL_UNKNOWN 6
1680 Standard_Integer BlocksRelation (const TopoDS_Shape& theBlock1,
1681 const TopoDS_Shape& theBlock2)
1683 // Compare bounding boxes before calling BRepExtrema_DistShapeShape
1684 Standard_Real Xmin1, Ymin1, Zmin1, Xmax1, Ymax1, Zmax1;
1685 Standard_Real Xmin2, Ymin2, Zmin2, Xmax2, Ymax2, Zmax2;
1687 BRepBndLib::Add(theBlock1, B1);
1688 BRepBndLib::Add(theBlock2, B2);
1689 B1.Get(Xmin1, Ymin1, Zmin1, Xmax1, Ymax1, Zmax1);
1690 B2.Get(Xmin2, Ymin2, Zmin2, Xmax2, Ymax2, Zmax2);
1691 if (Xmax2 < Xmin1 || Xmax1 < Xmin2 ||
1692 Ymax2 < Ymin1 || Ymax1 < Ymin2 ||
1693 Zmax2 < Zmin1 || Zmax1 < Zmin2) {
1694 return REL_NOT_CONNECTED;
1697 BRepExtrema_DistShapeShape dst (theBlock1, theBlock2);
1698 if (!dst.IsDone()) {
1702 if (dst.Value() > Precision::Confusion()) {
1703 return REL_NOT_CONNECTED;
1706 if (dst.InnerSolution()) {
1707 return REL_COLLISION_VV;
1710 Standard_Integer nbSol = dst.NbSolution();
1711 Standard_Integer relation = REL_OK;
1712 Standard_Integer nbVerts = 0;
1713 Standard_Integer nbEdges = 0;
1714 Standard_Integer sol = 1;
1715 for (; sol <= nbSol; sol++) {
1716 BRepExtrema_SupportType supp1 = dst.SupportTypeShape1(sol);
1717 BRepExtrema_SupportType supp2 = dst.SupportTypeShape2(sol);
1718 if (supp1 == BRepExtrema_IsVertex && supp2 == BRepExtrema_IsVertex) {
1720 } else if (supp1 == BRepExtrema_IsInFace || supp2 == BRepExtrema_IsInFace) {
1721 return REL_COLLISION_FF;
1722 } else if (supp1 == BRepExtrema_IsOnEdge && supp2 == BRepExtrema_IsOnEdge) {
1724 } else if ((supp1 == BRepExtrema_IsOnEdge && supp2 == BRepExtrema_IsVertex) ||
1725 (supp2 == BRepExtrema_IsOnEdge && supp1 == BRepExtrema_IsVertex)) {
1726 relation = REL_COLLISION_EE;
1731 if (relation != REL_OK) {
1735 TColStd_Array1OfInteger vertSol (1, nbVerts);
1736 TopTools_Array1OfShape V1 (1, nbVerts);
1737 TopTools_Array1OfShape V2 (1, nbVerts);
1738 Standard_Integer ivs = 0;
1739 for (sol = 1; sol <= nbSol; sol++) {
1740 if (dst.SupportTypeShape1(sol) == BRepExtrema_IsVertex &&
1741 dst.SupportTypeShape2(sol) == BRepExtrema_IsVertex) {
1742 TopoDS_Vertex Vcur = TopoDS::Vertex(dst.SupportOnShape1(sol));
1743 // Check, that this vertex is far enough from other solution vertices.
1744 Standard_Integer ii = 1;
1745 for (; ii <= ivs; ii++) {
1746 if (BRepTools::Compare(TopoDS::Vertex(V1(ii)), Vcur)) {
1753 V2(ivs) = dst.SupportOnShape2(sol);
1757 // As we deal only with quadrangles,
1758 // 2, 3 or 4 vertex solutions can be found.
1761 return REL_COLLISION_FF;
1763 return REL_NOT_CONNECTED;
1769 // Check sharing of coincident entities.
1770 if (ivs == 2 || ivs == 3) {
1771 // Map vertices and edges of the blocks
1772 TopTools_IndexedDataMapOfShapeListOfShape MVE1, MVE2;
1773 GEOMImpl_Block6Explorer::MapShapesAndAncestors
1774 (theBlock1, TopAbs_VERTEX, TopAbs_EDGE, MVE1);
1775 GEOMImpl_Block6Explorer::MapShapesAndAncestors
1776 (theBlock2, TopAbs_VERTEX, TopAbs_EDGE, MVE2);
1780 TopoDS_Shape anEdge1, anEdge2;
1781 GEOMImpl_Block6Explorer::FindEdge(anEdge1, V1(1), V1(2), MVE1);
1782 if (anEdge1.IsNull()) return REL_UNKNOWN;
1784 GEOMImpl_Block6Explorer::FindEdge(anEdge2, V2(1), V2(2), MVE2);
1785 if (anEdge2.IsNull()) return REL_UNKNOWN;
1787 if (!anEdge1.IsSame(anEdge2)) return REL_NOT_GLUED;
1789 } else { // ivs == 3
1790 // Find common edges
1791 Standard_Integer e1_v1 = 1;
1792 Standard_Integer e1_v2 = 2;
1793 Standard_Integer e2_v1 = 3;
1794 Standard_Integer e2_v2 = 1;
1796 TopoDS_Shape anEdge11, anEdge12;
1797 GEOMImpl_Block6Explorer::FindEdge(anEdge11, V1(e1_v1), V1(e1_v2), MVE1);
1798 if (anEdge11.IsNull()) {
1801 GEOMImpl_Block6Explorer::FindEdge(anEdge11, V1(e1_v1), V1(e1_v2), MVE1);
1802 if (anEdge11.IsNull()) return REL_UNKNOWN;
1804 GEOMImpl_Block6Explorer::FindEdge(anEdge12, V1(e2_v1), V1(e2_v2), MVE1);
1805 if (anEdge12.IsNull()) {
1807 GEOMImpl_Block6Explorer::FindEdge(anEdge12, V1(e2_v1), V1(e2_v2), MVE1);
1808 if (anEdge12.IsNull()) return REL_UNKNOWN;
1811 TopoDS_Shape anEdge21, anEdge22;
1812 GEOMImpl_Block6Explorer::FindEdge(anEdge21, V2(e1_v1), V2(e1_v2), MVE2);
1813 if (anEdge21.IsNull()) return REL_UNKNOWN;
1814 GEOMImpl_Block6Explorer::FindEdge(anEdge22, V2(e2_v1), V2(e2_v2), MVE2);
1815 if (anEdge22.IsNull()) return REL_UNKNOWN;
1817 // Check of edges coincidence (with some precision) have to be done here
1818 // if (!anEdge11.IsEqual(anEdge21)) return REL_UNKNOWN;
1819 // if (!anEdge12.IsEqual(anEdge22)) return REL_UNKNOWN;
1821 // Check of edges sharing
1822 if (!anEdge11.IsSame(anEdge21)) return REL_NOT_GLUED;
1823 if (!anEdge12.IsSame(anEdge22)) return REL_NOT_GLUED;
1828 // Map vertices and faces of the blocks
1829 TopTools_IndexedDataMapOfShapeListOfShape MVF1, MVF2;
1830 GEOMImpl_Block6Explorer::MapShapesAndAncestors
1831 (theBlock1, TopAbs_VERTEX, TopAbs_FACE, MVF1);
1832 GEOMImpl_Block6Explorer::MapShapesAndAncestors
1833 (theBlock2, TopAbs_VERTEX, TopAbs_FACE, MVF2);
1835 TopoDS_Shape aFace1, aFace2;
1836 GEOMImpl_Block6Explorer::FindFace(aFace1, V1(1), V1(2), V1(3), V1(4), MVF1);
1837 if (aFace1.IsNull()) return REL_UNKNOWN;
1838 GEOMImpl_Block6Explorer::FindFace(aFace2, V2(1), V2(2), V2(3), V2(4), MVF2);
1839 if (aFace2.IsNull()) return REL_UNKNOWN;
1841 // Check of faces coincidence (with some precision) have to be done here
1842 // if (!aFace1.IsEqual(aFace2)) return REL_UNKNOWN;
1844 // Check of faces sharing
1845 if (!aFace1.IsSame(aFace2)) return REL_NOT_GLUED;
1851 void FindConnected (const Standard_Integer theBlockIndex,
1852 const TColStd_Array2OfInteger& theRelations,
1853 TColStd_MapOfInteger& theProcessedMap,
1854 TColStd_MapOfInteger& theConnectedMap)
1856 theConnectedMap.Add(theBlockIndex);
1857 theProcessedMap.Add(theBlockIndex);
1859 Standard_Integer nbBlocks = theRelations.ColLength();
1860 Standard_Integer col = 1;
1861 for (; col <= nbBlocks; col++) {
1862 if (theRelations(theBlockIndex, col) == REL_OK ||
1863 theRelations(theBlockIndex, col) == REL_NOT_GLUED) {
1864 if (!theProcessedMap.Contains(col)) {
1865 FindConnected(col, theRelations, theProcessedMap, theConnectedMap);
1871 Standard_Boolean HasAnyConnection (const Standard_Integer theBlockIndex,
1872 const TColStd_MapOfInteger& theWith,
1873 const TColStd_Array2OfInteger& theRelations,
1874 TColStd_MapOfInteger& theProcessedMap)
1876 theProcessedMap.Add(theBlockIndex);
1878 Standard_Integer nbBlocks = theRelations.ColLength();
1879 Standard_Integer col = 1;
1880 for (; col <= nbBlocks; col++) {
1881 if (theRelations(theBlockIndex, col) != REL_NOT_CONNECTED) {
1882 if (!theProcessedMap.Contains(col)) {
1883 if (theWith.Contains(col))
1884 return Standard_True;
1885 if (HasAnyConnection(col, theWith, theRelations, theProcessedMap))
1886 return Standard_True;
1891 return Standard_False;
1894 //=============================================================================
1896 * CheckCompoundOfBlocksOld
1898 //=============================================================================
1899 Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocksOld
1900 (Handle(GEOM_Object) theCompound,
1901 list<BCError>& theErrors)
1905 if (theCompound.IsNull()) return Standard_False;
1906 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
1908 Standard_Boolean isCompOfBlocks = Standard_True;
1910 // Map sub-shapes and their indices
1911 TopTools_IndexedMapOfShape anIndices;
1912 TopExp::MapShapes(aBlockOrComp, anIndices);
1914 // 1. Report non-blocks
1915 TopTools_ListOfShape NOT; // Not blocks
1916 TopTools_ListOfShape DEG; // Hexahedral solids, having degenerated edges
1917 TopTools_ListOfShape SEA; // Hexahedral solids, having seam edges
1918 TopTools_ListOfShape BLO; // All blocks from the given compound
1919 AddBlocksFromOld(aBlockOrComp, BLO, NOT, DEG, SEA);
1921 if (NOT.Extent() > 0) {
1922 isCompOfBlocks = Standard_False;
1924 anErr.error = NOT_BLOCK;
1925 TopTools_ListIteratorOfListOfShape it (NOT);
1926 for (; it.More(); it.Next()) {
1927 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
1929 theErrors.push_back(anErr);
1932 if (DEG.Extent() > 0 || SEA.Extent() > 0) {
1933 isCompOfBlocks = Standard_False;
1935 anErr.error = EXTRA_EDGE;
1937 TopTools_ListIteratorOfListOfShape itDEG (DEG);
1938 for (; itDEG.More(); itDEG.Next()) {
1939 anErr.incriminated.push_back(anIndices.FindIndex(itDEG.Value()));
1942 TopTools_ListIteratorOfListOfShape itSEA (SEA);
1943 for (; itSEA.More(); itSEA.Next()) {
1944 anErr.incriminated.push_back(anIndices.FindIndex(itSEA.Value()));
1947 theErrors.push_back(anErr);
1950 Standard_Integer nbBlocks = BLO.Extent();
1951 if (nbBlocks == 0) {
1952 isCompOfBlocks = Standard_False;
1954 return isCompOfBlocks;
1956 if (nbBlocks == 1) {
1958 return isCompOfBlocks;
1961 // Convert list of blocks into array for easy and fast access
1962 Standard_Integer ibl = 1;
1963 TopTools_Array1OfShape aBlocks (1, nbBlocks);
1964 TopTools_ListIteratorOfListOfShape BLOit (BLO);
1965 for (; BLOit.More(); BLOit.Next(), ibl++) {
1966 aBlocks.SetValue(ibl, BLOit.Value());
1969 // 2. Find relations between all blocks,
1970 // report connection errors (NOT_GLUED and INVALID_CONNECTION)
1971 TColStd_Array2OfInteger aRelations (1, nbBlocks, 1, nbBlocks);
1972 aRelations.Init(REL_NOT_CONNECTED);
1974 Standard_Integer row = 1;
1975 for (row = 1; row <= nbBlocks; row++) {
1976 TopoDS_Shape aBlock = aBlocks.Value(row);
1978 Standard_Integer col = row + 1;
1979 for (; col <= nbBlocks; col++) {
1980 Standard_Integer aRel = BlocksRelation(aBlock, aBlocks.Value(col));
1981 if (aRel != REL_NOT_CONNECTED) {
1982 aRelations.SetValue(row, col, aRel);
1983 aRelations.SetValue(col, row, aRel);
1984 if (aRel == REL_NOT_GLUED) {
1985 // report connection error
1986 isCompOfBlocks = Standard_False;
1988 anErr.error = NOT_GLUED;
1989 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row)));
1990 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col)));
1991 theErrors.push_back(anErr);
1992 } else if (aRel == REL_COLLISION_VV ||
1993 aRel == REL_COLLISION_FF ||
1994 aRel == REL_COLLISION_EE ||
1995 aRel == REL_UNKNOWN) {
1996 // report connection error
1997 isCompOfBlocks = Standard_False;
1999 anErr.error = INVALID_CONNECTION;
2000 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row)));
2001 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col)));
2002 theErrors.push_back(anErr);
2009 // 3. Find largest set of connected (good connection or not glued) blocks
2010 TColStd_MapOfInteger aProcessedMap;
2011 TColStd_MapOfInteger aLargestSet;
2012 TColStd_MapOfInteger aCurrentSet;
2013 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2014 if (!aProcessedMap.Contains(ibl)) {
2015 aCurrentSet.Clear();
2016 FindConnected(ibl, aRelations, aProcessedMap, aCurrentSet);
2017 if (aCurrentSet.Extent() > aLargestSet.Extent()) {
2018 aLargestSet = aCurrentSet;
2023 // 4. Report all blocks, isolated from <aLargestSet>
2025 anErr.error = NOT_CONNECTED;
2026 Standard_Boolean hasIsolated = Standard_False;
2027 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2028 if (!aLargestSet.Contains(ibl)) {
2029 aProcessedMap.Clear();
2030 if (!HasAnyConnection(ibl, aLargestSet, aRelations, aProcessedMap)) {
2031 // report connection absence
2032 hasIsolated = Standard_True;
2033 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(ibl)));
2038 isCompOfBlocks = Standard_False;
2039 theErrors.push_back(anErr);
2043 return isCompOfBlocks;
2046 //=============================================================================
2050 //=============================================================================
2051 TCollection_AsciiString GEOMImpl_IBlocksOperations::PrintBCErrors
2052 (Handle(GEOM_Object) theCompound,
2053 const list<BCError>& theErrors)
2055 TCollection_AsciiString aDescr;
2057 list<BCError>::const_iterator errIt = theErrors.begin();
2059 for (; errIt != theErrors.end(); i++, errIt++) {
2060 BCError errStruct = *errIt;
2062 switch (errStruct.error) {
2064 aDescr += "\n\tNot a Blocks: ";
2067 aDescr += "\n\tHexahedral solids with degenerated and/or seam edges: ";
2069 case INVALID_CONNECTION:
2070 aDescr += "\n\tInvalid connection between two blocks: ";
2073 aDescr += "\n\tBlocks, not connected with main body: ";
2076 aDescr += "\n\tNot glued blocks: ";
2082 list<int> sshList = errStruct.incriminated;
2083 list<int>::iterator sshIt = sshList.begin();
2085 for (; sshIt != sshList.end(); jj++, sshIt++) {
2088 aDescr += TCollection_AsciiString(*sshIt);
2095 //=============================================================================
2097 * CheckCompoundOfBlocks
2099 //=============================================================================
2100 Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocks
2101 (Handle(GEOM_Object) theCompound,
2102 list<BCError>& theErrors)
2106 if (theCompound.IsNull()) return Standard_False;
2107 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2109 Standard_Boolean isCompOfBlocks = Standard_True;
2111 // Map sub-shapes and their indices
2112 TopTools_IndexedMapOfShape anIndices;
2113 TopExp::MapShapes(aBlockOrComp, anIndices);
2115 // 1. Separate blocks from non-blocks
2116 TopTools_ListOfShape NOT; // Not blocks
2117 TopTools_ListOfShape EXT; // Hexahedral solids, having degenerated and/or seam edges
2118 TopTools_ListOfShape BLO; // All blocks from the given compound
2119 AddBlocksFrom(aBlockOrComp, BLO, NOT, EXT);
2121 // Report non-blocks
2122 if (NOT.Extent() > 0) {
2123 isCompOfBlocks = Standard_False;
2125 anErr.error = NOT_BLOCK;
2126 TopTools_ListIteratorOfListOfShape it (NOT);
2127 for (; it.More(); it.Next()) {
2128 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
2130 theErrors.push_back(anErr);
2133 // Report solids, having degenerated and/or seam edges
2134 if (EXT.Extent() > 0) {
2135 isCompOfBlocks = Standard_False;
2137 anErr.error = EXTRA_EDGE;
2138 TopTools_ListIteratorOfListOfShape it (EXT);
2139 for (; it.More(); it.Next()) {
2140 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
2142 theErrors.push_back(anErr);
2145 Standard_Integer nbBlocks = BLO.Extent();
2146 if (nbBlocks == 0) {
2147 isCompOfBlocks = Standard_False;
2149 return isCompOfBlocks;
2151 if (nbBlocks == 1) {
2153 return isCompOfBlocks;
2156 // Prepare data for 2. and 3.
2157 TColStd_Array2OfInteger aRelations (1, nbBlocks, 1, nbBlocks);
2158 aRelations.Init(REL_NOT_CONNECTED);
2160 TopTools_IndexedMapOfShape mapBlocks;
2163 TopoDS_Compound aComp;
2164 BB.MakeCompound(aComp);
2166 TopTools_ListIteratorOfListOfShape BLOit (BLO);
2167 for (; BLOit.More(); BLOit.Next()) {
2168 mapBlocks.Add(BLOit.Value());
2169 BB.Add(aComp, BLOit.Value());
2172 // 2. Find glued blocks (having shared faces)
2173 TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
2174 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2175 (aComp, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
2177 Standard_Integer prevInd = 0, curInd = 0;
2178 Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
2179 for (; ind <= nbFaces; ind++) {
2180 const TopTools_ListOfShape& aGluedBlocks = mapFaceBlocks.FindFromIndex(ind);
2181 if (aGluedBlocks.Extent() > 1) { // Shared face found
2182 TopTools_ListIteratorOfListOfShape aGluedBlocksIt (aGluedBlocks);
2183 TopoDS_Shape prevBlock, curBlock;
2184 for (; aGluedBlocksIt.More(); aGluedBlocksIt.Next()) {
2185 curBlock = aGluedBlocksIt.Value();
2186 if (!prevBlock.IsNull()) {
2187 prevInd = mapBlocks.FindIndex(prevBlock);
2188 curInd = mapBlocks.FindIndex(curBlock);
2189 aRelations.SetValue(prevInd, curInd, REL_OK);
2190 aRelations.SetValue(curInd, prevInd, REL_OK);
2192 prevBlock = curBlock;
2197 // 3. Find not glued blocks
2198 GEOMAlgo_GlueAnalyser aGD;
2200 aGD.SetShape(aComp);
2201 aGD.SetTolerance(Precision::Confusion());
2202 aGD.SetCheckGeometry(Standard_True);
2205 Standard_Integer iErr, iWrn;
2206 iErr = aGD.ErrorStatus();
2208 SetErrorCode("Error in GEOMAlgo_GlueAnalyser");
2209 return isCompOfBlocks;
2211 iWrn = aGD.WarningStatus();
2213 MESSAGE("Warning in GEOMAlgo_GlueAnalyser");
2216 // Report not glued blocks
2217 if (aGD.HasSolidsToGlue()) {
2218 isCompOfBlocks = Standard_False;
2219 Standard_Integer aSx1Ind, aSx2Ind;
2221 const GEOMAlgo_ListOfCoupleOfShapes& aLCS = aGD.SolidsToGlue();
2222 GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS (aLCS);
2223 for (; aItCS.More(); aItCS.Next()) {
2224 const GEOMAlgo_CoupleOfShapes& aCS = aItCS.Value();
2225 const TopoDS_Shape& aSx1 = aCS.Shape1();
2226 const TopoDS_Shape& aSx2 = aCS.Shape2();
2228 aSx1Ind = mapBlocks.FindIndex(aSx1);
2229 aSx2Ind = mapBlocks.FindIndex(aSx2);
2230 aRelations.SetValue(aSx1Ind, aSx2Ind, NOT_GLUED);
2231 aRelations.SetValue(aSx2Ind, aSx1Ind, NOT_GLUED);
2234 anErr.error = NOT_GLUED;
2235 anErr.incriminated.push_back(anIndices.FindIndex(aSx1));
2236 anErr.incriminated.push_back(anIndices.FindIndex(aSx2));
2237 theErrors.push_back(anErr);
2241 // 4. Find largest set of connected (good connection or not glued) blocks
2242 Standard_Integer ibl = 1;
2243 TColStd_MapOfInteger aProcessedMap;
2244 TColStd_MapOfInteger aLargestSet;
2245 TColStd_MapOfInteger aCurrentSet;
2246 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2247 if (!aProcessedMap.Contains(ibl)) {
2248 aCurrentSet.Clear();
2249 FindConnected(ibl, aRelations, aProcessedMap, aCurrentSet);
2250 if (aCurrentSet.Extent() > aLargestSet.Extent()) {
2251 aLargestSet = aCurrentSet;
2256 // 5. Report all blocks, isolated from <aLargestSet>
2258 anErr.error = NOT_CONNECTED;
2259 Standard_Boolean hasIsolated = Standard_False;
2260 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2261 if (!aLargestSet.Contains(ibl)) {
2262 aProcessedMap.Clear();
2263 if (!HasAnyConnection(ibl, aLargestSet, aRelations, aProcessedMap)) {
2264 // report connection absence
2265 hasIsolated = Standard_True;
2266 anErr.incriminated.push_back(anIndices.FindIndex(mapBlocks.FindKey(ibl)));
2271 isCompOfBlocks = Standard_False;
2272 theErrors.push_back(anErr);
2276 return isCompOfBlocks;
2279 //=============================================================================
2283 //=============================================================================
2284 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::RemoveExtraEdges
2285 (Handle(GEOM_Object) theObject)
2289 if (theObject.IsNull()) return NULL;
2291 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2292 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be fixed
2294 //Add a new Copy object
2295 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2298 Handle(GEOM_Function) aFunction =
2299 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_REMOVE_EXTRA);
2301 //Check if the function is set correctly
2302 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2304 GEOMImpl_IBlockTrsf aTI (aFunction);
2305 aTI.SetOriginal(aLastFunction);
2307 //Compute the fixed shape
2309 if (!GetSolver()->ComputeFunction(aFunction)) {
2310 SetErrorCode("Block driver failed to remove extra edges of the given shape");
2314 catch (Standard_Failure) {
2315 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2316 SetErrorCode(aFail->GetMessageString());
2320 //Make a Python command
2321 GEOM::TPythonDump(aFunction) << aCopy
2322 << " = geompy.RemoveExtraEdges(" << theObject << ")";
2328 //=============================================================================
2332 //=============================================================================
2333 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::CheckAndImprove
2334 (Handle(GEOM_Object) theObject)
2338 if (theObject.IsNull()) return NULL;
2340 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2341 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be fixed
2343 //Add a new Copy object
2344 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2347 Handle(GEOM_Function) aFunction =
2348 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_COMPOUND_IMPROVE);
2350 //Check if the function is set correctly
2351 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2353 GEOMImpl_IBlockTrsf aTI (aFunction);
2354 aTI.SetOriginal(aLastFunction);
2356 //Compute the fixed shape
2358 if (!GetSolver()->ComputeFunction(aFunction)) {
2359 SetErrorCode("Block driver failed to improve the given blocks compound");
2363 catch (Standard_Failure) {
2364 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2365 SetErrorCode(aFail->GetMessageString());
2369 //Make a Python command
2370 GEOM::TPythonDump(aFunction) << aCopy
2371 << " = geompy.CheckAndImprove(" << theObject << ")";
2377 //=============================================================================
2379 * ExplodeCompoundOfBlocks
2381 //=============================================================================
2382 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::ExplodeCompoundOfBlocks
2383 (Handle(GEOM_Object) theCompound,
2384 const Standard_Integer theMinNbFaces,
2385 const Standard_Integer theMaxNbFaces)
2389 if (theCompound.IsNull()) return NULL;
2390 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2391 if (aBlockOrComp.IsNull()) return NULL;
2393 Handle(TColStd_HSequenceOfTransient) aBlocks = new TColStd_HSequenceOfTransient;
2394 Handle(GEOM_Object) anObj;
2395 Handle(GEOM_Function) aFunction;
2397 TopTools_MapOfShape mapShape;
2398 TCollection_AsciiString anAsciiList, anEntry;
2401 TopTools_IndexedMapOfShape anIndices;
2402 TopExp::MapShapes(aBlockOrComp, anIndices);
2403 Handle(TColStd_HArray1OfInteger) anArray;
2407 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2408 for (; exp.More(); exp.Next()) {
2409 if (mapShape.Add(exp.Current())) {
2410 TopoDS_Shape aSolid = exp.Current();
2412 TopTools_MapOfShape mapFaces;
2413 TopExp_Explorer expF (aSolid, TopAbs_FACE);
2414 Standard_Integer nbFaces = 0;
2415 for (; expF.More(); expF.Next()) {
2416 if (mapFaces.Add(expF.Current())) {
2421 if (theMinNbFaces <= nbFaces && nbFaces <= theMaxNbFaces) {
2422 anArray = new TColStd_HArray1OfInteger(1,1);
2423 anArray->SetValue(1, anIndices.FindIndex(aSolid));
2424 anObj = GetEngine()->AddSubShape(theCompound, anArray);
2425 aBlocks->Append(anObj);
2427 //Make a Python command
2428 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2429 anAsciiList += anEntry + ", ";
2434 catch (Standard_Failure) {
2435 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2436 SetErrorCode(aFail->GetMessageString());
2440 if (aBlocks->IsEmpty()) {
2441 SetErrorCode("There are no specified blocks in the given shape");
2445 anAsciiList.Trunc(anAsciiList.Length() - 2);
2447 //The explode doesn't change object so no new function is required.
2448 aFunction = theCompound->GetLastFunction();
2450 //Make a Python command
2451 GEOM::TPythonDump(aFunction, /*append=*/true)
2452 << "[" << anAsciiList.ToCString() << "] = geompy.MakeBlockExplode("
2453 << theCompound << ", " << theMinNbFaces << ", " << theMaxNbFaces << ")";
2459 //=============================================================================
2463 //=============================================================================
2464 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetBlockNearPoint
2465 (Handle(GEOM_Object) theCompound,
2466 Handle(GEOM_Object) thePoint)
2471 Handle(GEOM_Object) aResult;
2474 if (theCompound.IsNull() || thePoint.IsNull()) return NULL;
2476 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2477 if (aBlockOrComp.IsNull()) {
2478 SetErrorCode("Compound is null");
2481 if (aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
2482 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
2483 SetErrorCode("Shape to find block in is not a compound");
2487 TopoDS_Shape anArg = thePoint->GetValue();
2488 if (anArg.IsNull()) {
2489 SetErrorCode("Point is null");
2492 if (anArg.ShapeType() != TopAbs_VERTEX) {
2493 SetErrorCode("Shape for block identification is not a vertex");
2497 //Compute the Block value
2499 TopoDS_Shape aShape;
2501 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
2502 gp_Pnt aPnt = BRep_Tool::Pnt(aVert);
2503 Standard_Real PX, PY, PZ;
2504 aPnt.Coord(PX, PY, PZ);
2506 // 1. Classify the point relatively each block
2507 Standard_Integer nearest = 2, nbFound = 0;
2508 TopTools_DataMapOfShapeInteger mapShapeDist;
2509 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2510 for (; exp.More(); exp.Next()) {
2511 TopoDS_Shape aSolid = exp.Current();
2513 if (!mapShapeDist.IsBound(aSolid)) {
2514 Standard_Integer aDistance = 2;
2516 // 1.a. Classify relatively Bounding box
2517 Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
2519 BRepBndLib::Add(aSolid, BB);
2520 BB.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
2521 if (PX < Xmin || Xmax < PX ||
2522 PY < Ymin || Ymax < PY ||
2523 PZ < Zmin || Zmax < PZ) {
2524 // OUT of bounding box
2527 // 1.b. Classify relatively the solid itself
2528 BRepClass3d_SolidClassifier SC (aSolid, aPnt, Precision::Confusion());
2529 if (SC.State() == TopAbs_IN) {
2531 } else if (SC.State() == TopAbs_ON) {
2538 if (aDistance < nearest) {
2539 nearest = aDistance;
2543 // A first found block, containing the point inside, will be returned.
2544 // It is the solution, if there are no intersecting blocks in the compound.
2545 if (nearest == -1) break;
2547 } else if (aDistance == nearest) {
2552 mapShapeDist.Bind(aSolid, aDistance);
2553 } // if (!mapShapeDist.IsBound(aSolid))
2556 // 2. Define block, containing the point or having minimum distance to it
2559 // The point is on boundary of some blocks and there are
2560 // no blocks, having the point inside their volume
2561 SetErrorCode("Multiple blocks near the given point are found");
2564 } else if (nearest == 1) {
2565 // The point is outside some blocks and there are
2566 // no blocks, having the point inside or on boundary.
2567 // We will get a nearest block
2568 Standard_Real minDist = RealLast();
2569 TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
2570 for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
2571 if (mapShapeDistIter.Value() == 1) {
2572 TopoDS_Shape aSolid = mapShapeDistIter.Key();
2573 BRepExtrema_DistShapeShape aDistTool (aVert, aSolid);
2574 if (!aDistTool.IsDone()) {
2575 SetErrorCode("Can not find a distance from the given point to one of blocks");
2578 Standard_Real aDist = aDistTool.Value();
2579 if (aDist < minDist) {
2585 } else { // nearest == -1
2586 // // The point is inside some blocks.
2587 // // We will get a block with nearest center
2588 // Standard_Real minDist = RealLast();
2589 // TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
2590 // for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
2591 // if (mapShapeDistIter.Value() == -1) {
2592 // TopoDS_Shape aSolid = mapShapeDistIter.Key();
2593 // GProp_GProps aSystem;
2594 // BRepGProp::VolumeProperties(aSolid, aSystem);
2595 // gp_Pnt aCenterMass = aSystem.CentreOfMass();
2597 // Standard_Real aDist = aCenterMass.Distance(aPnt);
2598 // if (aDist < minDist) {
2605 } // if (nbFound > 1)
2608 SetErrorCode("There are no blocks near the given point");
2611 TopTools_IndexedMapOfShape anIndices;
2612 TopExp::MapShapes(aBlockOrComp, anIndices);
2613 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2614 anArray->SetValue(1, anIndices.FindIndex(aShape));
2615 aResult = GetEngine()->AddSubShape(theCompound, anArray);
2618 catch (Standard_Failure) {
2619 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2620 SetErrorCode(aFail->GetMessageString());
2624 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
2626 //Make a Python command
2627 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetBlockNearPoint("
2628 << theCompound << ", " << thePoint << ")";
2634 //=============================================================================
2638 //=============================================================================
2639 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetBlockByParts
2640 (Handle(GEOM_Object) theCompound,
2641 const Handle(TColStd_HSequenceOfTransient)& theParts)
2645 Handle(GEOM_Object) aResult;
2647 if (theCompound.IsNull() || theParts.IsNull()) return NULL;
2648 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2649 if (aBlockOrComp.IsNull()) return NULL;
2652 Standard_Integer argi, aLen = theParts->Length();
2653 TopTools_Array1OfShape anArgs (1, aLen);
2654 TCollection_AsciiString anEntry, aPartsDescr;
2655 for (argi = 1; argi <= aLen; argi++) {
2656 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theParts->Value(argi));
2657 Handle(GEOM_Function) aRef = anObj->GetLastFunction();
2658 if (aRef.IsNull()) return NULL;
2660 TopoDS_Shape anArg = aRef->GetValue();
2661 if (anArg.IsNull()) {
2662 SetErrorCode("Null shape is given as argument");
2665 anArgs(argi) = anArg;
2667 // For Python command
2668 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2669 if (argi > 1) aPartsDescr += ", ";
2670 aPartsDescr += anEntry;
2673 //Compute the Block value
2675 // 1. Explode compound on solids
2676 TopTools_MapOfShape mapShape;
2677 Standard_Integer nbSolids = 0;
2678 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2679 for (; exp.More(); exp.Next()) {
2680 if (mapShape.Add(exp.Current())) {
2686 Standard_Integer ind = 1;
2687 TopTools_Array1OfShape aSolids (1, nbSolids);
2688 TColStd_Array1OfInteger aNbParts (1, nbSolids);
2689 for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next(), ind++) {
2690 if (mapShape.Add(exp.Current())) {
2691 TopoDS_Shape aSolid = exp.Current();
2692 aSolids(ind) = aSolid;
2695 // 2. Define quantity of parts, contained in each solid
2696 TopTools_IndexedMapOfShape aSubShapes;
2697 TopExp::MapShapes(aSolid, aSubShapes);
2698 for (argi = 1; argi <= aLen; argi++) {
2699 if (aSubShapes.Contains(anArgs(argi))) {
2706 // 3. Define solid, containing maximum quantity of parts
2707 Standard_Integer maxNb = 0, nbFound = 0;
2708 TopoDS_Shape aShape;
2709 for (ind = 1; ind <= nbSolids; ind++) {
2710 if (aNbParts(ind) > maxNb) {
2711 maxNb = aNbParts(ind);
2712 aShape = aSolids(ind);
2714 } else if (aNbParts(ind) == maxNb) {
2720 SetErrorCode("Multiple blocks, containing maximum quantity of the given parts, are found");
2722 } else if (nbFound == 0) {
2723 SetErrorCode("There are no blocks, containing the given parts");
2726 TopTools_IndexedMapOfShape anIndices;
2727 TopExp::MapShapes(aBlockOrComp, anIndices);
2728 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2729 anArray->SetValue(1, anIndices.FindIndex(aShape));
2730 aResult = GetEngine()->AddSubShape(theCompound, anArray);
2732 } catch (Standard_Failure) {
2733 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2734 SetErrorCode(aFail->GetMessageString());
2738 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
2740 //Make a Python command
2741 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetBlockByParts("
2742 << theCompound << ", [" << aPartsDescr.ToCString() << "])";
2748 //=============================================================================
2752 //=============================================================================
2753 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::GetBlocksByParts
2754 (Handle(GEOM_Object) theCompound,
2755 const Handle(TColStd_HSequenceOfTransient)& theParts)
2759 if (theCompound.IsNull() || theParts.IsNull()) return NULL;
2760 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2761 if (aBlockOrComp.IsNull()) return NULL;
2763 Handle(TColStd_HSequenceOfTransient) aBlocks = new TColStd_HSequenceOfTransient;
2764 Handle(GEOM_Object) anObj;
2765 Handle(GEOM_Function) aFunction;
2768 Standard_Integer argi, aLen = theParts->Length();
2769 TopTools_Array1OfShape anArgs (1, aLen);
2770 TCollection_AsciiString anEntry, aPartsDescr, anAsciiList;
2772 for (argi = 1; argi <= aLen; argi++) {
2773 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theParts->Value(argi));
2774 Handle(GEOM_Function) aRef = anObj->GetLastFunction();
2775 if (aRef.IsNull()) return NULL;
2777 TopoDS_Shape anArg = aRef->GetValue();
2778 if (anArg.IsNull()) {
2779 SetErrorCode("Null shape is given as argument");
2782 anArgs(argi) = anArg;
2784 // For Python command
2785 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2786 aPartsDescr += anEntry + ", ";
2791 TopTools_MapOfShape mapShape;
2792 Standard_Integer nbSolids = 0;
2793 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2794 for (; exp.More(); exp.Next()) {
2795 if (mapShape.Add(exp.Current())) {
2801 Standard_Integer ind = 1;
2802 TopTools_Array1OfShape aSolids (1, nbSolids);
2803 TColStd_Array1OfInteger aNbParts (1, nbSolids);
2804 for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next(), ind++) {
2805 if (mapShape.Add(exp.Current())) {
2806 TopoDS_Shape aSolid = exp.Current();
2807 aSolids(ind) = aSolid;
2810 // 2. Define quantity of parts, contained in each solid
2811 TopTools_IndexedMapOfShape aSubShapes;
2812 TopExp::MapShapes(aSolid, aSubShapes);
2813 for (argi = 1; argi <= aLen; argi++) {
2814 if (aSubShapes.Contains(anArgs(argi))) {
2821 // 3. Define solid, containing maximum quantity of parts
2822 Standard_Integer maxNb = 0, nbFound = 0;
2823 for (ind = 1; ind <= nbSolids; ind++) {
2824 if (aNbParts(ind) > maxNb) {
2825 maxNb = aNbParts(ind);
2827 } else if (aNbParts(ind) == maxNb) {
2833 SetErrorCode("There are no blocks, containing the given parts");
2838 TopTools_IndexedMapOfShape anIndices;
2839 TopExp::MapShapes(aBlockOrComp, anIndices);
2840 Handle(TColStd_HArray1OfInteger) anArray;
2842 for (ind = 1; ind <= nbSolids; ind++) {
2843 if (aNbParts(ind) == maxNb) {
2844 anArray = new TColStd_HArray1OfInteger(1,1);
2845 anArray->SetValue(1, anIndices.FindIndex(aSolids(ind)));
2846 anObj = GetEngine()->AddSubShape(theCompound, anArray);
2847 aBlocks->Append(anObj);
2849 // For Python command
2850 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2851 anAsciiList += anEntry + ", ";
2852 if (aFunction.IsNull())
2853 aFunction = anObj->GetLastFunction();
2857 catch (Standard_Failure) {
2858 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2859 SetErrorCode(aFail->GetMessageString());
2863 //Make a Python command
2864 aPartsDescr.Trunc(aPartsDescr.Length() - 2);
2865 anAsciiList.Trunc(anAsciiList.Length() - 2);
2867 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2868 << "] = geompy.GetBlocksByParts(" << theCompound
2869 << ", [" << aPartsDescr.ToCString() << "])";
2875 //=============================================================================
2877 * MakeMultiTransformation1D
2879 //=============================================================================
2880 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeMultiTransformation1D
2881 (Handle(GEOM_Object) theObject,
2882 const Standard_Integer theDirFace1,
2883 const Standard_Integer theDirFace2,
2884 const Standard_Integer theNbTimes)
2888 if (theObject.IsNull()) return NULL;
2890 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2891 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be moved
2893 //Add a new Copy object
2894 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2896 //Add a translate function
2897 Handle(GEOM_Function) aFunction =
2898 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_MULTI_TRANSFORM_1D);
2900 //Check if the function is set correctly
2901 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2903 GEOMImpl_IBlockTrsf aTI (aFunction);
2904 aTI.SetOriginal(aLastFunction);
2905 aTI.SetFace1U(theDirFace1);
2906 aTI.SetFace2U(theDirFace2);
2907 aTI.SetNbIterU(theNbTimes);
2909 //Compute the transformation
2911 if (!GetSolver()->ComputeFunction(aFunction)) {
2912 SetErrorCode("Block driver failed to make multi-transformation");
2916 catch (Standard_Failure) {
2917 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2918 SetErrorCode(aFail->GetMessageString());
2922 //Make a Python command
2923 GEOM::TPythonDump(aFunction) << aCopy << " = geompy.MakeMultiTransformation1D("
2924 << theObject << ", " << theDirFace1 << ", " << theDirFace2 << ", " << theNbTimes << ")";
2930 //=============================================================================
2932 * MakeMultiTransformation2D
2934 //=============================================================================
2935 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeMultiTransformation2D
2936 (Handle(GEOM_Object) theObject,
2937 const Standard_Integer theDirFace1U,
2938 const Standard_Integer theDirFace2U,
2939 const Standard_Integer theNbTimesU,
2940 const Standard_Integer theDirFace1V,
2941 const Standard_Integer theDirFace2V,
2942 const Standard_Integer theNbTimesV)
2946 if (theObject.IsNull()) return NULL;
2948 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2949 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be moved
2951 //Add a new Copy object
2952 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2954 //Add a translate function
2955 Handle(GEOM_Function) aFunction =
2956 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_MULTI_TRANSFORM_2D);
2958 //Check if the function is set correctly
2959 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2961 GEOMImpl_IBlockTrsf aTI (aFunction);
2962 aTI.SetOriginal(aLastFunction);
2963 aTI.SetFace1U(theDirFace1U);
2964 aTI.SetFace2U(theDirFace2U);
2965 aTI.SetNbIterU(theNbTimesU);
2966 aTI.SetFace1V(theDirFace1V);
2967 aTI.SetFace2V(theDirFace2V);
2968 aTI.SetNbIterV(theNbTimesV);
2970 //Compute the transformation
2972 if (!GetSolver()->ComputeFunction(aFunction)) {
2973 SetErrorCode("Block driver failed to make multi-transformation");
2977 catch (Standard_Failure) {
2978 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2979 SetErrorCode(aFail->GetMessageString());
2983 //Make a Python command
2984 GEOM::TPythonDump(aFunction) << aCopy << " = geompy.MakeMultiTransformation2D("
2985 << theObject << ", " << theDirFace1U << ", " << theDirFace2U << ", " << theNbTimesU
2986 << ", " << theDirFace1V << ", " << theDirFace2V << ", " << theNbTimesV << ")";
2992 //=============================================================================
2996 //=============================================================================
2997 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::Propagate
2998 (Handle(GEOM_Object) theShape)
3002 if (theShape.IsNull()) return NULL;
3004 TopoDS_Shape aShape = theShape->GetValue();
3005 if (aShape.IsNull()) return NULL;
3007 TopTools_IndexedMapOfShape anIndices;
3008 TopExp::MapShapes(aShape, anIndices);
3010 TopTools_IndexedDataMapOfShapeListOfShape MEW;
3011 GEOMImpl_Block6Explorer::MapShapesAndAncestors
3012 (aShape, TopAbs_EDGE, TopAbs_WIRE, MEW);
3013 Standard_Integer ie, nbEdges = MEW.Extent();
3016 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
3018 TopTools_MapOfShape mapAcceptedEdges;
3019 TCollection_AsciiString aListRes, anEntry;
3021 for (ie = 1; ie <= nbEdges; ie++) {
3022 TopoDS_Shape curE = MEW.FindKey(ie);
3024 if (mapAcceptedEdges.Contains(curE)) continue;
3027 TopTools_ListOfShape currentChain;
3028 TopTools_ListOfShape listPrevEdges;
3030 currentChain.Append(curE);
3031 listPrevEdges.Append(curE);
3032 mapAcceptedEdges.Add(curE);
3034 // Collect all edges pass by pass
3035 while (listPrevEdges.Extent() > 0) {
3036 // List of edges, added to chain on this cycle pass
3037 TopTools_ListOfShape listCurEdges;
3039 // Find the next portion of edges
3040 TopTools_ListIteratorOfListOfShape itE (listPrevEdges);
3041 for (; itE.More(); itE.Next()) {
3042 TopoDS_Shape anE = itE.Value();
3044 // Iterate on faces, having edge <anE>
3045 TopTools_ListIteratorOfListOfShape itW (MEW.FindFromKey(anE));
3046 for (; itW.More(); itW.Next()) {
3047 TopoDS_Shape aW = itW.Value();
3048 TopoDS_Shape anOppE;
3050 BRepTools_WireExplorer aWE (TopoDS::Wire(aW));
3051 Standard_Integer nb = 1, found = 0;
3052 TopTools_Array1OfShape anEdges (1,4);
3053 for (; aWE.More(); aWE.Next(), nb++) {
3058 anEdges(nb) = aWE.Current();
3059 if (anEdges(nb).IsSame(anE)) found = nb;
3062 if (nb == 5 && found > 0) {
3063 // Quadrangle face found, get an opposite edge
3064 Standard_Integer opp = found + 2;
3065 if (opp > 4) opp -= 4;
3066 anOppE = anEdges(opp);
3068 if (!mapAcceptedEdges.Contains(anOppE)) {
3069 // Add found edge to the chain
3070 currentChain.Append(anOppE);
3071 listCurEdges.Append(anOppE);
3072 mapAcceptedEdges.Add(anOppE);
3074 } // if (nb == 5 && found > 0)
3075 } // for (; itF.More(); itF.Next())
3076 } // for (; itE.More(); itE.Next())
3078 listPrevEdges = listCurEdges;
3079 } // while (listPrevEdges.Extent() > 0)
3081 // Store the chain in the document
3082 Handle(TColStd_HArray1OfInteger) anArray =
3083 new TColStd_HArray1OfInteger (1, currentChain.Extent());
3085 // Fill array of sub-shape indices
3086 TopTools_ListIteratorOfListOfShape itSub (currentChain);
3087 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
3088 int id = anIndices.FindIndex(itSub.Value());
3089 anArray->SetValue(index, id);
3092 // Add a new group object
3093 Handle(GEOM_Object) aChain = GetEngine()->AddSubShape(theShape, anArray);
3096 aChain->SetType(GEOM_GROUP);
3098 // Set a sub shape type
3099 TDF_Label aFreeLabel = aChain->GetFreeLabel();
3100 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)TopAbs_EDGE);
3102 // Add the chain to the result
3103 aSeq->Append(aChain);
3105 //Make a Python command
3106 TDF_Tool::Entry(aChain->GetEntry(), anEntry);
3107 aListRes += anEntry + ", ";
3110 if (aSeq->IsEmpty()) {
3111 SetErrorCode("There are no quadrangle faces in the shape");
3115 aListRes.Trunc(aListRes.Length() - 2);
3117 // The Propagation doesn't change object so no new function is required.
3118 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
3120 // Make a Python command
3121 GEOM::TPythonDump(aFunction, /*append=*/true)
3122 << "[" << aListRes.ToCString() << "] = geompy.Propagate(" << theShape << ")";