3 #include "GEOMImpl_IBlocksOperations.hxx"
5 #include "GEOMImpl_Types.hxx"
7 #include "GEOMImpl_BlockDriver.hxx"
8 #include "GEOMImpl_IBlocks.hxx"
9 #include "GEOMImpl_IBlockTrsf.hxx"
10 #include "GEOMImpl_CopyDriver.hxx"
11 #include "GEOMImpl_Block6Explorer.hxx"
13 #include "GEOM_Function.hxx"
14 #include "GEOM_PythonDump.hxx"
16 #include "GEOMAlgo_GlueAnalyser.hxx"
17 #include "GEOMAlgo_CoupleOfShapes.hxx"
18 #include "GEOMAlgo_ListOfCoupleOfShapes.hxx"
19 #include "GEOMAlgo_ListIteratorOfListOfCoupleOfShapes.hxx"
20 #include "BlockFix_CheckTool.hxx"
22 #include "utilities.h"
24 #include "Utils_ExceptHandlers.hxx"
26 #include <TFunction_DriverTable.hxx>
27 #include <TFunction_Driver.hxx>
28 #include <TFunction_Logbook.hxx>
29 #include <TDataStd_Integer.hxx>
30 #include <TDF_Tool.hxx>
32 #include <BRep_Tool.hxx>
33 #include <BRep_Builder.hxx>
34 #include <BRepTools.hxx>
35 #include <BRepTools_WireExplorer.hxx>
36 #include <BRepGProp.hxx>
37 #include <BRepBndLib.hxx>
38 #include <BRepAdaptor_Surface.hxx>
39 #include <BRepClass_FaceClassifier.hxx>
40 #include <BRepClass3d_SolidClassifier.hxx>
41 #include <BRepExtrema_DistShapeShape.hxx>
45 #include <TopoDS_Edge.hxx>
46 #include <TopoDS_Vertex.hxx>
47 #include <TopoDS_Compound.hxx>
48 #include <TopoDS_Iterator.hxx>
50 #include <TopExp_Explorer.hxx>
51 #include <TopTools_MapOfShape.hxx>
52 #include <TopTools_Array1OfShape.hxx>
53 #include <TopTools_IndexedMapOfShape.hxx>
54 #include <TopTools_DataMapOfShapeInteger.hxx>
55 #include <TopTools_ListIteratorOfListOfShape.hxx>
56 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
57 #include <TopTools_DataMapIteratorOfDataMapOfShapeInteger.hxx>
59 #include <Bnd_Box.hxx>
60 #include <GProp_GProps.hxx>
62 #include <Geom_Surface.hxx>
63 #include <ShapeAnalysis_Surface.hxx>
65 #include <TColStd_MapOfInteger.hxx>
66 #include <TColStd_Array1OfReal.hxx>
67 #include <TColStd_Array1OfInteger.hxx>
68 #include <TColStd_Array2OfInteger.hxx>
70 //#include <OSD_Timer.hxx>
72 #include <Precision.hxx>
74 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
76 //=============================================================================
80 //=============================================================================
81 GEOMImpl_IBlocksOperations::GEOMImpl_IBlocksOperations (GEOM_Engine* theEngine, int theDocID)
82 : GEOM_IOperations(theEngine, theDocID)
84 MESSAGE("GEOMImpl_IBlocksOperations::GEOMImpl_IBlocksOperations");
87 //=============================================================================
91 //=============================================================================
92 GEOMImpl_IBlocksOperations::~GEOMImpl_IBlocksOperations()
94 MESSAGE("GEOMImpl_IBlocksOperations::~GEOMImpl_IBlocksOperations");
98 //=============================================================================
102 //=============================================================================
103 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad
104 (Handle(GEOM_Object) theEdge1, Handle(GEOM_Object) theEdge2,
105 Handle(GEOM_Object) theEdge3, Handle(GEOM_Object) theEdge4)
109 if (theEdge1.IsNull() || theEdge2.IsNull() ||
110 theEdge3.IsNull() || theEdge4.IsNull()) return NULL;
112 //Add a new Face object
113 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
115 //Add a new Face function
116 Handle(GEOM_Function) aFunction =
117 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_FOUR_EDGES);
119 //Check if the function is set correctly
120 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
122 GEOMImpl_IBlocks aPI (aFunction);
124 Handle(GEOM_Function) aRef1 = theEdge1->GetLastFunction();
125 Handle(GEOM_Function) aRef2 = theEdge2->GetLastFunction();
126 Handle(GEOM_Function) aRef3 = theEdge3->GetLastFunction();
127 Handle(GEOM_Function) aRef4 = theEdge4->GetLastFunction();
128 if (aRef1.IsNull() || aRef2.IsNull() ||
129 aRef3.IsNull() || aRef4.IsNull()) return NULL;
131 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
132 aShapesSeq->Append(aRef1);
133 aShapesSeq->Append(aRef2);
134 aShapesSeq->Append(aRef3);
135 aShapesSeq->Append(aRef4);
137 aPI.SetShapes(aShapesSeq);
139 //Compute the Face value
141 if (!GetSolver()->ComputeFunction(aFunction)) {
142 SetErrorCode("Block driver failed to compute a face");
146 catch (Standard_Failure) {
147 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
148 SetErrorCode(aFail->GetMessageString());
152 //Make a Python command
153 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeQuad("
154 << theEdge1 << ", " << theEdge2 << ", " << theEdge3 << ", " << theEdge4 << ")";
160 //=============================================================================
164 //=============================================================================
165 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad2Edges
166 (Handle(GEOM_Object) theEdge1, Handle(GEOM_Object) theEdge2)
170 if (theEdge1.IsNull() || theEdge2.IsNull()) return NULL;
172 //Add a new Face object
173 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
175 //Add a new Face function
176 Handle(GEOM_Function) aFunction =
177 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_TWO_EDGES);
179 //Check if the function is set correctly
180 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
182 GEOMImpl_IBlocks aPI (aFunction);
184 Handle(GEOM_Function) aRef1 = theEdge1->GetLastFunction();
185 Handle(GEOM_Function) aRef2 = theEdge2->GetLastFunction();
186 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
188 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
189 aShapesSeq->Append(aRef1);
190 aShapesSeq->Append(aRef2);
192 aPI.SetShapes(aShapesSeq);
194 //Compute the Face value
196 if (!GetSolver()->ComputeFunction(aFunction)) {
197 SetErrorCode("Block driver failed to compute a face");
201 catch (Standard_Failure) {
202 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
203 SetErrorCode(aFail->GetMessageString());
207 //Make a Python command
208 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeQuad2Edges("
209 << theEdge1 << ", " << theEdge2 << ")";
215 //=============================================================================
219 //=============================================================================
220 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad4Vertices
221 (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2,
222 Handle(GEOM_Object) thePnt3, Handle(GEOM_Object) thePnt4)
226 if (thePnt1.IsNull() || thePnt2.IsNull() ||
227 thePnt3.IsNull() || thePnt4.IsNull()) return NULL;
229 //Add a new Face object
230 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
232 //Add a new Face function
233 Handle(GEOM_Function) aFunction =
234 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_FOUR_PNT);
236 //Check if the function is set correctly
237 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
239 GEOMImpl_IBlocks aPI (aFunction);
241 Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
242 Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
243 Handle(GEOM_Function) aRef3 = thePnt3->GetLastFunction();
244 Handle(GEOM_Function) aRef4 = thePnt4->GetLastFunction();
245 if (aRef1.IsNull() || aRef2.IsNull() ||
246 aRef3.IsNull() || aRef4.IsNull()) return NULL;
248 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
249 aShapesSeq->Append(aRef1);
250 aShapesSeq->Append(aRef2);
251 aShapesSeq->Append(aRef3);
252 aShapesSeq->Append(aRef4);
254 aPI.SetShapes(aShapesSeq);
256 //Compute the Face value
258 if (!GetSolver()->ComputeFunction(aFunction)) {
259 SetErrorCode("Block driver failed to compute a face");
263 catch (Standard_Failure) {
264 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
265 SetErrorCode(aFail->GetMessageString());
269 //Make a Python command
270 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeQuad4Vertices("
271 << thePnt1 << ", " << thePnt2 << ", " << thePnt3 << ", " << thePnt4 << ")";
277 //=============================================================================
281 //=============================================================================
282 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeHexa
283 (Handle(GEOM_Object) theFace1, Handle(GEOM_Object) theFace2,
284 Handle(GEOM_Object) theFace3, Handle(GEOM_Object) theFace4,
285 Handle(GEOM_Object) theFace5, Handle(GEOM_Object) theFace6)
289 if (theFace1.IsNull() || theFace2.IsNull() ||
290 theFace3.IsNull() || theFace4.IsNull() ||
291 theFace5.IsNull() || theFace6.IsNull()) return NULL;
293 //Add a new Solid object
294 Handle(GEOM_Object) aBlock = GetEngine()->AddObject(GetDocID(), GEOM_BLOCK);
296 //Add a new Block function
297 Handle(GEOM_Function) aFunction =
298 aBlock->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_SIX_FACES);
300 //Check if the function is set correctly
301 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
303 GEOMImpl_IBlocks aPI (aFunction);
305 Handle(GEOM_Function) aRef1 = theFace1->GetLastFunction();
306 Handle(GEOM_Function) aRef2 = theFace2->GetLastFunction();
307 Handle(GEOM_Function) aRef3 = theFace3->GetLastFunction();
308 Handle(GEOM_Function) aRef4 = theFace4->GetLastFunction();
309 Handle(GEOM_Function) aRef5 = theFace5->GetLastFunction();
310 Handle(GEOM_Function) aRef6 = theFace6->GetLastFunction();
311 if (aRef1.IsNull() || aRef2.IsNull() ||
312 aRef3.IsNull() || aRef4.IsNull() ||
313 aRef5.IsNull() || aRef6.IsNull()) return NULL;
315 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
316 aShapesSeq->Append(aRef1);
317 aShapesSeq->Append(aRef2);
318 aShapesSeq->Append(aRef3);
319 aShapesSeq->Append(aRef4);
320 aShapesSeq->Append(aRef5);
321 aShapesSeq->Append(aRef6);
323 aPI.SetShapes(aShapesSeq);
325 //Compute the Block value
327 if (!GetSolver()->ComputeFunction(aFunction)) {
328 SetErrorCode("Block driver failed to compute a block");
332 catch (Standard_Failure) {
333 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
334 SetErrorCode(aFail->GetMessageString());
338 //Make a Python command
339 GEOM::TPythonDump(aFunction) << aBlock << " = geompy.MakeHexa("
340 << theFace1 << ", " << theFace2 << ", " << theFace3 << ", "
341 << theFace4 << ", " << theFace5 << ", " << theFace6 << ")";
347 //=============================================================================
351 //=============================================================================
352 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeHexa2Faces
353 (Handle(GEOM_Object) theFace1, Handle(GEOM_Object) theFace2)
357 if (theFace1.IsNull() || theFace2.IsNull()) return NULL;
359 //Add a new Solid object
360 Handle(GEOM_Object) aBlock = GetEngine()->AddObject(GetDocID(), GEOM_BLOCK);
362 //Add a new Block function
363 Handle(GEOM_Function) aFunction =
364 aBlock->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_TWO_FACES);
366 //Check if the function is set correctly
367 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
369 GEOMImpl_IBlocks aPI (aFunction);
371 Handle(GEOM_Function) aRef1 = theFace1->GetLastFunction();
372 Handle(GEOM_Function) aRef2 = theFace2->GetLastFunction();
373 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
375 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
376 aShapesSeq->Append(aRef1);
377 aShapesSeq->Append(aRef2);
379 aPI.SetShapes(aShapesSeq);
381 //Compute the Block value
383 if (!GetSolver()->ComputeFunction(aFunction)) {
384 SetErrorCode("Block driver failed to compute a block");
388 catch (Standard_Failure) {
389 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
390 SetErrorCode(aFail->GetMessageString());
394 //Make a Python command
395 GEOM::TPythonDump(aFunction) << aBlock << " = geompy.MakeHexa2Faces("
396 << theFace1 << ", " << theFace2 << ")";
402 //=============================================================================
406 //=============================================================================
407 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeBlockCompound
408 (Handle(GEOM_Object) theCompound)
412 if (theCompound.IsNull()) return NULL;
415 Handle(GEOM_Object) aBlockComp = GetEngine()->AddObject(GetDocID(), GEOM_COMPOUND);
417 //Add a new BlocksComp function
418 Handle(GEOM_Function) aFunction =
419 aBlockComp->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_COMPOUND_GLUE);
421 //Check if the function is set correctly
422 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
424 GEOMImpl_IBlocks aPI (aFunction);
426 Handle(GEOM_Function) aRef1 = theCompound->GetLastFunction();
427 if (aRef1.IsNull()) return NULL;
429 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
430 aShapesSeq->Append(aRef1);
432 aPI.SetShapes(aShapesSeq);
434 //Compute the Blocks Compound value
436 if (!GetSolver()->ComputeFunction(aFunction)) {
437 SetErrorCode("Block driver failed to compute a blocks compound");
441 catch (Standard_Failure) {
442 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
443 SetErrorCode(aFail->GetMessageString());
447 //Make a Python command
448 GEOM::TPythonDump(aFunction) << aBlockComp
449 << " = geompy.MakeBlockCompound(" << theCompound << ")";
455 //=============================================================================
459 //=============================================================================
460 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetPoint
461 (Handle(GEOM_Object) theShape,
462 const Standard_Real theX,
463 const Standard_Real theY,
464 const Standard_Real theZ,
465 const Standard_Real theEpsilon)
470 Handle(GEOM_Object) aResult;
473 if (theShape.IsNull()) return NULL;
475 TopoDS_Shape aBlockOrComp = theShape->GetValue();
476 if (aBlockOrComp.IsNull()) {
477 SetErrorCode("Block or compound is null");
480 if (aBlockOrComp.ShapeType() != TopAbs_SOLID &&
481 aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
482 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
483 SetErrorCode("Shape is neither a block, nor a compound of blocks");
487 //Compute the Vertex value
488 gp_Pnt P (theX, theY, theZ);
489 Standard_Real eps = Max(theEpsilon, Precision::Confusion());
492 Standard_Integer isFound = 0;
493 TopTools_MapOfShape mapShape;
494 TopExp_Explorer exp (aBlockOrComp, TopAbs_VERTEX);
496 for (; exp.More(); exp.Next()) {
497 if (mapShape.Add(exp.Current())) {
498 TopoDS_Vertex aVi = TopoDS::Vertex(exp.Current());
499 gp_Pnt aPi = BRep_Tool::Pnt(aVi);
500 if (aPi.Distance(P) < eps) {
508 SetErrorCode("Vertex has not been found");
510 } else if (isFound > 1) {
511 SetErrorCode("Multiple vertices found by the given coordinates and epsilon");
514 TopTools_IndexedMapOfShape anIndices;
515 TopExp::MapShapes(aBlockOrComp, anIndices);
516 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
517 anArray->SetValue(1, anIndices.FindIndex(V));
518 aResult = GetEngine()->AddSubShape(theShape, anArray);
521 //The GetPoint() doesn't change object so no new function is required.
522 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
523 TCollection_AsciiString anOldDescr = aFunction->GetDescription();
525 //Make a Python command
526 GEOM::TPythonDump(aFunction) << anOldDescr.ToCString() << "\n\t"
527 << aResult << " = geompy.GetPoint(" << theShape << ", "
528 << theX << ", " << theY << ", " << theZ << ", " << theEpsilon << ")";
534 //=============================================================================
538 //=============================================================================
539 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetEdge
540 (Handle(GEOM_Object) theShape,
541 Handle(GEOM_Object) thePoint1,
542 Handle(GEOM_Object) thePoint2)
547 Handle(GEOM_Object) aResult;
550 if (theShape.IsNull() || thePoint1.IsNull() || thePoint2.IsNull()) return NULL;
552 TopoDS_Shape aBlockOrComp = theShape->GetValue();
553 if (aBlockOrComp.IsNull()) {
554 SetErrorCode("Block or compound is null");
557 if (aBlockOrComp.ShapeType() != TopAbs_SOLID &&
558 aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
559 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
560 SetErrorCode("Shape is neither a block, nor a compound of blocks");
564 TopoDS_Shape anArg1 = thePoint1->GetValue();
565 TopoDS_Shape anArg2 = thePoint2->GetValue();
566 if (anArg1.IsNull() || anArg2.IsNull()) {
567 SetErrorCode("Null shape is given as argument");
570 if (anArg1.ShapeType() != TopAbs_VERTEX ||
571 anArg2.ShapeType() != TopAbs_VERTEX) {
572 SetErrorCode("Element for edge identification is not a vertex");
576 //Compute the Edge value
578 TopTools_IndexedDataMapOfShapeListOfShape MVE;
579 GEOMImpl_Block6Explorer::MapShapesAndAncestors
580 (aBlockOrComp, TopAbs_VERTEX, TopAbs_EDGE, MVE);
583 Standard_Integer ish, ext = MVE.Extent();
585 if (MVE.Contains(anArg1)) {
588 for (ish = 1; ish <= ext; ish++) {
589 TopoDS_Shape aShi = MVE.FindKey(ish);
590 if (BRepTools::Compare(TopoDS::Vertex(anArg1), TopoDS::Vertex(aShi))) {
597 if (MVE.Contains(anArg2)) {
600 for (ish = 1; ish <= ext; ish++) {
601 TopoDS_Shape aShi = MVE.FindKey(ish);
602 if (BRepTools::Compare(TopoDS::Vertex(anArg2), TopoDS::Vertex(aShi))) {
609 if (V1.IsNull() || V2.IsNull()) {
610 SetErrorCode("The given vertex does not belong to the shape");
615 Standard_Integer isFound =
616 GEOMImpl_Block6Explorer::FindEdge(anEdge, V1, V2, MVE, Standard_True);
618 SetErrorCode("The given vertices do not belong to one edge of the given shape");
620 } else if (isFound > 1) {
621 SetErrorCode("Multiple edges found by the given vertices of the shape");
624 TopTools_IndexedMapOfShape anIndices;
625 TopExp::MapShapes(aBlockOrComp, anIndices);
626 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
627 anArray->SetValue(1, anIndices.FindIndex(anEdge));
628 aResult = GetEngine()->AddSubShape(theShape, anArray);
630 } catch (Standard_Failure) {
631 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
632 SetErrorCode(aFail->GetMessageString());
636 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
638 //Make a Python command
639 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetEdge("
640 << theShape << ", " << thePoint1 << ", " << thePoint2 << ")";
646 //=============================================================================
650 //=============================================================================
651 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetEdgeNearPoint
652 (Handle(GEOM_Object) theShape,
653 Handle(GEOM_Object) thePoint)
658 Handle(GEOM_Object) aResult;
661 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
663 TopoDS_Shape aBlockOrComp = theShape->GetValue();
664 if (aBlockOrComp.IsNull()) {
665 SetErrorCode("Block or compound is null");
668 if (aBlockOrComp.ShapeType() != TopAbs_SOLID &&
669 aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
670 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
671 SetErrorCode("Shape is neither a block, nor a compound of blocks");
675 TopoDS_Shape anArg = thePoint->GetValue();
676 if (anArg.IsNull()) {
677 SetErrorCode("Null shape is given as argument");
680 if (anArg.ShapeType() != TopAbs_VERTEX) {
681 SetErrorCode("Element for edge identification is not a vertex");
685 //Compute the Edge value
689 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
691 // 1. Explode blocks on edges
692 TopTools_MapOfShape mapShape;
693 Standard_Integer nbEdges = 0;
694 TopExp_Explorer exp (aBlockOrComp, TopAbs_EDGE);
695 for (; exp.More(); exp.Next()) {
696 if (mapShape.Add(exp.Current())) {
702 Standard_Integer ind = 1;
703 TopTools_Array1OfShape anEdges (1, nbEdges);
704 TColStd_Array1OfReal aDistances (1, nbEdges);
705 for (exp.Init(aBlockOrComp, TopAbs_EDGE); exp.More(); exp.Next()) {
706 if (mapShape.Add(exp.Current())) {
707 TopoDS_Shape anEdge = exp.Current();
708 anEdges(ind) = anEdge;
710 // 2. Classify the point relatively each edge
711 BRepExtrema_DistShapeShape aDistTool (aVert, anEdges(ind));
712 if (!aDistTool.IsDone()) {
713 SetErrorCode("Can not find a distance from the given point to one of edges");
716 aDistances(ind) = aDistTool.Value();
721 // 3. Define edge, having minimum distance to the point
722 Standard_Real nearest = RealLast(), nbFound = 0;
723 Standard_Real prec = Precision::Confusion();
724 for (ind = 1; ind <= nbEdges; ind++) {
725 if (Abs(aDistances(ind) - nearest) < prec) {
727 } else if (aDistances(ind) < nearest) {
728 nearest = aDistances(ind);
729 aShape = anEdges(ind);
735 SetErrorCode("Multiple edges near the given point are found");
737 } else if (nbFound == 0) {
738 SetErrorCode("There are no edges near the given point");
741 TopTools_IndexedMapOfShape anIndices;
742 TopExp::MapShapes(aBlockOrComp, anIndices);
743 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
744 anArray->SetValue(1, anIndices.FindIndex(aShape));
745 aResult = GetEngine()->AddSubShape(theShape, anArray);
748 catch (Standard_Failure) {
749 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
750 SetErrorCode(aFail->GetMessageString());
754 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
756 //Make a Python command
757 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetEdgeNearPoint("
758 << theShape << ", " << thePoint << ")";
764 //=============================================================================
768 //=============================================================================
769 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByPoints
770 (Handle(GEOM_Object) theShape,
771 Handle(GEOM_Object) thePoint1,
772 Handle(GEOM_Object) thePoint2,
773 Handle(GEOM_Object) thePoint3,
774 Handle(GEOM_Object) thePoint4)
779 Handle(GEOM_Object) aResult;
782 if (theShape.IsNull() ||
783 thePoint1.IsNull() || thePoint2.IsNull() ||
784 thePoint3.IsNull() || thePoint4.IsNull()) return NULL;
786 TopoDS_Shape aBlockOrComp = theShape->GetValue();
787 if (aBlockOrComp.IsNull()) {
788 SetErrorCode("Block or compound is null");
791 if (aBlockOrComp.ShapeType() != TopAbs_SOLID &&
792 aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
793 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
794 SetErrorCode("Shape is neither a block, nor a compound of blocks");
798 TopoDS_Shape anArg1 = thePoint1->GetValue();
799 TopoDS_Shape anArg2 = thePoint2->GetValue();
800 TopoDS_Shape anArg3 = thePoint3->GetValue();
801 TopoDS_Shape anArg4 = thePoint4->GetValue();
802 if (anArg1.IsNull() || anArg2.IsNull() ||
803 anArg3.IsNull() || anArg4.IsNull()) {
804 SetErrorCode("Null shape is given as argument");
807 if (anArg1.ShapeType() != TopAbs_VERTEX ||
808 anArg2.ShapeType() != TopAbs_VERTEX ||
809 anArg3.ShapeType() != TopAbs_VERTEX ||
810 anArg4.ShapeType() != TopAbs_VERTEX) {
811 SetErrorCode("Element for face identification is not a vertex");
815 //Compute the Face value
819 TopTools_IndexedDataMapOfShapeListOfShape MVF;
820 GEOMImpl_Block6Explorer::MapShapesAndAncestors(aBlockOrComp, TopAbs_VERTEX, TopAbs_FACE, MVF);
822 TopoDS_Shape V1,V2,V3,V4;
823 Standard_Integer ish, ext = MVF.Extent();
825 if (MVF.Contains(anArg1)) {
828 for (ish = 1; ish <= ext; ish++) {
829 TopoDS_Shape aShi = MVF.FindKey(ish);
830 if (BRepTools::Compare(TopoDS::Vertex(anArg1), TopoDS::Vertex(aShi))) {
837 if (MVF.Contains(anArg2)) {
840 for (ish = 1; ish <= ext; ish++) {
841 TopoDS_Shape aShi = MVF.FindKey(ish);
842 if (BRepTools::Compare(TopoDS::Vertex(anArg2), TopoDS::Vertex(aShi))) {
849 if (MVF.Contains(anArg3)) {
852 for (ish = 1; ish <= ext; ish++) {
853 TopoDS_Shape aShi = MVF.FindKey(ish);
854 if (BRepTools::Compare(TopoDS::Vertex(anArg3), TopoDS::Vertex(aShi))) {
861 if (MVF.Contains(anArg4)) {
864 for (ish = 1; ish <= ext; ish++) {
865 TopoDS_Shape aShi = MVF.FindKey(ish);
866 if (BRepTools::Compare(TopoDS::Vertex(anArg4), TopoDS::Vertex(aShi))) {
873 if (V1.IsNull() || V2.IsNull() || V3.IsNull() || V4.IsNull()) {
874 SetErrorCode("The given vertex does not belong to the shape");
878 Standard_Integer isFound =
879 GEOMImpl_Block6Explorer::FindFace(aShape, V1, V2, V3, V4, MVF, Standard_True);
881 SetErrorCode("The given vertices do not belong to one face of the given shape");
883 } else if (isFound > 1) {
884 SetErrorCode("The given vertices belong to several faces of the given shape");
887 TopTools_IndexedMapOfShape anIndices;
888 TopExp::MapShapes(aBlockOrComp, anIndices);
889 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
890 anArray->SetValue(1, anIndices.FindIndex(aShape));
891 aResult = GetEngine()->AddSubShape(theShape, anArray);
894 catch (Standard_Failure) {
895 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
896 SetErrorCode(aFail->GetMessageString());
900 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
902 //Make a Python command
903 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByPoints("
904 << theShape << ", " << thePoint1 << ", " << thePoint2
905 << ", " << thePoint3 << ", " << thePoint4 << ")";
911 //=============================================================================
915 //=============================================================================
916 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByEdges
917 (Handle(GEOM_Object) theShape,
918 Handle(GEOM_Object) theEdge1,
919 Handle(GEOM_Object) theEdge2)
924 Handle(GEOM_Object) aResult;
927 if (theShape.IsNull() || theEdge1.IsNull() || theEdge2.IsNull()) return NULL;
929 TopoDS_Shape aBlockOrComp = theShape->GetValue();
930 if (aBlockOrComp.IsNull()) {
931 SetErrorCode("Block or compound is null");
934 if (aBlockOrComp.ShapeType() != TopAbs_SOLID &&
935 aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
936 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
937 SetErrorCode("Shape is neither a block, nor a compound of blocks");
941 TopoDS_Shape anArg1 = theEdge1->GetValue();
942 TopoDS_Shape anArg2 = theEdge2->GetValue();
943 if (anArg1.IsNull() || anArg2.IsNull()) {
944 SetErrorCode("Null shape is given as argument");
947 if (anArg1.ShapeType() != TopAbs_EDGE ||
948 anArg2.ShapeType() != TopAbs_EDGE) {
949 SetErrorCode("Element for face identification is not an edge");
953 //Compute the Face value
957 TopTools_IndexedDataMapOfShapeListOfShape MEF;
958 GEOMImpl_Block6Explorer::MapShapesAndAncestors(aBlockOrComp, TopAbs_EDGE, TopAbs_FACE, MEF);
961 Standard_Integer ish, ext = MEF.Extent();
963 if (MEF.Contains(anArg1)) {
966 for (ish = 1; ish <= ext; ish++) {
967 TopoDS_Shape aShi = MEF.FindKey(ish);
968 if (GEOMImpl_Block6Explorer::IsSimilarEdges(anArg1, aShi)) {
974 if (MEF.Contains(anArg2)) {
977 for (ish = 1; ish <= ext; ish++) {
978 TopoDS_Shape aShi = MEF.FindKey(ish);
979 if (GEOMImpl_Block6Explorer::IsSimilarEdges(anArg2, aShi)) {
985 if (E1.IsNull() || E2.IsNull()) {
986 SetErrorCode("The given edge does not belong to the shape");
990 const TopTools_ListOfShape& aFacesOfE1 = MEF.FindFromKey(E1);
991 const TopTools_ListOfShape& aFacesOfE2 = MEF.FindFromKey(E2);
993 Standard_Integer isFound = 0;
994 TopTools_ListIteratorOfListOfShape anIterF1 (aFacesOfE1);
995 for (; anIterF1.More(); anIterF1.Next()) {
997 TopTools_ListIteratorOfListOfShape anIterF2 (aFacesOfE2);
998 for (; anIterF2.More(); anIterF2.Next()) {
1000 if (anIterF1.Value().IsSame(anIterF2.Value())) {
1003 // Store the face, defined by two edges
1004 aShape = anIterF1.Value();
1009 SetErrorCode("The given edges do not belong to one face of the given shape");
1011 } else if (isFound > 1) {
1012 SetErrorCode("The given edges belong to several faces of the given shape");
1015 TopTools_IndexedMapOfShape anIndices;
1016 TopExp::MapShapes(aBlockOrComp, anIndices);
1017 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1018 anArray->SetValue(1, anIndices.FindIndex(aShape));
1019 aResult = GetEngine()->AddSubShape(theShape, anArray);
1022 catch (Standard_Failure) {
1023 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1024 SetErrorCode(aFail->GetMessageString());
1028 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1030 //Make a Python command
1031 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByEdges("
1032 << theShape << ", " << theEdge1 << ", " << theEdge2 << ")";
1038 //=============================================================================
1042 //=============================================================================
1043 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetOppositeFace
1044 (Handle(GEOM_Object) theShape,
1045 Handle(GEOM_Object) theFace)
1050 Handle(GEOM_Object) aResult;
1053 if (theShape.IsNull() || theFace.IsNull()) return NULL;
1055 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1056 if (aBlockOrComp.IsNull()) {
1057 SetErrorCode("Block is null");
1060 if (aBlockOrComp.ShapeType() != TopAbs_SOLID) {
1061 SetErrorCode("Shape is not a block");
1065 TopoDS_Shape anArg = theFace->GetValue();
1066 if (anArg.IsNull()) {
1067 SetErrorCode("Null shape is given as argument");
1070 if (anArg.ShapeType() != TopAbs_FACE) {
1071 SetErrorCode("Element for face identification is not a face");
1075 //Compute the Face value
1077 TopoDS_Shape aShape;
1079 GEOMImpl_Block6Explorer aBlockTool;
1080 aBlockTool.InitByBlockAndFace(aBlockOrComp, anArg);
1081 aShape = aBlockTool.GetFace(2);
1083 TopTools_IndexedMapOfShape anIndices;
1084 TopExp::MapShapes(aBlockOrComp, anIndices);
1085 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1086 anArray->SetValue(1, anIndices.FindIndex(aShape));
1087 aResult = GetEngine()->AddSubShape(theShape, anArray);
1089 catch (Standard_Failure) {
1090 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1091 SetErrorCode(aFail->GetMessageString());
1095 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1097 //Make a Python command
1098 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetOppositeFace("
1099 << theShape << ", " << theFace << ")";
1105 //=============================================================================
1109 //=============================================================================
1110 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceNearPoint
1111 (Handle(GEOM_Object) theShape,
1112 Handle(GEOM_Object) thePoint)
1117 Handle(GEOM_Object) aResult;
1120 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
1122 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1123 if (aBlockOrComp.IsNull()) {
1124 SetErrorCode("Block or compound is null");
1127 if (aBlockOrComp.ShapeType() != TopAbs_SOLID &&
1128 aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
1129 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
1130 SetErrorCode("Shape is neither a block, nor a compound of blocks");
1134 TopoDS_Shape anArg = thePoint->GetValue();
1135 if (anArg.IsNull()) {
1136 SetErrorCode("Null shape is given as argument");
1139 if (anArg.ShapeType() != TopAbs_VERTEX) {
1140 SetErrorCode("Element for face identification is not a vertex");
1144 //Compute the Face value
1146 TopoDS_Shape aShape;
1148 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
1149 gp_Pnt aPnt = BRep_Tool::Pnt(aVert);
1150 Standard_Real PX, PY, PZ;
1151 aPnt.Coord(PX, PY, PZ);
1153 // 1. Classify the point relatively each face
1154 Standard_Integer nearest = 2, nbFound = 0;
1155 TopTools_DataMapOfShapeInteger mapShapeDist;
1156 TopExp_Explorer exp (aBlockOrComp, TopAbs_FACE);
1157 for (; exp.More(); exp.Next()) {
1158 TopoDS_Shape aFace = exp.Current();
1160 if (!mapShapeDist.IsBound(aFace)) {
1161 Standard_Integer aDistance = 2;
1163 // 1.a. Classify relatively Surface
1164 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aFace));
1165 Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf);
1166 gp_Pnt2d p2dOnSurf = aSurfAna->ValueOfUV(aPnt, Precision::Confusion());
1167 gp_Pnt p3dOnSurf = aSurfAna->Value(p2dOnSurf);
1168 Standard_Real aDist = p3dOnSurf.Distance(aPnt);
1169 if (aDist > Precision::Confusion()) {
1173 // 1.b. Classify relatively the face itself
1174 BRepClass_FaceClassifier FC (TopoDS::Face(aFace), p2dOnSurf, Precision::Confusion());
1175 if (FC.State() == TopAbs_IN) {
1177 } else if (FC.State() == TopAbs_ON) {
1184 if (aDistance < nearest) {
1185 nearest = aDistance;
1189 // A first found face, containing the point inside, will be returned.
1190 // It is the solution, if there are no
1191 // coincident or intersecting faces in the compound.
1192 if (nearest == -1) break;
1194 } else if (aDistance == nearest) {
1199 mapShapeDist.Bind(aFace, aDistance);
1200 } // if (!mapShapeDist.IsBound(aFace))
1203 // 2. Define face, containing the point or having minimum distance to it
1206 // The point is on boundary of some faces and there are
1207 // no faces, having the point inside
1208 SetErrorCode("Multiple faces near the given point are found");
1211 } else if (nearest == 1) {
1212 // The point is outside some faces and there are
1213 // no faces, having the point inside or on boundary.
1214 // We will get a nearest face
1215 Standard_Real bigReal = RealLast();
1216 Standard_Real minDist = bigReal;
1217 TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
1218 for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
1219 if (mapShapeDistIter.Value() == 1) {
1220 TopoDS_Shape aFace = mapShapeDistIter.Key();
1221 Standard_Real aDist = bigReal;
1223 // 2.a. Fast check of distance - if point projection on surface is on face
1224 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aFace));
1225 Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf);
1226 gp_Pnt2d p2dOnSurf = aSurfAna->ValueOfUV(aPnt, Precision::Confusion());
1227 gp_Pnt p3dOnSurf = aSurfAna->Value(p2dOnSurf);
1228 aDist = p3dOnSurf.Distance(aPnt);
1230 BRepClass_FaceClassifier FC (TopoDS::Face(aFace), p2dOnSurf, Precision::Confusion());
1231 if (FC.State() == TopAbs_OUT) {
1232 if (aDist < minDist) {
1233 // 2.b. Slow check - if point projection on surface is outside of face
1234 BRepExtrema_DistShapeShape aDistTool (aVert, aFace);
1235 if (!aDistTool.IsDone()) {
1236 SetErrorCode("Can not find a distance from the given point to one of faces");
1239 aDist = aDistTool.Value();
1245 if (aDist < minDist) {
1251 } else { // nearest == -1
1252 // // The point is inside some faces.
1253 // // We will get a face with nearest center
1254 // Standard_Real minDist = RealLast();
1255 // TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
1256 // for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
1257 // if (mapShapeDistIter.Value() == -1) {
1258 // TopoDS_Shape aFace = mapShapeDistIter.Key();
1259 // GProp_GProps aSystem;
1260 // BRepGProp::SurfaceProperties(aFace, aSystem);
1261 // gp_Pnt aCenterMass = aSystem.CentreOfMass();
1263 // Standard_Real aDist = aCenterMass.Distance(aPnt);
1264 // if (aDist < minDist) {
1271 } // if (nbFound > 1)
1274 SetErrorCode("There are no faces near the given point");
1277 TopTools_IndexedMapOfShape anIndices;
1278 TopExp::MapShapes(aBlockOrComp, anIndices);
1279 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1280 anArray->SetValue(1, anIndices.FindIndex(aShape));
1281 aResult = GetEngine()->AddSubShape(theShape, anArray);
1284 catch (Standard_Failure) {
1285 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1286 SetErrorCode(aFail->GetMessageString());
1290 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1292 //Make a Python command
1293 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceNearPoint("
1294 << theShape << ", " << thePoint << ")";
1300 //=============================================================================
1304 //=============================================================================
1305 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByNormale
1306 (Handle(GEOM_Object) theShape,
1307 Handle(GEOM_Object) theVector)
1312 Handle(GEOM_Object) aResult;
1315 if (theShape.IsNull() || theVector.IsNull()) return NULL;
1317 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1318 if (aBlockOrComp.IsNull()) {
1319 SetErrorCode("Block or compound is null");
1322 if (aBlockOrComp.ShapeType() != TopAbs_SOLID &&
1323 aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
1324 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
1325 SetErrorCode("Shape is neither a block, nor a compound of blocks");
1329 TopoDS_Shape anArg = theVector->GetValue();
1330 if (anArg.IsNull()) {
1331 SetErrorCode("Null shape is given as argument");
1334 if (anArg.ShapeType() != TopAbs_EDGE) {
1335 SetErrorCode("Element for normale identification is not an edge");
1339 //Compute the Face value
1341 TopoDS_Shape aShape;
1343 TopoDS_Edge anEdge = TopoDS::Edge(anArg);
1344 TopoDS_Vertex V1, V2;
1345 TopExp::Vertices(anEdge, V1, V2, Standard_True);
1346 gp_Pnt P1 = BRep_Tool::Pnt(V1);
1347 gp_Pnt P2 = BRep_Tool::Pnt(V2);
1348 gp_Vec aVec (P1, P2);
1349 if (aVec.Magnitude() < Precision::Confusion()) {
1350 SetErrorCode("Vector with null magnitude is given");
1354 Standard_Real minAngle = RealLast();
1355 TopTools_MapOfShape mapShape;
1356 TopExp_Explorer exp (aBlockOrComp, TopAbs_FACE);
1357 for (; exp.More(); exp.Next()) {
1358 if (mapShape.Add(exp.Current())) {
1359 TopoDS_Face aFace = TopoDS::Face(exp.Current());
1360 BRepAdaptor_Surface SF (aFace);
1362 Standard_Real u, v, x;
1364 // find a point on the surface to get normal direction in
1365 u = SF.FirstUParameter();
1366 x = SF.LastUParameter();
1367 if (Precision::IsInfinite(u)) {
1368 u = (Precision::IsInfinite(x)) ? 0. : x;
1369 } else if (!Precision::IsInfinite(x)) {
1373 v = SF.FirstVParameter();
1374 x = SF.LastVParameter();
1375 if (Precision::IsInfinite(v)) {
1376 v = (Precision::IsInfinite(x)) ? 0. : x;
1377 } else if (!Precision::IsInfinite(x)) {
1381 // compute the normal direction
1383 SF.D1(u,v,P1,Vec1,Vec2);
1384 gp_Vec V = Vec1.Crossed(Vec2);
1386 if (V.Magnitude() < Precision::Confusion()) {
1387 SetErrorCode("Normal vector of a face has null magnitude");
1391 // consider the face orientation
1392 if (aFace.Orientation() == TopAbs_REVERSED ||
1393 aFace.Orientation() == TopAbs_INTERNAL) {
1397 // compute the angle and compare with the minimal one
1398 Standard_Real anAngle = aVec.Angle(V);
1399 if (anAngle < minAngle) {
1406 if (aShape.IsNull()) {
1407 SetErrorCode("Failed to find a face by the given normale");
1410 TopTools_IndexedMapOfShape anIndices;
1411 TopExp::MapShapes(aBlockOrComp, anIndices);
1412 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1413 anArray->SetValue(1, anIndices.FindIndex(aShape));
1414 aResult = GetEngine()->AddSubShape(theShape, anArray);
1417 catch (Standard_Failure) {
1418 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1419 SetErrorCode(aFail->GetMessageString());
1423 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1425 //Make a Python command
1426 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByNormale("
1427 << theShape << ", " << theVector << ")";
1433 //=============================================================================
1435 * IsCompoundOfBlocks
1437 //=============================================================================
1438 Standard_Boolean GEOMImpl_IBlocksOperations::IsCompoundOfBlocks
1439 (Handle(GEOM_Object) theCompound,
1440 const Standard_Integer theMinNbFaces,
1441 const Standard_Integer theMaxNbFaces,
1442 Standard_Integer& theNbBlocks)
1445 Standard_Boolean isCompOfBlocks = Standard_False;
1448 if (theCompound.IsNull()) return isCompOfBlocks;
1449 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
1452 isCompOfBlocks = Standard_True;
1454 TopTools_MapOfShape mapShape;
1455 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
1456 for (; exp.More(); exp.Next()) {
1457 if (mapShape.Add(exp.Current())) {
1458 TopoDS_Shape aSolid = exp.Current();
1460 TopTools_MapOfShape mapFaces;
1461 TopExp_Explorer expF (aSolid, TopAbs_FACE);
1462 Standard_Integer nbFaces = 0;
1463 for (; expF.More(); expF.Next()) {
1464 if (mapFaces.Add(expF.Current())) {
1466 if (nbFaces > theMaxNbFaces) {
1467 isCompOfBlocks = Standard_False;
1472 if (nbFaces < theMinNbFaces || theMaxNbFaces < nbFaces) {
1473 isCompOfBlocks = Standard_False;
1480 catch (Standard_Failure) {
1481 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1482 SetErrorCode(aFail->GetMessageString());
1483 return isCompOfBlocks;
1487 return isCompOfBlocks;
1490 //=============================================================================
1492 * Set of functions, used by CheckCompoundOfBlocks() method
1494 //=============================================================================
1495 void GEOMImpl_IBlocksOperations::AddBlocksFrom (const TopoDS_Shape& theShape,
1496 TopTools_ListOfShape& BLO,
1497 TopTools_ListOfShape& NOT,
1498 TopTools_ListOfShape& EXT)
1500 TopAbs_ShapeEnum aType = theShape.ShapeType();
1502 case TopAbs_COMPOUND:
1503 case TopAbs_COMPSOLID:
1505 TopoDS_Iterator It (theShape);
1506 for (; It.More(); It.Next()) {
1507 AddBlocksFrom(It.Value(), BLO, NOT, EXT);
1513 // Check, if there are seam or degenerated edges
1514 BlockFix_CheckTool aTool;
1515 aTool.SetShape(theShape);
1517 if (aTool.NbPossibleBlocks() > 0) {
1518 EXT.Append(theShape);
1520 // Count faces and edges in each face to recognize blocks
1521 TopTools_MapOfShape mapFaces;
1522 Standard_Integer nbFaces = 0;
1523 Standard_Boolean hasNonQuadr = Standard_False;
1524 TopExp_Explorer expF (theShape, TopAbs_FACE);
1526 for (; expF.More(); expF.Next()) {
1527 if (mapFaces.Add(expF.Current())) {
1529 if (nbFaces > 6) break;
1532 TopoDS_Shape aF = expF.Current();
1533 TopExp_Explorer wires (aF, TopAbs_WIRE);
1534 if (!wires.More()) {
1535 // no wire in the face
1536 hasNonQuadr = Standard_True;
1539 TopoDS_Shape aWire = wires.Current();
1542 // multiple wires in the face
1543 hasNonQuadr = Standard_True;
1547 // Check number of edges in the face
1548 Standard_Integer nbEdges = 0;
1549 TopTools_MapOfShape mapEdges;
1550 TopExp_Explorer expW (aWire, TopAbs_EDGE);
1551 for (; expW.More(); expW.Next()) {
1552 if (mapEdges.Add(expW.Current())) {
1554 if (nbEdges > 4) break;
1558 hasNonQuadr = Standard_True;
1563 if (nbFaces == 6 && !hasNonQuadr) {
1564 BLO.Append(theShape);
1566 NOT.Append(theShape);
1572 NOT.Append(theShape);
1576 void AddBlocksFromOld (const TopoDS_Shape& theShape,
1577 TopTools_ListOfShape& BLO,
1578 TopTools_ListOfShape& NOT,
1579 TopTools_ListOfShape& DEG,
1580 TopTools_ListOfShape& SEA)
1582 TopAbs_ShapeEnum aType = theShape.ShapeType();
1584 case TopAbs_COMPOUND:
1585 case TopAbs_COMPSOLID:
1587 TopoDS_Iterator It (theShape);
1588 for (; It.More(); It.Next()) {
1589 AddBlocksFromOld(It.Value(), BLO, NOT, DEG, SEA);
1595 TopTools_MapOfShape mapFaces;
1596 TopExp_Explorer expF (theShape, TopAbs_FACE);
1597 Standard_Integer nbFaces = 0;
1598 Standard_Boolean hasNonQuadr = Standard_False;
1599 Standard_Boolean hasDegenerated = Standard_False;
1600 Standard_Boolean hasSeam = Standard_False;
1601 for (; expF.More(); expF.Next()) {
1602 if (mapFaces.Add(expF.Current())) {
1604 if (nbFaces > 6) break;
1606 // Check number of edges in the face
1607 Standard_Integer nbEdges = 0;
1608 TopTools_MapOfShape mapEdges;
1611 TopoDS_Shape aF = expF.Current();
1612 TopExp_Explorer wires (aF, TopAbs_WIRE);
1613 if (!wires.More()) {
1614 // no wire in the face
1615 hasNonQuadr = Standard_True;
1618 TopoDS_Shape aWire = wires.Current();
1621 // multiple wires in the face
1622 hasNonQuadr = Standard_True;
1627 BRepTools_WireExplorer aWE (TopoDS::Wire(aWire), TopoDS::Face(aF));
1628 for (; aWE.More(); aWE.Next(), nbEdges++) {
1629 if (BRep_Tool::Degenerated(aWE.Current())) {
1630 // degenerated edge found
1631 hasDegenerated = Standard_True;
1634 if (mapEdges.Contains(aWE.Current())) {
1636 hasSeam = Standard_True;
1639 mapEdges.Add(aWE.Current());
1642 hasNonQuadr = Standard_True;
1647 if (hasDegenerated || hasSeam) {
1648 if (hasDegenerated) {
1649 DEG.Append(theShape);
1652 SEA.Append(theShape);
1654 } else if (hasNonQuadr) {
1655 NOT.Append(theShape);
1657 BLO.Append(theShape);
1660 NOT.Append(theShape);
1665 NOT.Append(theShape);
1669 #define REL_NOT_CONNECTED 0
1671 #define REL_NOT_GLUED 2
1672 #define REL_COLLISION_VV 3
1673 #define REL_COLLISION_FF 4
1674 #define REL_COLLISION_EE 5
1675 #define REL_UNKNOWN 6
1677 Standard_Integer BlocksRelation (const TopoDS_Shape& theBlock1,
1678 const TopoDS_Shape& theBlock2)
1680 // Compare bounding boxes before calling BRepExtrema_DistShapeShape
1681 Standard_Real Xmin1, Ymin1, Zmin1, Xmax1, Ymax1, Zmax1;
1682 Standard_Real Xmin2, Ymin2, Zmin2, Xmax2, Ymax2, Zmax2;
1684 BRepBndLib::Add(theBlock1, B1);
1685 BRepBndLib::Add(theBlock2, B2);
1686 B1.Get(Xmin1, Ymin1, Zmin1, Xmax1, Ymax1, Zmax1);
1687 B2.Get(Xmin2, Ymin2, Zmin2, Xmax2, Ymax2, Zmax2);
1688 if (Xmax2 < Xmin1 || Xmax1 < Xmin2 ||
1689 Ymax2 < Ymin1 || Ymax1 < Ymin2 ||
1690 Zmax2 < Zmin1 || Zmax1 < Zmin2) {
1691 return REL_NOT_CONNECTED;
1694 BRepExtrema_DistShapeShape dst (theBlock1, theBlock2);
1695 if (!dst.IsDone()) {
1699 if (dst.Value() > Precision::Confusion()) {
1700 return REL_NOT_CONNECTED;
1703 if (dst.InnerSolution()) {
1704 return REL_COLLISION_VV;
1707 Standard_Integer nbSol = dst.NbSolution();
1708 Standard_Integer relation = REL_OK;
1709 Standard_Integer nbVerts = 0;
1710 Standard_Integer nbEdges = 0;
1711 Standard_Integer sol = 1;
1712 for (; sol <= nbSol; sol++) {
1713 BRepExtrema_SupportType supp1 = dst.SupportTypeShape1(sol);
1714 BRepExtrema_SupportType supp2 = dst.SupportTypeShape2(sol);
1715 if (supp1 == BRepExtrema_IsVertex && supp2 == BRepExtrema_IsVertex) {
1717 } else if (supp1 == BRepExtrema_IsInFace || supp2 == BRepExtrema_IsInFace) {
1718 return REL_COLLISION_FF;
1719 } else if (supp1 == BRepExtrema_IsOnEdge && supp2 == BRepExtrema_IsOnEdge) {
1721 } else if ((supp1 == BRepExtrema_IsOnEdge && supp2 == BRepExtrema_IsVertex) ||
1722 (supp2 == BRepExtrema_IsOnEdge && supp1 == BRepExtrema_IsVertex)) {
1723 relation = REL_COLLISION_EE;
1728 if (relation != REL_OK) {
1732 TColStd_Array1OfInteger vertSol (1, nbVerts);
1733 TopTools_Array1OfShape V1 (1, nbVerts);
1734 TopTools_Array1OfShape V2 (1, nbVerts);
1735 Standard_Integer ivs = 0;
1736 for (sol = 1; sol <= nbSol; sol++) {
1737 if (dst.SupportTypeShape1(sol) == BRepExtrema_IsVertex &&
1738 dst.SupportTypeShape2(sol) == BRepExtrema_IsVertex) {
1739 TopoDS_Vertex Vcur = TopoDS::Vertex(dst.SupportOnShape1(sol));
1740 // Check, that this vertex is far enough from other solution vertices.
1741 Standard_Integer ii = 1;
1742 for (; ii <= ivs; ii++) {
1743 if (BRepTools::Compare(TopoDS::Vertex(V1(ii)), Vcur)) {
1750 V2(ivs) = dst.SupportOnShape2(sol);
1754 // As we deal only with quadrangles,
1755 // 2, 3 or 4 vertex solutions can be found.
1758 return REL_COLLISION_FF;
1760 return REL_NOT_CONNECTED;
1766 // Check sharing of coincident entities.
1767 if (ivs == 2 || ivs == 3) {
1768 // Map vertices and edges of the blocks
1769 TopTools_IndexedDataMapOfShapeListOfShape MVE1, MVE2;
1770 GEOMImpl_Block6Explorer::MapShapesAndAncestors
1771 (theBlock1, TopAbs_VERTEX, TopAbs_EDGE, MVE1);
1772 GEOMImpl_Block6Explorer::MapShapesAndAncestors
1773 (theBlock2, TopAbs_VERTEX, TopAbs_EDGE, MVE2);
1777 TopoDS_Shape anEdge1, anEdge2;
1778 GEOMImpl_Block6Explorer::FindEdge(anEdge1, V1(1), V1(2), MVE1);
1779 if (anEdge1.IsNull()) return REL_UNKNOWN;
1781 GEOMImpl_Block6Explorer::FindEdge(anEdge2, V2(1), V2(2), MVE2);
1782 if (anEdge2.IsNull()) return REL_UNKNOWN;
1784 if (!anEdge1.IsSame(anEdge2)) return REL_NOT_GLUED;
1786 } else { // ivs == 3
1787 // Find common edges
1788 Standard_Integer e1_v1 = 1;
1789 Standard_Integer e1_v2 = 2;
1790 Standard_Integer e2_v1 = 3;
1791 Standard_Integer e2_v2 = 1;
1793 TopoDS_Shape anEdge11, anEdge12;
1794 GEOMImpl_Block6Explorer::FindEdge(anEdge11, V1(e1_v1), V1(e1_v2), MVE1);
1795 if (anEdge11.IsNull()) {
1798 GEOMImpl_Block6Explorer::FindEdge(anEdge11, V1(e1_v1), V1(e1_v2), MVE1);
1799 if (anEdge11.IsNull()) return REL_UNKNOWN;
1801 GEOMImpl_Block6Explorer::FindEdge(anEdge12, V1(e2_v1), V1(e2_v2), MVE1);
1802 if (anEdge12.IsNull()) {
1804 GEOMImpl_Block6Explorer::FindEdge(anEdge12, V1(e2_v1), V1(e2_v2), MVE1);
1805 if (anEdge12.IsNull()) return REL_UNKNOWN;
1808 TopoDS_Shape anEdge21, anEdge22;
1809 GEOMImpl_Block6Explorer::FindEdge(anEdge21, V2(e1_v1), V2(e1_v2), MVE2);
1810 if (anEdge21.IsNull()) return REL_UNKNOWN;
1811 GEOMImpl_Block6Explorer::FindEdge(anEdge22, V2(e2_v1), V2(e2_v2), MVE2);
1812 if (anEdge22.IsNull()) return REL_UNKNOWN;
1814 // Check of edges coincidence (with some precision) have to be done here
1815 // if (!anEdge11.IsEqual(anEdge21)) return REL_UNKNOWN;
1816 // if (!anEdge12.IsEqual(anEdge22)) return REL_UNKNOWN;
1818 // Check of edges sharing
1819 if (!anEdge11.IsSame(anEdge21)) return REL_NOT_GLUED;
1820 if (!anEdge12.IsSame(anEdge22)) return REL_NOT_GLUED;
1825 // Map vertices and faces of the blocks
1826 TopTools_IndexedDataMapOfShapeListOfShape MVF1, MVF2;
1827 GEOMImpl_Block6Explorer::MapShapesAndAncestors
1828 (theBlock1, TopAbs_VERTEX, TopAbs_FACE, MVF1);
1829 GEOMImpl_Block6Explorer::MapShapesAndAncestors
1830 (theBlock2, TopAbs_VERTEX, TopAbs_FACE, MVF2);
1832 TopoDS_Shape aFace1, aFace2;
1833 GEOMImpl_Block6Explorer::FindFace(aFace1, V1(1), V1(2), V1(3), V1(4), MVF1);
1834 if (aFace1.IsNull()) return REL_UNKNOWN;
1835 GEOMImpl_Block6Explorer::FindFace(aFace2, V2(1), V2(2), V2(3), V2(4), MVF2);
1836 if (aFace2.IsNull()) return REL_UNKNOWN;
1838 // Check of faces coincidence (with some precision) have to be done here
1839 // if (!aFace1.IsEqual(aFace2)) return REL_UNKNOWN;
1841 // Check of faces sharing
1842 if (!aFace1.IsSame(aFace2)) return REL_NOT_GLUED;
1848 void FindConnected (const Standard_Integer theBlockIndex,
1849 const TColStd_Array2OfInteger& theRelations,
1850 TColStd_MapOfInteger& theProcessedMap,
1851 TColStd_MapOfInteger& theConnectedMap)
1853 theConnectedMap.Add(theBlockIndex);
1854 theProcessedMap.Add(theBlockIndex);
1856 Standard_Integer nbBlocks = theRelations.ColLength();
1857 Standard_Integer col = 1;
1858 for (; col <= nbBlocks; col++) {
1859 if (theRelations(theBlockIndex, col) == REL_OK ||
1860 theRelations(theBlockIndex, col) == REL_NOT_GLUED) {
1861 if (!theProcessedMap.Contains(col)) {
1862 FindConnected(col, theRelations, theProcessedMap, theConnectedMap);
1868 Standard_Boolean HasAnyConnection (const Standard_Integer theBlockIndex,
1869 const TColStd_MapOfInteger& theWith,
1870 const TColStd_Array2OfInteger& theRelations,
1871 TColStd_MapOfInteger& theProcessedMap)
1873 theProcessedMap.Add(theBlockIndex);
1875 Standard_Integer nbBlocks = theRelations.ColLength();
1876 Standard_Integer col = 1;
1877 for (; col <= nbBlocks; col++) {
1878 if (theRelations(theBlockIndex, col) != REL_NOT_CONNECTED) {
1879 if (!theProcessedMap.Contains(col)) {
1880 if (theWith.Contains(col))
1881 return Standard_True;
1882 if (HasAnyConnection(col, theWith, theRelations, theProcessedMap))
1883 return Standard_True;
1888 return Standard_False;
1891 //=============================================================================
1893 * CheckCompoundOfBlocksOld
1895 //=============================================================================
1896 Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocksOld
1897 (Handle(GEOM_Object) theCompound,
1898 list<BCError>& theErrors)
1902 if (theCompound.IsNull()) return Standard_False;
1903 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
1905 Standard_Boolean isCompOfBlocks = Standard_True;
1907 // Map sub-shapes and their indices
1908 TopTools_IndexedMapOfShape anIndices;
1909 TopExp::MapShapes(aBlockOrComp, anIndices);
1911 // 1. Report non-blocks
1912 TopTools_ListOfShape NOT; // Not blocks
1913 TopTools_ListOfShape DEG; // Hexahedral solids, having degenerated edges
1914 TopTools_ListOfShape SEA; // Hexahedral solids, having seam edges
1915 TopTools_ListOfShape BLO; // All blocks from the given compound
1916 AddBlocksFromOld(aBlockOrComp, BLO, NOT, DEG, SEA);
1918 if (NOT.Extent() > 0) {
1919 isCompOfBlocks = Standard_False;
1921 anErr.error = NOT_BLOCK;
1922 TopTools_ListIteratorOfListOfShape it (NOT);
1923 for (; it.More(); it.Next()) {
1924 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
1926 theErrors.push_back(anErr);
1929 if (DEG.Extent() > 0 || SEA.Extent() > 0) {
1930 isCompOfBlocks = Standard_False;
1932 anErr.error = EXTRA_EDGE;
1934 TopTools_ListIteratorOfListOfShape itDEG (DEG);
1935 for (; itDEG.More(); itDEG.Next()) {
1936 anErr.incriminated.push_back(anIndices.FindIndex(itDEG.Value()));
1939 TopTools_ListIteratorOfListOfShape itSEA (SEA);
1940 for (; itSEA.More(); itSEA.Next()) {
1941 anErr.incriminated.push_back(anIndices.FindIndex(itSEA.Value()));
1944 theErrors.push_back(anErr);
1947 Standard_Integer nbBlocks = BLO.Extent();
1948 if (nbBlocks == 0) {
1949 isCompOfBlocks = Standard_False;
1951 return isCompOfBlocks;
1953 if (nbBlocks == 1) {
1955 return isCompOfBlocks;
1958 // Convert list of blocks into array for easy and fast access
1959 Standard_Integer ibl = 1;
1960 TopTools_Array1OfShape aBlocks (1, nbBlocks);
1961 TopTools_ListIteratorOfListOfShape BLOit (BLO);
1962 for (; BLOit.More(); BLOit.Next(), ibl++) {
1963 aBlocks.SetValue(ibl, BLOit.Value());
1966 // 2. Find relations between all blocks,
1967 // report connection errors (NOT_GLUED and INVALID_CONNECTION)
1968 TColStd_Array2OfInteger aRelations (1, nbBlocks, 1, nbBlocks);
1969 aRelations.Init(REL_NOT_CONNECTED);
1971 Standard_Integer row = 1;
1972 for (row = 1; row <= nbBlocks; row++) {
1973 TopoDS_Shape aBlock = aBlocks.Value(row);
1975 Standard_Integer col = row + 1;
1976 for (; col <= nbBlocks; col++) {
1977 Standard_Integer aRel = BlocksRelation(aBlock, aBlocks.Value(col));
1978 if (aRel != REL_NOT_CONNECTED) {
1979 aRelations.SetValue(row, col, aRel);
1980 aRelations.SetValue(col, row, aRel);
1981 if (aRel == REL_NOT_GLUED) {
1982 // report connection error
1983 isCompOfBlocks = Standard_False;
1985 anErr.error = NOT_GLUED;
1986 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row)));
1987 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col)));
1988 theErrors.push_back(anErr);
1989 } else if (aRel == REL_COLLISION_VV ||
1990 aRel == REL_COLLISION_FF ||
1991 aRel == REL_COLLISION_EE ||
1992 aRel == REL_UNKNOWN) {
1993 // report connection error
1994 isCompOfBlocks = Standard_False;
1996 anErr.error = INVALID_CONNECTION;
1997 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row)));
1998 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col)));
1999 theErrors.push_back(anErr);
2006 // 3. Find largest set of connected (good connection or not glued) blocks
2007 TColStd_MapOfInteger aProcessedMap;
2008 TColStd_MapOfInteger aLargestSet;
2009 TColStd_MapOfInteger aCurrentSet;
2010 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2011 if (!aProcessedMap.Contains(ibl)) {
2012 aCurrentSet.Clear();
2013 FindConnected(ibl, aRelations, aProcessedMap, aCurrentSet);
2014 if (aCurrentSet.Extent() > aLargestSet.Extent()) {
2015 aLargestSet = aCurrentSet;
2020 // 4. Report all blocks, isolated from <aLargestSet>
2022 anErr.error = NOT_CONNECTED;
2023 Standard_Boolean hasIsolated = Standard_False;
2024 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2025 if (!aLargestSet.Contains(ibl)) {
2026 aProcessedMap.Clear();
2027 if (!HasAnyConnection(ibl, aLargestSet, aRelations, aProcessedMap)) {
2028 // report connection absence
2029 hasIsolated = Standard_True;
2030 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(ibl)));
2035 isCompOfBlocks = Standard_False;
2036 theErrors.push_back(anErr);
2040 return isCompOfBlocks;
2043 //=============================================================================
2047 //=============================================================================
2048 TCollection_AsciiString GEOMImpl_IBlocksOperations::PrintBCErrors
2049 (Handle(GEOM_Object) theCompound,
2050 const list<BCError>& theErrors)
2052 TCollection_AsciiString aDescr;
2054 list<BCError>::const_iterator errIt = theErrors.begin();
2056 for (; errIt != theErrors.end(); i++, errIt++) {
2057 BCError errStruct = *errIt;
2059 switch (errStruct.error) {
2061 aDescr += "\n\tNot a Blocks: ";
2064 aDescr += "\n\tHexahedral solids with degenerated and/or seam edges: ";
2066 case INVALID_CONNECTION:
2067 aDescr += "\n\tInvalid connection between two blocks: ";
2070 aDescr += "\n\tBlocks, not connected with main body: ";
2073 aDescr += "\n\tNot glued blocks: ";
2079 list<int> sshList = errStruct.incriminated;
2080 list<int>::iterator sshIt = sshList.begin();
2082 for (; sshIt != sshList.end(); jj++, sshIt++) {
2085 aDescr += TCollection_AsciiString(*sshIt);
2092 //=============================================================================
2094 * CheckCompoundOfBlocks
2096 //=============================================================================
2097 Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocks
2098 (Handle(GEOM_Object) theCompound,
2099 list<BCError>& theErrors)
2103 if (theCompound.IsNull()) return Standard_False;
2104 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2106 Standard_Boolean isCompOfBlocks = Standard_True;
2108 // Map sub-shapes and their indices
2109 TopTools_IndexedMapOfShape anIndices;
2110 TopExp::MapShapes(aBlockOrComp, anIndices);
2112 // 1. Separate blocks from non-blocks
2113 TopTools_ListOfShape NOT; // Not blocks
2114 TopTools_ListOfShape EXT; // Hexahedral solids, having degenerated and/or seam edges
2115 TopTools_ListOfShape BLO; // All blocks from the given compound
2116 AddBlocksFrom(aBlockOrComp, BLO, NOT, EXT);
2118 // Report non-blocks
2119 if (NOT.Extent() > 0) {
2120 isCompOfBlocks = Standard_False;
2122 anErr.error = NOT_BLOCK;
2123 TopTools_ListIteratorOfListOfShape it (NOT);
2124 for (; it.More(); it.Next()) {
2125 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
2127 theErrors.push_back(anErr);
2130 // Report solids, having degenerated and/or seam edges
2131 if (EXT.Extent() > 0) {
2132 isCompOfBlocks = Standard_False;
2134 anErr.error = EXTRA_EDGE;
2135 TopTools_ListIteratorOfListOfShape it (EXT);
2136 for (; it.More(); it.Next()) {
2137 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
2139 theErrors.push_back(anErr);
2142 Standard_Integer nbBlocks = BLO.Extent();
2143 if (nbBlocks == 0) {
2144 isCompOfBlocks = Standard_False;
2146 return isCompOfBlocks;
2148 if (nbBlocks == 1) {
2150 return isCompOfBlocks;
2153 // Prepare data for 2. and 3.
2154 TColStd_Array2OfInteger aRelations (1, nbBlocks, 1, nbBlocks);
2155 aRelations.Init(REL_NOT_CONNECTED);
2157 TopTools_IndexedMapOfShape mapBlocks;
2160 TopoDS_Compound aComp;
2161 BB.MakeCompound(aComp);
2163 TopTools_ListIteratorOfListOfShape BLOit (BLO);
2164 for (; BLOit.More(); BLOit.Next()) {
2165 mapBlocks.Add(BLOit.Value());
2166 BB.Add(aComp, BLOit.Value());
2169 // 2. Find glued blocks (having shared faces)
2170 TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
2171 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2172 (aComp, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
2174 Standard_Integer prevInd = 0, curInd = 0;
2175 Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
2176 for (; ind <= nbFaces; ind++) {
2177 const TopTools_ListOfShape& aGluedBlocks = mapFaceBlocks.FindFromIndex(ind);
2178 if (aGluedBlocks.Extent() > 1) { // Shared face found
2179 TopTools_ListIteratorOfListOfShape aGluedBlocksIt (aGluedBlocks);
2180 TopoDS_Shape prevBlock, curBlock;
2181 for (; aGluedBlocksIt.More(); aGluedBlocksIt.Next()) {
2182 curBlock = aGluedBlocksIt.Value();
2183 if (!prevBlock.IsNull()) {
2184 prevInd = mapBlocks.FindIndex(prevBlock);
2185 curInd = mapBlocks.FindIndex(curBlock);
2186 aRelations.SetValue(prevInd, curInd, REL_OK);
2187 aRelations.SetValue(curInd, prevInd, REL_OK);
2189 prevBlock = curBlock;
2194 // 3. Find not glued blocks
2195 GEOMAlgo_GlueAnalyser aGD;
2197 aGD.SetShape(aComp);
2198 aGD.SetTolerance(Precision::Confusion());
2199 aGD.SetCheckGeometry(Standard_True);
2202 Standard_Integer iErr, iWrn;
2203 iErr = aGD.ErrorStatus();
2205 SetErrorCode("Error in GEOMAlgo_GlueAnalyser");
2206 return isCompOfBlocks;
2208 iWrn = aGD.WarningStatus();
2210 MESSAGE("Warning in GEOMAlgo_GlueAnalyser");
2213 // Report not glued blocks
2214 if (aGD.HasSolidsToGlue()) {
2215 isCompOfBlocks = Standard_False;
2216 Standard_Integer aSx1Ind, aSx2Ind;
2218 const GEOMAlgo_ListOfCoupleOfShapes& aLCS = aGD.SolidsToGlue();
2219 GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS (aLCS);
2220 for (; aItCS.More(); aItCS.Next()) {
2221 const GEOMAlgo_CoupleOfShapes& aCS = aItCS.Value();
2222 const TopoDS_Shape& aSx1 = aCS.Shape1();
2223 const TopoDS_Shape& aSx2 = aCS.Shape2();
2225 aSx1Ind = mapBlocks.FindIndex(aSx1);
2226 aSx2Ind = mapBlocks.FindIndex(aSx2);
2227 aRelations.SetValue(aSx1Ind, aSx2Ind, NOT_GLUED);
2228 aRelations.SetValue(aSx2Ind, aSx1Ind, NOT_GLUED);
2231 anErr.error = NOT_GLUED;
2232 anErr.incriminated.push_back(anIndices.FindIndex(aSx1));
2233 anErr.incriminated.push_back(anIndices.FindIndex(aSx2));
2234 theErrors.push_back(anErr);
2238 // 4. Find largest set of connected (good connection or not glued) blocks
2239 Standard_Integer ibl = 1;
2240 TColStd_MapOfInteger aProcessedMap;
2241 TColStd_MapOfInteger aLargestSet;
2242 TColStd_MapOfInteger aCurrentSet;
2243 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2244 if (!aProcessedMap.Contains(ibl)) {
2245 aCurrentSet.Clear();
2246 FindConnected(ibl, aRelations, aProcessedMap, aCurrentSet);
2247 if (aCurrentSet.Extent() > aLargestSet.Extent()) {
2248 aLargestSet = aCurrentSet;
2253 // 5. Report all blocks, isolated from <aLargestSet>
2255 anErr.error = NOT_CONNECTED;
2256 Standard_Boolean hasIsolated = Standard_False;
2257 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2258 if (!aLargestSet.Contains(ibl)) {
2259 aProcessedMap.Clear();
2260 if (!HasAnyConnection(ibl, aLargestSet, aRelations, aProcessedMap)) {
2261 // report connection absence
2262 hasIsolated = Standard_True;
2263 anErr.incriminated.push_back(anIndices.FindIndex(mapBlocks.FindKey(ibl)));
2268 isCompOfBlocks = Standard_False;
2269 theErrors.push_back(anErr);
2273 return isCompOfBlocks;
2276 //=============================================================================
2280 //=============================================================================
2281 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::RemoveExtraEdges
2282 (Handle(GEOM_Object) theObject)
2286 if (theObject.IsNull()) return NULL;
2288 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2289 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be fixed
2291 //Add a new Copy object
2292 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2295 Handle(GEOM_Function) aFunction =
2296 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_REMOVE_EXTRA);
2298 //Check if the function is set correctly
2299 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2301 GEOMImpl_IBlockTrsf aTI (aFunction);
2302 aTI.SetOriginal(aLastFunction);
2304 //Compute the fixed shape
2306 if (!GetSolver()->ComputeFunction(aFunction)) {
2307 SetErrorCode("Block driver failed to remove extra edges of the given shape");
2311 catch (Standard_Failure) {
2312 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2313 SetErrorCode(aFail->GetMessageString());
2317 //Make a Python command
2318 GEOM::TPythonDump(aFunction) << aCopy
2319 << " = geompy.RemoveExtraEdges(" << theObject << ")";
2325 //=============================================================================
2329 //=============================================================================
2330 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::CheckAndImprove
2331 (Handle(GEOM_Object) theObject)
2335 if (theObject.IsNull()) return NULL;
2337 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2338 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be fixed
2340 //Add a new Copy object
2341 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2344 Handle(GEOM_Function) aFunction =
2345 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_COMPOUND_IMPROVE);
2347 //Check if the function is set correctly
2348 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2350 GEOMImpl_IBlockTrsf aTI (aFunction);
2351 aTI.SetOriginal(aLastFunction);
2353 //Compute the fixed shape
2355 if (!GetSolver()->ComputeFunction(aFunction)) {
2356 SetErrorCode("Block driver failed to improve the given blocks compound");
2360 catch (Standard_Failure) {
2361 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2362 SetErrorCode(aFail->GetMessageString());
2366 //Make a Python command
2367 GEOM::TPythonDump(aFunction) << aCopy
2368 << " = geompy.CheckAndImprove(" << theObject << ")";
2374 //=============================================================================
2376 * ExplodeCompoundOfBlocks
2378 //=============================================================================
2379 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::ExplodeCompoundOfBlocks
2380 (Handle(GEOM_Object) theCompound,
2381 const Standard_Integer theMinNbFaces,
2382 const Standard_Integer theMaxNbFaces)
2386 if (theCompound.IsNull()) return NULL;
2387 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2388 if (aBlockOrComp.IsNull()) return NULL;
2390 Handle(TColStd_HSequenceOfTransient) aBlocks = new TColStd_HSequenceOfTransient;
2391 Handle(GEOM_Object) anObj;
2392 Handle(GEOM_Function) aFunction;
2394 TopTools_MapOfShape mapShape;
2395 TCollection_AsciiString anAsciiList, anEntry;
2398 TopTools_IndexedMapOfShape anIndices;
2399 TopExp::MapShapes(aBlockOrComp, anIndices);
2400 Handle(TColStd_HArray1OfInteger) anArray;
2404 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2405 for (; exp.More(); exp.Next()) {
2406 if (mapShape.Add(exp.Current())) {
2407 TopoDS_Shape aSolid = exp.Current();
2409 TopTools_MapOfShape mapFaces;
2410 TopExp_Explorer expF (aSolid, TopAbs_FACE);
2411 Standard_Integer nbFaces = 0;
2412 for (; expF.More(); expF.Next()) {
2413 if (mapFaces.Add(expF.Current())) {
2418 if (theMinNbFaces <= nbFaces && nbFaces <= theMaxNbFaces) {
2419 anArray = new TColStd_HArray1OfInteger(1,1);
2420 anArray->SetValue(1, anIndices.FindIndex(aSolid));
2421 anObj = GetEngine()->AddSubShape(theCompound, anArray);
2422 aBlocks->Append(anObj);
2424 //Make a Python command
2425 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2426 anAsciiList += anEntry + ", ";
2431 catch (Standard_Failure) {
2432 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2433 SetErrorCode(aFail->GetMessageString());
2437 if (aBlocks->IsEmpty()) {
2438 SetErrorCode("There are no specified blocks in the given shape");
2442 anAsciiList.Trunc(anAsciiList.Length() - 2);
2444 //The explode doesn't change object so no new function is required.
2445 aFunction = theCompound->GetLastFunction();
2446 TCollection_AsciiString anOldDescr = aFunction->GetDescription();
2448 //Make a Python command
2449 GEOM::TPythonDump(aFunction) << anOldDescr.ToCString() << "\n\t["
2450 << anAsciiList.ToCString() << "] = geompy.MakeBlockExplode("
2451 << theCompound << ", " << theMinNbFaces << ", " << theMaxNbFaces << ")";
2457 //=============================================================================
2461 //=============================================================================
2462 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetBlockNearPoint
2463 (Handle(GEOM_Object) theCompound,
2464 Handle(GEOM_Object) thePoint)
2469 Handle(GEOM_Object) aResult;
2472 if (theCompound.IsNull() || thePoint.IsNull()) return NULL;
2474 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2475 if (aBlockOrComp.IsNull()) {
2476 SetErrorCode("Compound is null");
2479 if (aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
2480 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
2481 SetErrorCode("Shape to find block in is not a compound");
2485 TopoDS_Shape anArg = thePoint->GetValue();
2486 if (anArg.IsNull()) {
2487 SetErrorCode("Point is null");
2490 if (anArg.ShapeType() != TopAbs_VERTEX) {
2491 SetErrorCode("Shape for block identification is not a vertex");
2495 //Compute the Block value
2497 TopoDS_Shape aShape;
2499 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
2500 gp_Pnt aPnt = BRep_Tool::Pnt(aVert);
2501 Standard_Real PX, PY, PZ;
2502 aPnt.Coord(PX, PY, PZ);
2504 // 1. Classify the point relatively each block
2505 Standard_Integer nearest = 2, nbFound = 0;
2506 TopTools_DataMapOfShapeInteger mapShapeDist;
2507 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2508 for (; exp.More(); exp.Next()) {
2509 TopoDS_Shape aSolid = exp.Current();
2511 if (!mapShapeDist.IsBound(aSolid)) {
2512 Standard_Integer aDistance = 2;
2514 // 1.a. Classify relatively Bounding box
2515 Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
2517 BRepBndLib::Add(aSolid, BB);
2518 BB.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
2519 if (PX < Xmin || Xmax < PX ||
2520 PY < Ymin || Ymax < PY ||
2521 PZ < Zmin || Zmax < PZ) {
2522 // OUT of bounding box
2525 // 1.b. Classify relatively the solid itself
2526 BRepClass3d_SolidClassifier SC (aSolid, aPnt, Precision::Confusion());
2527 if (SC.State() == TopAbs_IN) {
2529 } else if (SC.State() == TopAbs_ON) {
2536 if (aDistance < nearest) {
2537 nearest = aDistance;
2541 // A first found block, containing the point inside, will be returned.
2542 // It is the solution, if there are no intersecting blocks in the compound.
2543 if (nearest == -1) break;
2545 } else if (aDistance == nearest) {
2550 mapShapeDist.Bind(aSolid, aDistance);
2551 } // if (!mapShapeDist.IsBound(aSolid))
2554 // 2. Define block, containing the point or having minimum distance to it
2557 // The point is on boundary of some blocks and there are
2558 // no blocks, having the point inside their volume
2559 SetErrorCode("Multiple blocks near the given point are found");
2562 } else if (nearest == 1) {
2563 // The point is outside some blocks and there are
2564 // no blocks, having the point inside or on boundary.
2565 // We will get a nearest block
2566 Standard_Real minDist = RealLast();
2567 TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
2568 for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
2569 if (mapShapeDistIter.Value() == 1) {
2570 TopoDS_Shape aSolid = mapShapeDistIter.Key();
2571 BRepExtrema_DistShapeShape aDistTool (aVert, aSolid);
2572 if (!aDistTool.IsDone()) {
2573 SetErrorCode("Can not find a distance from the given point to one of blocks");
2576 Standard_Real aDist = aDistTool.Value();
2577 if (aDist < minDist) {
2583 } else { // nearest == -1
2584 // // The point is inside some blocks.
2585 // // We will get a block with nearest center
2586 // Standard_Real minDist = RealLast();
2587 // TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
2588 // for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
2589 // if (mapShapeDistIter.Value() == -1) {
2590 // TopoDS_Shape aSolid = mapShapeDistIter.Key();
2591 // GProp_GProps aSystem;
2592 // BRepGProp::VolumeProperties(aSolid, aSystem);
2593 // gp_Pnt aCenterMass = aSystem.CentreOfMass();
2595 // Standard_Real aDist = aCenterMass.Distance(aPnt);
2596 // if (aDist < minDist) {
2603 } // if (nbFound > 1)
2606 SetErrorCode("There are no blocks near the given point");
2609 TopTools_IndexedMapOfShape anIndices;
2610 TopExp::MapShapes(aBlockOrComp, anIndices);
2611 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2612 anArray->SetValue(1, anIndices.FindIndex(aShape));
2613 aResult = GetEngine()->AddSubShape(theCompound, anArray);
2616 catch (Standard_Failure) {
2617 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2618 SetErrorCode(aFail->GetMessageString());
2622 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
2624 //Make a Python command
2625 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetBlockNearPoint("
2626 << theCompound << ", " << thePoint << ")";
2632 //=============================================================================
2636 //=============================================================================
2637 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetBlockByParts
2638 (Handle(GEOM_Object) theCompound,
2639 const Handle(TColStd_HSequenceOfTransient)& theParts)
2643 Handle(GEOM_Object) aResult;
2645 if (theCompound.IsNull() || theParts.IsNull()) return NULL;
2646 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2647 if (aBlockOrComp.IsNull()) return NULL;
2650 Standard_Integer argi, aLen = theParts->Length();
2651 TopTools_Array1OfShape anArgs (1, aLen);
2652 TCollection_AsciiString anEntry, aPartsDescr;
2653 for (argi = 1; argi <= aLen; argi++) {
2654 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theParts->Value(argi));
2655 Handle(GEOM_Function) aRef = anObj->GetLastFunction();
2656 if (aRef.IsNull()) return NULL;
2658 TopoDS_Shape anArg = aRef->GetValue();
2659 if (anArg.IsNull()) {
2660 SetErrorCode("Null shape is given as argument");
2663 anArgs(argi) = anArg;
2665 // For Python command
2666 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2667 if (argi > 1) aPartsDescr += ", ";
2668 aPartsDescr += anEntry;
2671 //Compute the Block value
2673 // 1. Explode compound on solids
2674 TopTools_MapOfShape mapShape;
2675 Standard_Integer nbSolids = 0;
2676 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2677 for (; exp.More(); exp.Next()) {
2678 if (mapShape.Add(exp.Current())) {
2684 Standard_Integer ind = 1;
2685 TopTools_Array1OfShape aSolids (1, nbSolids);
2686 TColStd_Array1OfInteger aNbParts (1, nbSolids);
2687 for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next(), ind++) {
2688 if (mapShape.Add(exp.Current())) {
2689 TopoDS_Shape aSolid = exp.Current();
2690 aSolids(ind) = aSolid;
2693 // 2. Define quantity of parts, contained in each solid
2694 TopTools_IndexedMapOfShape aSubShapes;
2695 TopExp::MapShapes(aSolid, aSubShapes);
2696 for (argi = 1; argi <= aLen; argi++) {
2697 if (aSubShapes.Contains(anArgs(argi))) {
2704 // 3. Define solid, containing maximum quantity of parts
2705 Standard_Integer maxNb = 0, nbFound = 0;
2706 TopoDS_Shape aShape;
2707 for (ind = 1; ind <= nbSolids; ind++) {
2708 if (aNbParts(ind) > maxNb) {
2709 maxNb = aNbParts(ind);
2710 aShape = aSolids(ind);
2712 } else if (aNbParts(ind) == maxNb) {
2718 SetErrorCode("Multiple blocks, containing maximum quantity of the given parts, are found");
2720 } else if (nbFound == 0) {
2721 SetErrorCode("There are no blocks, containing the given parts");
2724 TopTools_IndexedMapOfShape anIndices;
2725 TopExp::MapShapes(aBlockOrComp, anIndices);
2726 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2727 anArray->SetValue(1, anIndices.FindIndex(aShape));
2728 aResult = GetEngine()->AddSubShape(theCompound, anArray);
2730 } catch (Standard_Failure) {
2731 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2732 SetErrorCode(aFail->GetMessageString());
2736 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
2738 //Make a Python command
2739 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetBlockByParts("
2740 << theCompound << ", [" << aPartsDescr.ToCString() << "])";
2746 //=============================================================================
2750 //=============================================================================
2751 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::GetBlocksByParts
2752 (Handle(GEOM_Object) theCompound,
2753 const Handle(TColStd_HSequenceOfTransient)& theParts)
2757 if (theCompound.IsNull() || theParts.IsNull()) return NULL;
2758 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2759 if (aBlockOrComp.IsNull()) return NULL;
2761 Handle(TColStd_HSequenceOfTransient) aBlocks = new TColStd_HSequenceOfTransient;
2762 Handle(GEOM_Object) anObj;
2763 Handle(GEOM_Function) aFunction;
2766 Standard_Integer argi, aLen = theParts->Length();
2767 TopTools_Array1OfShape anArgs (1, aLen);
2768 TCollection_AsciiString anEntry, aPartsDescr, anAsciiList;
2770 for (argi = 1; argi <= aLen; argi++) {
2771 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theParts->Value(argi));
2772 Handle(GEOM_Function) aRef = anObj->GetLastFunction();
2773 if (aRef.IsNull()) return NULL;
2775 TopoDS_Shape anArg = aRef->GetValue();
2776 if (anArg.IsNull()) {
2777 SetErrorCode("Null shape is given as argument");
2780 anArgs(argi) = anArg;
2782 // For Python command
2783 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2784 aPartsDescr += anEntry + ", ";
2789 TopTools_MapOfShape mapShape;
2790 Standard_Integer nbSolids = 0;
2791 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2792 for (; exp.More(); exp.Next()) {
2793 if (mapShape.Add(exp.Current())) {
2799 Standard_Integer ind = 1;
2800 TopTools_Array1OfShape aSolids (1, nbSolids);
2801 TColStd_Array1OfInteger aNbParts (1, nbSolids);
2802 for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next(), ind++) {
2803 if (mapShape.Add(exp.Current())) {
2804 TopoDS_Shape aSolid = exp.Current();
2805 aSolids(ind) = aSolid;
2808 // 2. Define quantity of parts, contained in each solid
2809 TopTools_IndexedMapOfShape aSubShapes;
2810 TopExp::MapShapes(aSolid, aSubShapes);
2811 for (argi = 1; argi <= aLen; argi++) {
2812 if (aSubShapes.Contains(anArgs(argi))) {
2819 // 3. Define solid, containing maximum quantity of parts
2820 Standard_Integer maxNb = 0, nbFound = 0;
2821 for (ind = 1; ind <= nbSolids; ind++) {
2822 if (aNbParts(ind) > maxNb) {
2823 maxNb = aNbParts(ind);
2825 } else if (aNbParts(ind) == maxNb) {
2831 SetErrorCode("There are no blocks, containing the given parts");
2836 TopTools_IndexedMapOfShape anIndices;
2837 TopExp::MapShapes(aBlockOrComp, anIndices);
2838 Handle(TColStd_HArray1OfInteger) anArray;
2840 for (ind = 1; ind <= nbSolids; ind++) {
2841 if (aNbParts(ind) == maxNb) {
2842 anArray = new TColStd_HArray1OfInteger(1,1);
2843 anArray->SetValue(1, anIndices.FindIndex(aSolids(ind)));
2844 anObj = GetEngine()->AddSubShape(theCompound, anArray);
2845 aBlocks->Append(anObj);
2847 // For Python command
2848 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2849 anAsciiList += anEntry + ", ";
2850 if (aFunction.IsNull())
2851 aFunction = anObj->GetLastFunction();
2855 catch (Standard_Failure) {
2856 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2857 SetErrorCode(aFail->GetMessageString());
2861 //Make a Python command
2862 aPartsDescr.Trunc(aPartsDescr.Length() - 2);
2863 anAsciiList.Trunc(anAsciiList.Length() - 2);
2865 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2866 << "] = geompy.GetBlocksByParts(" << theCompound
2867 << ", [" << aPartsDescr.ToCString() << "])";
2873 //=============================================================================
2875 * MakeMultiTransformation1D
2877 //=============================================================================
2878 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeMultiTransformation1D
2879 (Handle(GEOM_Object) theObject,
2880 const Standard_Integer theDirFace1,
2881 const Standard_Integer theDirFace2,
2882 const Standard_Integer theNbTimes)
2886 if (theObject.IsNull()) return NULL;
2888 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2889 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be moved
2891 //Add a new Copy object
2892 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2894 //Add a translate function
2895 Handle(GEOM_Function) aFunction =
2896 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_MULTI_TRANSFORM_1D);
2898 //Check if the function is set correctly
2899 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2901 GEOMImpl_IBlockTrsf aTI (aFunction);
2902 aTI.SetOriginal(aLastFunction);
2903 aTI.SetFace1U(theDirFace1);
2904 aTI.SetFace2U(theDirFace2);
2905 aTI.SetNbIterU(theNbTimes);
2907 //Compute the transformation
2909 if (!GetSolver()->ComputeFunction(aFunction)) {
2910 SetErrorCode("Block driver failed to make multi-transformation");
2914 catch (Standard_Failure) {
2915 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2916 SetErrorCode(aFail->GetMessageString());
2920 //Make a Python command
2921 GEOM::TPythonDump(aFunction) << aCopy << " = geompy.MakeMultiTransformation1D("
2922 << theObject << ", " << theDirFace1 << ", " << theDirFace2 << ", " << theNbTimes << ")";
2928 //=============================================================================
2930 * MakeMultiTransformation2D
2932 //=============================================================================
2933 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeMultiTransformation2D
2934 (Handle(GEOM_Object) theObject,
2935 const Standard_Integer theDirFace1U,
2936 const Standard_Integer theDirFace2U,
2937 const Standard_Integer theNbTimesU,
2938 const Standard_Integer theDirFace1V,
2939 const Standard_Integer theDirFace2V,
2940 const Standard_Integer theNbTimesV)
2944 if (theObject.IsNull()) return NULL;
2946 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2947 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be moved
2949 //Add a new Copy object
2950 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2952 //Add a translate function
2953 Handle(GEOM_Function) aFunction =
2954 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_MULTI_TRANSFORM_2D);
2956 //Check if the function is set correctly
2957 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2959 GEOMImpl_IBlockTrsf aTI (aFunction);
2960 aTI.SetOriginal(aLastFunction);
2961 aTI.SetFace1U(theDirFace1U);
2962 aTI.SetFace2U(theDirFace2U);
2963 aTI.SetNbIterU(theNbTimesU);
2964 aTI.SetFace1V(theDirFace1V);
2965 aTI.SetFace2V(theDirFace2V);
2966 aTI.SetNbIterV(theNbTimesV);
2968 //Compute the transformation
2970 if (!GetSolver()->ComputeFunction(aFunction)) {
2971 SetErrorCode("Block driver failed to make multi-transformation");
2975 catch (Standard_Failure) {
2976 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2977 SetErrorCode(aFail->GetMessageString());
2981 //Make a Python command
2982 GEOM::TPythonDump(aFunction) << aCopy << " = geompy.MakeMultiTransformation2D("
2983 << theObject << ", " << theDirFace1U << ", " << theDirFace2U << ", " << theNbTimesU
2984 << ", " << theDirFace1V << ", " << theDirFace2V << ", " << theNbTimesV << ")";
2990 //=============================================================================
2994 //=============================================================================
2995 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::Propagate
2996 (Handle(GEOM_Object) theShape)
3000 if (theShape.IsNull()) return NULL;
3002 TopoDS_Shape aShape = theShape->GetValue();
3003 if (aShape.IsNull()) return NULL;
3005 TopTools_IndexedMapOfShape anIndices;
3006 TopExp::MapShapes(aShape, anIndices);
3008 TopTools_IndexedDataMapOfShapeListOfShape MEW;
3009 GEOMImpl_Block6Explorer::MapShapesAndAncestors
3010 (aShape, TopAbs_EDGE, TopAbs_WIRE, MEW);
3011 Standard_Integer ie, nbEdges = MEW.Extent();
3014 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
3016 TopTools_MapOfShape mapAcceptedEdges;
3017 TCollection_AsciiString aListRes, anEntry;
3019 for (ie = 1; ie <= nbEdges; ie++) {
3020 TopoDS_Shape curE = MEW.FindKey(ie);
3022 if (mapAcceptedEdges.Contains(curE)) continue;
3025 TopTools_ListOfShape currentChain;
3026 TopTools_ListOfShape listPrevEdges;
3028 currentChain.Append(curE);
3029 listPrevEdges.Append(curE);
3030 mapAcceptedEdges.Add(curE);
3032 // Collect all edges pass by pass
3033 while (listPrevEdges.Extent() > 0) {
3034 // List of edges, added to chain on this cycle pass
3035 TopTools_ListOfShape listCurEdges;
3037 // Find the next portion of edges
3038 TopTools_ListIteratorOfListOfShape itE (listPrevEdges);
3039 for (; itE.More(); itE.Next()) {
3040 TopoDS_Shape anE = itE.Value();
3042 // Iterate on faces, having edge <anE>
3043 TopTools_ListIteratorOfListOfShape itW (MEW.FindFromKey(anE));
3044 for (; itW.More(); itW.Next()) {
3045 TopoDS_Shape aW = itW.Value();
3046 TopoDS_Shape anOppE;
3048 BRepTools_WireExplorer aWE (TopoDS::Wire(aW));
3049 Standard_Integer nb = 1, found = 0;
3050 TopTools_Array1OfShape anEdges (1,4);
3051 for (; aWE.More(); aWE.Next(), nb++) {
3056 anEdges(nb) = aWE.Current();
3057 if (anEdges(nb).IsSame(anE)) found = nb;
3060 if (nb == 5 && found > 0) {
3061 // Quadrangle face found, get an opposite edge
3062 Standard_Integer opp = found + 2;
3063 if (opp > 4) opp -= 4;
3064 anOppE = anEdges(opp);
3066 if (!mapAcceptedEdges.Contains(anOppE)) {
3067 // Add found edge to the chain
3068 currentChain.Append(anOppE);
3069 listCurEdges.Append(anOppE);
3070 mapAcceptedEdges.Add(anOppE);
3072 } // if (nb == 5 && found > 0)
3073 } // for (; itF.More(); itF.Next())
3074 } // for (; itE.More(); itE.Next())
3076 listPrevEdges = listCurEdges;
3077 } // while (listPrevEdges.Extent() > 0)
3079 // Store the chain in the document
3080 Handle(TColStd_HArray1OfInteger) anArray =
3081 new TColStd_HArray1OfInteger (1, currentChain.Extent());
3083 // Fill array of sub-shape indices
3084 TopTools_ListIteratorOfListOfShape itSub (currentChain);
3085 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
3086 int id = anIndices.FindIndex(itSub.Value());
3087 anArray->SetValue(index, id);
3090 // Add a new group object
3091 Handle(GEOM_Object) aChain = GetEngine()->AddSubShape(theShape, anArray);
3094 aChain->SetType(GEOM_GROUP);
3096 // Set a sub shape type
3097 TDF_Label aFreeLabel = aChain->GetFreeLabel();
3098 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)TopAbs_EDGE);
3100 // Add the chain to the result
3101 aSeq->Append(aChain);
3103 //Make a Python command
3104 TDF_Tool::Entry(aChain->GetEntry(), anEntry);
3105 aListRes += anEntry + ", ";
3108 if (aSeq->IsEmpty()) {
3109 SetErrorCode("There are no quadrangle faces in the shape");
3113 aListRes.Trunc(aListRes.Length() - 2);
3115 // The Propagation doesn't change object so no new function is required.
3116 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
3117 TCollection_AsciiString anOldDescr = aFunction->GetDescription();
3119 // Make a Python command
3120 GEOM::TPythonDump(aFunction) << anOldDescr.ToCString() << "\n\t["
3121 << aListRes.ToCString() << "] = geompy.Propagate(" << theShape << ")";