1 // Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
24 #pragma warning( disable:4786 )
27 #include <Standard_Stream.hxx>
29 #include <GEOMImpl_IBlocksOperations.hxx>
31 #include <GEOMImpl_Types.hxx>
33 #include <GEOMImpl_BlockDriver.hxx>
34 #include <GEOMImpl_IBlocks.hxx>
35 #include <GEOMImpl_IBlockTrsf.hxx>
36 #include <GEOMImpl_CopyDriver.hxx>
37 #include <GEOMImpl_Block6Explorer.hxx>
38 #include <GEOMImpl_IShapesOperations.hxx>
40 #include <GEOM_Function.hxx>
41 #include <GEOM_PythonDump.hxx>
43 #include <GEOMAlgo_GlueAnalyser.hxx>
44 #include <GEOMAlgo_CoupleOfShapes.hxx>
45 #include <GEOMAlgo_ListOfCoupleOfShapes.hxx>
46 #include <GEOMAlgo_ListIteratorOfListOfCoupleOfShapes.hxx>
47 #include <BlockFix_CheckTool.hxx>
49 #include "utilities.h"
51 #include <Utils_ExceptHandlers.hxx>
53 #include <TFunction_DriverTable.hxx>
54 #include <TFunction_Driver.hxx>
55 #include <TFunction_Logbook.hxx>
56 #include <TDataStd_Integer.hxx>
57 #include <TDF_Tool.hxx>
59 #include <BRep_Tool.hxx>
60 #include <BRep_Builder.hxx>
61 #include <BRepTools.hxx>
62 #include <BRepTools_WireExplorer.hxx>
63 #include <BRepGProp.hxx>
64 #include <BRepBndLib.hxx>
65 #include <BRepAdaptor_Surface.hxx>
66 #include <BRepClass_FaceClassifier.hxx>
67 #include <BRepClass3d_SolidClassifier.hxx>
68 #include <BRepExtrema_DistShapeShape.hxx>
72 #include <TopoDS_Edge.hxx>
73 #include <TopoDS_Vertex.hxx>
74 #include <TopoDS_Compound.hxx>
75 #include <TopoDS_Iterator.hxx>
77 #include <TopExp_Explorer.hxx>
78 #include <TopTools_MapOfShape.hxx>
79 #include <TopTools_Array1OfShape.hxx>
80 #include <TopTools_IndexedMapOfShape.hxx>
81 #include <TopTools_DataMapOfShapeInteger.hxx>
82 #include <TopTools_ListIteratorOfListOfShape.hxx>
83 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
84 #include <TopTools_DataMapIteratorOfDataMapOfShapeInteger.hxx>
86 #include <Bnd_Box.hxx>
87 #include <GProp_GProps.hxx>
89 #include <Geom_Surface.hxx>
90 #include <ShapeAnalysis_Surface.hxx>
92 #include <TColStd_MapOfInteger.hxx>
93 #include <TColStd_Array1OfReal.hxx>
94 #include <TColStd_Array1OfInteger.hxx>
95 #include <TColStd_Array2OfInteger.hxx>
97 //#include <OSD_Timer.hxx>
99 #include <Precision.hxx>
101 #include <Standard_Failure.hxx>
102 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
104 //=============================================================================
108 //=============================================================================
109 GEOMImpl_IBlocksOperations::GEOMImpl_IBlocksOperations (GEOM_Engine* theEngine, int theDocID)
110 : GEOM_IOperations(theEngine, theDocID)
112 MESSAGE("GEOMImpl_IBlocksOperations::GEOMImpl_IBlocksOperations");
115 //=============================================================================
119 //=============================================================================
120 GEOMImpl_IBlocksOperations::~GEOMImpl_IBlocksOperations()
122 MESSAGE("GEOMImpl_IBlocksOperations::~GEOMImpl_IBlocksOperations");
126 //=============================================================================
130 //=============================================================================
131 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad
132 (Handle(GEOM_Object) theEdge1, Handle(GEOM_Object) theEdge2,
133 Handle(GEOM_Object) theEdge3, Handle(GEOM_Object) theEdge4)
137 if (theEdge1.IsNull() || theEdge2.IsNull() ||
138 theEdge3.IsNull() || theEdge4.IsNull()) return NULL;
140 //Add a new Face object
141 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
143 //Add a new Face function
144 Handle(GEOM_Function) aFunction =
145 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_FOUR_EDGES);
147 //Check if the function is set correctly
148 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
150 GEOMImpl_IBlocks aPI (aFunction);
152 Handle(GEOM_Function) aRef1 = theEdge1->GetLastFunction();
153 Handle(GEOM_Function) aRef2 = theEdge2->GetLastFunction();
154 Handle(GEOM_Function) aRef3 = theEdge3->GetLastFunction();
155 Handle(GEOM_Function) aRef4 = theEdge4->GetLastFunction();
156 if (aRef1.IsNull() || aRef2.IsNull() ||
157 aRef3.IsNull() || aRef4.IsNull()) return NULL;
159 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
160 aShapesSeq->Append(aRef1);
161 aShapesSeq->Append(aRef2);
162 aShapesSeq->Append(aRef3);
163 aShapesSeq->Append(aRef4);
165 aPI.SetShapes(aShapesSeq);
167 //Compute the Face value
169 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
172 if (!GetSolver()->ComputeFunction(aFunction)) {
173 SetErrorCode("Block driver failed to compute a face");
177 catch (Standard_Failure) {
178 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
179 SetErrorCode(aFail->GetMessageString());
183 //Make a Python command
184 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeQuad("
185 << theEdge1 << ", " << theEdge2 << ", " << theEdge3 << ", " << theEdge4 << ")";
191 //=============================================================================
195 //=============================================================================
196 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad2Edges
197 (Handle(GEOM_Object) theEdge1, Handle(GEOM_Object) theEdge2)
201 if (theEdge1.IsNull() || theEdge2.IsNull()) return NULL;
203 //Add a new Face object
204 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
206 //Add a new Face function
207 Handle(GEOM_Function) aFunction =
208 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_TWO_EDGES);
210 //Check if the function is set correctly
211 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
213 GEOMImpl_IBlocks aPI (aFunction);
215 Handle(GEOM_Function) aRef1 = theEdge1->GetLastFunction();
216 Handle(GEOM_Function) aRef2 = theEdge2->GetLastFunction();
217 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
219 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
220 aShapesSeq->Append(aRef1);
221 aShapesSeq->Append(aRef2);
223 aPI.SetShapes(aShapesSeq);
225 //Compute the Face value
227 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
230 if (!GetSolver()->ComputeFunction(aFunction)) {
231 SetErrorCode("Block driver failed to compute a face");
235 catch (Standard_Failure) {
236 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
237 SetErrorCode(aFail->GetMessageString());
241 //Make a Python command
242 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeQuad2Edges("
243 << theEdge1 << ", " << theEdge2 << ")";
249 //=============================================================================
253 //=============================================================================
254 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad4Vertices
255 (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2,
256 Handle(GEOM_Object) thePnt3, Handle(GEOM_Object) thePnt4)
260 if (thePnt1.IsNull() || thePnt2.IsNull() ||
261 thePnt3.IsNull() || thePnt4.IsNull()) return NULL;
263 //Add a new Face object
264 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
266 //Add a new Face function
267 Handle(GEOM_Function) aFunction =
268 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_FOUR_PNT);
270 //Check if the function is set correctly
271 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
273 GEOMImpl_IBlocks aPI (aFunction);
275 Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
276 Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
277 Handle(GEOM_Function) aRef3 = thePnt3->GetLastFunction();
278 Handle(GEOM_Function) aRef4 = thePnt4->GetLastFunction();
279 if (aRef1.IsNull() || aRef2.IsNull() ||
280 aRef3.IsNull() || aRef4.IsNull()) return NULL;
282 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
283 aShapesSeq->Append(aRef1);
284 aShapesSeq->Append(aRef2);
285 aShapesSeq->Append(aRef3);
286 aShapesSeq->Append(aRef4);
288 aPI.SetShapes(aShapesSeq);
290 //Compute the Face value
292 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
295 if (!GetSolver()->ComputeFunction(aFunction)) {
296 SetErrorCode("Block driver failed to compute a face");
300 catch (Standard_Failure) {
301 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
302 SetErrorCode(aFail->GetMessageString());
306 //Make a Python command
307 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeQuad4Vertices("
308 << thePnt1 << ", " << thePnt2 << ", " << thePnt3 << ", " << thePnt4 << ")";
314 //=============================================================================
318 //=============================================================================
319 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeHexa
320 (Handle(GEOM_Object) theFace1, Handle(GEOM_Object) theFace2,
321 Handle(GEOM_Object) theFace3, Handle(GEOM_Object) theFace4,
322 Handle(GEOM_Object) theFace5, Handle(GEOM_Object) theFace6)
326 if (theFace1.IsNull() || theFace2.IsNull() ||
327 theFace3.IsNull() || theFace4.IsNull() ||
328 theFace5.IsNull() || theFace6.IsNull()) return NULL;
330 //Add a new Solid object
331 Handle(GEOM_Object) aBlock = GetEngine()->AddObject(GetDocID(), GEOM_BLOCK);
333 //Add a new Block function
334 Handle(GEOM_Function) aFunction =
335 aBlock->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_SIX_FACES);
337 //Check if the function is set correctly
338 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
340 GEOMImpl_IBlocks aPI (aFunction);
342 Handle(GEOM_Function) aRef1 = theFace1->GetLastFunction();
343 Handle(GEOM_Function) aRef2 = theFace2->GetLastFunction();
344 Handle(GEOM_Function) aRef3 = theFace3->GetLastFunction();
345 Handle(GEOM_Function) aRef4 = theFace4->GetLastFunction();
346 Handle(GEOM_Function) aRef5 = theFace5->GetLastFunction();
347 Handle(GEOM_Function) aRef6 = theFace6->GetLastFunction();
348 if (aRef1.IsNull() || aRef2.IsNull() ||
349 aRef3.IsNull() || aRef4.IsNull() ||
350 aRef5.IsNull() || aRef6.IsNull()) return NULL;
352 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
353 aShapesSeq->Append(aRef1);
354 aShapesSeq->Append(aRef2);
355 aShapesSeq->Append(aRef3);
356 aShapesSeq->Append(aRef4);
357 aShapesSeq->Append(aRef5);
358 aShapesSeq->Append(aRef6);
360 aPI.SetShapes(aShapesSeq);
362 //Compute the Block value
364 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
367 if (!GetSolver()->ComputeFunction(aFunction)) {
368 SetErrorCode("Block driver failed to compute a block");
372 catch (Standard_Failure) {
373 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
374 SetErrorCode(aFail->GetMessageString());
378 //Make a Python command
379 GEOM::TPythonDump(aFunction) << aBlock << " = geompy.MakeHexa("
380 << theFace1 << ", " << theFace2 << ", " << theFace3 << ", "
381 << theFace4 << ", " << theFace5 << ", " << theFace6 << ")";
387 //=============================================================================
391 //=============================================================================
392 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeHexa2Faces
393 (Handle(GEOM_Object) theFace1, Handle(GEOM_Object) theFace2)
397 if (theFace1.IsNull() || theFace2.IsNull()) return NULL;
399 //Add a new Solid object
400 Handle(GEOM_Object) aBlock = GetEngine()->AddObject(GetDocID(), GEOM_BLOCK);
402 //Add a new Block function
403 Handle(GEOM_Function) aFunction =
404 aBlock->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_TWO_FACES);
406 //Check if the function is set correctly
407 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
409 GEOMImpl_IBlocks aPI (aFunction);
411 Handle(GEOM_Function) aRef1 = theFace1->GetLastFunction();
412 Handle(GEOM_Function) aRef2 = theFace2->GetLastFunction();
413 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
415 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
416 aShapesSeq->Append(aRef1);
417 aShapesSeq->Append(aRef2);
419 aPI.SetShapes(aShapesSeq);
421 //Compute the Block value
423 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
426 if (!GetSolver()->ComputeFunction(aFunction)) {
427 SetErrorCode("Block driver failed to compute a block");
431 catch (Standard_Failure) {
432 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
433 SetErrorCode(aFail->GetMessageString());
437 //Make a Python command
438 GEOM::TPythonDump(aFunction) << aBlock << " = geompy.MakeHexa2Faces("
439 << theFace1 << ", " << theFace2 << ")";
445 //=============================================================================
449 //=============================================================================
450 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeBlockCompound
451 (Handle(GEOM_Object) theCompound)
455 if (theCompound.IsNull()) return NULL;
458 Handle(GEOM_Object) aBlockComp = GetEngine()->AddObject(GetDocID(), GEOM_COMPOUND);
460 //Add a new BlocksComp function
461 Handle(GEOM_Function) aFunction =
462 aBlockComp->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_COMPOUND_GLUE);
464 //Check if the function is set correctly
465 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
467 GEOMImpl_IBlocks aPI (aFunction);
469 Handle(GEOM_Function) aRef1 = theCompound->GetLastFunction();
470 if (aRef1.IsNull()) return NULL;
472 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
473 aShapesSeq->Append(aRef1);
475 aPI.SetShapes(aShapesSeq);
477 //Compute the Blocks Compound value
479 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
482 if (!GetSolver()->ComputeFunction(aFunction)) {
483 SetErrorCode("Block driver failed to compute a blocks compound");
487 catch (Standard_Failure) {
488 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
489 SetErrorCode(aFail->GetMessageString());
493 //Make a Python command
494 GEOM::TPythonDump(aFunction) << aBlockComp
495 << " = geompy.MakeBlockCompound(" << theCompound << ")";
501 //=============================================================================
505 //=============================================================================
506 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetPoint
507 (Handle(GEOM_Object) theShape,
508 const Standard_Real theX,
509 const Standard_Real theY,
510 const Standard_Real theZ,
511 const Standard_Real theEpsilon)
516 Handle(GEOM_Object) aResult;
519 if (theShape.IsNull()) return NULL;
521 TopoDS_Shape aBlockOrComp = theShape->GetValue();
522 if (aBlockOrComp.IsNull()) {
523 SetErrorCode("Given shape is null");
527 //Compute the Vertex value
528 gp_Pnt P (theX, theY, theZ);
529 Standard_Real eps = Max(theEpsilon, Precision::Confusion());
532 Standard_Integer isFound = 0;
533 TopTools_MapOfShape mapShape;
534 TopExp_Explorer exp (aBlockOrComp, TopAbs_VERTEX);
536 for (; exp.More(); exp.Next()) {
537 if (mapShape.Add(exp.Current())) {
538 TopoDS_Vertex aVi = TopoDS::Vertex(exp.Current());
539 gp_Pnt aPi = BRep_Tool::Pnt(aVi);
540 if (aPi.Distance(P) < eps) {
548 SetErrorCode("Vertex has not been found");
550 } else if (isFound > 1) {
551 SetErrorCode("Multiple vertices found by the given coordinates and epsilon");
554 TopTools_IndexedMapOfShape anIndices;
555 TopExp::MapShapes(aBlockOrComp, anIndices);
556 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
557 anArray->SetValue(1, anIndices.FindIndex(V));
558 aResult = GetEngine()->AddSubShape(theShape, anArray);
561 //The GetPoint() doesn't change object so no new function is required.
562 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
564 //Make a Python command
565 GEOM::TPythonDump(aFunction, /*append=*/true)
566 << aResult << " = geompy.GetPoint(" << theShape << ", "
567 << theX << ", " << theY << ", " << theZ << ", " << theEpsilon << ")";
573 //=============================================================================
577 //=============================================================================
578 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetVertexNearPoint
579 (Handle(GEOM_Object) theShape,
580 Handle(GEOM_Object) thePoint)
585 Handle(GEOM_Object) aResult;
588 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
590 TopoDS_Shape aBlockOrComp = theShape->GetValue();
591 TopoDS_Shape aPoint = thePoint->GetValue();
592 if (aBlockOrComp.IsNull() || aPoint.IsNull()) {
593 SetErrorCode("Given shape is null");
597 if (aPoint.ShapeType() != TopAbs_VERTEX) {
598 SetErrorCode("Element for vertex identification is not a vertex");
602 TopoDS_Vertex aVert = TopoDS::Vertex(aPoint);
603 gp_Pnt aP = BRep_Tool::Pnt(aVert);
605 // Compute the Vertex value
607 bool isFound = false;
608 Standard_Real aDist = RealLast();
609 TopTools_MapOfShape mapShape;
611 TopExp_Explorer exp (aBlockOrComp, TopAbs_VERTEX);
612 for (; exp.More(); exp.Next()) {
613 if (mapShape.Add(exp.Current())) {
614 TopoDS_Vertex aVi = TopoDS::Vertex(exp.Current());
615 gp_Pnt aPi = BRep_Tool::Pnt(aVi);
616 Standard_Real aDisti = aPi.Distance(aP);
617 if (aDisti < aDist) {
626 SetErrorCode("Vertex has not been found");
630 TopTools_IndexedMapOfShape anIndices;
631 TopExp::MapShapes(aBlockOrComp, anIndices);
632 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
633 anArray->SetValue(1, anIndices.FindIndex(V));
634 aResult = GetEngine()->AddSubShape(theShape, anArray);
636 // The GetPoint() doesn't change object so no new function is required.
637 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
639 // Make a Python command
640 GEOM::TPythonDump(aFunction, /*append=*/true)
641 << aResult << " = geompy.GetVertexNearPoint("
642 << theShape << ", " << thePoint << ")";
648 //=============================================================================
652 //=============================================================================
653 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetEdge
654 (Handle(GEOM_Object) theShape,
655 Handle(GEOM_Object) thePoint1,
656 Handle(GEOM_Object) thePoint2)
661 Handle(GEOM_Object) aResult;
664 if (theShape.IsNull() || thePoint1.IsNull() || thePoint2.IsNull()) return NULL;
666 TopoDS_Shape aBlockOrComp = theShape->GetValue();
667 if (aBlockOrComp.IsNull()) {
668 SetErrorCode("Given shape is null");
672 TopoDS_Shape anArg1 = thePoint1->GetValue();
673 TopoDS_Shape anArg2 = thePoint2->GetValue();
674 if (anArg1.IsNull() || anArg2.IsNull()) {
675 SetErrorCode("Null shape is given as argument");
678 if (anArg1.ShapeType() != TopAbs_VERTEX ||
679 anArg2.ShapeType() != TopAbs_VERTEX) {
680 SetErrorCode("Element for edge identification is not a vertex");
684 //Compute the Edge value
686 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
689 TopTools_IndexedDataMapOfShapeListOfShape MVE;
690 GEOMImpl_Block6Explorer::MapShapesAndAncestors
691 (aBlockOrComp, TopAbs_VERTEX, TopAbs_EDGE, MVE);
694 Standard_Integer ish, ext = MVE.Extent();
696 if (MVE.Contains(anArg1)) {
699 for (ish = 1; ish <= ext; ish++) {
700 TopoDS_Shape aShi = MVE.FindKey(ish);
701 if (BRepTools::Compare(TopoDS::Vertex(anArg1), TopoDS::Vertex(aShi))) {
708 if (MVE.Contains(anArg2)) {
711 for (ish = 1; ish <= ext; ish++) {
712 TopoDS_Shape aShi = MVE.FindKey(ish);
713 if (BRepTools::Compare(TopoDS::Vertex(anArg2), TopoDS::Vertex(aShi))) {
720 if (V1.IsNull() || V2.IsNull()) {
721 SetErrorCode("The given vertex does not belong to the shape");
726 Standard_Integer isFound =
727 GEOMImpl_Block6Explorer::FindEdge(anEdge, V1, V2, MVE, Standard_True);
729 SetErrorCode("The given vertices do not belong to one edge of the given shape");
731 } else if (isFound > 1) {
732 SetErrorCode("Multiple edges found by the given vertices of the shape");
735 TopTools_IndexedMapOfShape anIndices;
736 TopExp::MapShapes(aBlockOrComp, anIndices);
737 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
738 anArray->SetValue(1, anIndices.FindIndex(anEdge));
739 aResult = GetEngine()->AddSubShape(theShape, anArray);
741 } catch (Standard_Failure) {
742 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
743 SetErrorCode(aFail->GetMessageString());
747 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
749 //Make a Python command
750 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetEdge("
751 << theShape << ", " << thePoint1 << ", " << thePoint2 << ")";
757 //=============================================================================
761 //=============================================================================
762 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetEdgeNearPoint
763 (Handle(GEOM_Object) theShape,
764 Handle(GEOM_Object) thePoint)
769 Handle(GEOM_Object) aResult;
772 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
774 TopoDS_Shape aBlockOrComp = theShape->GetValue();
775 if (aBlockOrComp.IsNull()) {
776 SetErrorCode("Given shape is null");
780 TopoDS_Shape anArg = thePoint->GetValue();
781 if (anArg.IsNull()) {
782 SetErrorCode("Null shape is given as argument");
785 if (anArg.ShapeType() != TopAbs_VERTEX) {
786 SetErrorCode("Element for edge identification is not a vertex");
790 //Compute the Edge value
792 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
797 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
799 // 1. Explode blocks on edges
800 TopTools_MapOfShape mapShape;
801 Standard_Integer nbEdges = 0;
802 TopExp_Explorer exp (aBlockOrComp, TopAbs_EDGE);
803 for (; exp.More(); exp.Next()) {
804 if (mapShape.Add(exp.Current())) {
810 SetErrorCode("Given shape contains no edges");
815 Standard_Integer ind = 1;
816 TopTools_Array1OfShape anEdges (1, nbEdges);
817 TColStd_Array1OfReal aDistances (1, nbEdges);
818 for (exp.Init(aBlockOrComp, TopAbs_EDGE); exp.More(); exp.Next()) {
819 if (mapShape.Add(exp.Current())) {
820 TopoDS_Shape anEdge = exp.Current();
821 anEdges(ind) = anEdge;
823 // 2. Classify the point relatively each edge
824 BRepExtrema_DistShapeShape aDistTool (aVert, anEdges(ind));
825 if (!aDistTool.IsDone()) {
826 SetErrorCode("Can not find a distance from the given point to one of edges");
829 aDistances(ind) = aDistTool.Value();
834 // 3. Define edge, having minimum distance to the point
835 Standard_Real nearest = RealLast(), nbFound = 0;
836 Standard_Real prec = Precision::Confusion();
837 for (ind = 1; ind <= nbEdges; ind++) {
838 if (Abs(aDistances(ind) - nearest) < prec) {
840 } else if (aDistances(ind) < nearest) {
841 nearest = aDistances(ind);
842 aShape = anEdges(ind);
848 SetErrorCode("Multiple edges near the given point are found");
850 } else if (nbFound == 0) {
851 SetErrorCode("There are no edges near the given point");
854 TopTools_IndexedMapOfShape anIndices;
855 TopExp::MapShapes(aBlockOrComp, anIndices);
856 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
857 anArray->SetValue(1, anIndices.FindIndex(aShape));
858 aResult = GetEngine()->AddSubShape(theShape, anArray);
861 catch (Standard_Failure) {
862 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
863 SetErrorCode(aFail->GetMessageString());
867 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
869 //Make a Python command
870 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetEdgeNearPoint("
871 << theShape << ", " << thePoint << ")";
877 //=============================================================================
881 //=============================================================================
882 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByPoints
883 (Handle(GEOM_Object) theShape,
884 Handle(GEOM_Object) thePoint1,
885 Handle(GEOM_Object) thePoint2,
886 Handle(GEOM_Object) thePoint3,
887 Handle(GEOM_Object) thePoint4)
892 Handle(GEOM_Object) aResult;
895 if (theShape.IsNull() ||
896 thePoint1.IsNull() || thePoint2.IsNull() ||
897 thePoint3.IsNull() || thePoint4.IsNull()) return NULL;
899 TopoDS_Shape aBlockOrComp = theShape->GetValue();
900 if (aBlockOrComp.IsNull()) {
901 SetErrorCode("Block or compound is null");
905 TopoDS_Shape anArg1 = thePoint1->GetValue();
906 TopoDS_Shape anArg2 = thePoint2->GetValue();
907 TopoDS_Shape anArg3 = thePoint3->GetValue();
908 TopoDS_Shape anArg4 = thePoint4->GetValue();
909 if (anArg1.IsNull() || anArg2.IsNull() ||
910 anArg3.IsNull() || anArg4.IsNull()) {
911 SetErrorCode("Null shape is given as argument");
914 if (anArg1.ShapeType() != TopAbs_VERTEX ||
915 anArg2.ShapeType() != TopAbs_VERTEX ||
916 anArg3.ShapeType() != TopAbs_VERTEX ||
917 anArg4.ShapeType() != TopAbs_VERTEX) {
918 SetErrorCode("Element for face identification is not a vertex");
922 //Compute the Face value
924 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
929 TopTools_IndexedDataMapOfShapeListOfShape MVF;
930 GEOMImpl_Block6Explorer::MapShapesAndAncestors(aBlockOrComp, TopAbs_VERTEX, TopAbs_FACE, MVF);
932 TopoDS_Shape V1,V2,V3,V4;
933 Standard_Integer ish, ext = MVF.Extent();
935 if (MVF.Contains(anArg1)) {
938 for (ish = 1; ish <= ext; ish++) {
939 TopoDS_Shape aShi = MVF.FindKey(ish);
940 if (BRepTools::Compare(TopoDS::Vertex(anArg1), TopoDS::Vertex(aShi))) {
947 if (MVF.Contains(anArg2)) {
950 for (ish = 1; ish <= ext; ish++) {
951 TopoDS_Shape aShi = MVF.FindKey(ish);
952 if (BRepTools::Compare(TopoDS::Vertex(anArg2), TopoDS::Vertex(aShi))) {
959 if (MVF.Contains(anArg3)) {
962 for (ish = 1; ish <= ext; ish++) {
963 TopoDS_Shape aShi = MVF.FindKey(ish);
964 if (BRepTools::Compare(TopoDS::Vertex(anArg3), TopoDS::Vertex(aShi))) {
971 if (MVF.Contains(anArg4)) {
974 for (ish = 1; ish <= ext; ish++) {
975 TopoDS_Shape aShi = MVF.FindKey(ish);
976 if (BRepTools::Compare(TopoDS::Vertex(anArg4), TopoDS::Vertex(aShi))) {
983 if (V1.IsNull() || V2.IsNull() || V3.IsNull() || V4.IsNull()) {
984 SetErrorCode("The given vertex does not belong to the shape");
988 Standard_Integer isFound =
989 GEOMImpl_Block6Explorer::FindFace(aShape, V1, V2, V3, V4, MVF, Standard_True);
991 SetErrorCode("The given vertices do not belong to one face of the given shape");
993 } else if (isFound > 1) {
994 SetErrorCode("The given vertices belong to several faces of the given shape");
997 TopTools_IndexedMapOfShape anIndices;
998 TopExp::MapShapes(aBlockOrComp, anIndices);
999 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1000 anArray->SetValue(1, anIndices.FindIndex(aShape));
1001 aResult = GetEngine()->AddSubShape(theShape, anArray);
1004 catch (Standard_Failure) {
1005 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1006 SetErrorCode(aFail->GetMessageString());
1010 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1012 //Make a Python command
1013 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByPoints("
1014 << theShape << ", " << thePoint1 << ", " << thePoint2
1015 << ", " << thePoint3 << ", " << thePoint4 << ")";
1021 //=============================================================================
1025 //=============================================================================
1026 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByEdges
1027 (Handle(GEOM_Object) theShape,
1028 Handle(GEOM_Object) theEdge1,
1029 Handle(GEOM_Object) theEdge2)
1034 Handle(GEOM_Object) aResult;
1037 if (theShape.IsNull() || theEdge1.IsNull() || theEdge2.IsNull()) return NULL;
1039 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1040 if (aBlockOrComp.IsNull()) {
1041 SetErrorCode("Block or compound is null");
1045 TopoDS_Shape anArg1 = theEdge1->GetValue();
1046 TopoDS_Shape anArg2 = theEdge2->GetValue();
1047 if (anArg1.IsNull() || anArg2.IsNull()) {
1048 SetErrorCode("Null shape is given as argument");
1051 if (anArg1.ShapeType() != TopAbs_EDGE ||
1052 anArg2.ShapeType() != TopAbs_EDGE) {
1053 SetErrorCode("Element for face identification is not an edge");
1057 //Compute the Face value
1059 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1062 TopoDS_Shape aShape;
1064 TopTools_IndexedDataMapOfShapeListOfShape MEF;
1065 GEOMImpl_Block6Explorer::MapShapesAndAncestors(aBlockOrComp, TopAbs_EDGE, TopAbs_FACE, MEF);
1068 Standard_Integer ish, ext = MEF.Extent();
1070 if (MEF.Contains(anArg1)) {
1073 for (ish = 1; ish <= ext; ish++) {
1074 TopoDS_Shape aShi = MEF.FindKey(ish);
1075 if (GEOMImpl_Block6Explorer::IsSimilarEdges(anArg1, aShi)) {
1081 if (MEF.Contains(anArg2)) {
1084 for (ish = 1; ish <= ext; ish++) {
1085 TopoDS_Shape aShi = MEF.FindKey(ish);
1086 if (GEOMImpl_Block6Explorer::IsSimilarEdges(anArg2, aShi)) {
1092 if (E1.IsNull() || E2.IsNull()) {
1093 SetErrorCode("The given edge does not belong to the shape");
1097 const TopTools_ListOfShape& aFacesOfE1 = MEF.FindFromKey(E1);
1098 const TopTools_ListOfShape& aFacesOfE2 = MEF.FindFromKey(E2);
1100 Standard_Integer isFound = 0;
1101 TopTools_ListIteratorOfListOfShape anIterF1 (aFacesOfE1);
1102 for (; anIterF1.More(); anIterF1.Next()) {
1104 TopTools_ListIteratorOfListOfShape anIterF2 (aFacesOfE2);
1105 for (; anIterF2.More(); anIterF2.Next()) {
1107 if (anIterF1.Value().IsSame(anIterF2.Value())) {
1110 // Store the face, defined by two edges
1111 aShape = anIterF1.Value();
1116 SetErrorCode("The given edges do not belong to one face of the given shape");
1118 } else if (isFound > 1) {
1119 SetErrorCode("The given edges belong to several faces of the given shape");
1122 TopTools_IndexedMapOfShape anIndices;
1123 TopExp::MapShapes(aBlockOrComp, anIndices);
1124 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1125 anArray->SetValue(1, anIndices.FindIndex(aShape));
1126 aResult = GetEngine()->AddSubShape(theShape, anArray);
1129 catch (Standard_Failure) {
1130 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1131 SetErrorCode(aFail->GetMessageString());
1135 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1137 //Make a Python command
1138 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByEdges("
1139 << theShape << ", " << theEdge1 << ", " << theEdge2 << ")";
1145 //=============================================================================
1149 //=============================================================================
1150 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetOppositeFace
1151 (Handle(GEOM_Object) theShape,
1152 Handle(GEOM_Object) theFace)
1157 Handle(GEOM_Object) aResult;
1160 if (theShape.IsNull() || theFace.IsNull()) return NULL;
1162 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1163 if (aBlockOrComp.IsNull()) {
1164 SetErrorCode("Block is null");
1167 if (aBlockOrComp.ShapeType() != TopAbs_SOLID) {
1168 SetErrorCode("Shape is not a block");
1172 TopoDS_Shape anArg = theFace->GetValue();
1173 if (anArg.IsNull()) {
1174 SetErrorCode("Null shape is given as argument");
1177 if (anArg.ShapeType() != TopAbs_FACE) {
1178 SetErrorCode("Element for face identification is not a face");
1182 //Compute the Face value
1184 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1187 TopoDS_Shape aShape;
1189 GEOMImpl_Block6Explorer aBlockTool;
1190 aBlockTool.InitByBlockAndFace(aBlockOrComp, anArg);
1191 aShape = aBlockTool.GetFace(2);
1193 TopTools_IndexedMapOfShape anIndices;
1194 TopExp::MapShapes(aBlockOrComp, anIndices);
1195 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1196 anArray->SetValue(1, anIndices.FindIndex(aShape));
1197 aResult = GetEngine()->AddSubShape(theShape, anArray);
1199 catch (Standard_Failure) {
1200 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1201 SetErrorCode(aFail->GetMessageString());
1205 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1207 //Make a Python command
1208 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetOppositeFace("
1209 << theShape << ", " << theFace << ")";
1215 //=============================================================================
1219 //=============================================================================
1220 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceNearPoint
1221 (Handle(GEOM_Object) theShape,
1222 Handle(GEOM_Object) thePoint)
1227 Handle(GEOM_Object) aResult;
1230 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
1232 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1233 if (aBlockOrComp.IsNull()) {
1234 SetErrorCode("Block or compound is null");
1238 TopoDS_Shape anArg = thePoint->GetValue();
1239 if (anArg.IsNull()) {
1240 SetErrorCode("Null shape is given as argument");
1243 if (anArg.ShapeType() != TopAbs_VERTEX) {
1244 SetErrorCode("Element for face identification is not a vertex");
1248 //Compute the Face value
1250 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1253 TopoDS_Shape aShape;
1255 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
1256 gp_Pnt aPnt = BRep_Tool::Pnt(aVert);
1257 Standard_Real PX, PY, PZ;
1258 aPnt.Coord(PX, PY, PZ);
1260 // 1. Classify the point relatively each face
1261 Standard_Integer nearest = 2, nbFound = 0;
1262 TopTools_DataMapOfShapeInteger mapShapeDist;
1263 TopExp_Explorer exp (aBlockOrComp, TopAbs_FACE);
1264 for (; exp.More(); exp.Next()) {
1265 TopoDS_Shape aFace = exp.Current();
1267 if (!mapShapeDist.IsBound(aFace)) {
1268 Standard_Integer aDistance = 2;
1270 // 1.a. Classify relatively Surface
1271 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aFace));
1272 Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf);
1273 gp_Pnt2d p2dOnSurf = aSurfAna->ValueOfUV(aPnt, Precision::Confusion());
1274 gp_Pnt p3dOnSurf = aSurfAna->Value(p2dOnSurf);
1275 Standard_Real aDist = p3dOnSurf.Distance(aPnt);
1276 if (aDist > Precision::Confusion()) {
1280 // 1.b. Classify relatively the face itself
1281 BRepClass_FaceClassifier FC (TopoDS::Face(aFace), p2dOnSurf, Precision::Confusion());
1282 if (FC.State() == TopAbs_IN) {
1284 } else if (FC.State() == TopAbs_ON) {
1291 if (aDistance < nearest) {
1292 nearest = aDistance;
1296 // A first found face, containing the point inside, will be returned.
1297 // It is the solution, if there are no
1298 // coincident or intersecting faces in the compound.
1299 if (nearest == -1) break;
1301 } else if (aDistance == nearest) {
1306 mapShapeDist.Bind(aFace, aDistance);
1307 } // if (!mapShapeDist.IsBound(aFace))
1310 // 2. Define face, containing the point or having minimum distance to it
1313 // The point is on boundary of some faces and there are
1314 // no faces, having the point inside
1315 SetErrorCode("Multiple faces near the given point are found");
1318 } else if (nearest == 1) {
1319 // The point is outside some faces and there are
1320 // no faces, having the point inside or on boundary.
1321 // We will get a nearest face
1322 Standard_Real bigReal = RealLast();
1323 Standard_Real minDist = bigReal;
1324 TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
1325 for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
1326 if (mapShapeDistIter.Value() == 1) {
1327 TopoDS_Shape aFace = mapShapeDistIter.Key();
1328 Standard_Real aDist = bigReal;
1330 // 2.a. Fast check of distance - if point projection on surface is on face
1331 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aFace));
1332 Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf);
1333 gp_Pnt2d p2dOnSurf = aSurfAna->ValueOfUV(aPnt, Precision::Confusion());
1334 gp_Pnt p3dOnSurf = aSurfAna->Value(p2dOnSurf);
1335 aDist = p3dOnSurf.Distance(aPnt);
1337 BRepClass_FaceClassifier FC (TopoDS::Face(aFace), p2dOnSurf, Precision::Confusion());
1338 if (FC.State() == TopAbs_OUT) {
1339 if (aDist < minDist) {
1340 // 2.b. Slow check - if point projection on surface is outside of face
1341 BRepExtrema_DistShapeShape aDistTool (aVert, aFace);
1342 if (!aDistTool.IsDone()) {
1343 SetErrorCode("Can not find a distance from the given point to one of faces");
1346 aDist = aDistTool.Value();
1352 if (aDist < minDist) {
1358 } else { // nearest == -1
1359 // // The point is inside some faces.
1360 // // We will get a face with nearest center
1361 // Standard_Real minDist = RealLast();
1362 // TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
1363 // for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
1364 // if (mapShapeDistIter.Value() == -1) {
1365 // TopoDS_Shape aFace = mapShapeDistIter.Key();
1366 // GProp_GProps aSystem;
1367 // BRepGProp::SurfaceProperties(aFace, aSystem);
1368 // gp_Pnt aCenterMass = aSystem.CentreOfMass();
1370 // Standard_Real aDist = aCenterMass.Distance(aPnt);
1371 // if (aDist < minDist) {
1378 } // if (nbFound > 1)
1381 SetErrorCode("There are no faces near the given point");
1384 TopTools_IndexedMapOfShape anIndices;
1385 TopExp::MapShapes(aBlockOrComp, anIndices);
1386 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1387 anArray->SetValue(1, anIndices.FindIndex(aShape));
1388 aResult = GetEngine()->AddSubShape(theShape, anArray);
1391 catch (Standard_Failure) {
1392 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1393 SetErrorCode(aFail->GetMessageString());
1397 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1399 //Make a Python command
1400 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceNearPoint("
1401 << theShape << ", " << thePoint << ")";
1407 //=============================================================================
1411 //=============================================================================
1412 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByNormale
1413 (Handle(GEOM_Object) theShape,
1414 Handle(GEOM_Object) theVector)
1419 Handle(GEOM_Object) aResult;
1422 if (theShape.IsNull() || theVector.IsNull()) return NULL;
1424 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1425 if (aBlockOrComp.IsNull()) {
1426 SetErrorCode("Block or compound is null");
1430 TopoDS_Shape anArg = theVector->GetValue();
1431 if (anArg.IsNull()) {
1432 SetErrorCode("Null shape is given as argument");
1435 if (anArg.ShapeType() != TopAbs_EDGE) {
1436 SetErrorCode("Element for normale identification is not an edge");
1440 //Compute the Face value
1442 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1445 TopoDS_Shape aShape;
1447 TopoDS_Edge anEdge = TopoDS::Edge(anArg);
1448 TopoDS_Vertex V1, V2;
1449 TopExp::Vertices(anEdge, V1, V2, Standard_True);
1450 gp_Pnt P1 = BRep_Tool::Pnt(V1);
1451 gp_Pnt P2 = BRep_Tool::Pnt(V2);
1452 gp_Vec aVec (P1, P2);
1453 if (aVec.Magnitude() < Precision::Confusion()) {
1454 SetErrorCode("Vector with null magnitude is given");
1458 Standard_Real minAngle = RealLast();
1459 TopTools_MapOfShape mapShape;
1460 TopExp_Explorer exp (aBlockOrComp, TopAbs_FACE);
1461 for (; exp.More(); exp.Next()) {
1462 if (mapShape.Add(exp.Current())) {
1463 TopoDS_Face aFace = TopoDS::Face(exp.Current());
1464 BRepAdaptor_Surface SF (aFace);
1466 Standard_Real u, v, x;
1468 // find a point on the surface to get normal direction in
1469 u = SF.FirstUParameter();
1470 x = SF.LastUParameter();
1471 if (Precision::IsInfinite(u)) {
1472 u = (Precision::IsInfinite(x)) ? 0. : x;
1473 } else if (!Precision::IsInfinite(x)) {
1477 v = SF.FirstVParameter();
1478 x = SF.LastVParameter();
1479 if (Precision::IsInfinite(v)) {
1480 v = (Precision::IsInfinite(x)) ? 0. : x;
1481 } else if (!Precision::IsInfinite(x)) {
1485 // compute the normal direction
1487 SF.D1(u,v,P1,Vec1,Vec2);
1488 gp_Vec V = Vec1.Crossed(Vec2);
1490 if (V.Magnitude() < Precision::Confusion()) {
1491 SetErrorCode("Normal vector of a face has null magnitude");
1495 // consider the face orientation
1496 if (aFace.Orientation() == TopAbs_REVERSED ||
1497 aFace.Orientation() == TopAbs_INTERNAL) {
1501 // compute the angle and compare with the minimal one
1502 Standard_Real anAngle = aVec.Angle(V);
1503 if (anAngle < minAngle) {
1510 if (aShape.IsNull()) {
1511 SetErrorCode("Failed to find a face by the given normale");
1514 TopTools_IndexedMapOfShape anIndices;
1515 TopExp::MapShapes(aBlockOrComp, anIndices);
1516 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1517 anArray->SetValue(1, anIndices.FindIndex(aShape));
1518 aResult = GetEngine()->AddSubShape(theShape, anArray);
1521 catch (Standard_Failure) {
1522 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1523 SetErrorCode(aFail->GetMessageString());
1527 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1529 //Make a Python command
1530 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByNormale("
1531 << theShape << ", " << theVector << ")";
1537 //=============================================================================
1539 * GetShapesNearPoint
1541 //=============================================================================
1542 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetShapesNearPoint
1543 (Handle(GEOM_Object) theShape,
1544 Handle(GEOM_Object) thePoint,
1545 const Standard_Integer theShapeType,
1546 const Standard_Real theConstTolerance)
1551 Handle(GEOM_Object) aResult;
1554 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
1556 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1557 if (aBlockOrComp.IsNull()) {
1558 SetErrorCode("Block or compound is null");
1562 TopoDS_Shape anArg = thePoint->GetValue();
1563 if (anArg.IsNull()) {
1564 SetErrorCode("Null shape is given as argument");
1567 if (anArg.ShapeType() != TopAbs_VERTEX) {
1568 SetErrorCode("Element for face identification is not a vertex");
1572 if (theShapeType < TopAbs_SOLID || TopAbs_VERTEX < theShapeType) {
1573 SetErrorCode("Invalid type of result is requested");
1577 Standard_Real theTolerance = theConstTolerance;
1578 if (theTolerance < Precision::Confusion()) {
1579 theTolerance = Precision::Confusion();
1582 // Compute the result
1584 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1587 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
1589 TopTools_MapOfShape mapShape;
1590 Standard_Integer nbEdges = 0;
1591 TopExp_Explorer exp (aBlockOrComp, TopAbs_ShapeEnum(theShapeType));
1592 for (; exp.More(); exp.Next()) {
1593 if (mapShape.Add(exp.Current())) {
1599 SetErrorCode("Given shape contains no subshapes of requested type");
1603 // Calculate distances and find min
1605 Standard_Integer ind = 1;
1606 Standard_Real aMinDist = RealLast();
1607 TopTools_Array1OfShape anEdges (1, nbEdges);
1608 TColStd_Array1OfReal aDistances (1, nbEdges);
1609 for (exp.Init(aBlockOrComp, TopAbs_ShapeEnum(theShapeType)); exp.More(); exp.Next()) {
1610 if (mapShape.Add(exp.Current())) {
1611 TopoDS_Shape anEdge = exp.Current();
1612 anEdges(ind) = anEdge;
1614 BRepExtrema_DistShapeShape aDistTool (aVert, anEdges(ind));
1615 if (!aDistTool.IsDone()) {
1616 SetErrorCode("Can not find a distance from the given point to one of subshapes");
1619 aDistances(ind) = aDistTool.Value();
1620 if (aDistances(ind) < aMinDist) {
1621 aMinDist = aDistances(ind);
1627 if (aMinDist < RealLast()) {
1628 // Collect subshapes with distance < (aMinDist + theTolerance)
1629 int nbSubShapes = 0;
1630 TopTools_Array1OfShape aNearShapes (1, nbEdges);
1631 for (ind = 1; ind <= nbEdges; ind++) {
1632 if (aDistances(ind) < aMinDist + theTolerance) {
1634 aNearShapes(nbSubShapes) = anEdges(ind);
1639 TopTools_IndexedMapOfShape anIndices;
1640 TopExp::MapShapes(aBlockOrComp, anIndices);
1641 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger (1, nbSubShapes);
1642 for (ind = 1; ind <= nbSubShapes; ind++) {
1643 anArray->SetValue(ind, anIndices.FindIndex(aNearShapes(ind)));
1645 aResult = GetEngine()->AddSubShape(theShape, anArray);
1648 catch (Standard_Failure) {
1649 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1650 SetErrorCode(aFail->GetMessageString());
1654 if (aResult.IsNull())
1657 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1659 //Make a Python command
1660 GEOM::TPythonDump(aFunction)
1661 << aResult << " = geompy.GetShapesNearPoint(" << theShape << ", " << thePoint
1662 << ", " << TopAbs_ShapeEnum(theShapeType) << ", " << theTolerance << ")";
1668 //=============================================================================
1670 * IsCompoundOfBlocks
1672 //=============================================================================
1673 Standard_Boolean GEOMImpl_IBlocksOperations::IsCompoundOfBlocks
1674 (Handle(GEOM_Object) theCompound,
1675 const Standard_Integer theMinNbFaces,
1676 const Standard_Integer theMaxNbFaces,
1677 Standard_Integer& theNbBlocks)
1680 Standard_Boolean isCompOfBlocks = Standard_False;
1683 if (theCompound.IsNull()) return isCompOfBlocks;
1684 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
1687 isCompOfBlocks = Standard_True;
1689 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1692 TopTools_MapOfShape mapShape;
1693 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
1694 for (; exp.More(); exp.Next()) {
1695 if (mapShape.Add(exp.Current())) {
1696 TopoDS_Shape aSolid = exp.Current();
1698 TopTools_MapOfShape mapFaces;
1699 TopExp_Explorer expF (aSolid, TopAbs_FACE);
1700 Standard_Integer nbFaces = 0;
1701 for (; expF.More(); expF.Next()) {
1702 if (mapFaces.Add(expF.Current())) {
1704 if (nbFaces > theMaxNbFaces) {
1705 isCompOfBlocks = Standard_False;
1710 if (nbFaces < theMinNbFaces || theMaxNbFaces < nbFaces) {
1711 isCompOfBlocks = Standard_False;
1718 catch (Standard_Failure) {
1719 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1720 SetErrorCode(aFail->GetMessageString());
1721 return isCompOfBlocks;
1725 return isCompOfBlocks;
1728 //=============================================================================
1730 * Set of functions, used by CheckCompoundOfBlocks() method
1732 //=============================================================================
1733 void GEOMImpl_IBlocksOperations::AddBlocksFrom (const TopoDS_Shape& theShape,
1734 TopTools_ListOfShape& BLO,
1735 TopTools_ListOfShape& NOT,
1736 TopTools_ListOfShape& EXT)
1738 TopAbs_ShapeEnum aType = theShape.ShapeType();
1740 case TopAbs_COMPOUND:
1741 case TopAbs_COMPSOLID:
1743 TopoDS_Iterator It (theShape);
1744 for (; It.More(); It.Next()) {
1745 AddBlocksFrom(It.Value(), BLO, NOT, EXT);
1751 // Check, if there are seam or degenerated edges
1752 BlockFix_CheckTool aTool;
1753 aTool.SetShape(theShape);
1755 if (aTool.NbPossibleBlocks() > 0) {
1756 EXT.Append(theShape);
1758 // Count faces and edges in each face to recognize blocks
1759 TopTools_MapOfShape mapFaces;
1760 Standard_Integer nbFaces = 0;
1761 Standard_Boolean hasNonQuadr = Standard_False;
1762 TopExp_Explorer expF (theShape, TopAbs_FACE);
1764 for (; expF.More(); expF.Next()) {
1765 if (mapFaces.Add(expF.Current())) {
1767 if (nbFaces > 6) break;
1770 TopoDS_Shape aF = expF.Current();
1771 TopExp_Explorer wires (aF, TopAbs_WIRE);
1772 if (!wires.More()) {
1773 // no wire in the face
1774 hasNonQuadr = Standard_True;
1777 TopoDS_Shape aWire = wires.Current();
1780 // multiple wires in the face
1781 hasNonQuadr = Standard_True;
1785 // Check number of edges in the face
1786 Standard_Integer nbEdges = 0;
1787 TopTools_MapOfShape mapEdges;
1788 TopExp_Explorer expW (aWire, TopAbs_EDGE);
1789 for (; expW.More(); expW.Next()) {
1790 if (mapEdges.Add(expW.Current())) {
1792 if (nbEdges > 4) break;
1796 hasNonQuadr = Standard_True;
1801 if (nbFaces == 6 && !hasNonQuadr) {
1802 BLO.Append(theShape);
1804 NOT.Append(theShape);
1810 NOT.Append(theShape);
1814 void AddBlocksFromOld (const TopoDS_Shape& theShape,
1815 TopTools_ListOfShape& BLO,
1816 TopTools_ListOfShape& NOT,
1817 TopTools_ListOfShape& DEG,
1818 TopTools_ListOfShape& SEA)
1820 TopAbs_ShapeEnum aType = theShape.ShapeType();
1822 case TopAbs_COMPOUND:
1823 case TopAbs_COMPSOLID:
1825 TopoDS_Iterator It (theShape);
1826 for (; It.More(); It.Next()) {
1827 AddBlocksFromOld(It.Value(), BLO, NOT, DEG, SEA);
1833 TopTools_MapOfShape mapFaces;
1834 TopExp_Explorer expF (theShape, TopAbs_FACE);
1835 Standard_Integer nbFaces = 0;
1836 Standard_Boolean hasNonQuadr = Standard_False;
1837 Standard_Boolean hasDegenerated = Standard_False;
1838 Standard_Boolean hasSeam = Standard_False;
1839 for (; expF.More(); expF.Next()) {
1840 if (mapFaces.Add(expF.Current())) {
1842 if (nbFaces > 6) break;
1844 // Check number of edges in the face
1845 Standard_Integer nbEdges = 0;
1846 TopTools_MapOfShape mapEdges;
1849 TopoDS_Shape aF = expF.Current();
1850 TopExp_Explorer wires (aF, TopAbs_WIRE);
1851 if (!wires.More()) {
1852 // no wire in the face
1853 hasNonQuadr = Standard_True;
1856 TopoDS_Shape aWire = wires.Current();
1859 // multiple wires in the face
1860 hasNonQuadr = Standard_True;
1865 BRepTools_WireExplorer aWE (TopoDS::Wire(aWire), TopoDS::Face(aF));
1866 for (; aWE.More(); aWE.Next(), nbEdges++) {
1867 if (BRep_Tool::Degenerated(aWE.Current())) {
1868 // degenerated edge found
1869 hasDegenerated = Standard_True;
1872 if (mapEdges.Contains(aWE.Current())) {
1874 hasSeam = Standard_True;
1877 mapEdges.Add(aWE.Current());
1880 hasNonQuadr = Standard_True;
1885 if (hasDegenerated || hasSeam) {
1886 if (hasDegenerated) {
1887 DEG.Append(theShape);
1890 SEA.Append(theShape);
1892 } else if (hasNonQuadr) {
1893 NOT.Append(theShape);
1895 BLO.Append(theShape);
1898 NOT.Append(theShape);
1903 NOT.Append(theShape);
1907 #define REL_NOT_CONNECTED 0
1909 #define REL_NOT_GLUED 2
1910 #define REL_COLLISION_VV 3
1911 #define REL_COLLISION_FF 4
1912 #define REL_COLLISION_EE 5
1913 #define REL_UNKNOWN 6
1915 Standard_Integer BlocksRelation (const TopoDS_Shape& theBlock1,
1916 const TopoDS_Shape& theBlock2)
1918 // Compare bounding boxes before calling BRepExtrema_DistShapeShape
1919 Standard_Real Xmin1, Ymin1, Zmin1, Xmax1, Ymax1, Zmax1;
1920 Standard_Real Xmin2, Ymin2, Zmin2, Xmax2, Ymax2, Zmax2;
1922 BRepBndLib::Add(theBlock1, B1);
1923 BRepBndLib::Add(theBlock2, B2);
1924 B1.Get(Xmin1, Ymin1, Zmin1, Xmax1, Ymax1, Zmax1);
1925 B2.Get(Xmin2, Ymin2, Zmin2, Xmax2, Ymax2, Zmax2);
1926 if (Xmax2 < Xmin1 || Xmax1 < Xmin2 ||
1927 Ymax2 < Ymin1 || Ymax1 < Ymin2 ||
1928 Zmax2 < Zmin1 || Zmax1 < Zmin2) {
1929 return REL_NOT_CONNECTED;
1932 BRepExtrema_DistShapeShape dst (theBlock1, theBlock2);
1933 if (!dst.IsDone()) {
1937 if (dst.Value() > Precision::Confusion()) {
1938 return REL_NOT_CONNECTED;
1941 if (dst.InnerSolution()) {
1942 return REL_COLLISION_VV;
1945 Standard_Integer nbSol = dst.NbSolution();
1946 Standard_Integer relation = REL_OK;
1947 Standard_Integer nbVerts = 0;
1948 Standard_Integer nbEdges = 0;
1949 Standard_Integer sol = 1;
1950 for (; sol <= nbSol; sol++) {
1951 BRepExtrema_SupportType supp1 = dst.SupportTypeShape1(sol);
1952 BRepExtrema_SupportType supp2 = dst.SupportTypeShape2(sol);
1953 if (supp1 == BRepExtrema_IsVertex && supp2 == BRepExtrema_IsVertex) {
1955 } else if (supp1 == BRepExtrema_IsInFace || supp2 == BRepExtrema_IsInFace) {
1956 return REL_COLLISION_FF;
1957 } else if (supp1 == BRepExtrema_IsOnEdge && supp2 == BRepExtrema_IsOnEdge) {
1959 } else if ((supp1 == BRepExtrema_IsOnEdge && supp2 == BRepExtrema_IsVertex) ||
1960 (supp2 == BRepExtrema_IsOnEdge && supp1 == BRepExtrema_IsVertex)) {
1961 relation = REL_COLLISION_EE;
1966 if (relation != REL_OK) {
1970 TColStd_Array1OfInteger vertSol (1, nbVerts);
1971 TopTools_Array1OfShape V1 (1, nbVerts);
1972 TopTools_Array1OfShape V2 (1, nbVerts);
1973 Standard_Integer ivs = 0;
1974 for (sol = 1; sol <= nbSol; sol++) {
1975 if (dst.SupportTypeShape1(sol) == BRepExtrema_IsVertex &&
1976 dst.SupportTypeShape2(sol) == BRepExtrema_IsVertex) {
1977 TopoDS_Vertex Vcur = TopoDS::Vertex(dst.SupportOnShape1(sol));
1978 // Check, that this vertex is far enough from other solution vertices.
1979 Standard_Integer ii = 1;
1980 for (; ii <= ivs; ii++) {
1981 if (BRepTools::Compare(TopoDS::Vertex(V1(ii)), Vcur)) {
1988 V2(ivs) = dst.SupportOnShape2(sol);
1992 // As we deal only with quadrangles,
1993 // 2, 3 or 4 vertex solutions can be found.
1996 return REL_COLLISION_FF;
1998 return REL_NOT_CONNECTED;
2004 // Check sharing of coincident entities.
2005 if (ivs == 2 || ivs == 3) {
2006 // Map vertices and edges of the blocks
2007 TopTools_IndexedDataMapOfShapeListOfShape MVE1, MVE2;
2008 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2009 (theBlock1, TopAbs_VERTEX, TopAbs_EDGE, MVE1);
2010 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2011 (theBlock2, TopAbs_VERTEX, TopAbs_EDGE, MVE2);
2015 TopoDS_Shape anEdge1, anEdge2;
2016 GEOMImpl_Block6Explorer::FindEdge(anEdge1, V1(1), V1(2), MVE1);
2017 if (anEdge1.IsNull()) return REL_UNKNOWN;
2019 GEOMImpl_Block6Explorer::FindEdge(anEdge2, V2(1), V2(2), MVE2);
2020 if (anEdge2.IsNull()) return REL_UNKNOWN;
2022 if (!anEdge1.IsSame(anEdge2)) return REL_NOT_GLUED;
2024 } else { // ivs == 3
2025 // Find common edges
2026 Standard_Integer e1_v1 = 1;
2027 Standard_Integer e1_v2 = 2;
2028 Standard_Integer e2_v1 = 3;
2029 Standard_Integer e2_v2 = 1;
2031 TopoDS_Shape anEdge11, anEdge12;
2032 GEOMImpl_Block6Explorer::FindEdge(anEdge11, V1(e1_v1), V1(e1_v2), MVE1);
2033 if (anEdge11.IsNull()) {
2036 GEOMImpl_Block6Explorer::FindEdge(anEdge11, V1(e1_v1), V1(e1_v2), MVE1);
2037 if (anEdge11.IsNull()) return REL_UNKNOWN;
2039 GEOMImpl_Block6Explorer::FindEdge(anEdge12, V1(e2_v1), V1(e2_v2), MVE1);
2040 if (anEdge12.IsNull()) {
2042 GEOMImpl_Block6Explorer::FindEdge(anEdge12, V1(e2_v1), V1(e2_v2), MVE1);
2043 if (anEdge12.IsNull()) return REL_UNKNOWN;
2046 TopoDS_Shape anEdge21, anEdge22;
2047 GEOMImpl_Block6Explorer::FindEdge(anEdge21, V2(e1_v1), V2(e1_v2), MVE2);
2048 if (anEdge21.IsNull()) return REL_UNKNOWN;
2049 GEOMImpl_Block6Explorer::FindEdge(anEdge22, V2(e2_v1), V2(e2_v2), MVE2);
2050 if (anEdge22.IsNull()) return REL_UNKNOWN;
2052 // Check of edges coincidence (with some precision) have to be done here
2053 // if (!anEdge11.IsEqual(anEdge21)) return REL_UNKNOWN;
2054 // if (!anEdge12.IsEqual(anEdge22)) return REL_UNKNOWN;
2056 // Check of edges sharing
2057 if (!anEdge11.IsSame(anEdge21)) return REL_NOT_GLUED;
2058 if (!anEdge12.IsSame(anEdge22)) return REL_NOT_GLUED;
2063 // Map vertices and faces of the blocks
2064 TopTools_IndexedDataMapOfShapeListOfShape MVF1, MVF2;
2065 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2066 (theBlock1, TopAbs_VERTEX, TopAbs_FACE, MVF1);
2067 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2068 (theBlock2, TopAbs_VERTEX, TopAbs_FACE, MVF2);
2070 TopoDS_Shape aFace1, aFace2;
2071 GEOMImpl_Block6Explorer::FindFace(aFace1, V1(1), V1(2), V1(3), V1(4), MVF1);
2072 if (aFace1.IsNull()) return REL_UNKNOWN;
2073 GEOMImpl_Block6Explorer::FindFace(aFace2, V2(1), V2(2), V2(3), V2(4), MVF2);
2074 if (aFace2.IsNull()) return REL_UNKNOWN;
2076 // Check of faces coincidence (with some precision) have to be done here
2077 // if (!aFace1.IsEqual(aFace2)) return REL_UNKNOWN;
2079 // Check of faces sharing
2080 if (!aFace1.IsSame(aFace2)) return REL_NOT_GLUED;
2086 void FindConnected (const Standard_Integer theBlockIndex,
2087 const TColStd_Array2OfInteger& theRelations,
2088 TColStd_MapOfInteger& theProcessedMap,
2089 TColStd_MapOfInteger& theConnectedMap)
2091 theConnectedMap.Add(theBlockIndex);
2092 theProcessedMap.Add(theBlockIndex);
2094 Standard_Integer nbBlocks = theRelations.ColLength();
2095 Standard_Integer col = 1;
2096 for (; col <= nbBlocks; col++) {
2097 if (theRelations(theBlockIndex, col) == REL_OK ||
2098 theRelations(theBlockIndex, col) == REL_NOT_GLUED) {
2099 if (!theProcessedMap.Contains(col)) {
2100 FindConnected(col, theRelations, theProcessedMap, theConnectedMap);
2106 Standard_Boolean HasAnyConnection (const Standard_Integer theBlockIndex,
2107 const TColStd_MapOfInteger& theWith,
2108 const TColStd_Array2OfInteger& theRelations,
2109 TColStd_MapOfInteger& theProcessedMap)
2111 theProcessedMap.Add(theBlockIndex);
2113 Standard_Integer nbBlocks = theRelations.ColLength();
2114 Standard_Integer col = 1;
2115 for (; col <= nbBlocks; col++) {
2116 if (theRelations(theBlockIndex, col) != REL_NOT_CONNECTED) {
2117 if (!theProcessedMap.Contains(col)) {
2118 if (theWith.Contains(col))
2119 return Standard_True;
2120 if (HasAnyConnection(col, theWith, theRelations, theProcessedMap))
2121 return Standard_True;
2126 return Standard_False;
2129 //=============================================================================
2131 * CheckCompoundOfBlocksOld
2133 //=============================================================================
2134 Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocksOld
2135 (Handle(GEOM_Object) theCompound,
2136 std::list<BCError>& theErrors)
2140 if (theCompound.IsNull()) return Standard_False;
2141 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2143 Standard_Boolean isCompOfBlocks = Standard_True;
2145 // Map sub-shapes and their indices
2146 TopTools_IndexedMapOfShape anIndices;
2147 TopExp::MapShapes(aBlockOrComp, anIndices);
2149 // 1. Report non-blocks
2150 TopTools_ListOfShape NOT; // Not blocks
2151 TopTools_ListOfShape DEG; // Hexahedral solids, having degenerated edges
2152 TopTools_ListOfShape SEA; // Hexahedral solids, having seam edges
2153 TopTools_ListOfShape BLO; // All blocks from the given compound
2154 AddBlocksFromOld(aBlockOrComp, BLO, NOT, DEG, SEA);
2156 if (NOT.Extent() > 0) {
2157 isCompOfBlocks = Standard_False;
2159 anErr.error = NOT_BLOCK;
2160 TopTools_ListIteratorOfListOfShape it (NOT);
2161 for (; it.More(); it.Next()) {
2162 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
2164 theErrors.push_back(anErr);
2167 if (DEG.Extent() > 0 || SEA.Extent() > 0) {
2168 isCompOfBlocks = Standard_False;
2170 anErr.error = EXTRA_EDGE;
2172 TopTools_ListIteratorOfListOfShape itDEG (DEG);
2173 for (; itDEG.More(); itDEG.Next()) {
2174 anErr.incriminated.push_back(anIndices.FindIndex(itDEG.Value()));
2177 TopTools_ListIteratorOfListOfShape itSEA (SEA);
2178 for (; itSEA.More(); itSEA.Next()) {
2179 anErr.incriminated.push_back(anIndices.FindIndex(itSEA.Value()));
2182 theErrors.push_back(anErr);
2185 Standard_Integer nbBlocks = BLO.Extent();
2186 if (nbBlocks == 0) {
2187 isCompOfBlocks = Standard_False;
2189 return isCompOfBlocks;
2191 if (nbBlocks == 1) {
2193 return isCompOfBlocks;
2196 // Convert list of blocks into array for easy and fast access
2197 Standard_Integer ibl = 1;
2198 TopTools_Array1OfShape aBlocks (1, nbBlocks);
2199 TopTools_ListIteratorOfListOfShape BLOit (BLO);
2200 for (; BLOit.More(); BLOit.Next(), ibl++) {
2201 aBlocks.SetValue(ibl, BLOit.Value());
2204 // 2. Find relations between all blocks,
2205 // report connection errors (NOT_GLUED and INVALID_CONNECTION)
2206 TColStd_Array2OfInteger aRelations (1, nbBlocks, 1, nbBlocks);
2207 aRelations.Init(REL_NOT_CONNECTED);
2209 Standard_Integer row = 1;
2210 for (row = 1; row <= nbBlocks; row++) {
2211 TopoDS_Shape aBlock = aBlocks.Value(row);
2213 Standard_Integer col = row + 1;
2214 for (; col <= nbBlocks; col++) {
2215 Standard_Integer aRel = BlocksRelation(aBlock, aBlocks.Value(col));
2216 if (aRel != REL_NOT_CONNECTED) {
2217 aRelations.SetValue(row, col, aRel);
2218 aRelations.SetValue(col, row, aRel);
2219 if (aRel == REL_NOT_GLUED) {
2220 // report connection error
2221 isCompOfBlocks = Standard_False;
2223 anErr.error = NOT_GLUED;
2224 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row)));
2225 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col)));
2226 theErrors.push_back(anErr);
2227 } else if (aRel == REL_COLLISION_VV ||
2228 aRel == REL_COLLISION_FF ||
2229 aRel == REL_COLLISION_EE ||
2230 aRel == REL_UNKNOWN) {
2231 // report connection error
2232 isCompOfBlocks = Standard_False;
2234 anErr.error = INVALID_CONNECTION;
2235 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row)));
2236 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col)));
2237 theErrors.push_back(anErr);
2244 // 3. Find largest set of connected (good connection or not glued) blocks
2245 TColStd_MapOfInteger aProcessedMap;
2246 TColStd_MapOfInteger aLargestSet;
2247 TColStd_MapOfInteger aCurrentSet;
2248 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2249 if (!aProcessedMap.Contains(ibl)) {
2250 aCurrentSet.Clear();
2251 FindConnected(ibl, aRelations, aProcessedMap, aCurrentSet);
2252 if (aCurrentSet.Extent() > aLargestSet.Extent()) {
2253 aLargestSet = aCurrentSet;
2258 // 4. Report all blocks, isolated from <aLargestSet>
2260 anErr.error = NOT_CONNECTED;
2261 Standard_Boolean hasIsolated = Standard_False;
2262 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2263 if (!aLargestSet.Contains(ibl)) {
2264 aProcessedMap.Clear();
2265 if (!HasAnyConnection(ibl, aLargestSet, aRelations, aProcessedMap)) {
2266 // report connection absence
2267 hasIsolated = Standard_True;
2268 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(ibl)));
2273 isCompOfBlocks = Standard_False;
2274 theErrors.push_back(anErr);
2278 return isCompOfBlocks;
2281 //=============================================================================
2285 //=============================================================================
2286 TCollection_AsciiString GEOMImpl_IBlocksOperations::PrintBCErrors
2287 (Handle(GEOM_Object) theCompound,
2288 const std::list<BCError>& theErrors)
2290 TCollection_AsciiString aDescr;
2292 std::list<BCError>::const_iterator errIt = theErrors.begin();
2294 for (; errIt != theErrors.end(); i++, errIt++) {
2295 BCError errStruct = *errIt;
2297 switch (errStruct.error) {
2299 aDescr += "\n\tNot a Blocks: ";
2302 aDescr += "\n\tHexahedral solids with degenerated and/or seam edges: ";
2304 case INVALID_CONNECTION:
2305 aDescr += "\n\tInvalid connection between two blocks: ";
2308 aDescr += "\n\tBlocks, not connected with main body: ";
2311 aDescr += "\n\tNot glued blocks: ";
2317 std::list<int> sshList = errStruct.incriminated;
2318 std::list<int>::iterator sshIt = sshList.begin();
2320 for (; sshIt != sshList.end(); jj++, sshIt++) {
2323 aDescr += TCollection_AsciiString(*sshIt);
2330 //=============================================================================
2332 * CheckCompoundOfBlocks
2334 //=============================================================================
2335 Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocks
2336 (Handle(GEOM_Object) theCompound,
2337 std::list<BCError>& theErrors)
2341 if (theCompound.IsNull()) return Standard_False;
2342 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2344 Standard_Boolean isCompOfBlocks = Standard_True;
2346 // Map sub-shapes and their indices
2347 TopTools_IndexedMapOfShape anIndices;
2348 TopExp::MapShapes(aBlockOrComp, anIndices);
2350 // 1. Separate blocks from non-blocks
2351 TopTools_ListOfShape NOT; // Not blocks
2352 TopTools_ListOfShape EXT; // Hexahedral solids, having degenerated and/or seam edges
2353 TopTools_ListOfShape BLO; // All blocks from the given compound
2354 AddBlocksFrom(aBlockOrComp, BLO, NOT, EXT);
2356 // Report non-blocks
2357 if (NOT.Extent() > 0) {
2358 isCompOfBlocks = Standard_False;
2360 anErr.error = NOT_BLOCK;
2361 TopTools_ListIteratorOfListOfShape it (NOT);
2362 for (; it.More(); it.Next()) {
2363 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
2365 theErrors.push_back(anErr);
2368 // Report solids, having degenerated and/or seam edges
2369 if (EXT.Extent() > 0) {
2370 isCompOfBlocks = Standard_False;
2372 anErr.error = EXTRA_EDGE;
2373 TopTools_ListIteratorOfListOfShape it (EXT);
2374 for (; it.More(); it.Next()) {
2375 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
2377 theErrors.push_back(anErr);
2380 Standard_Integer nbBlocks = BLO.Extent();
2381 if (nbBlocks == 0) {
2382 isCompOfBlocks = Standard_False;
2384 return isCompOfBlocks;
2386 if (nbBlocks == 1) {
2388 return isCompOfBlocks;
2391 // Prepare data for 2. and 3.
2392 TColStd_Array2OfInteger aRelations (1, nbBlocks, 1, nbBlocks);
2393 aRelations.Init(REL_NOT_CONNECTED);
2395 TopTools_IndexedMapOfShape mapBlocks;
2398 TopoDS_Compound aComp;
2399 BB.MakeCompound(aComp);
2401 TopTools_ListIteratorOfListOfShape BLOit (BLO);
2402 for (; BLOit.More(); BLOit.Next()) {
2403 mapBlocks.Add(BLOit.Value());
2404 BB.Add(aComp, BLOit.Value());
2407 // 2. Find glued blocks (having shared faces)
2408 TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
2409 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2410 (aComp, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
2412 Standard_Integer prevInd = 0, curInd = 0;
2413 Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
2414 for (; ind <= nbFaces; ind++) {
2415 const TopTools_ListOfShape& aGluedBlocks = mapFaceBlocks.FindFromIndex(ind);
2416 if (aGluedBlocks.Extent() > 1) { // Shared face found
2417 TopTools_ListIteratorOfListOfShape aGluedBlocksIt (aGluedBlocks);
2418 TopoDS_Shape prevBlock, curBlock;
2419 for (; aGluedBlocksIt.More(); aGluedBlocksIt.Next()) {
2420 curBlock = aGluedBlocksIt.Value();
2421 if (!prevBlock.IsNull()) {
2422 prevInd = mapBlocks.FindIndex(prevBlock);
2423 curInd = mapBlocks.FindIndex(curBlock);
2424 aRelations.SetValue(prevInd, curInd, REL_OK);
2425 aRelations.SetValue(curInd, prevInd, REL_OK);
2427 prevBlock = curBlock;
2432 // 3. Find not glued blocks
2433 GEOMAlgo_GlueAnalyser aGD;
2435 aGD.SetShape(aComp);
2436 aGD.SetTolerance(Precision::Confusion());
2437 aGD.SetCheckGeometry(Standard_True);
2440 Standard_Integer iErr, iWrn;
2441 iErr = aGD.ErrorStatus();
2443 SetErrorCode("Error in GEOMAlgo_GlueAnalyser");
2444 return isCompOfBlocks;
2446 iWrn = aGD.WarningStatus();
2448 MESSAGE("Warning in GEOMAlgo_GlueAnalyser");
2451 // Report not glued blocks
2452 if (aGD.HasSolidsToGlue()) {
2453 isCompOfBlocks = Standard_False;
2454 Standard_Integer aSx1Ind, aSx2Ind;
2456 const GEOMAlgo_ListOfCoupleOfShapes& aLCS = aGD.SolidsToGlue();
2457 GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS (aLCS);
2458 for (; aItCS.More(); aItCS.Next()) {
2459 const GEOMAlgo_CoupleOfShapes& aCS = aItCS.Value();
2460 const TopoDS_Shape& aSx1 = aCS.Shape1();
2461 const TopoDS_Shape& aSx2 = aCS.Shape2();
2463 aSx1Ind = mapBlocks.FindIndex(aSx1);
2464 aSx2Ind = mapBlocks.FindIndex(aSx2);
2465 aRelations.SetValue(aSx1Ind, aSx2Ind, NOT_GLUED);
2466 aRelations.SetValue(aSx2Ind, aSx1Ind, NOT_GLUED);
2469 anErr.error = NOT_GLUED;
2470 anErr.incriminated.push_back(anIndices.FindIndex(aSx1));
2471 anErr.incriminated.push_back(anIndices.FindIndex(aSx2));
2472 theErrors.push_back(anErr);
2476 // 4. Find largest set of connected (good connection or not glued) blocks
2477 Standard_Integer ibl = 1;
2478 TColStd_MapOfInteger aProcessedMap;
2479 TColStd_MapOfInteger aLargestSet;
2480 TColStd_MapOfInteger aCurrentSet;
2481 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2482 if (!aProcessedMap.Contains(ibl)) {
2483 aCurrentSet.Clear();
2484 FindConnected(ibl, aRelations, aProcessedMap, aCurrentSet);
2485 if (aCurrentSet.Extent() > aLargestSet.Extent()) {
2486 aLargestSet = aCurrentSet;
2491 // 5. Report all blocks, isolated from <aLargestSet>
2493 anErr.error = NOT_CONNECTED;
2494 Standard_Boolean hasIsolated = Standard_False;
2495 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2496 if (!aLargestSet.Contains(ibl)) {
2497 aProcessedMap.Clear();
2498 if (!HasAnyConnection(ibl, aLargestSet, aRelations, aProcessedMap)) {
2499 // report connection absence
2500 hasIsolated = Standard_True;
2501 anErr.incriminated.push_back(anIndices.FindIndex(mapBlocks.FindKey(ibl)));
2506 isCompOfBlocks = Standard_False;
2507 theErrors.push_back(anErr);
2511 return isCompOfBlocks;
2514 //=============================================================================
2518 //=============================================================================
2519 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::RemoveExtraEdges
2520 (Handle(GEOM_Object) theObject,
2521 const Standard_Integer theOptimumNbFaces)
2525 if (theObject.IsNull()) return NULL;
2527 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2528 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be fixed
2530 //Add a new Copy object
2531 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2534 Handle(GEOM_Function) aFunction =
2535 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_REMOVE_EXTRA);
2537 //Check if the function is set correctly
2538 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2540 GEOMImpl_IBlockTrsf aTI (aFunction);
2541 aTI.SetOriginal(aLastFunction);
2542 aTI.SetOptimumNbFaces(theOptimumNbFaces);
2544 //Compute the fixed shape
2546 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
2549 if (!GetSolver()->ComputeFunction(aFunction)) {
2550 SetErrorCode("Block driver failed to remove extra edges of the given shape");
2554 catch (Standard_Failure) {
2555 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2556 SetErrorCode(aFail->GetMessageString());
2560 //Make a Python command
2561 std::string doUnionFaces = (theOptimumNbFaces < 0) ? "False" : "True";
2562 GEOM::TPythonDump(aFunction) << aCopy << " = geompy.RemoveExtraEdges("
2563 << theObject << ", " << doUnionFaces.data() << ")";
2569 //=============================================================================
2573 //=============================================================================
2574 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::CheckAndImprove
2575 (Handle(GEOM_Object) theObject)
2579 if (theObject.IsNull()) return NULL;
2581 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2582 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be fixed
2584 //Add a new Copy object
2585 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2588 Handle(GEOM_Function) aFunction =
2589 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_COMPOUND_IMPROVE);
2591 //Check if the function is set correctly
2592 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2594 GEOMImpl_IBlockTrsf aTI (aFunction);
2595 aTI.SetOriginal(aLastFunction);
2597 // -1 means do not unite faces on common surface (?except case of seam edge between them?)
2598 //aTI.SetOptimumNbFaces(-1);
2599 aTI.SetOptimumNbFaces(6);
2601 //Compute the fixed shape
2603 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
2606 if (!GetSolver()->ComputeFunction(aFunction)) {
2607 SetErrorCode("Block driver failed to improve the given blocks compound");
2611 catch (Standard_Failure) {
2612 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2613 SetErrorCode(aFail->GetMessageString());
2617 //Make a Python command
2618 GEOM::TPythonDump(aFunction) << aCopy
2619 << " = geompy.CheckAndImprove(" << theObject << ")";
2625 //=============================================================================
2627 * ExplodeCompoundOfBlocks
2629 //=============================================================================
2630 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::ExplodeCompoundOfBlocks
2631 (Handle(GEOM_Object) theCompound,
2632 const Standard_Integer theMinNbFaces,
2633 const Standard_Integer theMaxNbFaces)
2637 if (theCompound.IsNull()) return NULL;
2638 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2639 if (aBlockOrComp.IsNull()) return NULL;
2641 Handle(TColStd_HSequenceOfTransient) aBlocks = new TColStd_HSequenceOfTransient;
2642 Handle(GEOM_Object) anObj;
2643 Handle(GEOM_Function) aFunction;
2645 TopTools_MapOfShape mapShape;
2646 TCollection_AsciiString anAsciiList, anEntry;
2649 TopTools_IndexedMapOfShape anIndices;
2650 TopExp::MapShapes(aBlockOrComp, anIndices);
2651 Handle(TColStd_HArray1OfInteger) anArray;
2655 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
2658 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2659 for (; exp.More(); exp.Next()) {
2660 if (mapShape.Add(exp.Current())) {
2661 TopoDS_Shape aSolid = exp.Current();
2663 TopTools_MapOfShape mapFaces;
2664 TopExp_Explorer expF (aSolid, TopAbs_FACE);
2665 Standard_Integer nbFaces = 0;
2666 for (; expF.More(); expF.Next()) {
2667 if (mapFaces.Add(expF.Current())) {
2672 if (theMinNbFaces <= nbFaces && nbFaces <= theMaxNbFaces) {
2673 anArray = new TColStd_HArray1OfInteger(1,1);
2674 anArray->SetValue(1, anIndices.FindIndex(aSolid));
2675 anObj = GetEngine()->AddSubShape(theCompound, anArray);
2676 aBlocks->Append(anObj);
2678 //Make a Python command
2679 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2680 anAsciiList += anEntry + ", ";
2685 catch (Standard_Failure) {
2686 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2687 SetErrorCode(aFail->GetMessageString());
2691 if (aBlocks->IsEmpty()) {
2692 SetErrorCode("There are no specified blocks in the given shape");
2696 anAsciiList.Trunc(anAsciiList.Length() - 2);
2698 //The explode doesn't change object so no new function is required.
2699 aFunction = theCompound->GetLastFunction();
2701 //Make a Python command
2702 GEOM::TPythonDump(aFunction, /*append=*/true)
2703 << "[" << anAsciiList.ToCString() << "] = geompy.MakeBlockExplode("
2704 << theCompound << ", " << theMinNbFaces << ", " << theMaxNbFaces << ")";
2710 //=============================================================================
2714 //=============================================================================
2715 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetBlockNearPoint
2716 (Handle(GEOM_Object) theCompound,
2717 Handle(GEOM_Object) thePoint)
2722 Handle(GEOM_Object) aResult;
2725 if (theCompound.IsNull() || thePoint.IsNull()) return NULL;
2727 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2728 if (aBlockOrComp.IsNull()) {
2729 SetErrorCode("Compound is null");
2732 if (aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
2733 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
2734 SetErrorCode("Shape to find block in is not a compound");
2738 TopoDS_Shape anArg = thePoint->GetValue();
2739 if (anArg.IsNull()) {
2740 SetErrorCode("Point is null");
2743 if (anArg.ShapeType() != TopAbs_VERTEX) {
2744 SetErrorCode("Shape for block identification is not a vertex");
2748 //Compute the Block value
2750 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
2753 TopoDS_Shape aShape;
2755 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
2756 gp_Pnt aPnt = BRep_Tool::Pnt(aVert);
2757 Standard_Real PX, PY, PZ;
2758 aPnt.Coord(PX, PY, PZ);
2760 // 1. Classify the point relatively each block
2761 Standard_Integer nearest = 2, nbFound = 0;
2762 TopTools_DataMapOfShapeInteger mapShapeDist;
2763 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2764 for (; exp.More(); exp.Next()) {
2765 TopoDS_Shape aSolid = exp.Current();
2767 if (!mapShapeDist.IsBound(aSolid)) {
2768 Standard_Integer aDistance = 2;
2770 // 1.a. Classify relatively Bounding box
2771 Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
2773 BRepBndLib::Add(aSolid, BB);
2774 BB.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
2775 if (PX < Xmin || Xmax < PX ||
2776 PY < Ymin || Ymax < PY ||
2777 PZ < Zmin || Zmax < PZ) {
2778 // OUT of bounding box
2781 // 1.b. Classify relatively the solid itself
2782 BRepClass3d_SolidClassifier SC (aSolid, aPnt, Precision::Confusion());
2783 if (SC.State() == TopAbs_IN) {
2785 } else if (SC.State() == TopAbs_ON) {
2792 if (aDistance < nearest) {
2793 nearest = aDistance;
2797 // A first found block, containing the point inside, will be returned.
2798 // It is the solution, if there are no intersecting blocks in the compound.
2799 if (nearest == -1) break;
2801 } else if (aDistance == nearest) {
2806 mapShapeDist.Bind(aSolid, aDistance);
2807 } // if (!mapShapeDist.IsBound(aSolid))
2810 // 2. Define block, containing the point or having minimum distance to it
2813 // The point is on boundary of some blocks and there are
2814 // no blocks, having the point inside their volume
2815 SetErrorCode("Multiple blocks near the given point are found");
2818 } else if (nearest == 1) {
2819 // The point is outside some blocks and there are
2820 // no blocks, having the point inside or on boundary.
2821 // We will get a nearest block
2822 Standard_Real minDist = RealLast();
2823 TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
2824 for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
2825 if (mapShapeDistIter.Value() == 1) {
2826 TopoDS_Shape aSolid = mapShapeDistIter.Key();
2827 BRepExtrema_DistShapeShape aDistTool (aVert, aSolid);
2828 if (!aDistTool.IsDone()) {
2829 SetErrorCode("Can not find a distance from the given point to one of blocks");
2832 Standard_Real aDist = aDistTool.Value();
2833 if (aDist < minDist) {
2839 } else { // nearest == -1
2840 // // The point is inside some blocks.
2841 // // We will get a block with nearest center
2842 // Standard_Real minDist = RealLast();
2843 // TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
2844 // for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
2845 // if (mapShapeDistIter.Value() == -1) {
2846 // TopoDS_Shape aSolid = mapShapeDistIter.Key();
2847 // GProp_GProps aSystem;
2848 // BRepGProp::VolumeProperties(aSolid, aSystem);
2849 // gp_Pnt aCenterMass = aSystem.CentreOfMass();
2851 // Standard_Real aDist = aCenterMass.Distance(aPnt);
2852 // if (aDist < minDist) {
2859 } // if (nbFound > 1)
2862 SetErrorCode("There are no blocks near the given point");
2865 TopTools_IndexedMapOfShape anIndices;
2866 TopExp::MapShapes(aBlockOrComp, anIndices);
2867 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2868 anArray->SetValue(1, anIndices.FindIndex(aShape));
2869 aResult = GetEngine()->AddSubShape(theCompound, anArray);
2872 catch (Standard_Failure) {
2873 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2874 SetErrorCode(aFail->GetMessageString());
2878 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
2880 //Make a Python command
2881 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetBlockNearPoint("
2882 << theCompound << ", " << thePoint << ")";
2888 //=============================================================================
2892 //=============================================================================
2893 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetBlockByParts
2894 (Handle(GEOM_Object) theCompound,
2895 const Handle(TColStd_HSequenceOfTransient)& theParts)
2899 Handle(GEOM_Object) aResult;
2901 if (theCompound.IsNull() || theParts.IsNull()) return NULL;
2902 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2903 if (aBlockOrComp.IsNull()) return NULL;
2906 Standard_Integer argi, aLen = theParts->Length();
2907 TopTools_Array1OfShape anArgs (1, aLen);
2908 TCollection_AsciiString anEntry, aPartsDescr;
2909 for (argi = 1; argi <= aLen; argi++) {
2910 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theParts->Value(argi));
2911 Handle(GEOM_Function) aRef = anObj->GetLastFunction();
2912 if (aRef.IsNull()) return NULL;
2914 TopoDS_Shape anArg = aRef->GetValue();
2915 if (anArg.IsNull()) {
2916 SetErrorCode("Null shape is given as argument");
2919 anArgs(argi) = anArg;
2921 // For Python command
2922 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2923 if (argi > 1) aPartsDescr += ", ";
2924 aPartsDescr += anEntry;
2927 //Compute the Block value
2929 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
2932 // 1. Explode compound on solids
2933 TopTools_MapOfShape mapShape;
2934 Standard_Integer nbSolids = 0;
2935 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2936 for (; exp.More(); exp.Next()) {
2937 if (mapShape.Add(exp.Current())) {
2943 Standard_Integer ind = 1;
2944 TopTools_Array1OfShape aSolids (1, nbSolids);
2945 TColStd_Array1OfInteger aNbParts (1, nbSolids);
2946 for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next(), ind++) {
2947 if (mapShape.Add(exp.Current())) {
2948 TopoDS_Shape aSolid = exp.Current();
2949 aSolids(ind) = aSolid;
2952 // 2. Define quantity of parts, contained in each solid
2953 TopTools_IndexedMapOfShape aSubShapes;
2954 TopExp::MapShapes(aSolid, aSubShapes);
2955 for (argi = 1; argi <= aLen; argi++) {
2956 if (aSubShapes.Contains(anArgs(argi))) {
2963 // 3. Define solid, containing maximum quantity of parts
2964 Standard_Integer maxNb = 0, nbFound = 0;
2965 TopoDS_Shape aShape;
2966 for (ind = 1; ind <= nbSolids; ind++) {
2967 if (aNbParts(ind) > maxNb) {
2968 maxNb = aNbParts(ind);
2969 aShape = aSolids(ind);
2971 } else if (aNbParts(ind) == maxNb) {
2977 SetErrorCode("Multiple blocks, containing maximum quantity of the given parts, are found");
2979 } else if (nbFound == 0) {
2980 SetErrorCode("There are no blocks, containing the given parts");
2983 TopTools_IndexedMapOfShape anIndices;
2984 TopExp::MapShapes(aBlockOrComp, anIndices);
2985 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2986 anArray->SetValue(1, anIndices.FindIndex(aShape));
2987 aResult = GetEngine()->AddSubShape(theCompound, anArray);
2989 } catch (Standard_Failure) {
2990 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2991 SetErrorCode(aFail->GetMessageString());
2995 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
2997 //Make a Python command
2998 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetBlockByParts("
2999 << theCompound << ", [" << aPartsDescr.ToCString() << "])";
3005 //=============================================================================
3009 //=============================================================================
3010 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::GetBlocksByParts
3011 (Handle(GEOM_Object) theCompound,
3012 const Handle(TColStd_HSequenceOfTransient)& theParts)
3016 if (theCompound.IsNull() || theParts.IsNull()) return NULL;
3017 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
3018 if (aBlockOrComp.IsNull()) return NULL;
3020 Handle(TColStd_HSequenceOfTransient) aBlocks = new TColStd_HSequenceOfTransient;
3021 Handle(GEOM_Object) anObj;
3022 Handle(GEOM_Function) aFunction;
3025 Standard_Integer argi, aLen = theParts->Length();
3026 TopTools_Array1OfShape anArgs (1, aLen);
3027 TCollection_AsciiString anEntry, aPartsDescr, anAsciiList;
3029 for (argi = 1; argi <= aLen; argi++) {
3030 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theParts->Value(argi));
3031 Handle(GEOM_Function) aRef = anObj->GetLastFunction();
3032 if (aRef.IsNull()) return NULL;
3034 TopoDS_Shape anArg = aRef->GetValue();
3035 if (anArg.IsNull()) {
3036 SetErrorCode("Null shape is given as argument");
3039 anArgs(argi) = anArg;
3041 // For Python command
3042 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
3043 aPartsDescr += anEntry + ", ";
3048 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
3051 TopTools_MapOfShape mapShape;
3052 Standard_Integer nbSolids = 0;
3053 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
3054 for (; exp.More(); exp.Next()) {
3055 if (mapShape.Add(exp.Current())) {
3061 Standard_Integer ind = 1;
3062 TopTools_Array1OfShape aSolids (1, nbSolids);
3063 TColStd_Array1OfInteger aNbParts (1, nbSolids);
3064 for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next(), ind++) {
3065 if (mapShape.Add(exp.Current())) {
3066 TopoDS_Shape aSolid = exp.Current();
3067 aSolids(ind) = aSolid;
3070 // 2. Define quantity of parts, contained in each solid
3071 TopTools_IndexedMapOfShape aSubShapes;
3072 TopExp::MapShapes(aSolid, aSubShapes);
3073 for (argi = 1; argi <= aLen; argi++) {
3074 if (aSubShapes.Contains(anArgs(argi))) {
3081 // 3. Define solid, containing maximum quantity of parts
3082 Standard_Integer maxNb = 0, nbFound = 0;
3083 for (ind = 1; ind <= nbSolids; ind++) {
3084 if (aNbParts(ind) > maxNb) {
3085 maxNb = aNbParts(ind);
3087 } else if (aNbParts(ind) == maxNb) {
3093 SetErrorCode("There are no blocks, containing the given parts");
3098 TopTools_IndexedMapOfShape anIndices;
3099 TopExp::MapShapes(aBlockOrComp, anIndices);
3100 Handle(TColStd_HArray1OfInteger) anArray;
3102 for (ind = 1; ind <= nbSolids; ind++) {
3103 if (aNbParts(ind) == maxNb) {
3104 anArray = new TColStd_HArray1OfInteger(1,1);
3105 anArray->SetValue(1, anIndices.FindIndex(aSolids(ind)));
3106 anObj = GetEngine()->AddSubShape(theCompound, anArray);
3107 aBlocks->Append(anObj);
3109 // For Python command
3110 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
3111 anAsciiList += anEntry + ", ";
3112 if (aFunction.IsNull())
3113 aFunction = anObj->GetLastFunction();
3117 catch (Standard_Failure) {
3118 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3119 SetErrorCode(aFail->GetMessageString());
3123 //Make a Python command
3124 aPartsDescr.Trunc(aPartsDescr.Length() - 2);
3125 anAsciiList.Trunc(anAsciiList.Length() - 2);
3127 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3128 << "] = geompy.GetBlocksByParts(" << theCompound
3129 << ", [" << aPartsDescr.ToCString() << "])";
3135 //=============================================================================
3137 * MakeMultiTransformation1D
3139 //=============================================================================
3140 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeMultiTransformation1D
3141 (Handle(GEOM_Object) theObject,
3142 const Standard_Integer theDirFace1,
3143 const Standard_Integer theDirFace2,
3144 const Standard_Integer theNbTimes)
3148 if (theObject.IsNull()) return NULL;
3150 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
3151 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be moved
3153 //Add a new Copy object
3154 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
3156 //Add a translate function
3157 Handle(GEOM_Function) aFunction =
3158 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_MULTI_TRANSFORM_1D);
3160 //Check if the function is set correctly
3161 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
3163 GEOMImpl_IBlockTrsf aTI (aFunction);
3164 aTI.SetOriginal(aLastFunction);
3165 aTI.SetFace1U(theDirFace1);
3166 aTI.SetFace2U(theDirFace2);
3167 aTI.SetNbIterU(theNbTimes);
3169 //Compute the transformation
3171 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
3174 if (!GetSolver()->ComputeFunction(aFunction)) {
3175 SetErrorCode("Block driver failed to make multi-transformation");
3179 catch (Standard_Failure) {
3180 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3181 SetErrorCode(aFail->GetMessageString());
3185 //Make a Python command
3186 GEOM::TPythonDump(aFunction) << aCopy << " = geompy.MakeMultiTransformation1D("
3187 << theObject << ", " << theDirFace1 << ", " << theDirFace2 << ", " << theNbTimes << ")";
3193 //=============================================================================
3195 * MakeMultiTransformation2D
3197 //=============================================================================
3198 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeMultiTransformation2D
3199 (Handle(GEOM_Object) theObject,
3200 const Standard_Integer theDirFace1U,
3201 const Standard_Integer theDirFace2U,
3202 const Standard_Integer theNbTimesU,
3203 const Standard_Integer theDirFace1V,
3204 const Standard_Integer theDirFace2V,
3205 const Standard_Integer theNbTimesV)
3209 if (theObject.IsNull()) return NULL;
3211 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
3212 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be moved
3214 //Add a new Copy object
3215 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
3217 //Add a translate function
3218 Handle(GEOM_Function) aFunction =
3219 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_MULTI_TRANSFORM_2D);
3221 //Check if the function is set correctly
3222 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
3224 GEOMImpl_IBlockTrsf aTI (aFunction);
3225 aTI.SetOriginal(aLastFunction);
3226 aTI.SetFace1U(theDirFace1U);
3227 aTI.SetFace2U(theDirFace2U);
3228 aTI.SetNbIterU(theNbTimesU);
3229 aTI.SetFace1V(theDirFace1V);
3230 aTI.SetFace2V(theDirFace2V);
3231 aTI.SetNbIterV(theNbTimesV);
3233 //Compute the transformation
3235 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
3238 if (!GetSolver()->ComputeFunction(aFunction)) {
3239 SetErrorCode("Block driver failed to make multi-transformation");
3243 catch (Standard_Failure) {
3244 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3245 SetErrorCode(aFail->GetMessageString());
3249 //Make a Python command
3250 GEOM::TPythonDump(aFunction) << aCopy << " = geompy.MakeMultiTransformation2D("
3251 << theObject << ", " << theDirFace1U << ", " << theDirFace2U << ", " << theNbTimesU
3252 << ", " << theDirFace1V << ", " << theDirFace2V << ", " << theNbTimesV << ")";
3258 //=============================================================================
3262 //=============================================================================
3263 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::Propagate
3264 (Handle(GEOM_Object) theShape)
3268 if (theShape.IsNull()) return NULL;
3270 TopoDS_Shape aShape = theShape->GetValue();
3271 if (aShape.IsNull()) return NULL;
3273 TopTools_IndexedMapOfShape anIndices;
3274 TopExp::MapShapes(aShape, anIndices);
3276 TopTools_IndexedDataMapOfShapeListOfShape MEW;
3277 GEOMImpl_Block6Explorer::MapShapesAndAncestors
3278 (aShape, TopAbs_EDGE, TopAbs_WIRE, MEW);
3279 Standard_Integer ie, nbEdges = MEW.Extent();
3282 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
3284 TopTools_MapOfShape mapAcceptedEdges;
3285 TCollection_AsciiString aListRes, anEntry;
3287 // Sort shapes in current chain (Mantis issue 21053)
3288 TopTools_DataMapOfShapeListOfShape aMapChains;
3289 TopTools_ListOfShape aFirstInChains;
3291 for (ie = 1; ie <= nbEdges; ie++) {
3292 TopoDS_Shape curE = MEW.FindKey(ie);
3294 if (mapAcceptedEdges.Contains(curE)) continue;
3297 TopTools_ListOfShape currentChain;
3298 TopTools_ListOfShape listPrevEdges;
3300 currentChain.Append(curE);
3301 listPrevEdges.Append(curE);
3302 mapAcceptedEdges.Add(curE);
3304 // Collect all edges pass by pass
3305 while (listPrevEdges.Extent() > 0) {
3306 // List of edges, added to chain on this cycle pass
3307 TopTools_ListOfShape listCurEdges;
3309 // Find the next portion of edges
3310 TopTools_ListIteratorOfListOfShape itE (listPrevEdges);
3311 for (; itE.More(); itE.Next()) {
3312 TopoDS_Shape anE = itE.Value();
3314 // Iterate on faces, having edge <anE>
3315 TopTools_ListIteratorOfListOfShape itW (MEW.FindFromKey(anE));
3316 for (; itW.More(); itW.Next()) {
3317 TopoDS_Shape aW = itW.Value();
3318 TopoDS_Shape anOppE;
3320 BRepTools_WireExplorer aWE (TopoDS::Wire(aW));
3321 Standard_Integer nb = 1, found = 0;
3322 TopTools_Array1OfShape anEdges (1,4);
3323 for (; aWE.More(); aWE.Next(), nb++) {
3328 anEdges(nb) = aWE.Current();
3329 if (anEdges(nb).IsSame(anE)) found = nb;
3332 if (nb == 5 && found > 0) {
3333 // Quadrangle face found, get an opposite edge
3334 Standard_Integer opp = found + 2;
3335 if (opp > 4) opp -= 4;
3336 anOppE = anEdges(opp);
3338 if (!mapAcceptedEdges.Contains(anOppE)) {
3339 // Add found edge to the chain
3340 currentChain.Append(anOppE);
3341 listCurEdges.Append(anOppE);
3342 mapAcceptedEdges.Add(anOppE);
3344 } // if (nb == 5 && found > 0)
3345 } // for (; itF.More(); itF.Next())
3346 } // for (; itE.More(); itE.Next())
3348 listPrevEdges = listCurEdges;
3349 } // while (listPrevEdges.Extent() > 0)
3351 // Sort shapes in current chain (Mantis issue 21053)
3352 GEOMImpl_IShapesOperations::SortShapes(currentChain, Standard_False);
3353 aFirstInChains.Append(currentChain.First());
3354 aMapChains.Bind(currentChain.First(), currentChain);
3357 // Sort chains (Mantis issue 21053)
3358 GEOMImpl_IShapesOperations::SortShapes(aFirstInChains, Standard_False);
3360 // Store sorted chains in the document
3361 TopTools_ListIteratorOfListOfShape aChainsIt (aFirstInChains);
3362 for (; aChainsIt.More(); aChainsIt.Next()) {
3363 TopoDS_Shape aFirstInChain = aChainsIt.Value();
3364 const TopTools_ListOfShape& currentChain = aMapChains.Find(aFirstInChain);
3366 // Store the chain in the document
3367 Handle(TColStd_HArray1OfInteger) anArray =
3368 new TColStd_HArray1OfInteger (1, currentChain.Extent());
3370 // Fill array of sub-shape indices
3371 TopTools_ListIteratorOfListOfShape itSub (currentChain);
3372 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
3373 int id = anIndices.FindIndex(itSub.Value());
3374 anArray->SetValue(index, id);
3377 // Add a new group object
3378 Handle(GEOM_Object) aChain = GetEngine()->AddSubShape(theShape, anArray);
3381 aChain->SetType(GEOM_GROUP);
3383 // Set a sub shape type
3384 TDF_Label aFreeLabel = aChain->GetFreeLabel();
3385 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)TopAbs_EDGE);
3387 // Add the chain to the result
3388 aSeq->Append(aChain);
3390 //Make a Python command
3391 TDF_Tool::Entry(aChain->GetEntry(), anEntry);
3392 aListRes += anEntry + ", ";
3395 if (aSeq->IsEmpty()) {
3396 SetErrorCode("There are no quadrangle faces in the shape");
3400 aListRes.Trunc(aListRes.Length() - 2);
3402 // The Propagation doesn't change object so no new function is required.
3403 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
3405 // Make a Python command
3406 GEOM::TPythonDump(aFunction, /*append=*/true)
3407 << "[" << aListRes.ToCString() << "] = geompy.Propagate(" << theShape << ")";