1 // Copyright (C) 2007-2013 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>
39 #include <GEOMUtils.hxx>
41 #include <GEOM_Function.hxx>
42 #include <GEOM_PythonDump.hxx>
44 #include <GEOMAlgo_GlueAnalyser.hxx>
45 #include <GEOMAlgo_CoupleOfShapes.hxx>
46 #include <GEOMAlgo_ListOfCoupleOfShapes.hxx>
47 #include <GEOMAlgo_ListIteratorOfListOfCoupleOfShapes.hxx>
48 #include <BlockFix_CheckTool.hxx>
50 #include <Basics_OCCTVersion.hxx>
52 #include "utilities.h"
54 #include <Utils_ExceptHandlers.hxx>
56 #include <TFunction_DriverTable.hxx>
57 #include <TFunction_Driver.hxx>
58 #include <TFunction_Logbook.hxx>
59 #include <TDataStd_Integer.hxx>
60 #include <TDF_Tool.hxx>
62 #include <BRep_Tool.hxx>
63 #include <BRep_Builder.hxx>
64 #include <BRepTools.hxx>
65 #include <BRepTools_WireExplorer.hxx>
66 #include <BRepGProp.hxx>
67 #include <BRepBndLib.hxx>
68 #include <BRepAdaptor_Surface.hxx>
69 #include <BRepClass_FaceClassifier.hxx>
70 #include <BRepClass3d_SolidClassifier.hxx>
71 #include <BRepExtrema_DistShapeShape.hxx>
75 #include <TopoDS_Edge.hxx>
76 #include <TopoDS_Vertex.hxx>
77 #include <TopoDS_Compound.hxx>
78 #include <TopoDS_Iterator.hxx>
80 #include <TopExp_Explorer.hxx>
81 #include <TopTools_MapOfShape.hxx>
82 #include <TopTools_Array1OfShape.hxx>
83 #include <TopTools_IndexedMapOfShape.hxx>
84 #include <TopTools_DataMapOfShapeInteger.hxx>
85 #include <TopTools_ListIteratorOfListOfShape.hxx>
86 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
87 #include <TopTools_DataMapIteratorOfDataMapOfShapeInteger.hxx>
89 #include <Bnd_Box.hxx>
90 #include <GProp_GProps.hxx>
92 #include <Geom_Surface.hxx>
93 #include <ShapeAnalysis_Surface.hxx>
95 #include <TColStd_MapOfInteger.hxx>
96 #include <TColStd_Array1OfReal.hxx>
97 #include <TColStd_Array1OfInteger.hxx>
98 #include <TColStd_Array2OfInteger.hxx>
100 //#include <OSD_Timer.hxx>
102 #include <Precision.hxx>
104 #include <Standard_Failure.hxx>
105 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
107 //=============================================================================
111 //=============================================================================
112 GEOMImpl_IBlocksOperations::GEOMImpl_IBlocksOperations (GEOM_Engine* theEngine, int theDocID)
113 : GEOM_IOperations(theEngine, theDocID)
115 MESSAGE("GEOMImpl_IBlocksOperations::GEOMImpl_IBlocksOperations");
118 //=============================================================================
122 //=============================================================================
123 GEOMImpl_IBlocksOperations::~GEOMImpl_IBlocksOperations()
125 MESSAGE("GEOMImpl_IBlocksOperations::~GEOMImpl_IBlocksOperations");
129 //=============================================================================
133 //=============================================================================
134 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad
135 (Handle(GEOM_Object) theEdge1, Handle(GEOM_Object) theEdge2,
136 Handle(GEOM_Object) theEdge3, Handle(GEOM_Object) theEdge4)
140 if (theEdge1.IsNull() || theEdge2.IsNull() ||
141 theEdge3.IsNull() || theEdge4.IsNull()) return NULL;
143 //Add a new Face object
144 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
146 //Add a new Face function
147 Handle(GEOM_Function) aFunction =
148 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_FOUR_EDGES);
150 //Check if the function is set correctly
151 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
153 GEOMImpl_IBlocks aPI (aFunction);
155 Handle(GEOM_Function) aRef1 = theEdge1->GetLastFunction();
156 Handle(GEOM_Function) aRef2 = theEdge2->GetLastFunction();
157 Handle(GEOM_Function) aRef3 = theEdge3->GetLastFunction();
158 Handle(GEOM_Function) aRef4 = theEdge4->GetLastFunction();
159 if (aRef1.IsNull() || aRef2.IsNull() ||
160 aRef3.IsNull() || aRef4.IsNull()) return NULL;
162 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
163 aShapesSeq->Append(aRef1);
164 aShapesSeq->Append(aRef2);
165 aShapesSeq->Append(aRef3);
166 aShapesSeq->Append(aRef4);
168 aPI.SetShapes(aShapesSeq);
170 //Compute the Face value
172 #if OCC_VERSION_LARGE > 0x06010000
175 if (!GetSolver()->ComputeFunction(aFunction)) {
176 SetErrorCode("Block driver failed to compute a face");
180 catch (Standard_Failure) {
181 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
182 SetErrorCode(aFail->GetMessageString());
186 //Make a Python command
187 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeQuad("
188 << theEdge1 << ", " << theEdge2 << ", " << theEdge3 << ", " << theEdge4 << ")";
194 //=============================================================================
198 //=============================================================================
199 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad2Edges
200 (Handle(GEOM_Object) theEdge1, Handle(GEOM_Object) theEdge2)
204 if (theEdge1.IsNull() || theEdge2.IsNull()) return NULL;
206 //Add a new Face object
207 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
209 //Add a new Face function
210 Handle(GEOM_Function) aFunction =
211 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_TWO_EDGES);
213 //Check if the function is set correctly
214 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
216 GEOMImpl_IBlocks aPI (aFunction);
218 Handle(GEOM_Function) aRef1 = theEdge1->GetLastFunction();
219 Handle(GEOM_Function) aRef2 = theEdge2->GetLastFunction();
220 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
222 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
223 aShapesSeq->Append(aRef1);
224 aShapesSeq->Append(aRef2);
226 aPI.SetShapes(aShapesSeq);
228 //Compute the Face value
230 #if OCC_VERSION_LARGE > 0x06010000
233 if (!GetSolver()->ComputeFunction(aFunction)) {
234 SetErrorCode("Block driver failed to compute a face");
238 catch (Standard_Failure) {
239 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
240 SetErrorCode(aFail->GetMessageString());
244 //Make a Python command
245 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeQuad2Edges("
246 << theEdge1 << ", " << theEdge2 << ")";
252 //=============================================================================
256 //=============================================================================
257 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad4Vertices
258 (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2,
259 Handle(GEOM_Object) thePnt3, Handle(GEOM_Object) thePnt4)
263 if (thePnt1.IsNull() || thePnt2.IsNull() ||
264 thePnt3.IsNull() || thePnt4.IsNull()) return NULL;
266 //Add a new Face object
267 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
269 //Add a new Face function
270 Handle(GEOM_Function) aFunction =
271 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_FOUR_PNT);
273 //Check if the function is set correctly
274 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
276 GEOMImpl_IBlocks aPI (aFunction);
278 Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
279 Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
280 Handle(GEOM_Function) aRef3 = thePnt3->GetLastFunction();
281 Handle(GEOM_Function) aRef4 = thePnt4->GetLastFunction();
282 if (aRef1.IsNull() || aRef2.IsNull() ||
283 aRef3.IsNull() || aRef4.IsNull()) return NULL;
285 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
286 aShapesSeq->Append(aRef1);
287 aShapesSeq->Append(aRef2);
288 aShapesSeq->Append(aRef3);
289 aShapesSeq->Append(aRef4);
291 aPI.SetShapes(aShapesSeq);
293 //Compute the Face value
295 #if OCC_VERSION_LARGE > 0x06010000
298 if (!GetSolver()->ComputeFunction(aFunction)) {
299 SetErrorCode("Block driver failed to compute a face");
303 catch (Standard_Failure) {
304 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
305 SetErrorCode(aFail->GetMessageString());
309 //Make a Python command
310 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeQuad4Vertices("
311 << thePnt1 << ", " << thePnt2 << ", " << thePnt3 << ", " << thePnt4 << ")";
317 //=============================================================================
321 //=============================================================================
322 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeHexa
323 (Handle(GEOM_Object) theFace1, Handle(GEOM_Object) theFace2,
324 Handle(GEOM_Object) theFace3, Handle(GEOM_Object) theFace4,
325 Handle(GEOM_Object) theFace5, Handle(GEOM_Object) theFace6)
329 if (theFace1.IsNull() || theFace2.IsNull() ||
330 theFace3.IsNull() || theFace4.IsNull() ||
331 theFace5.IsNull() || theFace6.IsNull()) return NULL;
333 //Add a new Solid object
334 Handle(GEOM_Object) aBlock = GetEngine()->AddObject(GetDocID(), GEOM_BLOCK);
336 //Add a new Block function
337 Handle(GEOM_Function) aFunction =
338 aBlock->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_SIX_FACES);
340 //Check if the function is set correctly
341 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
343 GEOMImpl_IBlocks aPI (aFunction);
345 Handle(GEOM_Function) aRef1 = theFace1->GetLastFunction();
346 Handle(GEOM_Function) aRef2 = theFace2->GetLastFunction();
347 Handle(GEOM_Function) aRef3 = theFace3->GetLastFunction();
348 Handle(GEOM_Function) aRef4 = theFace4->GetLastFunction();
349 Handle(GEOM_Function) aRef5 = theFace5->GetLastFunction();
350 Handle(GEOM_Function) aRef6 = theFace6->GetLastFunction();
351 if (aRef1.IsNull() || aRef2.IsNull() ||
352 aRef3.IsNull() || aRef4.IsNull() ||
353 aRef5.IsNull() || aRef6.IsNull()) return NULL;
355 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
356 aShapesSeq->Append(aRef1);
357 aShapesSeq->Append(aRef2);
358 aShapesSeq->Append(aRef3);
359 aShapesSeq->Append(aRef4);
360 aShapesSeq->Append(aRef5);
361 aShapesSeq->Append(aRef6);
363 aPI.SetShapes(aShapesSeq);
365 //Compute the Block value
367 #if OCC_VERSION_LARGE > 0x06010000
370 if (!GetSolver()->ComputeFunction(aFunction)) {
371 SetErrorCode("Block driver failed to compute a block");
375 catch (Standard_Failure) {
376 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
377 SetErrorCode(aFail->GetMessageString());
381 //Make a Python command
382 GEOM::TPythonDump(aFunction) << aBlock << " = geompy.MakeHexa("
383 << theFace1 << ", " << theFace2 << ", " << theFace3 << ", "
384 << theFace4 << ", " << theFace5 << ", " << theFace6 << ")";
390 //=============================================================================
394 //=============================================================================
395 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeHexa2Faces
396 (Handle(GEOM_Object) theFace1, Handle(GEOM_Object) theFace2)
400 if (theFace1.IsNull() || theFace2.IsNull()) return NULL;
402 //Add a new Solid object
403 Handle(GEOM_Object) aBlock = GetEngine()->AddObject(GetDocID(), GEOM_BLOCK);
405 //Add a new Block function
406 Handle(GEOM_Function) aFunction =
407 aBlock->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_TWO_FACES);
409 //Check if the function is set correctly
410 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
412 GEOMImpl_IBlocks aPI (aFunction);
414 Handle(GEOM_Function) aRef1 = theFace1->GetLastFunction();
415 Handle(GEOM_Function) aRef2 = theFace2->GetLastFunction();
416 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
418 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
419 aShapesSeq->Append(aRef1);
420 aShapesSeq->Append(aRef2);
422 aPI.SetShapes(aShapesSeq);
424 //Compute the Block value
426 #if OCC_VERSION_LARGE > 0x06010000
429 if (!GetSolver()->ComputeFunction(aFunction)) {
430 SetErrorCode("Block driver failed to compute a block");
434 catch (Standard_Failure) {
435 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
436 SetErrorCode(aFail->GetMessageString());
440 //Make a Python command
441 GEOM::TPythonDump(aFunction) << aBlock << " = geompy.MakeHexa2Faces("
442 << theFace1 << ", " << theFace2 << ")";
448 //=============================================================================
452 //=============================================================================
453 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeBlockCompound
454 (Handle(GEOM_Object) theCompound)
458 if (theCompound.IsNull()) return NULL;
461 Handle(GEOM_Object) aBlockComp = GetEngine()->AddObject(GetDocID(), GEOM_COMPOUND);
463 //Add a new BlocksComp function
464 Handle(GEOM_Function) aFunction =
465 aBlockComp->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_COMPOUND_GLUE);
467 //Check if the function is set correctly
468 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
470 GEOMImpl_IBlocks aPI (aFunction);
472 Handle(GEOM_Function) aRef1 = theCompound->GetLastFunction();
473 if (aRef1.IsNull()) return NULL;
475 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
476 aShapesSeq->Append(aRef1);
478 aPI.SetShapes(aShapesSeq);
480 //Compute the Blocks Compound value
482 #if OCC_VERSION_LARGE > 0x06010000
485 if (!GetSolver()->ComputeFunction(aFunction)) {
486 SetErrorCode("Block driver failed to compute a blocks compound");
490 catch (Standard_Failure) {
491 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
492 SetErrorCode(aFail->GetMessageString());
496 //Make a Python command
497 GEOM::TPythonDump(aFunction) << aBlockComp
498 << " = geompy.MakeBlockCompound(" << theCompound << ")";
504 //=============================================================================
508 //=============================================================================
509 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetPoint
510 (Handle(GEOM_Object) theShape,
511 const Standard_Real theX,
512 const Standard_Real theY,
513 const Standard_Real theZ,
514 const Standard_Real theEpsilon)
519 Handle(GEOM_Object) aResult;
522 if (theShape.IsNull()) return NULL;
524 TopoDS_Shape aBlockOrComp = theShape->GetValue();
525 if (aBlockOrComp.IsNull()) {
526 SetErrorCode("Given shape is null");
530 //Compute the Vertex value
531 gp_Pnt P (theX, theY, theZ);
532 Standard_Real eps = Max(theEpsilon, Precision::Confusion());
535 Standard_Integer isFound = 0;
536 TopTools_MapOfShape mapShape;
537 TopExp_Explorer exp (aBlockOrComp, TopAbs_VERTEX);
539 for (; exp.More(); exp.Next()) {
540 if (mapShape.Add(exp.Current())) {
541 TopoDS_Vertex aVi = TopoDS::Vertex(exp.Current());
542 gp_Pnt aPi = BRep_Tool::Pnt(aVi);
543 if (aPi.Distance(P) < eps) {
551 SetErrorCode("Vertex has not been found");
553 } else if (isFound > 1) {
554 SetErrorCode("Multiple vertices found by the given coordinates and epsilon");
557 TopTools_IndexedMapOfShape anIndices;
558 TopExp::MapShapes(aBlockOrComp, anIndices);
559 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
560 anArray->SetValue(1, anIndices.FindIndex(V));
561 aResult = GetEngine()->AddSubShape(theShape, anArray);
564 //The GetPoint() doesn't change object so no new function is required.
565 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
567 //Make a Python command
568 GEOM::TPythonDump(aFunction, /*append=*/true)
569 << aResult << " = geompy.GetPoint(" << theShape << ", "
570 << theX << ", " << theY << ", " << theZ << ", " << theEpsilon << ")";
576 //=============================================================================
580 //=============================================================================
581 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetVertexNearPoint
582 (Handle(GEOM_Object) theShape,
583 Handle(GEOM_Object) thePoint)
588 Handle(GEOM_Object) aResult;
591 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
593 TopoDS_Shape aBlockOrComp = theShape->GetValue();
594 TopoDS_Shape aPoint = thePoint->GetValue();
595 if (aBlockOrComp.IsNull() || aPoint.IsNull()) {
596 SetErrorCode("Given shape is null");
600 if (aPoint.ShapeType() != TopAbs_VERTEX) {
601 SetErrorCode("Element for vertex identification is not a vertex");
605 TopoDS_Vertex aVert = TopoDS::Vertex(aPoint);
606 gp_Pnt aP = BRep_Tool::Pnt(aVert);
608 // Compute the Vertex value
610 bool isFound = false;
611 Standard_Real aDist = RealLast();
612 TopTools_MapOfShape mapShape;
614 TopExp_Explorer exp (aBlockOrComp, TopAbs_VERTEX);
615 for (; exp.More(); exp.Next()) {
616 if (mapShape.Add(exp.Current())) {
617 TopoDS_Vertex aVi = TopoDS::Vertex(exp.Current());
618 gp_Pnt aPi = BRep_Tool::Pnt(aVi);
619 Standard_Real aDisti = aPi.Distance(aP);
620 if (aDisti < aDist) {
629 SetErrorCode("Vertex has not been found");
633 TopTools_IndexedMapOfShape anIndices;
634 TopExp::MapShapes(aBlockOrComp, anIndices);
635 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
636 anArray->SetValue(1, anIndices.FindIndex(V));
637 aResult = GetEngine()->AddSubShape(theShape, anArray);
639 // The GetPoint() doesn't change object so no new function is required.
640 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
642 // Make a Python command
643 GEOM::TPythonDump(aFunction, /*append=*/true)
644 << aResult << " = geompy.GetVertexNearPoint("
645 << theShape << ", " << thePoint << ")";
651 //=============================================================================
655 //=============================================================================
656 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetEdge
657 (Handle(GEOM_Object) theShape,
658 Handle(GEOM_Object) thePoint1,
659 Handle(GEOM_Object) thePoint2)
664 Handle(GEOM_Object) aResult;
667 if (theShape.IsNull() || thePoint1.IsNull() || thePoint2.IsNull()) return NULL;
669 TopoDS_Shape aBlockOrComp = theShape->GetValue();
670 if (aBlockOrComp.IsNull()) {
671 SetErrorCode("Given shape is null");
675 TopoDS_Shape anArg1 = thePoint1->GetValue();
676 TopoDS_Shape anArg2 = thePoint2->GetValue();
677 if (anArg1.IsNull() || anArg2.IsNull()) {
678 SetErrorCode("Null shape is given as argument");
681 if (anArg1.ShapeType() != TopAbs_VERTEX ||
682 anArg2.ShapeType() != TopAbs_VERTEX) {
683 SetErrorCode("Element for edge identification is not a vertex");
687 //Compute the Edge value
689 #if OCC_VERSION_LARGE > 0x06010000
692 TopTools_IndexedDataMapOfShapeListOfShape MVE;
693 GEOMImpl_Block6Explorer::MapShapesAndAncestors
694 (aBlockOrComp, TopAbs_VERTEX, TopAbs_EDGE, MVE);
697 Standard_Integer ish, ext = MVE.Extent();
699 if (MVE.Contains(anArg1)) {
702 for (ish = 1; ish <= ext; ish++) {
703 TopoDS_Shape aShi = MVE.FindKey(ish);
704 if (BRepTools::Compare(TopoDS::Vertex(anArg1), TopoDS::Vertex(aShi))) {
711 if (MVE.Contains(anArg2)) {
714 for (ish = 1; ish <= ext; ish++) {
715 TopoDS_Shape aShi = MVE.FindKey(ish);
716 if (BRepTools::Compare(TopoDS::Vertex(anArg2), TopoDS::Vertex(aShi))) {
723 if (V1.IsNull() || V2.IsNull()) {
724 SetErrorCode("The given vertex does not belong to the shape");
729 Standard_Integer isFound =
730 GEOMImpl_Block6Explorer::FindEdge(anEdge, V1, V2, MVE, Standard_True);
732 SetErrorCode("The given vertices do not belong to one edge of the given shape");
734 } else if (isFound > 1) {
735 SetErrorCode("Multiple edges found by the given vertices of the shape");
738 TopTools_IndexedMapOfShape anIndices;
739 TopExp::MapShapes(aBlockOrComp, anIndices);
740 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
741 anArray->SetValue(1, anIndices.FindIndex(anEdge));
742 aResult = GetEngine()->AddSubShape(theShape, anArray);
744 } catch (Standard_Failure) {
745 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
746 SetErrorCode(aFail->GetMessageString());
750 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
752 //Make a Python command
753 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetEdge("
754 << theShape << ", " << thePoint1 << ", " << thePoint2 << ")";
760 //=============================================================================
764 //=============================================================================
765 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetEdgeNearPoint
766 (Handle(GEOM_Object) theShape,
767 Handle(GEOM_Object) thePoint)
772 Handle(GEOM_Object) aResult;
775 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
777 TopoDS_Shape aBlockOrComp = theShape->GetValue();
778 if (aBlockOrComp.IsNull()) {
779 SetErrorCode("Given shape is null");
783 TopoDS_Shape anArg = thePoint->GetValue();
784 if (anArg.IsNull()) {
785 SetErrorCode("Null shape is given as argument");
788 if (anArg.ShapeType() != TopAbs_VERTEX) {
789 SetErrorCode("Element for edge identification is not a vertex");
793 //Compute the Edge value
795 #if OCC_VERSION_LARGE > 0x06010000
798 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
799 TopoDS_Shape aShape = GEOMUtils::GetEdgeNearPoint(aBlockOrComp, aVert);
801 TopTools_IndexedMapOfShape anIndices;
802 TopExp::MapShapes(aBlockOrComp, anIndices);
803 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
804 anArray->SetValue(1, anIndices.FindIndex(aShape));
805 aResult = GetEngine()->AddSubShape(theShape, anArray);
807 catch (Standard_Failure) {
808 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
809 SetErrorCode(aFail->GetMessageString());
813 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
815 //Make a Python command
816 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetEdgeNearPoint("
817 << theShape << ", " << thePoint << ")";
823 //=============================================================================
827 //=============================================================================
828 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByPoints
829 (Handle(GEOM_Object) theShape,
830 Handle(GEOM_Object) thePoint1,
831 Handle(GEOM_Object) thePoint2,
832 Handle(GEOM_Object) thePoint3,
833 Handle(GEOM_Object) thePoint4)
838 Handle(GEOM_Object) aResult;
841 if (theShape.IsNull() ||
842 thePoint1.IsNull() || thePoint2.IsNull() ||
843 thePoint3.IsNull() || thePoint4.IsNull()) return NULL;
845 TopoDS_Shape aBlockOrComp = theShape->GetValue();
846 if (aBlockOrComp.IsNull()) {
847 SetErrorCode("Block or compound is null");
851 TopoDS_Shape anArg1 = thePoint1->GetValue();
852 TopoDS_Shape anArg2 = thePoint2->GetValue();
853 TopoDS_Shape anArg3 = thePoint3->GetValue();
854 TopoDS_Shape anArg4 = thePoint4->GetValue();
855 if (anArg1.IsNull() || anArg2.IsNull() ||
856 anArg3.IsNull() || anArg4.IsNull()) {
857 SetErrorCode("Null shape is given as argument");
860 if (anArg1.ShapeType() != TopAbs_VERTEX ||
861 anArg2.ShapeType() != TopAbs_VERTEX ||
862 anArg3.ShapeType() != TopAbs_VERTEX ||
863 anArg4.ShapeType() != TopAbs_VERTEX) {
864 SetErrorCode("Element for face identification is not a vertex");
868 //Compute the Face value
870 #if OCC_VERSION_LARGE > 0x06010000
875 TopTools_IndexedDataMapOfShapeListOfShape MVF;
876 GEOMImpl_Block6Explorer::MapShapesAndAncestors(aBlockOrComp, TopAbs_VERTEX, TopAbs_FACE, MVF);
878 TopoDS_Shape V1,V2,V3,V4;
879 Standard_Integer ish, ext = MVF.Extent();
881 if (MVF.Contains(anArg1)) {
884 for (ish = 1; ish <= ext; ish++) {
885 TopoDS_Shape aShi = MVF.FindKey(ish);
886 if (BRepTools::Compare(TopoDS::Vertex(anArg1), TopoDS::Vertex(aShi))) {
893 if (MVF.Contains(anArg2)) {
896 for (ish = 1; ish <= ext; ish++) {
897 TopoDS_Shape aShi = MVF.FindKey(ish);
898 if (BRepTools::Compare(TopoDS::Vertex(anArg2), TopoDS::Vertex(aShi))) {
905 if (MVF.Contains(anArg3)) {
908 for (ish = 1; ish <= ext; ish++) {
909 TopoDS_Shape aShi = MVF.FindKey(ish);
910 if (BRepTools::Compare(TopoDS::Vertex(anArg3), TopoDS::Vertex(aShi))) {
917 if (MVF.Contains(anArg4)) {
920 for (ish = 1; ish <= ext; ish++) {
921 TopoDS_Shape aShi = MVF.FindKey(ish);
922 if (BRepTools::Compare(TopoDS::Vertex(anArg4), TopoDS::Vertex(aShi))) {
929 if (V1.IsNull() || V2.IsNull() || V3.IsNull() || V4.IsNull()) {
930 SetErrorCode("The given vertex does not belong to the shape");
934 Standard_Integer isFound =
935 GEOMImpl_Block6Explorer::FindFace(aShape, V1, V2, V3, V4, MVF, Standard_True);
937 SetErrorCode("The given vertices do not belong to one face of the given shape");
939 } else if (isFound > 1) {
940 SetErrorCode("The given vertices belong to several faces of the given shape");
943 TopTools_IndexedMapOfShape anIndices;
944 TopExp::MapShapes(aBlockOrComp, anIndices);
945 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
946 anArray->SetValue(1, anIndices.FindIndex(aShape));
947 aResult = GetEngine()->AddSubShape(theShape, anArray);
950 catch (Standard_Failure) {
951 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
952 SetErrorCode(aFail->GetMessageString());
956 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
958 //Make a Python command
959 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByPoints("
960 << theShape << ", " << thePoint1 << ", " << thePoint2
961 << ", " << thePoint3 << ", " << thePoint4 << ")";
967 //=============================================================================
971 //=============================================================================
972 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByEdges
973 (Handle(GEOM_Object) theShape,
974 Handle(GEOM_Object) theEdge1,
975 Handle(GEOM_Object) theEdge2)
980 Handle(GEOM_Object) aResult;
983 if (theShape.IsNull() || theEdge1.IsNull() || theEdge2.IsNull()) return NULL;
985 TopoDS_Shape aBlockOrComp = theShape->GetValue();
986 if (aBlockOrComp.IsNull()) {
987 SetErrorCode("Block or compound is null");
991 TopoDS_Shape anArg1 = theEdge1->GetValue();
992 TopoDS_Shape anArg2 = theEdge2->GetValue();
993 if (anArg1.IsNull() || anArg2.IsNull()) {
994 SetErrorCode("Null shape is given as argument");
997 if (anArg1.ShapeType() != TopAbs_EDGE ||
998 anArg2.ShapeType() != TopAbs_EDGE) {
999 SetErrorCode("Element for face identification is not an edge");
1003 //Compute the Face value
1005 #if OCC_VERSION_LARGE > 0x06010000
1008 TopoDS_Shape aShape;
1010 TopTools_IndexedDataMapOfShapeListOfShape MEF;
1011 GEOMImpl_Block6Explorer::MapShapesAndAncestors(aBlockOrComp, TopAbs_EDGE, TopAbs_FACE, MEF);
1014 Standard_Integer ish, ext = MEF.Extent();
1016 if (MEF.Contains(anArg1)) {
1019 for (ish = 1; ish <= ext; ish++) {
1020 TopoDS_Shape aShi = MEF.FindKey(ish);
1021 if (GEOMImpl_Block6Explorer::IsSimilarEdges(anArg1, aShi)) {
1027 if (MEF.Contains(anArg2)) {
1030 for (ish = 1; ish <= ext; ish++) {
1031 TopoDS_Shape aShi = MEF.FindKey(ish);
1032 if (GEOMImpl_Block6Explorer::IsSimilarEdges(anArg2, aShi)) {
1038 if (E1.IsNull() || E2.IsNull()) {
1039 SetErrorCode("The given edge does not belong to the shape");
1043 const TopTools_ListOfShape& aFacesOfE1 = MEF.FindFromKey(E1);
1044 const TopTools_ListOfShape& aFacesOfE2 = MEF.FindFromKey(E2);
1046 Standard_Integer isFound = 0;
1047 TopTools_ListIteratorOfListOfShape anIterF1 (aFacesOfE1);
1048 for (; anIterF1.More(); anIterF1.Next()) {
1050 TopTools_ListIteratorOfListOfShape anIterF2 (aFacesOfE2);
1051 for (; anIterF2.More(); anIterF2.Next()) {
1053 if (anIterF1.Value().IsSame(anIterF2.Value())) {
1056 // Store the face, defined by two edges
1057 aShape = anIterF1.Value();
1062 SetErrorCode("The given edges do not belong to one face of the given shape");
1064 } else if (isFound > 1) {
1065 SetErrorCode("The given edges belong to several faces of the given shape");
1068 TopTools_IndexedMapOfShape anIndices;
1069 TopExp::MapShapes(aBlockOrComp, anIndices);
1070 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1071 anArray->SetValue(1, anIndices.FindIndex(aShape));
1072 aResult = GetEngine()->AddSubShape(theShape, anArray);
1075 catch (Standard_Failure) {
1076 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1077 SetErrorCode(aFail->GetMessageString());
1081 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1083 //Make a Python command
1084 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByEdges("
1085 << theShape << ", " << theEdge1 << ", " << theEdge2 << ")";
1091 //=============================================================================
1095 //=============================================================================
1096 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetOppositeFace
1097 (Handle(GEOM_Object) theShape,
1098 Handle(GEOM_Object) theFace)
1103 Handle(GEOM_Object) aResult;
1106 if (theShape.IsNull() || theFace.IsNull()) return NULL;
1108 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1109 if (aBlockOrComp.IsNull()) {
1110 SetErrorCode("Block is null");
1113 if (aBlockOrComp.ShapeType() != TopAbs_SOLID) {
1114 SetErrorCode("Shape is not a block");
1118 TopoDS_Shape anArg = theFace->GetValue();
1119 if (anArg.IsNull()) {
1120 SetErrorCode("Null shape is given as argument");
1123 if (anArg.ShapeType() != TopAbs_FACE) {
1124 SetErrorCode("Element for face identification is not a face");
1128 //Compute the Face value
1130 #if OCC_VERSION_LARGE > 0x06010000
1133 TopoDS_Shape aShape;
1135 GEOMImpl_Block6Explorer aBlockTool;
1136 aBlockTool.InitByBlockAndFace(aBlockOrComp, anArg);
1137 aShape = aBlockTool.GetFace(2);
1139 TopTools_IndexedMapOfShape anIndices;
1140 TopExp::MapShapes(aBlockOrComp, anIndices);
1141 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1142 anArray->SetValue(1, anIndices.FindIndex(aShape));
1143 aResult = GetEngine()->AddSubShape(theShape, anArray);
1145 catch (Standard_Failure) {
1146 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1147 SetErrorCode(aFail->GetMessageString());
1151 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1153 //Make a Python command
1154 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetOppositeFace("
1155 << theShape << ", " << theFace << ")";
1161 //=============================================================================
1165 //=============================================================================
1166 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceNearPoint
1167 (Handle(GEOM_Object) theShape,
1168 Handle(GEOM_Object) thePoint)
1173 Handle(GEOM_Object) aResult;
1176 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
1178 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1179 if (aBlockOrComp.IsNull()) {
1180 SetErrorCode("Block or compound is null");
1184 TopoDS_Shape anArg = thePoint->GetValue();
1185 if (anArg.IsNull()) {
1186 SetErrorCode("Null shape is given as argument");
1189 if (anArg.ShapeType() != TopAbs_VERTEX) {
1190 SetErrorCode("Element for face identification is not a vertex");
1194 //Compute the Face value
1196 #if OCC_VERSION_LARGE > 0x06010000
1199 TopoDS_Shape aShape;
1201 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
1202 gp_Pnt aPnt = BRep_Tool::Pnt(aVert);
1203 Standard_Real PX, PY, PZ;
1204 aPnt.Coord(PX, PY, PZ);
1206 // 1. Classify the point relatively each face
1207 Standard_Integer nearest = 2, nbFound = 0;
1208 TopTools_DataMapOfShapeInteger mapShapeDist;
1209 TopExp_Explorer exp (aBlockOrComp, TopAbs_FACE);
1210 for (; exp.More(); exp.Next()) {
1211 TopoDS_Shape aFace = exp.Current();
1213 if (!mapShapeDist.IsBound(aFace)) {
1214 Standard_Integer aDistance = 2;
1216 // 1.a. Classify relatively Surface
1217 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aFace));
1218 Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf);
1219 gp_Pnt2d p2dOnSurf = aSurfAna->ValueOfUV(aPnt, Precision::Confusion());
1220 gp_Pnt p3dOnSurf = aSurfAna->Value(p2dOnSurf);
1221 Standard_Real aDist = p3dOnSurf.Distance(aPnt);
1222 if (aDist > Precision::Confusion()) {
1226 // 1.b. Classify relatively the face itself
1227 BRepClass_FaceClassifier FC (TopoDS::Face(aFace), p2dOnSurf, Precision::Confusion());
1228 if (FC.State() == TopAbs_IN) {
1230 } else if (FC.State() == TopAbs_ON) {
1237 if (aDistance < nearest) {
1238 nearest = aDistance;
1242 // A first found face, containing the point inside, will be returned.
1243 // It is the solution, if there are no
1244 // coincident or intersecting faces in the compound.
1245 if (nearest == -1) break;
1247 } else if (aDistance == nearest) {
1252 mapShapeDist.Bind(aFace, aDistance);
1253 } // if (!mapShapeDist.IsBound(aFace))
1256 // 2. Define face, containing the point or having minimum distance to it
1259 // The point is on boundary of some faces and there are
1260 // no faces, having the point inside
1261 SetErrorCode("Multiple faces near the given point are found");
1264 } else if (nearest == 1) {
1265 // The point is outside some faces and there are
1266 // no faces, having the point inside or on boundary.
1267 // We will get a nearest face
1268 Standard_Real bigReal = RealLast();
1269 Standard_Real minDist = bigReal;
1270 TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
1271 for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
1272 if (mapShapeDistIter.Value() == 1) {
1273 TopoDS_Shape aFace = mapShapeDistIter.Key();
1274 Standard_Real aDist = bigReal;
1276 // 2.a. Fast check of distance - if point projection on surface is on face
1277 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aFace));
1278 Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf);
1279 gp_Pnt2d p2dOnSurf = aSurfAna->ValueOfUV(aPnt, Precision::Confusion());
1280 gp_Pnt p3dOnSurf = aSurfAna->Value(p2dOnSurf);
1281 aDist = p3dOnSurf.Distance(aPnt);
1283 BRepClass_FaceClassifier FC (TopoDS::Face(aFace), p2dOnSurf, Precision::Confusion());
1284 if (FC.State() == TopAbs_OUT) {
1285 if (aDist < minDist) {
1286 // 2.b. Slow check - if point projection on surface is outside of face
1287 BRepExtrema_DistShapeShape aDistTool (aVert, aFace);
1288 if (!aDistTool.IsDone()) {
1289 SetErrorCode("Can not find a distance from the given point to one of faces");
1292 aDist = aDistTool.Value();
1298 if (aDist < minDist) {
1304 } else { // nearest == -1
1305 // // The point is inside some faces.
1306 // // We will get a face with nearest center
1307 // Standard_Real minDist = RealLast();
1308 // TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
1309 // for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
1310 // if (mapShapeDistIter.Value() == -1) {
1311 // TopoDS_Shape aFace = mapShapeDistIter.Key();
1312 // GProp_GProps aSystem;
1313 // BRepGProp::SurfaceProperties(aFace, aSystem);
1314 // gp_Pnt aCenterMass = aSystem.CentreOfMass();
1316 // Standard_Real aDist = aCenterMass.Distance(aPnt);
1317 // if (aDist < minDist) {
1324 } // if (nbFound > 1)
1327 SetErrorCode("There are no faces near the given point");
1330 TopTools_IndexedMapOfShape anIndices;
1331 TopExp::MapShapes(aBlockOrComp, anIndices);
1332 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1333 anArray->SetValue(1, anIndices.FindIndex(aShape));
1334 aResult = GetEngine()->AddSubShape(theShape, anArray);
1337 catch (Standard_Failure) {
1338 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1339 SetErrorCode(aFail->GetMessageString());
1343 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1345 //Make a Python command
1346 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceNearPoint("
1347 << theShape << ", " << thePoint << ")";
1353 //=============================================================================
1357 //=============================================================================
1358 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByNormale
1359 (Handle(GEOM_Object) theShape,
1360 Handle(GEOM_Object) theVector)
1365 Handle(GEOM_Object) aResult;
1368 if (theShape.IsNull() || theVector.IsNull()) return NULL;
1370 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1371 if (aBlockOrComp.IsNull()) {
1372 SetErrorCode("Block or compound is null");
1376 TopoDS_Shape anArg = theVector->GetValue();
1377 if (anArg.IsNull()) {
1378 SetErrorCode("Null shape is given as argument");
1381 if (anArg.ShapeType() != TopAbs_EDGE) {
1382 SetErrorCode("Element for normale identification is not an edge");
1386 //Compute the Face value
1388 #if OCC_VERSION_LARGE > 0x06010000
1391 TopoDS_Shape aShape;
1393 TopoDS_Edge anEdge = TopoDS::Edge(anArg);
1394 TopoDS_Vertex V1, V2;
1395 TopExp::Vertices(anEdge, V1, V2, Standard_True);
1396 gp_Pnt P1 = BRep_Tool::Pnt(V1);
1397 gp_Pnt P2 = BRep_Tool::Pnt(V2);
1398 gp_Vec aVec (P1, P2);
1399 if (aVec.Magnitude() < Precision::Confusion()) {
1400 SetErrorCode("Vector with null magnitude is given");
1404 Standard_Real minAngle = RealLast();
1405 TopTools_MapOfShape mapShape;
1406 TopExp_Explorer exp (aBlockOrComp, TopAbs_FACE);
1407 for (; exp.More(); exp.Next()) {
1408 if (mapShape.Add(exp.Current())) {
1409 TopoDS_Face aFace = TopoDS::Face(exp.Current());
1410 BRepAdaptor_Surface SF (aFace);
1412 Standard_Real u, v, x;
1414 // find a point on the surface to get normal direction in
1415 u = SF.FirstUParameter();
1416 x = SF.LastUParameter();
1417 if (Precision::IsInfinite(u)) {
1418 u = (Precision::IsInfinite(x)) ? 0. : x;
1419 } else if (!Precision::IsInfinite(x)) {
1423 v = SF.FirstVParameter();
1424 x = SF.LastVParameter();
1425 if (Precision::IsInfinite(v)) {
1426 v = (Precision::IsInfinite(x)) ? 0. : x;
1427 } else if (!Precision::IsInfinite(x)) {
1431 // compute the normal direction
1433 SF.D1(u,v,P1,Vec1,Vec2);
1434 gp_Vec V = Vec1.Crossed(Vec2);
1436 if (V.Magnitude() < Precision::Confusion()) {
1437 SetErrorCode("Normal vector of a face has null magnitude");
1441 // consider the face orientation
1442 if (aFace.Orientation() == TopAbs_REVERSED ||
1443 aFace.Orientation() == TopAbs_INTERNAL) {
1447 // compute the angle and compare with the minimal one
1448 Standard_Real anAngle = aVec.Angle(V);
1449 if (anAngle < minAngle) {
1456 if (aShape.IsNull()) {
1457 SetErrorCode("Failed to find a face by the given normale");
1460 TopTools_IndexedMapOfShape anIndices;
1461 TopExp::MapShapes(aBlockOrComp, anIndices);
1462 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1463 anArray->SetValue(1, anIndices.FindIndex(aShape));
1464 aResult = GetEngine()->AddSubShape(theShape, anArray);
1467 catch (Standard_Failure) {
1468 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1469 SetErrorCode(aFail->GetMessageString());
1473 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1475 //Make a Python command
1476 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByNormale("
1477 << theShape << ", " << theVector << ")";
1483 //=============================================================================
1485 * GetShapesNearPoint
1487 //=============================================================================
1488 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetShapesNearPoint
1489 (Handle(GEOM_Object) theShape,
1490 Handle(GEOM_Object) thePoint,
1491 const Standard_Integer theShapeType,
1492 const Standard_Real theConstTolerance)
1497 Handle(GEOM_Object) aResult;
1500 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
1502 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1503 if (aBlockOrComp.IsNull()) {
1504 SetErrorCode("Block or compound is null");
1508 TopoDS_Shape anArg = thePoint->GetValue();
1509 if (anArg.IsNull()) {
1510 SetErrorCode("Null shape is given as argument");
1513 if (anArg.ShapeType() != TopAbs_VERTEX) {
1514 SetErrorCode("Element for face identification is not a vertex");
1518 if (theShapeType < TopAbs_SOLID || TopAbs_VERTEX < theShapeType) {
1519 SetErrorCode("Invalid type of result is requested");
1523 Standard_Real theTolerance = theConstTolerance;
1524 if (theTolerance < Precision::Confusion()) {
1525 theTolerance = Precision::Confusion();
1528 // Compute the result
1530 #if OCC_VERSION_LARGE > 0x06010000
1533 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
1535 TopTools_MapOfShape mapShape;
1536 Standard_Integer nbEdges = 0;
1537 TopExp_Explorer exp (aBlockOrComp, TopAbs_ShapeEnum(theShapeType));
1538 for (; exp.More(); exp.Next()) {
1539 if (mapShape.Add(exp.Current())) {
1545 SetErrorCode("Given shape contains no sub-shapes of requested type");
1549 // Calculate distances and find min
1551 Standard_Integer ind = 1;
1552 Standard_Real aMinDist = RealLast();
1553 TopTools_Array1OfShape anEdges (1, nbEdges);
1554 TColStd_Array1OfReal aDistances (1, nbEdges);
1555 for (exp.Init(aBlockOrComp, TopAbs_ShapeEnum(theShapeType)); exp.More(); exp.Next()) {
1556 if (mapShape.Add(exp.Current())) {
1557 TopoDS_Shape anEdge = exp.Current();
1558 anEdges(ind) = anEdge;
1560 BRepExtrema_DistShapeShape aDistTool (aVert, anEdges(ind));
1561 if (!aDistTool.IsDone()) {
1562 SetErrorCode("Can not find a distance from the given point to one of sub-shapes");
1565 aDistances(ind) = aDistTool.Value();
1566 if (aDistances(ind) < aMinDist) {
1567 aMinDist = aDistances(ind);
1573 if (aMinDist < RealLast()) {
1574 // Collect sub-shapes with distance < (aMinDist + theTolerance)
1575 int nbSubShapes = 0;
1576 TopTools_Array1OfShape aNearShapes (1, nbEdges);
1577 for (ind = 1; ind <= nbEdges; ind++) {
1578 if (aDistances(ind) < aMinDist + theTolerance) {
1580 aNearShapes(nbSubShapes) = anEdges(ind);
1585 TopTools_IndexedMapOfShape anIndices;
1586 TopExp::MapShapes(aBlockOrComp, anIndices);
1587 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger (1, nbSubShapes);
1588 for (ind = 1; ind <= nbSubShapes; ind++) {
1589 anArray->SetValue(ind, anIndices.FindIndex(aNearShapes(ind)));
1591 aResult = GetEngine()->AddSubShape(theShape, anArray);
1594 catch (Standard_Failure) {
1595 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1596 SetErrorCode(aFail->GetMessageString());
1600 if (aResult.IsNull())
1603 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1605 //Make a Python command
1606 GEOM::TPythonDump(aFunction)
1607 << aResult << " = geompy.GetShapesNearPoint(" << theShape << ", " << thePoint
1608 << ", " << TopAbs_ShapeEnum(theShapeType) << ", " << theTolerance << ")";
1614 //=============================================================================
1616 * IsCompoundOfBlocks
1618 //=============================================================================
1619 Standard_Boolean GEOMImpl_IBlocksOperations::IsCompoundOfBlocks
1620 (Handle(GEOM_Object) theCompound,
1621 const Standard_Integer theMinNbFaces,
1622 const Standard_Integer theMaxNbFaces,
1623 Standard_Integer& theNbBlocks)
1626 Standard_Boolean isCompOfBlocks = Standard_False;
1629 if (theCompound.IsNull()) return isCompOfBlocks;
1630 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
1633 isCompOfBlocks = Standard_True;
1635 #if OCC_VERSION_LARGE > 0x06010000
1638 TopTools_MapOfShape mapShape;
1639 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
1640 for (; exp.More(); exp.Next()) {
1641 if (mapShape.Add(exp.Current())) {
1642 TopoDS_Shape aSolid = exp.Current();
1644 TopTools_MapOfShape mapFaces;
1645 TopExp_Explorer expF (aSolid, TopAbs_FACE);
1646 Standard_Integer nbFaces = 0;
1647 for (; expF.More(); expF.Next()) {
1648 if (mapFaces.Add(expF.Current())) {
1650 if (nbFaces > theMaxNbFaces) {
1651 isCompOfBlocks = Standard_False;
1656 if (nbFaces < theMinNbFaces || theMaxNbFaces < nbFaces) {
1657 isCompOfBlocks = Standard_False;
1664 catch (Standard_Failure) {
1665 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1666 SetErrorCode(aFail->GetMessageString());
1667 return isCompOfBlocks;
1671 return isCompOfBlocks;
1674 //=============================================================================
1676 * Set of functions, used by CheckCompoundOfBlocks() method
1678 //=============================================================================
1679 void GEOMImpl_IBlocksOperations::AddBlocksFrom (const TopoDS_Shape& theShape,
1680 TopTools_ListOfShape& BLO,
1681 TopTools_ListOfShape& NOT,
1682 TopTools_ListOfShape& EXT,
1683 TopTools_ListOfShape& NOQ)
1685 TopAbs_ShapeEnum aType = theShape.ShapeType();
1687 case TopAbs_COMPOUND:
1688 case TopAbs_COMPSOLID:
1690 TopoDS_Iterator It (theShape);
1691 for (; It.More(); It.Next()) {
1692 AddBlocksFrom(It.Value(), BLO, NOT, EXT, NOQ);
1698 // Check, if there are seam or degenerated edges
1699 BlockFix_CheckTool aTool;
1700 aTool.SetShape(theShape);
1702 if (aTool.NbPossibleBlocks() > 0) {
1703 EXT.Append(theShape);
1705 // Count faces and edges in each face to recognize blocks
1706 TopTools_MapOfShape mapFaces;
1707 Standard_Integer nbFaces = 0;
1708 Standard_Boolean hasNonQuadr = Standard_False;
1709 TopExp_Explorer expF (theShape, TopAbs_FACE);
1711 for (; expF.More(); expF.Next()) {
1712 if (mapFaces.Add(expF.Current())) {
1714 //0021483//if (nbFaces > 6) break;
1717 TopoDS_Shape aF = expF.Current();
1718 TopExp_Explorer wires (aF, TopAbs_WIRE);
1719 if (!wires.More()) {
1720 // no wire in the face
1721 hasNonQuadr = Standard_True;
1722 NOQ.Append(aF);//0021483
1726 TopoDS_Shape aWire = wires.Current();
1729 // multiple wires in the face
1730 hasNonQuadr = Standard_True;
1731 NOQ.Append(aF);//0021483
1736 // Check number of edges in the face
1737 Standard_Integer nbEdges = 0;
1738 TopTools_MapOfShape mapEdges;
1739 TopExp_Explorer expW (aWire, TopAbs_EDGE);
1740 for (; expW.More(); expW.Next()) {
1741 if (mapEdges.Add(expW.Current())) {
1743 if (nbEdges > 4) break;
1747 hasNonQuadr = Standard_True;
1748 NOQ.Append(aF);//0021483
1753 if (nbFaces == 6 && !hasNonQuadr) {
1754 BLO.Append(theShape);
1756 NOT.Append(theShape);
1761 case TopAbs_SHELL: //0021483
1762 case TopAbs_FACE: //0021483
1764 // Count edges in each face
1765 TopTools_MapOfShape mapFaces;
1766 TopExp_Explorer expF (theShape, TopAbs_FACE);
1767 for (; expF.More(); expF.Next()) {
1768 if (mapFaces.Add(expF.Current())) {
1770 TopoDS_Shape aF = expF.Current();
1771 TopExp_Explorer wires (aF, TopAbs_WIRE);
1772 if (!wires.More()) {
1773 // no wire in the face
1774 NOQ.Append(aF);//0021483
1777 TopoDS_Shape aWire = wires.Current();
1780 // multiple wires in the face
1781 NOQ.Append(aF);//0021483
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 NOQ.Append(aF);//0021483
1803 NOT.Append(theShape);
1807 void AddBlocksFromOld (const TopoDS_Shape& theShape,
1808 TopTools_ListOfShape& BLO,
1809 TopTools_ListOfShape& NOT,
1810 TopTools_ListOfShape& DEG,
1811 TopTools_ListOfShape& SEA)
1813 TopAbs_ShapeEnum aType = theShape.ShapeType();
1815 case TopAbs_COMPOUND:
1816 case TopAbs_COMPSOLID:
1818 TopoDS_Iterator It (theShape);
1819 for (; It.More(); It.Next()) {
1820 AddBlocksFromOld(It.Value(), BLO, NOT, DEG, SEA);
1826 TopTools_MapOfShape mapFaces;
1827 TopExp_Explorer expF (theShape, TopAbs_FACE);
1828 Standard_Integer nbFaces = 0;
1829 Standard_Boolean hasNonQuadr = Standard_False;
1830 Standard_Boolean hasDegenerated = Standard_False;
1831 Standard_Boolean hasSeam = Standard_False;
1832 for (; expF.More(); expF.Next()) {
1833 if (mapFaces.Add(expF.Current())) {
1835 if (nbFaces > 6) break;
1837 // Check number of edges in the face
1838 Standard_Integer nbEdges = 0;
1839 TopTools_MapOfShape mapEdges;
1842 TopoDS_Shape aF = expF.Current();
1843 TopExp_Explorer wires (aF, TopAbs_WIRE);
1844 if (!wires.More()) {
1845 // no wire in the face
1846 hasNonQuadr = Standard_True;
1849 TopoDS_Shape aWire = wires.Current();
1852 // multiple wires in the face
1853 hasNonQuadr = Standard_True;
1858 BRepTools_WireExplorer aWE (TopoDS::Wire(aWire), TopoDS::Face(aF));
1859 for (; aWE.More(); aWE.Next(), nbEdges++) {
1860 if (BRep_Tool::Degenerated(aWE.Current())) {
1861 // degenerated edge found
1862 hasDegenerated = Standard_True;
1865 if (mapEdges.Contains(aWE.Current())) {
1867 hasSeam = Standard_True;
1870 mapEdges.Add(aWE.Current());
1873 hasNonQuadr = Standard_True;
1878 if (hasDegenerated || hasSeam) {
1879 if (hasDegenerated) {
1880 DEG.Append(theShape);
1883 SEA.Append(theShape);
1885 } else if (hasNonQuadr) {
1886 NOT.Append(theShape);
1888 BLO.Append(theShape);
1891 NOT.Append(theShape);
1896 NOT.Append(theShape);
1900 #define REL_NOT_CONNECTED 0
1902 #define REL_NOT_GLUED 2
1903 #define REL_COLLISION_VV 3
1904 #define REL_COLLISION_FF 4
1905 #define REL_COLLISION_EE 5
1906 #define REL_UNKNOWN 6
1908 Standard_Integer BlocksRelation (const TopoDS_Shape& theBlock1,
1909 const TopoDS_Shape& theBlock2)
1911 // Compare bounding boxes before calling BRepExtrema_DistShapeShape
1912 Standard_Real Xmin1, Ymin1, Zmin1, Xmax1, Ymax1, Zmax1;
1913 Standard_Real Xmin2, Ymin2, Zmin2, Xmax2, Ymax2, Zmax2;
1915 BRepBndLib::Add(theBlock1, B1);
1916 BRepBndLib::Add(theBlock2, B2);
1917 B1.Get(Xmin1, Ymin1, Zmin1, Xmax1, Ymax1, Zmax1);
1918 B2.Get(Xmin2, Ymin2, Zmin2, Xmax2, Ymax2, Zmax2);
1919 if (Xmax2 < Xmin1 || Xmax1 < Xmin2 ||
1920 Ymax2 < Ymin1 || Ymax1 < Ymin2 ||
1921 Zmax2 < Zmin1 || Zmax1 < Zmin2) {
1922 return REL_NOT_CONNECTED;
1925 BRepExtrema_DistShapeShape dst (theBlock1, theBlock2);
1926 if (!dst.IsDone()) {
1930 if (dst.Value() > Precision::Confusion()) {
1931 return REL_NOT_CONNECTED;
1934 if (dst.InnerSolution()) {
1935 return REL_COLLISION_VV;
1938 Standard_Integer nbSol = dst.NbSolution();
1939 Standard_Integer relation = REL_OK;
1940 Standard_Integer nbVerts = 0;
1941 Standard_Integer nbEdges = 0;
1942 Standard_Integer sol = 1;
1943 for (; sol <= nbSol; sol++) {
1944 BRepExtrema_SupportType supp1 = dst.SupportTypeShape1(sol);
1945 BRepExtrema_SupportType supp2 = dst.SupportTypeShape2(sol);
1946 if (supp1 == BRepExtrema_IsVertex && supp2 == BRepExtrema_IsVertex) {
1948 } else if (supp1 == BRepExtrema_IsInFace || supp2 == BRepExtrema_IsInFace) {
1949 return REL_COLLISION_FF;
1950 } else if (supp1 == BRepExtrema_IsOnEdge && supp2 == BRepExtrema_IsOnEdge) {
1952 } else if ((supp1 == BRepExtrema_IsOnEdge && supp2 == BRepExtrema_IsVertex) ||
1953 (supp2 == BRepExtrema_IsOnEdge && supp1 == BRepExtrema_IsVertex)) {
1954 relation = REL_COLLISION_EE;
1959 if (relation != REL_OK) {
1963 TColStd_Array1OfInteger vertSol (1, nbVerts);
1964 TopTools_Array1OfShape V1 (1, nbVerts);
1965 TopTools_Array1OfShape V2 (1, nbVerts);
1966 Standard_Integer ivs = 0;
1967 for (sol = 1; sol <= nbSol; sol++) {
1968 if (dst.SupportTypeShape1(sol) == BRepExtrema_IsVertex &&
1969 dst.SupportTypeShape2(sol) == BRepExtrema_IsVertex) {
1970 TopoDS_Vertex Vcur = TopoDS::Vertex(dst.SupportOnShape1(sol));
1971 // Check, that this vertex is far enough from other solution vertices.
1972 Standard_Integer ii = 1;
1973 for (; ii <= ivs; ii++) {
1974 if (BRepTools::Compare(TopoDS::Vertex(V1(ii)), Vcur)) {
1981 V2(ivs) = dst.SupportOnShape2(sol);
1985 // As we deal only with quadrangles,
1986 // 2, 3 or 4 vertex solutions can be found.
1989 return REL_COLLISION_FF;
1991 return REL_NOT_CONNECTED;
1997 // Check sharing of coincident entities.
1998 if (ivs == 2 || ivs == 3) {
1999 // Map vertices and edges of the blocks
2000 TopTools_IndexedDataMapOfShapeListOfShape MVE1, MVE2;
2001 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2002 (theBlock1, TopAbs_VERTEX, TopAbs_EDGE, MVE1);
2003 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2004 (theBlock2, TopAbs_VERTEX, TopAbs_EDGE, MVE2);
2008 TopoDS_Shape anEdge1, anEdge2;
2009 GEOMImpl_Block6Explorer::FindEdge(anEdge1, V1(1), V1(2), MVE1);
2010 if (anEdge1.IsNull()) return REL_UNKNOWN;
2012 GEOMImpl_Block6Explorer::FindEdge(anEdge2, V2(1), V2(2), MVE2);
2013 if (anEdge2.IsNull()) return REL_UNKNOWN;
2015 if (!anEdge1.IsSame(anEdge2)) return REL_NOT_GLUED;
2017 } else { // ivs == 3
2018 // Find common edges
2019 Standard_Integer e1_v1 = 1;
2020 Standard_Integer e1_v2 = 2;
2021 Standard_Integer e2_v1 = 3;
2022 Standard_Integer e2_v2 = 1;
2024 TopoDS_Shape anEdge11, anEdge12;
2025 GEOMImpl_Block6Explorer::FindEdge(anEdge11, V1(e1_v1), V1(e1_v2), MVE1);
2026 if (anEdge11.IsNull()) {
2029 GEOMImpl_Block6Explorer::FindEdge(anEdge11, V1(e1_v1), V1(e1_v2), MVE1);
2030 if (anEdge11.IsNull()) return REL_UNKNOWN;
2032 GEOMImpl_Block6Explorer::FindEdge(anEdge12, V1(e2_v1), V1(e2_v2), MVE1);
2033 if (anEdge12.IsNull()) {
2035 GEOMImpl_Block6Explorer::FindEdge(anEdge12, V1(e2_v1), V1(e2_v2), MVE1);
2036 if (anEdge12.IsNull()) return REL_UNKNOWN;
2039 TopoDS_Shape anEdge21, anEdge22;
2040 GEOMImpl_Block6Explorer::FindEdge(anEdge21, V2(e1_v1), V2(e1_v2), MVE2);
2041 if (anEdge21.IsNull()) return REL_UNKNOWN;
2042 GEOMImpl_Block6Explorer::FindEdge(anEdge22, V2(e2_v1), V2(e2_v2), MVE2);
2043 if (anEdge22.IsNull()) return REL_UNKNOWN;
2045 // Check of edges coincidence (with some precision) have to be done here
2046 // if (!anEdge11.IsEqual(anEdge21)) return REL_UNKNOWN;
2047 // if (!anEdge12.IsEqual(anEdge22)) return REL_UNKNOWN;
2049 // Check of edges sharing
2050 if (!anEdge11.IsSame(anEdge21)) return REL_NOT_GLUED;
2051 if (!anEdge12.IsSame(anEdge22)) return REL_NOT_GLUED;
2056 // Map vertices and faces of the blocks
2057 TopTools_IndexedDataMapOfShapeListOfShape MVF1, MVF2;
2058 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2059 (theBlock1, TopAbs_VERTEX, TopAbs_FACE, MVF1);
2060 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2061 (theBlock2, TopAbs_VERTEX, TopAbs_FACE, MVF2);
2063 TopoDS_Shape aFace1, aFace2;
2064 GEOMImpl_Block6Explorer::FindFace(aFace1, V1(1), V1(2), V1(3), V1(4), MVF1);
2065 if (aFace1.IsNull()) return REL_UNKNOWN;
2066 GEOMImpl_Block6Explorer::FindFace(aFace2, V2(1), V2(2), V2(3), V2(4), MVF2);
2067 if (aFace2.IsNull()) return REL_UNKNOWN;
2069 // Check of faces coincidence (with some precision) have to be done here
2070 // if (!aFace1.IsEqual(aFace2)) return REL_UNKNOWN;
2072 // Check of faces sharing
2073 if (!aFace1.IsSame(aFace2)) return REL_NOT_GLUED;
2079 void FindConnected (const Standard_Integer theBlockIndex,
2080 const TColStd_Array2OfInteger& theRelations,
2081 TColStd_MapOfInteger& theProcessedMap,
2082 TColStd_MapOfInteger& theConnectedMap)
2084 theConnectedMap.Add(theBlockIndex);
2085 theProcessedMap.Add(theBlockIndex);
2087 Standard_Integer nbBlocks = theRelations.ColLength();
2088 Standard_Integer col = 1;
2089 for (; col <= nbBlocks; col++) {
2090 if (theRelations(theBlockIndex, col) == REL_OK ||
2091 theRelations(theBlockIndex, col) == REL_NOT_GLUED) {
2092 if (!theProcessedMap.Contains(col)) {
2093 FindConnected(col, theRelations, theProcessedMap, theConnectedMap);
2099 Standard_Boolean HasAnyConnection (const Standard_Integer theBlockIndex,
2100 const TColStd_MapOfInteger& theWith,
2101 const TColStd_Array2OfInteger& theRelations,
2102 TColStd_MapOfInteger& theProcessedMap)
2104 theProcessedMap.Add(theBlockIndex);
2106 Standard_Integer nbBlocks = theRelations.ColLength();
2107 Standard_Integer col = 1;
2108 for (; col <= nbBlocks; col++) {
2109 if (theRelations(theBlockIndex, col) != REL_NOT_CONNECTED) {
2110 if (!theProcessedMap.Contains(col)) {
2111 if (theWith.Contains(col))
2112 return Standard_True;
2113 if (HasAnyConnection(col, theWith, theRelations, theProcessedMap))
2114 return Standard_True;
2119 return Standard_False;
2122 //=============================================================================
2124 * CheckCompoundOfBlocksOld
2126 //=============================================================================
2127 Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocksOld
2128 (Handle(GEOM_Object) theCompound,
2129 std::list<BCError>& theErrors)
2133 if (theCompound.IsNull()) return Standard_False;
2134 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2136 Standard_Boolean isCompOfBlocks = Standard_True;
2138 // Map sub-shapes and their indices
2139 TopTools_IndexedMapOfShape anIndices;
2140 TopExp::MapShapes(aBlockOrComp, anIndices);
2142 // 1. Report non-blocks
2143 TopTools_ListOfShape NOT; // Not blocks
2144 TopTools_ListOfShape DEG; // Hexahedral solids, having degenerated edges
2145 TopTools_ListOfShape SEA; // Hexahedral solids, having seam edges
2146 TopTools_ListOfShape BLO; // All blocks from the given compound
2147 AddBlocksFromOld(aBlockOrComp, BLO, NOT, DEG, SEA);
2149 if (NOT.Extent() > 0) {
2150 isCompOfBlocks = Standard_False;
2152 anErr.error = NOT_BLOCK;
2153 TopTools_ListIteratorOfListOfShape it (NOT);
2154 for (; it.More(); it.Next()) {
2155 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
2157 theErrors.push_back(anErr);
2160 if (DEG.Extent() > 0 || SEA.Extent() > 0) {
2161 isCompOfBlocks = Standard_False;
2163 anErr.error = EXTRA_EDGE;
2165 TopTools_ListIteratorOfListOfShape itDEG (DEG);
2166 for (; itDEG.More(); itDEG.Next()) {
2167 anErr.incriminated.push_back(anIndices.FindIndex(itDEG.Value()));
2170 TopTools_ListIteratorOfListOfShape itSEA (SEA);
2171 for (; itSEA.More(); itSEA.Next()) {
2172 anErr.incriminated.push_back(anIndices.FindIndex(itSEA.Value()));
2175 theErrors.push_back(anErr);
2178 Standard_Integer nbBlocks = BLO.Extent();
2179 if (nbBlocks == 0) {
2180 isCompOfBlocks = Standard_False;
2182 return isCompOfBlocks;
2184 if (nbBlocks == 1) {
2186 return isCompOfBlocks;
2189 // Convert list of blocks into array for easy and fast access
2190 Standard_Integer ibl = 1;
2191 TopTools_Array1OfShape aBlocks (1, nbBlocks);
2192 TopTools_ListIteratorOfListOfShape BLOit (BLO);
2193 for (; BLOit.More(); BLOit.Next(), ibl++) {
2194 aBlocks.SetValue(ibl, BLOit.Value());
2197 // 2. Find relations between all blocks,
2198 // report connection errors (NOT_GLUED and INVALID_CONNECTION)
2199 TColStd_Array2OfInteger aRelations (1, nbBlocks, 1, nbBlocks);
2200 aRelations.Init(REL_NOT_CONNECTED);
2202 Standard_Integer row = 1;
2203 for (row = 1; row <= nbBlocks; row++) {
2204 TopoDS_Shape aBlock = aBlocks.Value(row);
2206 Standard_Integer col = row + 1;
2207 for (; col <= nbBlocks; col++) {
2208 Standard_Integer aRel = BlocksRelation(aBlock, aBlocks.Value(col));
2209 if (aRel != REL_NOT_CONNECTED) {
2210 aRelations.SetValue(row, col, aRel);
2211 aRelations.SetValue(col, row, aRel);
2212 if (aRel == REL_NOT_GLUED) {
2213 // report connection error
2214 isCompOfBlocks = Standard_False;
2216 anErr.error = NOT_GLUED;
2217 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row)));
2218 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col)));
2219 theErrors.push_back(anErr);
2220 } else if (aRel == REL_COLLISION_VV ||
2221 aRel == REL_COLLISION_FF ||
2222 aRel == REL_COLLISION_EE ||
2223 aRel == REL_UNKNOWN) {
2224 // report connection error
2225 isCompOfBlocks = Standard_False;
2227 anErr.error = INVALID_CONNECTION;
2228 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row)));
2229 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col)));
2230 theErrors.push_back(anErr);
2237 // 3. Find largest set of connected (good connection or not glued) blocks
2238 TColStd_MapOfInteger aProcessedMap;
2239 TColStd_MapOfInteger aLargestSet;
2240 TColStd_MapOfInteger aCurrentSet;
2241 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2242 if (!aProcessedMap.Contains(ibl)) {
2243 aCurrentSet.Clear();
2244 FindConnected(ibl, aRelations, aProcessedMap, aCurrentSet);
2245 if (aCurrentSet.Extent() > aLargestSet.Extent()) {
2246 aLargestSet = aCurrentSet;
2251 // 4. Report all blocks, isolated from <aLargestSet>
2253 anErr.error = NOT_CONNECTED;
2254 Standard_Boolean hasIsolated = Standard_False;
2255 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2256 if (!aLargestSet.Contains(ibl)) {
2257 aProcessedMap.Clear();
2258 if (!HasAnyConnection(ibl, aLargestSet, aRelations, aProcessedMap)) {
2259 // report connection absence
2260 hasIsolated = Standard_True;
2261 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(ibl)));
2266 isCompOfBlocks = Standard_False;
2267 theErrors.push_back(anErr);
2271 return isCompOfBlocks;
2274 //=============================================================================
2278 //=============================================================================
2279 TCollection_AsciiString GEOMImpl_IBlocksOperations::PrintBCErrors
2280 (Handle(GEOM_Object) theCompound,
2281 const std::list<BCError>& theErrors)
2283 TCollection_AsciiString aDescr;
2285 std::list<BCError>::const_iterator errIt = theErrors.begin();
2287 for (; errIt != theErrors.end(); i++, errIt++) {
2288 BCError errStruct = *errIt;
2290 switch (errStruct.error) {
2292 aDescr += "\n\tNot a Blocks: ";
2295 aDescr += "\n\tHexahedral solids with degenerated and/or seam edges: ";
2297 case INVALID_CONNECTION:
2298 aDescr += "\n\tInvalid connection between two blocks: ";
2301 aDescr += "\n\tBlocks, not connected with main body: ";
2304 aDescr += "\n\tNot glued blocks: ";
2310 std::list<int> sshList = errStruct.incriminated;
2311 std::list<int>::iterator sshIt = sshList.begin();
2313 for (; sshIt != sshList.end(); jj++, sshIt++) {
2316 aDescr += TCollection_AsciiString(*sshIt);
2323 //=============================================================================
2325 * CheckCompoundOfBlocks
2327 //=============================================================================
2328 Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocks
2329 (Handle(GEOM_Object) theCompound,
2330 std::list<BCError>& theErrors)
2334 if (theCompound.IsNull()) return Standard_False;
2335 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2337 Standard_Boolean isCompOfBlocks = Standard_True;
2339 // Map sub-shapes and their indices
2340 TopTools_IndexedMapOfShape anIndices;
2341 TopExp::MapShapes(aBlockOrComp, anIndices);
2343 // 1. Separate blocks from non-blocks
2344 TopTools_ListOfShape NOT; // Not blocks
2345 TopTools_ListOfShape EXT; // Hexahedral solids, having degenerated and/or seam edges
2346 TopTools_ListOfShape BLO; // All blocks from the given compound
2347 TopTools_ListOfShape NOQ; // All non-quadrangular faces
2348 AddBlocksFrom(aBlockOrComp, BLO, NOT, EXT, NOQ);
2350 // Report non-blocks
2351 if (NOT.Extent() > 0) {
2352 isCompOfBlocks = Standard_False;
2354 anErr.error = NOT_BLOCK;
2355 TopTools_ListIteratorOfListOfShape it (NOT);
2356 for (; it.More(); it.Next()) {
2357 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
2359 theErrors.push_back(anErr);
2362 // Report solids, having degenerated and/or seam edges
2363 if (EXT.Extent() > 0) {
2364 isCompOfBlocks = Standard_False;
2366 anErr.error = EXTRA_EDGE;
2367 TopTools_ListIteratorOfListOfShape it (EXT);
2368 for (; it.More(); it.Next()) {
2369 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
2371 theErrors.push_back(anErr);
2374 Standard_Integer nbBlocks = BLO.Extent();
2375 if (nbBlocks == 0) {
2376 isCompOfBlocks = Standard_False;
2378 return isCompOfBlocks;
2380 if (nbBlocks == 1) {
2382 return isCompOfBlocks;
2385 // Prepare data for 2. and 3.
2386 TColStd_Array2OfInteger aRelations (1, nbBlocks, 1, nbBlocks);
2387 aRelations.Init(REL_NOT_CONNECTED);
2389 TopTools_IndexedMapOfShape mapBlocks;
2392 TopoDS_Compound aComp;
2393 BB.MakeCompound(aComp);
2395 TopTools_ListIteratorOfListOfShape BLOit (BLO);
2396 for (; BLOit.More(); BLOit.Next()) {
2397 mapBlocks.Add(BLOit.Value());
2398 BB.Add(aComp, BLOit.Value());
2401 // 2. Find glued blocks (having shared faces)
2402 TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
2403 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2404 (aComp, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
2406 Standard_Integer prevInd = 0, curInd = 0;
2407 Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
2408 for (; ind <= nbFaces; ind++) {
2409 const TopTools_ListOfShape& aGluedBlocks = mapFaceBlocks.FindFromIndex(ind);
2410 if (aGluedBlocks.Extent() > 1) { // Shared face found
2411 TopTools_ListIteratorOfListOfShape aGluedBlocksIt (aGluedBlocks);
2412 TopoDS_Shape prevBlock, curBlock;
2413 for (; aGluedBlocksIt.More(); aGluedBlocksIt.Next()) {
2414 curBlock = aGluedBlocksIt.Value();
2415 if (!prevBlock.IsNull()) {
2416 prevInd = mapBlocks.FindIndex(prevBlock);
2417 curInd = mapBlocks.FindIndex(curBlock);
2418 aRelations.SetValue(prevInd, curInd, REL_OK);
2419 aRelations.SetValue(curInd, prevInd, REL_OK);
2421 prevBlock = curBlock;
2426 // 3. Find not glued blocks
2427 GEOMAlgo_GlueAnalyser aGD;
2429 aGD.SetShape(aComp);
2430 aGD.SetTolerance(Precision::Confusion());
2431 aGD.SetCheckGeometry(Standard_True);
2434 Standard_Integer iErr, iWrn;
2435 iErr = aGD.ErrorStatus();
2437 SetErrorCode("Error in GEOMAlgo_GlueAnalyser");
2438 return isCompOfBlocks;
2440 iWrn = aGD.WarningStatus();
2442 MESSAGE("Warning in GEOMAlgo_GlueAnalyser");
2445 // Report not glued blocks
2446 if (aGD.HasSolidsToGlue()) {
2447 isCompOfBlocks = Standard_False;
2448 Standard_Integer aSx1Ind, aSx2Ind;
2450 const GEOMAlgo_ListOfCoupleOfShapes& aLCS = aGD.SolidsToGlue();
2451 GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS (aLCS);
2452 for (; aItCS.More(); aItCS.Next()) {
2453 const GEOMAlgo_CoupleOfShapes& aCS = aItCS.Value();
2454 const TopoDS_Shape& aSx1 = aCS.Shape1();
2455 const TopoDS_Shape& aSx2 = aCS.Shape2();
2457 aSx1Ind = mapBlocks.FindIndex(aSx1);
2458 aSx2Ind = mapBlocks.FindIndex(aSx2);
2459 aRelations.SetValue(aSx1Ind, aSx2Ind, NOT_GLUED);
2460 aRelations.SetValue(aSx2Ind, aSx1Ind, NOT_GLUED);
2463 anErr.error = NOT_GLUED;
2464 anErr.incriminated.push_back(anIndices.FindIndex(aSx1));
2465 anErr.incriminated.push_back(anIndices.FindIndex(aSx2));
2466 theErrors.push_back(anErr);
2470 // 4. Find largest set of connected (good connection or not glued) blocks
2471 Standard_Integer ibl = 1;
2472 TColStd_MapOfInteger aProcessedMap;
2473 TColStd_MapOfInteger aLargestSet;
2474 TColStd_MapOfInteger aCurrentSet;
2475 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2476 if (!aProcessedMap.Contains(ibl)) {
2477 aCurrentSet.Clear();
2478 FindConnected(ibl, aRelations, aProcessedMap, aCurrentSet);
2479 if (aCurrentSet.Extent() > aLargestSet.Extent()) {
2480 aLargestSet = aCurrentSet;
2485 // 5. Report all blocks, isolated from <aLargestSet>
2487 anErr.error = NOT_CONNECTED;
2488 Standard_Boolean hasIsolated = Standard_False;
2489 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2490 if (!aLargestSet.Contains(ibl)) {
2491 aProcessedMap.Clear();
2492 if (!HasAnyConnection(ibl, aLargestSet, aRelations, aProcessedMap)) {
2493 // report connection absence
2494 hasIsolated = Standard_True;
2495 anErr.incriminated.push_back(anIndices.FindIndex(mapBlocks.FindKey(ibl)));
2500 isCompOfBlocks = Standard_False;
2501 theErrors.push_back(anErr);
2505 return isCompOfBlocks;
2508 //=============================================================================
2512 //=============================================================================
2513 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetNonBlocks
2514 (Handle(GEOM_Object) theShape,
2515 Handle(GEOM_Object)& theNonQuads)
2519 if (theShape.IsNull()) return NULL;
2520 TopoDS_Shape aShape = theShape->GetValue();
2522 // Separate blocks from non-blocks
2523 TopTools_ListOfShape BLO; // All blocks from the given compound
2524 TopTools_ListOfShape NOT; // Not blocks
2525 TopTools_ListOfShape EXT; // Hexahedral solids, having degenerated and/or seam edges
2526 TopTools_ListOfShape NOQ; // All non-quadrangular faces
2527 AddBlocksFrom(aShape, BLO, NOT, EXT, NOQ);
2529 if (NOT.IsEmpty() && EXT.IsEmpty() && NOQ.IsEmpty()) {
2530 SetErrorCode("NOT_FOUND_ANY");
2534 // Map sub-shapes and their indices
2535 TopTools_IndexedMapOfShape anIndices;
2536 TopExp::MapShapes(aShape, anIndices);
2539 Handle(GEOM_Object) aNonBlocks;
2540 if (NOT.Extent() > 0 || EXT.Extent() > 0) {
2541 Handle(TColStd_HArray1OfInteger) anArray =
2542 new TColStd_HArray1OfInteger (1, NOT.Extent() + EXT.Extent());
2543 Standard_Integer ii = 1;
2544 TopTools_ListIteratorOfListOfShape it1 (NOT);
2545 for (; it1.More(); it1.Next(), ii++) {
2546 anArray->SetValue(ii, anIndices.FindIndex(it1.Value()));
2548 TopTools_ListIteratorOfListOfShape it2 (EXT);
2549 for (; it2.More(); it2.Next(), ii++) {
2550 anArray->SetValue(ii, anIndices.FindIndex(it2.Value()));
2553 aNonBlocks = GetEngine()->AddSubShape(theShape, anArray);
2554 if (aNonBlocks.IsNull()) {
2555 SetErrorCode("Error in algorithm: result found, but cannot be returned.");
2558 aNonBlocks->SetType(GEOM_GROUP);
2559 TDF_Label aFreeLabel = aNonBlocks->GetFreeLabel();
2560 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)TopAbs_SOLID);
2564 if (NOQ.Extent() > 0) {
2565 Handle(TColStd_HArray1OfInteger) anArray =
2566 new TColStd_HArray1OfInteger (1, NOQ.Extent());
2567 Standard_Integer ii = 1;
2568 TopTools_ListIteratorOfListOfShape it1 (NOQ);
2569 for (; it1.More(); it1.Next(), ii++) {
2570 anArray->SetValue(ii, anIndices.FindIndex(it1.Value()));
2573 theNonQuads = GetEngine()->AddSubShape(theShape, anArray);
2574 if (theNonQuads.IsNull()) {
2575 SetErrorCode("Error in algorithm: result found, but cannot be returned.");
2578 theNonQuads->SetType(GEOM_GROUP);
2579 TDF_Label aFreeLabel = theNonQuads->GetFreeLabel();
2580 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)TopAbs_FACE);
2583 //Make a Python command
2584 Handle(GEOM_Function) aMainShape = theShape->GetLastFunction();
2585 GEOM::TPythonDump pd (aMainShape, /*append=*/true);
2587 if (aNonBlocks.IsNull())
2588 pd << "no_bad_solids";
2592 if (theNonQuads.IsNull())
2593 pd << "no_bad_faces";
2596 pd << ") = geompy.GetNonBlocks(" << theShape << ")";
2602 //=============================================================================
2606 //=============================================================================
2607 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::RemoveExtraEdges
2608 (Handle(GEOM_Object) theObject,
2609 const Standard_Integer theOptimumNbFaces)
2613 if (theObject.IsNull()) return NULL;
2615 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2616 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be fixed
2618 //Add a new Copy object
2619 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2622 Handle(GEOM_Function) aFunction =
2623 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_REMOVE_EXTRA);
2625 //Check if the function is set correctly
2626 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2628 GEOMImpl_IBlockTrsf aTI (aFunction);
2629 aTI.SetOriginal(aLastFunction);
2630 aTI.SetOptimumNbFaces(theOptimumNbFaces);
2632 //Compute the fixed shape
2634 #if OCC_VERSION_LARGE > 0x06010000
2637 if (!GetSolver()->ComputeFunction(aFunction)) {
2638 SetErrorCode("Block driver failed to remove extra edges of the given shape");
2642 catch (Standard_Failure) {
2643 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2644 SetErrorCode(aFail->GetMessageString());
2648 //Make a Python command
2649 std::string doUnionFaces = (theOptimumNbFaces < 0) ? "False" : "True";
2650 GEOM::TPythonDump(aFunction) << aCopy << " = geompy.RemoveExtraEdges("
2651 << theObject << ", " << doUnionFaces.data() << ")";
2657 //=============================================================================
2661 //=============================================================================
2662 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::UnionFaces
2663 (Handle(GEOM_Object) theObject)
2667 if (theObject.IsNull()) return NULL;
2669 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2670 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be fixed
2672 //Add a new Copy object
2673 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2676 Handle(GEOM_Function) aFunction =
2677 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_UNION_FACES);
2679 //Check if the function is set correctly
2680 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2682 GEOMImpl_IBlockTrsf aTI (aFunction);
2683 aTI.SetOriginal(aLastFunction);
2685 //Compute the fixed shape
2687 #if OCC_VERSION_LARGE > 0x06010000
2690 if (!GetSolver()->ComputeFunction(aFunction)) {
2691 SetErrorCode("Block driver failed to remove extra edges of the given shape");
2695 catch (Standard_Failure) {
2696 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2697 SetErrorCode(aFail->GetMessageString());
2701 //Make a Python command
2702 GEOM::TPythonDump(aFunction) << aCopy << " = geompy.UnionFaces("
2703 << theObject << ")";
2709 //=============================================================================
2713 //=============================================================================
2714 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::CheckAndImprove
2715 (Handle(GEOM_Object) theObject)
2719 if (theObject.IsNull()) return NULL;
2721 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2722 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be fixed
2724 //Add a new Copy object
2725 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2728 Handle(GEOM_Function) aFunction =
2729 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_COMPOUND_IMPROVE);
2731 //Check if the function is set correctly
2732 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2734 GEOMImpl_IBlockTrsf aTI (aFunction);
2735 aTI.SetOriginal(aLastFunction);
2737 // -1 means do not unite faces on common surface (?except case of seam edge between them?)
2738 //aTI.SetOptimumNbFaces(-1);
2739 aTI.SetOptimumNbFaces(6);
2741 //Compute the fixed shape
2743 #if OCC_VERSION_LARGE > 0x06010000
2746 if (!GetSolver()->ComputeFunction(aFunction)) {
2747 SetErrorCode("Block driver failed to improve the given blocks compound");
2751 catch (Standard_Failure) {
2752 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2753 SetErrorCode(aFail->GetMessageString());
2757 //Make a Python command
2758 GEOM::TPythonDump(aFunction) << aCopy
2759 << " = geompy.CheckAndImprove(" << theObject << ")";
2765 //=============================================================================
2767 * ExplodeCompoundOfBlocks
2769 //=============================================================================
2770 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::ExplodeCompoundOfBlocks
2771 (Handle(GEOM_Object) theCompound,
2772 const Standard_Integer theMinNbFaces,
2773 const Standard_Integer theMaxNbFaces)
2777 if (theCompound.IsNull()) return NULL;
2778 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2779 if (aBlockOrComp.IsNull()) return NULL;
2781 Handle(TColStd_HSequenceOfTransient) aBlocks = new TColStd_HSequenceOfTransient;
2782 Handle(GEOM_Object) anObj;
2783 Handle(GEOM_Function) aFunction;
2785 TopTools_MapOfShape mapShape;
2786 TCollection_AsciiString anAsciiList, anEntry;
2789 TopTools_IndexedMapOfShape anIndices;
2790 TopExp::MapShapes(aBlockOrComp, anIndices);
2791 Handle(TColStd_HArray1OfInteger) anArray;
2795 #if OCC_VERSION_LARGE > 0x06010000
2798 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2799 for (; exp.More(); exp.Next()) {
2800 if (mapShape.Add(exp.Current())) {
2801 TopoDS_Shape aSolid = exp.Current();
2803 TopTools_MapOfShape mapFaces;
2804 TopExp_Explorer expF (aSolid, TopAbs_FACE);
2805 Standard_Integer nbFaces = 0;
2806 for (; expF.More(); expF.Next()) {
2807 if (mapFaces.Add(expF.Current())) {
2812 if (theMinNbFaces <= nbFaces && nbFaces <= theMaxNbFaces) {
2813 anArray = new TColStd_HArray1OfInteger(1,1);
2814 anArray->SetValue(1, anIndices.FindIndex(aSolid));
2815 anObj = GetEngine()->AddSubShape(theCompound, anArray);
2816 aBlocks->Append(anObj);
2818 //Make a Python command
2819 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2820 anAsciiList += anEntry + ", ";
2825 catch (Standard_Failure) {
2826 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2827 SetErrorCode(aFail->GetMessageString());
2831 if (aBlocks->IsEmpty()) {
2832 SetErrorCode("There are no specified blocks in the given shape");
2836 anAsciiList.Trunc(anAsciiList.Length() - 2);
2838 //The explode doesn't change object so no new function is required.
2839 aFunction = theCompound->GetLastFunction();
2841 //Make a Python command
2842 GEOM::TPythonDump(aFunction, /*append=*/true)
2843 << "[" << anAsciiList.ToCString() << "] = geompy.MakeBlockExplode("
2844 << theCompound << ", " << theMinNbFaces << ", " << theMaxNbFaces << ")";
2850 //=============================================================================
2854 //=============================================================================
2855 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetBlockNearPoint
2856 (Handle(GEOM_Object) theCompound,
2857 Handle(GEOM_Object) thePoint)
2862 Handle(GEOM_Object) aResult;
2865 if (theCompound.IsNull() || thePoint.IsNull()) return NULL;
2867 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2868 if (aBlockOrComp.IsNull()) {
2869 SetErrorCode("Compound is null");
2872 if (aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
2873 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
2874 SetErrorCode("Shape to find block in is not a compound");
2878 TopoDS_Shape anArg = thePoint->GetValue();
2879 if (anArg.IsNull()) {
2880 SetErrorCode("Point is null");
2883 if (anArg.ShapeType() != TopAbs_VERTEX) {
2884 SetErrorCode("Shape for block identification is not a vertex");
2888 //Compute the Block value
2890 #if OCC_VERSION_LARGE > 0x06010000
2893 TopoDS_Shape aShape;
2895 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
2896 gp_Pnt aPnt = BRep_Tool::Pnt(aVert);
2897 Standard_Real PX, PY, PZ;
2898 aPnt.Coord(PX, PY, PZ);
2900 // 1. Classify the point relatively each block
2901 Standard_Integer nearest = 2, nbFound = 0;
2902 TopTools_DataMapOfShapeInteger mapShapeDist;
2903 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2904 for (; exp.More(); exp.Next()) {
2905 TopoDS_Shape aSolid = exp.Current();
2907 if (!mapShapeDist.IsBound(aSolid)) {
2908 Standard_Integer aDistance = 2;
2910 // 1.a. Classify relatively Bounding box
2911 Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
2913 BRepBndLib::Add(aSolid, BB);
2914 BB.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
2915 if (PX < Xmin || Xmax < PX ||
2916 PY < Ymin || Ymax < PY ||
2917 PZ < Zmin || Zmax < PZ) {
2918 // OUT of bounding box
2921 // 1.b. Classify relatively the solid itself
2922 BRepClass3d_SolidClassifier SC (aSolid, aPnt, Precision::Confusion());
2923 if (SC.State() == TopAbs_IN) {
2925 } else if (SC.State() == TopAbs_ON) {
2932 if (aDistance < nearest) {
2933 nearest = aDistance;
2937 // A first found block, containing the point inside, will be returned.
2938 // It is the solution, if there are no intersecting blocks in the compound.
2939 if (nearest == -1) break;
2941 } else if (aDistance == nearest) {
2946 mapShapeDist.Bind(aSolid, aDistance);
2947 } // if (!mapShapeDist.IsBound(aSolid))
2950 // 2. Define block, containing the point or having minimum distance to it
2953 // The point is on boundary of some blocks and there are
2954 // no blocks, having the point inside their volume
2955 SetErrorCode("Multiple blocks near the given point are found");
2958 } else if (nearest == 1) {
2959 // The point is outside some blocks and there are
2960 // no blocks, having the point inside or on boundary.
2961 // We will get a nearest block
2962 Standard_Real minDist = RealLast();
2963 TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
2964 for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
2965 if (mapShapeDistIter.Value() == 1) {
2966 TopoDS_Shape aSolid = mapShapeDistIter.Key();
2967 BRepExtrema_DistShapeShape aDistTool (aVert, aSolid);
2968 if (!aDistTool.IsDone()) {
2969 SetErrorCode("Can not find a distance from the given point to one of blocks");
2972 Standard_Real aDist = aDistTool.Value();
2973 if (aDist < minDist) {
2979 } else { // nearest == -1
2980 // // The point is inside some blocks.
2981 // // We will get a block with nearest center
2982 // Standard_Real minDist = RealLast();
2983 // TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
2984 // for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
2985 // if (mapShapeDistIter.Value() == -1) {
2986 // TopoDS_Shape aSolid = mapShapeDistIter.Key();
2987 // GProp_GProps aSystem;
2988 // BRepGProp::VolumeProperties(aSolid, aSystem);
2989 // gp_Pnt aCenterMass = aSystem.CentreOfMass();
2991 // Standard_Real aDist = aCenterMass.Distance(aPnt);
2992 // if (aDist < minDist) {
2999 } // if (nbFound > 1)
3002 SetErrorCode("There are no blocks near the given point");
3005 TopTools_IndexedMapOfShape anIndices;
3006 TopExp::MapShapes(aBlockOrComp, anIndices);
3007 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
3008 anArray->SetValue(1, anIndices.FindIndex(aShape));
3009 aResult = GetEngine()->AddSubShape(theCompound, anArray);
3012 catch (Standard_Failure) {
3013 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3014 SetErrorCode(aFail->GetMessageString());
3018 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
3020 //Make a Python command
3021 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetBlockNearPoint("
3022 << theCompound << ", " << thePoint << ")";
3028 //=============================================================================
3032 //=============================================================================
3033 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetBlockByParts
3034 (Handle(GEOM_Object) theCompound,
3035 const Handle(TColStd_HSequenceOfTransient)& theParts)
3039 Handle(GEOM_Object) aResult;
3041 if (theCompound.IsNull() || theParts.IsNull()) return NULL;
3042 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
3043 if (aBlockOrComp.IsNull()) return NULL;
3046 Standard_Integer argi, aLen = theParts->Length();
3047 TopTools_Array1OfShape anArgs (1, aLen);
3048 TCollection_AsciiString anEntry, aPartsDescr;
3049 for (argi = 1; argi <= aLen; argi++) {
3050 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theParts->Value(argi));
3051 Handle(GEOM_Function) aRef = anObj->GetLastFunction();
3052 if (aRef.IsNull()) return NULL;
3054 TopoDS_Shape anArg = aRef->GetValue();
3055 if (anArg.IsNull()) {
3056 SetErrorCode("Null shape is given as argument");
3059 anArgs(argi) = anArg;
3061 // For Python command
3062 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
3063 if (argi > 1) aPartsDescr += ", ";
3064 aPartsDescr += anEntry;
3067 //Compute the Block value
3069 #if OCC_VERSION_LARGE > 0x06010000
3072 // 1. Explode compound on solids
3073 TopTools_MapOfShape mapShape;
3074 Standard_Integer nbSolids = 0;
3075 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
3076 for (; exp.More(); exp.Next()) {
3077 if (mapShape.Add(exp.Current())) {
3083 Standard_Integer ind = 1;
3084 TopTools_Array1OfShape aSolids (1, nbSolids);
3085 TColStd_Array1OfInteger aNbParts (1, nbSolids);
3086 for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next(), ind++) {
3087 if (mapShape.Add(exp.Current())) {
3088 TopoDS_Shape aSolid = exp.Current();
3089 aSolids(ind) = aSolid;
3092 // 2. Define quantity of parts, contained in each solid
3093 TopTools_IndexedMapOfShape aSubShapes;
3094 TopExp::MapShapes(aSolid, aSubShapes);
3095 for (argi = 1; argi <= aLen; argi++) {
3096 if (aSubShapes.Contains(anArgs(argi))) {
3103 // 3. Define solid, containing maximum quantity of parts
3104 Standard_Integer maxNb = 0, nbFound = 0;
3105 TopoDS_Shape aShape;
3106 for (ind = 1; ind <= nbSolids; ind++) {
3107 if (aNbParts(ind) > maxNb) {
3108 maxNb = aNbParts(ind);
3109 aShape = aSolids(ind);
3111 } else if (aNbParts(ind) == maxNb) {
3117 SetErrorCode("Multiple blocks, containing maximum quantity of the given parts, are found");
3119 } else if (nbFound == 0) {
3120 SetErrorCode("There are no blocks, containing the given parts");
3123 TopTools_IndexedMapOfShape anIndices;
3124 TopExp::MapShapes(aBlockOrComp, anIndices);
3125 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
3126 anArray->SetValue(1, anIndices.FindIndex(aShape));
3127 aResult = GetEngine()->AddSubShape(theCompound, anArray);
3129 } catch (Standard_Failure) {
3130 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3131 SetErrorCode(aFail->GetMessageString());
3135 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
3137 //Make a Python command
3138 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetBlockByParts("
3139 << theCompound << ", [" << aPartsDescr.ToCString() << "])";
3145 //=============================================================================
3149 //=============================================================================
3150 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::GetBlocksByParts
3151 (Handle(GEOM_Object) theCompound,
3152 const Handle(TColStd_HSequenceOfTransient)& theParts)
3156 if (theCompound.IsNull() || theParts.IsNull()) return NULL;
3157 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
3158 if (aBlockOrComp.IsNull()) return NULL;
3160 Handle(TColStd_HSequenceOfTransient) aBlocks = new TColStd_HSequenceOfTransient;
3161 Handle(GEOM_Object) anObj;
3162 Handle(GEOM_Function) aFunction;
3165 Standard_Integer argi, aLen = theParts->Length();
3166 TopTools_Array1OfShape anArgs (1, aLen);
3167 TCollection_AsciiString anEntry, aPartsDescr, anAsciiList;
3169 for (argi = 1; argi <= aLen; argi++) {
3170 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theParts->Value(argi));
3171 Handle(GEOM_Function) aRef = anObj->GetLastFunction();
3172 if (aRef.IsNull()) return NULL;
3174 TopoDS_Shape anArg = aRef->GetValue();
3175 if (anArg.IsNull()) {
3176 SetErrorCode("Null shape is given as argument");
3179 anArgs(argi) = anArg;
3181 // For Python command
3182 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
3183 aPartsDescr += anEntry + ", ";
3188 #if OCC_VERSION_LARGE > 0x06010000
3191 TopTools_MapOfShape mapShape;
3192 Standard_Integer nbSolids = 0;
3193 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
3194 for (; exp.More(); exp.Next()) {
3195 if (mapShape.Add(exp.Current())) {
3201 Standard_Integer ind = 1;
3202 TopTools_Array1OfShape aSolids (1, nbSolids);
3203 TColStd_Array1OfInteger aNbParts (1, nbSolids);
3204 for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next(), ind++) {
3205 if (mapShape.Add(exp.Current())) {
3206 TopoDS_Shape aSolid = exp.Current();
3207 aSolids(ind) = aSolid;
3210 // 2. Define quantity of parts, contained in each solid
3211 TopTools_IndexedMapOfShape aSubShapes;
3212 TopExp::MapShapes(aSolid, aSubShapes);
3213 for (argi = 1; argi <= aLen; argi++) {
3214 if (aSubShapes.Contains(anArgs(argi))) {
3221 // 3. Define solid, containing maximum quantity of parts
3222 Standard_Integer maxNb = 0, nbFound = 0;
3223 for (ind = 1; ind <= nbSolids; ind++) {
3224 if (aNbParts(ind) > maxNb) {
3225 maxNb = aNbParts(ind);
3227 } else if (aNbParts(ind) == maxNb) {
3233 SetErrorCode("There are no blocks, containing the given parts");
3238 TopTools_IndexedMapOfShape anIndices;
3239 TopExp::MapShapes(aBlockOrComp, anIndices);
3240 Handle(TColStd_HArray1OfInteger) anArray;
3242 for (ind = 1; ind <= nbSolids; ind++) {
3243 if (aNbParts(ind) == maxNb) {
3244 anArray = new TColStd_HArray1OfInteger(1,1);
3245 anArray->SetValue(1, anIndices.FindIndex(aSolids(ind)));
3246 anObj = GetEngine()->AddSubShape(theCompound, anArray);
3247 aBlocks->Append(anObj);
3249 // For Python command
3250 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
3251 anAsciiList += anEntry + ", ";
3252 if (aFunction.IsNull())
3253 aFunction = anObj->GetLastFunction();
3257 catch (Standard_Failure) {
3258 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3259 SetErrorCode(aFail->GetMessageString());
3263 //Make a Python command
3264 aPartsDescr.Trunc(aPartsDescr.Length() - 2);
3265 anAsciiList.Trunc(anAsciiList.Length() - 2);
3267 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3268 << "] = geompy.GetBlocksByParts(" << theCompound
3269 << ", [" << aPartsDescr.ToCString() << "])";
3275 //=============================================================================
3277 * MakeMultiTransformation1D
3279 //=============================================================================
3280 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeMultiTransformation1D
3281 (Handle(GEOM_Object) theObject,
3282 const Standard_Integer theDirFace1,
3283 const Standard_Integer theDirFace2,
3284 const Standard_Integer theNbTimes)
3288 if (theObject.IsNull()) return NULL;
3290 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
3291 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be moved
3293 //Add a new Copy object
3294 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
3296 //Add a translate function
3297 Handle(GEOM_Function) aFunction =
3298 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_MULTI_TRANSFORM_1D);
3300 //Check if the function is set correctly
3301 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
3303 GEOMImpl_IBlockTrsf aTI (aFunction);
3304 aTI.SetOriginal(aLastFunction);
3305 aTI.SetFace1U(theDirFace1);
3306 aTI.SetFace2U(theDirFace2);
3307 aTI.SetNbIterU(theNbTimes);
3309 //Compute the transformation
3311 #if OCC_VERSION_LARGE > 0x06010000
3314 if (!GetSolver()->ComputeFunction(aFunction)) {
3315 SetErrorCode("Block driver failed to make multi-transformation");
3319 catch (Standard_Failure) {
3320 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3321 SetErrorCode(aFail->GetMessageString());
3325 //Make a Python command
3326 GEOM::TPythonDump(aFunction) << aCopy << " = geompy.MakeMultiTransformation1D("
3327 << theObject << ", " << theDirFace1 << ", " << theDirFace2 << ", " << theNbTimes << ")";
3333 //=============================================================================
3335 * MakeMultiTransformation2D
3337 //=============================================================================
3338 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeMultiTransformation2D
3339 (Handle(GEOM_Object) theObject,
3340 const Standard_Integer theDirFace1U,
3341 const Standard_Integer theDirFace2U,
3342 const Standard_Integer theNbTimesU,
3343 const Standard_Integer theDirFace1V,
3344 const Standard_Integer theDirFace2V,
3345 const Standard_Integer theNbTimesV)
3349 if (theObject.IsNull()) return NULL;
3351 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
3352 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be moved
3354 //Add a new Copy object
3355 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
3357 //Add a translate function
3358 Handle(GEOM_Function) aFunction =
3359 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_MULTI_TRANSFORM_2D);
3361 //Check if the function is set correctly
3362 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
3364 GEOMImpl_IBlockTrsf aTI (aFunction);
3365 aTI.SetOriginal(aLastFunction);
3366 aTI.SetFace1U(theDirFace1U);
3367 aTI.SetFace2U(theDirFace2U);
3368 aTI.SetNbIterU(theNbTimesU);
3369 aTI.SetFace1V(theDirFace1V);
3370 aTI.SetFace2V(theDirFace2V);
3371 aTI.SetNbIterV(theNbTimesV);
3373 //Compute the transformation
3375 #if OCC_VERSION_LARGE > 0x06010000
3378 if (!GetSolver()->ComputeFunction(aFunction)) {
3379 SetErrorCode("Block driver failed to make multi-transformation");
3383 catch (Standard_Failure) {
3384 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3385 SetErrorCode(aFail->GetMessageString());
3389 //Make a Python command
3390 GEOM::TPythonDump(aFunction) << aCopy << " = geompy.MakeMultiTransformation2D("
3391 << theObject << ", " << theDirFace1U << ", " << theDirFace2U << ", " << theNbTimesU
3392 << ", " << theDirFace1V << ", " << theDirFace2V << ", " << theNbTimesV << ")";
3398 //=============================================================================
3402 //=============================================================================
3403 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::Propagate
3404 (Handle(GEOM_Object) theShape)
3408 if (theShape.IsNull()) return NULL;
3410 TopoDS_Shape aShape = theShape->GetValue();
3411 if (aShape.IsNull()) return NULL;
3413 TopTools_IndexedMapOfShape anIndices;
3414 TopExp::MapShapes(aShape, anIndices);
3416 TopTools_IndexedDataMapOfShapeListOfShape MEW;
3417 GEOMImpl_Block6Explorer::MapShapesAndAncestors
3418 (aShape, TopAbs_EDGE, TopAbs_WIRE, MEW);
3419 Standard_Integer ie, nbEdges = MEW.Extent();
3422 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
3424 TopTools_MapOfShape mapAcceptedEdges;
3425 TCollection_AsciiString aListRes, anEntry;
3427 // Sort shapes in current chain (Mantis issue 21053)
3428 TopTools_DataMapOfShapeListOfShape aMapChains;
3429 TopTools_ListOfShape aFirstInChains;
3431 for (ie = 1; ie <= nbEdges; ie++) {
3432 TopoDS_Shape curE = MEW.FindKey(ie);
3434 if (mapAcceptedEdges.Contains(curE)) continue;
3437 TopTools_ListOfShape currentChain;
3438 TopTools_ListOfShape listPrevEdges;
3440 currentChain.Append(curE);
3441 listPrevEdges.Append(curE);
3442 mapAcceptedEdges.Add(curE);
3444 // Collect all edges pass by pass
3445 while (listPrevEdges.Extent() > 0) {
3446 // List of edges, added to chain on this cycle pass
3447 TopTools_ListOfShape listCurEdges;
3449 // Find the next portion of edges
3450 TopTools_ListIteratorOfListOfShape itE (listPrevEdges);
3451 for (; itE.More(); itE.Next()) {
3452 TopoDS_Shape anE = itE.Value();
3454 // Iterate on faces, having edge <anE>
3455 TopTools_ListIteratorOfListOfShape itW (MEW.FindFromKey(anE));
3456 for (; itW.More(); itW.Next()) {
3457 TopoDS_Shape aW = itW.Value();
3458 TopoDS_Shape anOppE;
3460 BRepTools_WireExplorer aWE (TopoDS::Wire(aW));
3461 Standard_Integer nb = 1, found = 0;
3462 TopTools_Array1OfShape anEdges (1,4);
3463 for (; aWE.More(); aWE.Next(), nb++) {
3468 anEdges(nb) = aWE.Current();
3469 if (anEdges(nb).IsSame(anE)) found = nb;
3472 if (nb == 5 && found > 0) {
3473 // Quadrangle face found, get an opposite edge
3474 Standard_Integer opp = found + 2;
3475 if (opp > 4) opp -= 4;
3476 anOppE = anEdges(opp);
3478 if (!mapAcceptedEdges.Contains(anOppE)) {
3479 // Add found edge to the chain
3480 currentChain.Append(anOppE);
3481 listCurEdges.Append(anOppE);
3482 mapAcceptedEdges.Add(anOppE);
3484 } // if (nb == 5 && found > 0)
3485 } // for (; itF.More(); itF.Next())
3486 } // for (; itE.More(); itE.Next())
3488 listPrevEdges = listCurEdges;
3489 } // while (listPrevEdges.Extent() > 0)
3491 // Sort shapes in current chain (Mantis issue 21053)
3492 GEOMUtils::SortShapes(currentChain, Standard_False);
3493 aFirstInChains.Append(currentChain.First());
3494 aMapChains.Bind(currentChain.First(), currentChain);
3497 // Sort chains (Mantis issue 21053)
3498 GEOMUtils::SortShapes(aFirstInChains, Standard_False);
3500 // Store sorted chains in the document
3501 TopTools_ListIteratorOfListOfShape aChainsIt (aFirstInChains);
3502 for (; aChainsIt.More(); aChainsIt.Next()) {
3503 TopoDS_Shape aFirstInChain = aChainsIt.Value();
3504 const TopTools_ListOfShape& currentChain = aMapChains.Find(aFirstInChain);
3506 // Store the chain in the document
3507 Handle(TColStd_HArray1OfInteger) anArray =
3508 new TColStd_HArray1OfInteger (1, currentChain.Extent());
3510 // Fill array of sub-shape indices
3511 TopTools_ListIteratorOfListOfShape itSub (currentChain);
3512 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
3513 int id = anIndices.FindIndex(itSub.Value());
3514 anArray->SetValue(index, id);
3517 // Add a new group object
3518 Handle(GEOM_Object) aChain = GetEngine()->AddSubShape(theShape, anArray);
3521 aChain->SetType(GEOM_GROUP);
3523 // Set a sub-shape type
3524 TDF_Label aFreeLabel = aChain->GetFreeLabel();
3525 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)TopAbs_EDGE);
3527 // Add the chain to the result
3528 aSeq->Append(aChain);
3530 //Make a Python command
3531 TDF_Tool::Entry(aChain->GetEntry(), anEntry);
3532 aListRes += anEntry + ", ";
3535 if (aSeq->IsEmpty()) {
3536 SetErrorCode("There are no quadrangle faces in the shape");
3540 aListRes.Trunc(aListRes.Length() - 2);
3542 // The Propagation doesn't change object so no new function is required.
3543 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
3545 // Make a Python command
3546 GEOM::TPythonDump(aFunction, /*append=*/true)
3547 << "[" << aListRes.ToCString() << "] = geompy.Propagate(" << theShape << ")";