1 // Copyright (C) 2007-2014 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, or (at your option) any later version.
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_Block6Explorer.hxx>
38 #include <GEOMUtils.hxx>
40 #include <GEOM_Function.hxx>
41 #include <GEOM_PythonDump.hxx>
43 #include <GEOMAlgo_GlueAnalyser.hxx>
44 #include <GEOMAlgo_CoupleOfShapes.hxx>
45 #include <GEOMAlgo_ListOfCoupleOfShapes.hxx>
46 #include <GEOMAlgo_ListIteratorOfListOfCoupleOfShapes.hxx>
47 #include <BlockFix_CheckTool.hxx>
49 #include <Basics_OCCTVersion.hxx>
51 #include "utilities.h"
53 #include <Utils_ExceptHandlers.hxx>
55 #include <TFunction_DriverTable.hxx>
56 #include <TFunction_Driver.hxx>
57 #include <TFunction_Logbook.hxx>
58 #include <TDataStd_Integer.hxx>
59 #include <TDF_Tool.hxx>
61 #include <BRep_Tool.hxx>
62 #include <BRep_Builder.hxx>
63 #include <BRepTools.hxx>
64 #include <BRepTools_WireExplorer.hxx>
65 #include <BRepGProp.hxx>
66 #include <BRepBndLib.hxx>
67 #include <BRepAdaptor_Surface.hxx>
68 #include <BRepClass_FaceClassifier.hxx>
69 #include <BRepClass3d_SolidClassifier.hxx>
70 #include <BRepExtrema_DistShapeShape.hxx>
74 #include <TopoDS_Edge.hxx>
75 #include <TopoDS_Vertex.hxx>
76 #include <TopoDS_Compound.hxx>
77 #include <TopoDS_Iterator.hxx>
79 #include <TopExp_Explorer.hxx>
80 #include <TopTools_MapOfShape.hxx>
81 #include <TopTools_Array1OfShape.hxx>
82 #include <TopTools_IndexedMapOfShape.hxx>
83 #include <TopTools_DataMapOfShapeInteger.hxx>
84 #include <TopTools_ListIteratorOfListOfShape.hxx>
85 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
86 #include <TopTools_DataMapIteratorOfDataMapOfShapeInteger.hxx>
88 #include <Bnd_Box.hxx>
89 #include <GProp_GProps.hxx>
91 #include <Geom_Surface.hxx>
92 #include <ShapeAnalysis_Surface.hxx>
94 #include <TColStd_MapOfInteger.hxx>
95 #include <TColStd_Array1OfReal.hxx>
96 #include <TColStd_Array1OfInteger.hxx>
97 #include <TColStd_Array2OfInteger.hxx>
99 //#include <OSD_Timer.hxx>
101 #include <Precision.hxx>
103 #include <Standard_Failure.hxx>
104 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
106 //=============================================================================
110 //=============================================================================
111 GEOMImpl_IBlocksOperations::GEOMImpl_IBlocksOperations (GEOM_Engine* theEngine, int theDocID)
112 : GEOM_IOperations(theEngine, theDocID)
114 MESSAGE("GEOMImpl_IBlocksOperations::GEOMImpl_IBlocksOperations");
117 //=============================================================================
121 //=============================================================================
122 GEOMImpl_IBlocksOperations::~GEOMImpl_IBlocksOperations()
124 MESSAGE("GEOMImpl_IBlocksOperations::~GEOMImpl_IBlocksOperations");
128 //=============================================================================
132 //=============================================================================
133 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad
134 (Handle(GEOM_Object) theEdge1, Handle(GEOM_Object) theEdge2,
135 Handle(GEOM_Object) theEdge3, Handle(GEOM_Object) theEdge4)
139 if (theEdge1.IsNull() || theEdge2.IsNull() ||
140 theEdge3.IsNull() || theEdge4.IsNull()) return NULL;
142 //Add a new Face object
143 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
145 //Add a new Face function
146 Handle(GEOM_Function) aFunction =
147 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_FOUR_EDGES);
149 //Check if the function is set correctly
150 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
152 GEOMImpl_IBlocks aPI (aFunction);
154 Handle(GEOM_Function) aRef1 = theEdge1->GetLastFunction();
155 Handle(GEOM_Function) aRef2 = theEdge2->GetLastFunction();
156 Handle(GEOM_Function) aRef3 = theEdge3->GetLastFunction();
157 Handle(GEOM_Function) aRef4 = theEdge4->GetLastFunction();
158 if (aRef1.IsNull() || aRef2.IsNull() ||
159 aRef3.IsNull() || aRef4.IsNull()) return NULL;
161 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
162 aShapesSeq->Append(aRef1);
163 aShapesSeq->Append(aRef2);
164 aShapesSeq->Append(aRef3);
165 aShapesSeq->Append(aRef4);
167 aPI.SetShapes(aShapesSeq);
169 //Compute the Face value
171 #if OCC_VERSION_LARGE > 0x06010000
174 if (!GetSolver()->ComputeFunction(aFunction)) {
175 SetErrorCode("Block driver failed to compute a face");
179 catch (Standard_Failure) {
180 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
181 SetErrorCode(aFail->GetMessageString());
185 //Make a Python command
186 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeQuad("
187 << theEdge1 << ", " << theEdge2 << ", " << theEdge3 << ", " << theEdge4 << ")";
193 //=============================================================================
197 //=============================================================================
198 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad2Edges
199 (Handle(GEOM_Object) theEdge1, Handle(GEOM_Object) theEdge2)
203 if (theEdge1.IsNull() || theEdge2.IsNull()) return NULL;
205 //Add a new Face object
206 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
208 //Add a new Face function
209 Handle(GEOM_Function) aFunction =
210 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_TWO_EDGES);
212 //Check if the function is set correctly
213 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
215 GEOMImpl_IBlocks aPI (aFunction);
217 Handle(GEOM_Function) aRef1 = theEdge1->GetLastFunction();
218 Handle(GEOM_Function) aRef2 = theEdge2->GetLastFunction();
219 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
221 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
222 aShapesSeq->Append(aRef1);
223 aShapesSeq->Append(aRef2);
225 aPI.SetShapes(aShapesSeq);
227 //Compute the Face value
229 #if OCC_VERSION_LARGE > 0x06010000
232 if (!GetSolver()->ComputeFunction(aFunction)) {
233 SetErrorCode("Block driver failed to compute a face");
237 catch (Standard_Failure) {
238 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
239 SetErrorCode(aFail->GetMessageString());
243 //Make a Python command
244 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeQuad2Edges("
245 << theEdge1 << ", " << theEdge2 << ")";
251 //=============================================================================
255 //=============================================================================
256 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad4Vertices
257 (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2,
258 Handle(GEOM_Object) thePnt3, Handle(GEOM_Object) thePnt4)
262 if (thePnt1.IsNull() || thePnt2.IsNull() ||
263 thePnt3.IsNull() || thePnt4.IsNull()) return NULL;
265 //Add a new Face object
266 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
268 //Add a new Face function
269 Handle(GEOM_Function) aFunction =
270 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_FOUR_PNT);
272 //Check if the function is set correctly
273 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
275 GEOMImpl_IBlocks aPI (aFunction);
277 Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
278 Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
279 Handle(GEOM_Function) aRef3 = thePnt3->GetLastFunction();
280 Handle(GEOM_Function) aRef4 = thePnt4->GetLastFunction();
281 if (aRef1.IsNull() || aRef2.IsNull() ||
282 aRef3.IsNull() || aRef4.IsNull()) return NULL;
284 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
285 aShapesSeq->Append(aRef1);
286 aShapesSeq->Append(aRef2);
287 aShapesSeq->Append(aRef3);
288 aShapesSeq->Append(aRef4);
290 aPI.SetShapes(aShapesSeq);
292 //Compute the Face value
294 #if OCC_VERSION_LARGE > 0x06010000
297 if (!GetSolver()->ComputeFunction(aFunction)) {
298 SetErrorCode("Block driver failed to compute a face");
302 catch (Standard_Failure) {
303 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
304 SetErrorCode(aFail->GetMessageString());
308 //Make a Python command
309 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeQuad4Vertices("
310 << thePnt1 << ", " << thePnt2 << ", " << thePnt3 << ", " << thePnt4 << ")";
316 //=============================================================================
320 //=============================================================================
321 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeHexa
322 (Handle(GEOM_Object) theFace1, Handle(GEOM_Object) theFace2,
323 Handle(GEOM_Object) theFace3, Handle(GEOM_Object) theFace4,
324 Handle(GEOM_Object) theFace5, Handle(GEOM_Object) theFace6)
328 if (theFace1.IsNull() || theFace2.IsNull() ||
329 theFace3.IsNull() || theFace4.IsNull() ||
330 theFace5.IsNull() || theFace6.IsNull()) return NULL;
332 //Add a new Solid object
333 Handle(GEOM_Object) aBlock = GetEngine()->AddObject(GetDocID(), GEOM_BLOCK);
335 //Add a new Block function
336 Handle(GEOM_Function) aFunction =
337 aBlock->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_SIX_FACES);
339 //Check if the function is set correctly
340 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
342 GEOMImpl_IBlocks aPI (aFunction);
344 Handle(GEOM_Function) aRef1 = theFace1->GetLastFunction();
345 Handle(GEOM_Function) aRef2 = theFace2->GetLastFunction();
346 Handle(GEOM_Function) aRef3 = theFace3->GetLastFunction();
347 Handle(GEOM_Function) aRef4 = theFace4->GetLastFunction();
348 Handle(GEOM_Function) aRef5 = theFace5->GetLastFunction();
349 Handle(GEOM_Function) aRef6 = theFace6->GetLastFunction();
350 if (aRef1.IsNull() || aRef2.IsNull() ||
351 aRef3.IsNull() || aRef4.IsNull() ||
352 aRef5.IsNull() || aRef6.IsNull()) return NULL;
354 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
355 aShapesSeq->Append(aRef1);
356 aShapesSeq->Append(aRef2);
357 aShapesSeq->Append(aRef3);
358 aShapesSeq->Append(aRef4);
359 aShapesSeq->Append(aRef5);
360 aShapesSeq->Append(aRef6);
362 aPI.SetShapes(aShapesSeq);
364 //Compute the Block value
366 #if OCC_VERSION_LARGE > 0x06010000
369 if (!GetSolver()->ComputeFunction(aFunction)) {
370 SetErrorCode("Block driver failed to compute a block");
374 catch (Standard_Failure) {
375 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
376 SetErrorCode(aFail->GetMessageString());
380 //Make a Python command
381 GEOM::TPythonDump(aFunction) << aBlock << " = geompy.MakeHexa("
382 << theFace1 << ", " << theFace2 << ", " << theFace3 << ", "
383 << theFace4 << ", " << theFace5 << ", " << theFace6 << ")";
389 //=============================================================================
393 //=============================================================================
394 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeHexa2Faces
395 (Handle(GEOM_Object) theFace1, Handle(GEOM_Object) theFace2)
399 if (theFace1.IsNull() || theFace2.IsNull()) return NULL;
401 //Add a new Solid object
402 Handle(GEOM_Object) aBlock = GetEngine()->AddObject(GetDocID(), GEOM_BLOCK);
404 //Add a new Block function
405 Handle(GEOM_Function) aFunction =
406 aBlock->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_TWO_FACES);
408 //Check if the function is set correctly
409 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
411 GEOMImpl_IBlocks aPI (aFunction);
413 Handle(GEOM_Function) aRef1 = theFace1->GetLastFunction();
414 Handle(GEOM_Function) aRef2 = theFace2->GetLastFunction();
415 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
417 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
418 aShapesSeq->Append(aRef1);
419 aShapesSeq->Append(aRef2);
421 aPI.SetShapes(aShapesSeq);
423 //Compute the Block value
425 #if OCC_VERSION_LARGE > 0x06010000
428 if (!GetSolver()->ComputeFunction(aFunction)) {
429 SetErrorCode("Block driver failed to compute a block");
433 catch (Standard_Failure) {
434 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
435 SetErrorCode(aFail->GetMessageString());
439 //Make a Python command
440 GEOM::TPythonDump(aFunction) << aBlock << " = geompy.MakeHexa2Faces("
441 << theFace1 << ", " << theFace2 << ")";
447 //=============================================================================
451 //=============================================================================
452 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeBlockCompound
453 (Handle(GEOM_Object) theCompound)
457 if (theCompound.IsNull()) return NULL;
460 Handle(GEOM_Object) aBlockComp = GetEngine()->AddObject(GetDocID(), GEOM_COMPOUND);
462 //Add a new BlocksComp function
463 Handle(GEOM_Function) aFunction =
464 aBlockComp->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_COMPOUND_GLUE);
466 //Check if the function is set correctly
467 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
469 GEOMImpl_IBlocks aPI (aFunction);
471 Handle(GEOM_Function) aRef1 = theCompound->GetLastFunction();
472 if (aRef1.IsNull()) return NULL;
474 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
475 aShapesSeq->Append(aRef1);
477 aPI.SetShapes(aShapesSeq);
479 //Compute the Blocks Compound value
481 #if OCC_VERSION_LARGE > 0x06010000
484 if (!GetSolver()->ComputeFunction(aFunction)) {
485 SetErrorCode("Block driver failed to compute a blocks compound");
489 catch (Standard_Failure) {
490 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
491 SetErrorCode(aFail->GetMessageString());
495 //Make a Python command
496 GEOM::TPythonDump(aFunction) << aBlockComp
497 << " = geompy.MakeBlockCompound(" << theCompound << ")";
503 //=============================================================================
507 //=============================================================================
508 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetPoint
509 (Handle(GEOM_Object) theShape,
510 const Standard_Real theX,
511 const Standard_Real theY,
512 const Standard_Real theZ,
513 const Standard_Real theEpsilon)
518 Handle(GEOM_Object) aResult;
521 if (theShape.IsNull()) return NULL;
523 TopoDS_Shape aBlockOrComp = theShape->GetValue();
524 if (aBlockOrComp.IsNull()) {
525 SetErrorCode("Given shape is null");
529 //Compute the Vertex value
530 gp_Pnt P (theX, theY, theZ);
531 Standard_Real eps = Max(theEpsilon, Precision::Confusion());
534 Standard_Integer isFound = 0;
535 TopTools_MapOfShape mapShape;
536 TopExp_Explorer exp (aBlockOrComp, TopAbs_VERTEX);
538 for (; exp.More(); exp.Next()) {
539 if (mapShape.Add(exp.Current())) {
540 TopoDS_Vertex aVi = TopoDS::Vertex(exp.Current());
541 gp_Pnt aPi = BRep_Tool::Pnt(aVi);
542 if (aPi.Distance(P) < eps) {
550 SetErrorCode("Vertex has not been found");
552 } else if (isFound > 1) {
553 SetErrorCode("Multiple vertices found by the given coordinates and epsilon");
556 TopTools_IndexedMapOfShape anIndices;
557 TopExp::MapShapes(aBlockOrComp, anIndices);
558 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
559 anArray->SetValue(1, anIndices.FindIndex(V));
560 aResult = GetEngine()->AddSubShape(theShape, anArray);
563 //The GetPoint() doesn't change object so no new function is required.
564 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
566 //Make a Python command
567 GEOM::TPythonDump(aFunction, /*append=*/true)
568 << aResult << " = geompy.GetPoint(" << theShape << ", "
569 << theX << ", " << theY << ", " << theZ << ", " << theEpsilon << ")";
575 //=============================================================================
579 //=============================================================================
580 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetVertexNearPoint
581 (Handle(GEOM_Object) theShape,
582 Handle(GEOM_Object) thePoint)
587 Handle(GEOM_Object) aResult;
590 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
592 TopoDS_Shape aBlockOrComp = theShape->GetValue();
593 TopoDS_Shape aPoint = thePoint->GetValue();
594 if (aBlockOrComp.IsNull() || aPoint.IsNull()) {
595 SetErrorCode("Given shape is null");
599 if (aPoint.ShapeType() != TopAbs_VERTEX) {
600 SetErrorCode("Element for vertex identification is not a vertex");
604 TopoDS_Vertex aVert = TopoDS::Vertex(aPoint);
605 gp_Pnt aP = BRep_Tool::Pnt(aVert);
607 // Compute the Vertex value
609 bool isFound = false;
610 Standard_Real aDist = RealLast();
611 TopTools_MapOfShape mapShape;
613 TopExp_Explorer exp (aBlockOrComp, TopAbs_VERTEX);
614 for (; exp.More(); exp.Next()) {
615 if (mapShape.Add(exp.Current())) {
616 TopoDS_Vertex aVi = TopoDS::Vertex(exp.Current());
617 gp_Pnt aPi = BRep_Tool::Pnt(aVi);
618 Standard_Real aDisti = aPi.Distance(aP);
619 if (aDisti < aDist) {
628 SetErrorCode("Vertex has not been found");
632 TopTools_IndexedMapOfShape anIndices;
633 TopExp::MapShapes(aBlockOrComp, anIndices);
634 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
635 anArray->SetValue(1, anIndices.FindIndex(V));
636 aResult = GetEngine()->AddSubShape(theShape, anArray);
638 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
640 // Make a Python command
641 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetVertexNearPoint("
642 << theShape << ", " << thePoint << ")";
648 //=============================================================================
652 //=============================================================================
653 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetEdge
654 (Handle(GEOM_Object) theShape,
655 Handle(GEOM_Object) thePoint1,
656 Handle(GEOM_Object) thePoint2)
661 Handle(GEOM_Object) aResult;
664 if (theShape.IsNull() || thePoint1.IsNull() || thePoint2.IsNull()) return NULL;
666 TopoDS_Shape aBlockOrComp = theShape->GetValue();
667 if (aBlockOrComp.IsNull()) {
668 SetErrorCode("Given shape is null");
672 TopoDS_Shape anArg1 = thePoint1->GetValue();
673 TopoDS_Shape anArg2 = thePoint2->GetValue();
674 if (anArg1.IsNull() || anArg2.IsNull()) {
675 SetErrorCode("Null shape is given as argument");
678 if (anArg1.ShapeType() != TopAbs_VERTEX ||
679 anArg2.ShapeType() != TopAbs_VERTEX) {
680 SetErrorCode("Element for edge identification is not a vertex");
684 //Compute the Edge value
686 #if OCC_VERSION_LARGE > 0x06010000
689 TopTools_IndexedDataMapOfShapeListOfShape MVE;
690 GEOMImpl_Block6Explorer::MapShapesAndAncestors
691 (aBlockOrComp, TopAbs_VERTEX, TopAbs_EDGE, MVE);
694 Standard_Integer ish, ext = MVE.Extent();
696 if (MVE.Contains(anArg1)) {
699 for (ish = 1; ish <= ext; ish++) {
700 TopoDS_Shape aShi = MVE.FindKey(ish);
701 if (BRepTools::Compare(TopoDS::Vertex(anArg1), TopoDS::Vertex(aShi))) {
708 if (MVE.Contains(anArg2)) {
711 for (ish = 1; ish <= ext; ish++) {
712 TopoDS_Shape aShi = MVE.FindKey(ish);
713 if (BRepTools::Compare(TopoDS::Vertex(anArg2), TopoDS::Vertex(aShi))) {
720 if (V1.IsNull() || V2.IsNull()) {
721 SetErrorCode("The given vertex does not belong to the shape");
726 Standard_Integer isFound =
727 GEOMImpl_Block6Explorer::FindEdge(anEdge, V1, V2, MVE, Standard_True);
729 SetErrorCode("The given vertices do not belong to one edge of the given shape");
731 } else if (isFound > 1) {
732 SetErrorCode("Multiple edges found by the given vertices of the shape");
735 TopTools_IndexedMapOfShape anIndices;
736 TopExp::MapShapes(aBlockOrComp, anIndices);
737 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
738 anArray->SetValue(1, anIndices.FindIndex(anEdge));
739 aResult = GetEngine()->AddSubShape(theShape, anArray);
741 } catch (Standard_Failure) {
742 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
743 SetErrorCode(aFail->GetMessageString());
747 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
749 //Make a Python command
750 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetEdge("
751 << theShape << ", " << thePoint1 << ", " << thePoint2 << ")";
757 //=============================================================================
761 //=============================================================================
762 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetEdgeNearPoint
763 (Handle(GEOM_Object) theShape,
764 Handle(GEOM_Object) thePoint)
769 Handle(GEOM_Object) aResult;
772 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
774 TopoDS_Shape aBlockOrComp = theShape->GetValue();
775 if (aBlockOrComp.IsNull()) {
776 SetErrorCode("Given shape is null");
780 TopoDS_Shape anArg = thePoint->GetValue();
781 if (anArg.IsNull()) {
782 SetErrorCode("Null shape is given as argument");
785 if (anArg.ShapeType() != TopAbs_VERTEX) {
786 SetErrorCode("Element for edge identification is not a vertex");
790 //Compute the Edge value
792 #if OCC_VERSION_LARGE > 0x06010000
795 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
796 TopoDS_Shape aShape = GEOMUtils::GetEdgeNearPoint(aBlockOrComp, aVert);
798 TopTools_IndexedMapOfShape anIndices;
799 TopExp::MapShapes(aBlockOrComp, anIndices);
800 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
801 anArray->SetValue(1, anIndices.FindIndex(aShape));
802 aResult = GetEngine()->AddSubShape(theShape, anArray);
804 catch (Standard_Failure) {
805 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
806 SetErrorCode(aFail->GetMessageString());
810 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
812 //Make a Python command
813 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetEdgeNearPoint("
814 << theShape << ", " << thePoint << ")";
820 //=============================================================================
824 //=============================================================================
825 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByPoints
826 (Handle(GEOM_Object) theShape,
827 Handle(GEOM_Object) thePoint1,
828 Handle(GEOM_Object) thePoint2,
829 Handle(GEOM_Object) thePoint3,
830 Handle(GEOM_Object) thePoint4)
835 Handle(GEOM_Object) aResult;
838 if (theShape.IsNull() ||
839 thePoint1.IsNull() || thePoint2.IsNull() ||
840 thePoint3.IsNull() || thePoint4.IsNull()) return NULL;
842 TopoDS_Shape aBlockOrComp = theShape->GetValue();
843 if (aBlockOrComp.IsNull()) {
844 SetErrorCode("Block or compound is null");
848 TopoDS_Shape anArg1 = thePoint1->GetValue();
849 TopoDS_Shape anArg2 = thePoint2->GetValue();
850 TopoDS_Shape anArg3 = thePoint3->GetValue();
851 TopoDS_Shape anArg4 = thePoint4->GetValue();
852 if (anArg1.IsNull() || anArg2.IsNull() ||
853 anArg3.IsNull() || anArg4.IsNull()) {
854 SetErrorCode("Null shape is given as argument");
857 if (anArg1.ShapeType() != TopAbs_VERTEX ||
858 anArg2.ShapeType() != TopAbs_VERTEX ||
859 anArg3.ShapeType() != TopAbs_VERTEX ||
860 anArg4.ShapeType() != TopAbs_VERTEX) {
861 SetErrorCode("Element for face identification is not a vertex");
865 //Compute the Face value
867 #if OCC_VERSION_LARGE > 0x06010000
872 TopTools_IndexedDataMapOfShapeListOfShape MVF;
873 GEOMImpl_Block6Explorer::MapShapesAndAncestors(aBlockOrComp, TopAbs_VERTEX, TopAbs_FACE, MVF);
875 TopoDS_Shape V1,V2,V3,V4;
876 Standard_Integer ish, ext = MVF.Extent();
878 if (MVF.Contains(anArg1)) {
881 for (ish = 1; ish <= ext; ish++) {
882 TopoDS_Shape aShi = MVF.FindKey(ish);
883 if (BRepTools::Compare(TopoDS::Vertex(anArg1), TopoDS::Vertex(aShi))) {
890 if (MVF.Contains(anArg2)) {
893 for (ish = 1; ish <= ext; ish++) {
894 TopoDS_Shape aShi = MVF.FindKey(ish);
895 if (BRepTools::Compare(TopoDS::Vertex(anArg2), TopoDS::Vertex(aShi))) {
902 if (MVF.Contains(anArg3)) {
905 for (ish = 1; ish <= ext; ish++) {
906 TopoDS_Shape aShi = MVF.FindKey(ish);
907 if (BRepTools::Compare(TopoDS::Vertex(anArg3), TopoDS::Vertex(aShi))) {
914 if (MVF.Contains(anArg4)) {
917 for (ish = 1; ish <= ext; ish++) {
918 TopoDS_Shape aShi = MVF.FindKey(ish);
919 if (BRepTools::Compare(TopoDS::Vertex(anArg4), TopoDS::Vertex(aShi))) {
926 if (V1.IsNull() || V2.IsNull() || V3.IsNull() || V4.IsNull()) {
927 SetErrorCode("The given vertex does not belong to the shape");
931 Standard_Integer isFound =
932 GEOMImpl_Block6Explorer::FindFace(aShape, V1, V2, V3, V4, MVF, Standard_True);
934 SetErrorCode("The given vertices do not belong to one face of the given shape");
936 } else if (isFound > 1) {
937 SetErrorCode("The given vertices belong to several faces of the given shape");
940 TopTools_IndexedMapOfShape anIndices;
941 TopExp::MapShapes(aBlockOrComp, anIndices);
942 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
943 anArray->SetValue(1, anIndices.FindIndex(aShape));
944 aResult = GetEngine()->AddSubShape(theShape, anArray);
947 catch (Standard_Failure) {
948 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
949 SetErrorCode(aFail->GetMessageString());
953 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
955 //Make a Python command
956 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByPoints("
957 << theShape << ", " << thePoint1 << ", " << thePoint2
958 << ", " << thePoint3 << ", " << thePoint4 << ")";
964 //=============================================================================
968 //=============================================================================
969 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByEdges
970 (Handle(GEOM_Object) theShape,
971 Handle(GEOM_Object) theEdge1,
972 Handle(GEOM_Object) theEdge2)
977 Handle(GEOM_Object) aResult;
980 if (theShape.IsNull() || theEdge1.IsNull() || theEdge2.IsNull()) return NULL;
982 TopoDS_Shape aBlockOrComp = theShape->GetValue();
983 if (aBlockOrComp.IsNull()) {
984 SetErrorCode("Block or compound is null");
988 TopoDS_Shape anArg1 = theEdge1->GetValue();
989 TopoDS_Shape anArg2 = theEdge2->GetValue();
990 if (anArg1.IsNull() || anArg2.IsNull()) {
991 SetErrorCode("Null shape is given as argument");
994 if (anArg1.ShapeType() != TopAbs_EDGE ||
995 anArg2.ShapeType() != TopAbs_EDGE) {
996 SetErrorCode("Element for face identification is not an edge");
1000 //Compute the Face value
1002 #if OCC_VERSION_LARGE > 0x06010000
1005 TopoDS_Shape aShape;
1007 TopTools_IndexedDataMapOfShapeListOfShape MEF;
1008 GEOMImpl_Block6Explorer::MapShapesAndAncestors(aBlockOrComp, TopAbs_EDGE, TopAbs_FACE, MEF);
1011 Standard_Integer ish, ext = MEF.Extent();
1013 if (MEF.Contains(anArg1)) {
1016 for (ish = 1; ish <= ext; ish++) {
1017 TopoDS_Shape aShi = MEF.FindKey(ish);
1018 if (GEOMImpl_Block6Explorer::IsSimilarEdges(anArg1, aShi)) {
1024 if (MEF.Contains(anArg2)) {
1027 for (ish = 1; ish <= ext; ish++) {
1028 TopoDS_Shape aShi = MEF.FindKey(ish);
1029 if (GEOMImpl_Block6Explorer::IsSimilarEdges(anArg2, aShi)) {
1035 if (E1.IsNull() || E2.IsNull()) {
1036 SetErrorCode("The given edge does not belong to the shape");
1040 const TopTools_ListOfShape& aFacesOfE1 = MEF.FindFromKey(E1);
1041 const TopTools_ListOfShape& aFacesOfE2 = MEF.FindFromKey(E2);
1043 Standard_Integer isFound = 0;
1044 TopTools_ListIteratorOfListOfShape anIterF1 (aFacesOfE1);
1045 for (; anIterF1.More(); anIterF1.Next()) {
1047 TopTools_ListIteratorOfListOfShape anIterF2 (aFacesOfE2);
1048 for (; anIterF2.More(); anIterF2.Next()) {
1050 if (anIterF1.Value().IsSame(anIterF2.Value())) {
1053 // Store the face, defined by two edges
1054 aShape = anIterF1.Value();
1059 SetErrorCode("The given edges do not belong to one face of the given shape");
1061 } else if (isFound > 1) {
1062 SetErrorCode("The given edges belong to several faces of the given shape");
1065 TopTools_IndexedMapOfShape anIndices;
1066 TopExp::MapShapes(aBlockOrComp, anIndices);
1067 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1068 anArray->SetValue(1, anIndices.FindIndex(aShape));
1069 aResult = GetEngine()->AddSubShape(theShape, anArray);
1072 catch (Standard_Failure) {
1073 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1074 SetErrorCode(aFail->GetMessageString());
1078 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1080 //Make a Python command
1081 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByEdges("
1082 << theShape << ", " << theEdge1 << ", " << theEdge2 << ")";
1088 //=============================================================================
1092 //=============================================================================
1093 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetOppositeFace
1094 (Handle(GEOM_Object) theShape,
1095 Handle(GEOM_Object) theFace)
1100 Handle(GEOM_Object) aResult;
1103 if (theShape.IsNull() || theFace.IsNull()) return NULL;
1105 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1106 if (aBlockOrComp.IsNull()) {
1107 SetErrorCode("Block is null");
1110 if (aBlockOrComp.ShapeType() != TopAbs_SOLID) {
1111 SetErrorCode("Shape is not a block");
1115 TopoDS_Shape anArg = theFace->GetValue();
1116 if (anArg.IsNull()) {
1117 SetErrorCode("Null shape is given as argument");
1120 if (anArg.ShapeType() != TopAbs_FACE) {
1121 SetErrorCode("Element for face identification is not a face");
1125 //Compute the Face value
1127 #if OCC_VERSION_LARGE > 0x06010000
1130 TopoDS_Shape aShape;
1132 GEOMImpl_Block6Explorer aBlockTool;
1133 aBlockTool.InitByBlockAndFace(aBlockOrComp, anArg);
1134 aShape = aBlockTool.GetFace(2);
1136 TopTools_IndexedMapOfShape anIndices;
1137 TopExp::MapShapes(aBlockOrComp, anIndices);
1138 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1139 anArray->SetValue(1, anIndices.FindIndex(aShape));
1140 aResult = GetEngine()->AddSubShape(theShape, anArray);
1142 catch (Standard_Failure) {
1143 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1144 SetErrorCode(aFail->GetMessageString());
1148 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1150 //Make a Python command
1151 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetOppositeFace("
1152 << theShape << ", " << theFace << ")";
1158 //=============================================================================
1162 //=============================================================================
1163 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceNearPoint
1164 (Handle(GEOM_Object) theShape,
1165 Handle(GEOM_Object) thePoint)
1170 Handle(GEOM_Object) aResult;
1173 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
1175 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1176 if (aBlockOrComp.IsNull()) {
1177 SetErrorCode("Block or compound is null");
1181 TopoDS_Shape anArg = thePoint->GetValue();
1182 if (anArg.IsNull()) {
1183 SetErrorCode("Null shape is given as argument");
1186 if (anArg.ShapeType() != TopAbs_VERTEX) {
1187 SetErrorCode("Element for face identification is not a vertex");
1191 //Compute the Face value
1193 #if OCC_VERSION_LARGE > 0x06010000
1196 TopoDS_Shape aShape;
1198 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
1199 gp_Pnt aPnt = BRep_Tool::Pnt(aVert);
1200 Standard_Real PX, PY, PZ;
1201 aPnt.Coord(PX, PY, PZ);
1203 // 1. Classify the point relatively each face
1204 Standard_Integer nearest = 2, nbFound = 0;
1205 TopTools_DataMapOfShapeInteger mapShapeDist;
1206 TopExp_Explorer exp (aBlockOrComp, TopAbs_FACE);
1207 for (; exp.More(); exp.Next()) {
1208 TopoDS_Shape aFace = exp.Current();
1210 if (!mapShapeDist.IsBound(aFace)) {
1211 Standard_Integer aDistance = 2;
1213 // 1.a. Classify relatively Surface
1214 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aFace));
1215 Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf);
1216 gp_Pnt2d p2dOnSurf = aSurfAna->ValueOfUV(aPnt, Precision::Confusion());
1217 gp_Pnt p3dOnSurf = aSurfAna->Value(p2dOnSurf);
1218 Standard_Real aDist = p3dOnSurf.Distance(aPnt);
1219 if (aDist > Precision::Confusion()) {
1223 // 1.b. Classify relatively the face itself
1224 BRepClass_FaceClassifier FC (TopoDS::Face(aFace), p2dOnSurf, Precision::Confusion());
1225 if (FC.State() == TopAbs_IN) {
1227 } else if (FC.State() == TopAbs_ON) {
1234 if (aDistance < nearest) {
1235 nearest = aDistance;
1239 // A first found face, containing the point inside, will be returned.
1240 // It is the solution, if there are no
1241 // coincident or intersecting faces in the compound.
1242 if (nearest == -1) break;
1244 } else if (aDistance == nearest) {
1249 mapShapeDist.Bind(aFace, aDistance);
1250 } // if (!mapShapeDist.IsBound(aFace))
1253 // 2. Define face, containing the point or having minimum distance to it
1256 // The point is on boundary of some faces and there are
1257 // no faces, having the point inside
1258 SetErrorCode("Multiple faces near the given point are found");
1261 } else if (nearest == 1) {
1262 // The point is outside some faces and there are
1263 // no faces, having the point inside or on boundary.
1264 // We will get a nearest face
1265 Standard_Real bigReal = RealLast();
1266 Standard_Real minDist = bigReal;
1267 TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
1268 for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
1269 if (mapShapeDistIter.Value() == 1) {
1270 TopoDS_Shape aFace = mapShapeDistIter.Key();
1271 Standard_Real aDist = bigReal;
1273 // 2.a. Fast check of distance - if point projection on surface is on face
1274 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aFace));
1275 Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf);
1276 gp_Pnt2d p2dOnSurf = aSurfAna->ValueOfUV(aPnt, Precision::Confusion());
1277 gp_Pnt p3dOnSurf = aSurfAna->Value(p2dOnSurf);
1278 aDist = p3dOnSurf.Distance(aPnt);
1280 BRepClass_FaceClassifier FC (TopoDS::Face(aFace), p2dOnSurf, Precision::Confusion());
1281 if (FC.State() == TopAbs_OUT) {
1282 if (aDist < minDist) {
1283 // 2.b. Slow check - if point projection on surface is outside of face
1284 BRepExtrema_DistShapeShape aDistTool (aVert, aFace);
1285 if (!aDistTool.IsDone()) {
1286 SetErrorCode("Can not find a distance from the given point to one of faces");
1289 aDist = aDistTool.Value();
1295 if (aDist < minDist) {
1301 } else { // nearest == -1
1302 // // The point is inside some faces.
1303 // // We will get a face with nearest center
1304 // Standard_Real minDist = RealLast();
1305 // TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
1306 // for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
1307 // if (mapShapeDistIter.Value() == -1) {
1308 // TopoDS_Shape aFace = mapShapeDistIter.Key();
1309 // GProp_GProps aSystem;
1310 // BRepGProp::SurfaceProperties(aFace, aSystem);
1311 // gp_Pnt aCenterMass = aSystem.CentreOfMass();
1313 // Standard_Real aDist = aCenterMass.Distance(aPnt);
1314 // if (aDist < minDist) {
1321 } // if (nbFound > 1)
1324 SetErrorCode("There are no faces near the given point");
1327 TopTools_IndexedMapOfShape anIndices;
1328 TopExp::MapShapes(aBlockOrComp, anIndices);
1329 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1330 anArray->SetValue(1, anIndices.FindIndex(aShape));
1331 aResult = GetEngine()->AddSubShape(theShape, anArray);
1334 catch (Standard_Failure) {
1335 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1336 SetErrorCode(aFail->GetMessageString());
1340 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1342 //Make a Python command
1343 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceNearPoint("
1344 << theShape << ", " << thePoint << ")";
1350 //=============================================================================
1354 //=============================================================================
1355 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByNormale
1356 (Handle(GEOM_Object) theShape,
1357 Handle(GEOM_Object) theVector)
1362 Handle(GEOM_Object) aResult;
1365 if (theShape.IsNull() || theVector.IsNull()) return NULL;
1367 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1368 if (aBlockOrComp.IsNull()) {
1369 SetErrorCode("Block or compound is null");
1373 TopoDS_Shape anArg = theVector->GetValue();
1374 if (anArg.IsNull()) {
1375 SetErrorCode("Null shape is given as argument");
1378 if (anArg.ShapeType() != TopAbs_EDGE) {
1379 SetErrorCode("Element for normale identification is not an edge");
1383 //Compute the Face value
1385 #if OCC_VERSION_LARGE > 0x06010000
1388 TopoDS_Shape aShape;
1390 TopoDS_Edge anEdge = TopoDS::Edge(anArg);
1391 TopoDS_Vertex V1, V2;
1392 TopExp::Vertices(anEdge, V1, V2, Standard_True);
1393 gp_Pnt P1 = BRep_Tool::Pnt(V1);
1394 gp_Pnt P2 = BRep_Tool::Pnt(V2);
1395 gp_Vec aVec (P1, P2);
1396 if (aVec.Magnitude() < Precision::Confusion()) {
1397 SetErrorCode("Vector with null magnitude is given");
1401 Standard_Real minAngle = RealLast();
1402 TopTools_MapOfShape mapShape;
1403 TopExp_Explorer exp (aBlockOrComp, TopAbs_FACE);
1404 for (; exp.More(); exp.Next()) {
1405 if (mapShape.Add(exp.Current())) {
1406 TopoDS_Face aFace = TopoDS::Face(exp.Current());
1407 BRepAdaptor_Surface SF (aFace);
1409 Standard_Real u, v, x;
1411 // find a point on the surface to get normal direction in
1412 u = SF.FirstUParameter();
1413 x = SF.LastUParameter();
1414 if (Precision::IsInfinite(u)) {
1415 u = (Precision::IsInfinite(x)) ? 0. : x;
1416 } else if (!Precision::IsInfinite(x)) {
1420 v = SF.FirstVParameter();
1421 x = SF.LastVParameter();
1422 if (Precision::IsInfinite(v)) {
1423 v = (Precision::IsInfinite(x)) ? 0. : x;
1424 } else if (!Precision::IsInfinite(x)) {
1428 // compute the normal direction
1430 SF.D1(u,v,P1,Vec1,Vec2);
1431 gp_Vec V = Vec1.Crossed(Vec2);
1433 if (V.Magnitude() < Precision::Confusion()) {
1434 SetErrorCode("Normal vector of a face has null magnitude");
1438 // consider the face orientation
1439 if (aFace.Orientation() == TopAbs_REVERSED ||
1440 aFace.Orientation() == TopAbs_INTERNAL) {
1444 // compute the angle and compare with the minimal one
1445 Standard_Real anAngle = aVec.Angle(V);
1446 if (anAngle < minAngle) {
1453 if (aShape.IsNull()) {
1454 SetErrorCode("Failed to find a face by the given normale");
1457 TopTools_IndexedMapOfShape anIndices;
1458 TopExp::MapShapes(aBlockOrComp, anIndices);
1459 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1460 anArray->SetValue(1, anIndices.FindIndex(aShape));
1461 aResult = GetEngine()->AddSubShape(theShape, anArray);
1464 catch (Standard_Failure) {
1465 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1466 SetErrorCode(aFail->GetMessageString());
1470 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1472 //Make a Python command
1473 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByNormale("
1474 << theShape << ", " << theVector << ")";
1480 //=============================================================================
1482 * GetShapesNearPoint
1484 //=============================================================================
1485 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetShapesNearPoint
1486 (Handle(GEOM_Object) theShape,
1487 Handle(GEOM_Object) thePoint,
1488 const Standard_Integer theShapeType,
1489 const Standard_Real theConstTolerance)
1494 Handle(GEOM_Object) aResult;
1497 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
1499 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1500 if (aBlockOrComp.IsNull()) {
1501 SetErrorCode("Block or compound is null");
1505 TopoDS_Shape anArg = thePoint->GetValue();
1506 if (anArg.IsNull()) {
1507 SetErrorCode("Null shape is given as argument");
1510 if (anArg.ShapeType() != TopAbs_VERTEX) {
1511 SetErrorCode("Element for face identification is not a vertex");
1515 if (theShapeType < TopAbs_SOLID || TopAbs_VERTEX < theShapeType) {
1516 SetErrorCode("Invalid type of result is requested");
1520 Standard_Real theTolerance = theConstTolerance;
1521 if (theTolerance < Precision::Confusion()) {
1522 theTolerance = Precision::Confusion();
1525 // Compute the result
1527 #if OCC_VERSION_LARGE > 0x06010000
1530 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
1532 TopTools_MapOfShape mapShape;
1533 Standard_Integer nbEdges = 0;
1534 TopExp_Explorer exp (aBlockOrComp, TopAbs_ShapeEnum(theShapeType));
1535 for (; exp.More(); exp.Next()) {
1536 if (mapShape.Add(exp.Current())) {
1542 SetErrorCode("Given shape contains no sub-shapes of requested type");
1546 // Calculate distances and find min
1548 Standard_Integer ind = 1;
1549 Standard_Real aMinDist = RealLast();
1550 TopTools_Array1OfShape anEdges (1, nbEdges);
1551 TColStd_Array1OfReal aDistances (1, nbEdges);
1552 for (exp.Init(aBlockOrComp, TopAbs_ShapeEnum(theShapeType)); exp.More(); exp.Next()) {
1553 if (mapShape.Add(exp.Current())) {
1554 TopoDS_Shape anEdge = exp.Current();
1555 anEdges(ind) = anEdge;
1557 BRepExtrema_DistShapeShape aDistTool (aVert, anEdges(ind));
1558 if (!aDistTool.IsDone()) {
1559 SetErrorCode("Can not find a distance from the given point to one of sub-shapes");
1562 aDistances(ind) = aDistTool.Value();
1563 if (aDistances(ind) < aMinDist) {
1564 aMinDist = aDistances(ind);
1570 if (aMinDist < RealLast()) {
1571 // Collect sub-shapes with distance < (aMinDist + theTolerance)
1572 int nbSubShapes = 0;
1573 TopTools_Array1OfShape aNearShapes (1, nbEdges);
1574 for (ind = 1; ind <= nbEdges; ind++) {
1575 if (aDistances(ind) < aMinDist + theTolerance) {
1577 aNearShapes(nbSubShapes) = anEdges(ind);
1582 TopTools_IndexedMapOfShape anIndices;
1583 TopExp::MapShapes(aBlockOrComp, anIndices);
1584 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger (1, nbSubShapes);
1585 for (ind = 1; ind <= nbSubShapes; ind++) {
1586 anArray->SetValue(ind, anIndices.FindIndex(aNearShapes(ind)));
1588 aResult = GetEngine()->AddSubShape(theShape, anArray);
1591 catch (Standard_Failure) {
1592 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1593 SetErrorCode(aFail->GetMessageString());
1597 if (aResult.IsNull())
1600 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1602 //Make a Python command
1603 GEOM::TPythonDump(aFunction)
1604 << aResult << " = geompy.GetShapesNearPoint(" << theShape << ", " << thePoint
1605 << ", " << TopAbs_ShapeEnum(theShapeType) << ", " << theTolerance << ")";
1611 //=============================================================================
1613 * IsCompoundOfBlocks
1615 //=============================================================================
1616 Standard_Boolean GEOMImpl_IBlocksOperations::IsCompoundOfBlocks
1617 (Handle(GEOM_Object) theCompound,
1618 const Standard_Integer theMinNbFaces,
1619 const Standard_Integer theMaxNbFaces,
1620 Standard_Integer& theNbBlocks)
1623 Standard_Boolean isCompOfBlocks = Standard_False;
1626 if (theCompound.IsNull()) return isCompOfBlocks;
1627 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
1630 isCompOfBlocks = Standard_True;
1632 #if OCC_VERSION_LARGE > 0x06010000
1635 TopTools_MapOfShape mapShape;
1636 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
1637 for (; exp.More(); exp.Next()) {
1638 if (mapShape.Add(exp.Current())) {
1639 TopoDS_Shape aSolid = exp.Current();
1641 TopTools_MapOfShape mapFaces;
1642 TopExp_Explorer expF (aSolid, TopAbs_FACE);
1643 Standard_Integer nbFaces = 0;
1644 for (; expF.More(); expF.Next()) {
1645 if (mapFaces.Add(expF.Current())) {
1647 if (nbFaces > theMaxNbFaces) {
1648 isCompOfBlocks = Standard_False;
1653 if (nbFaces < theMinNbFaces || theMaxNbFaces < nbFaces) {
1654 isCompOfBlocks = Standard_False;
1661 catch (Standard_Failure) {
1662 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1663 SetErrorCode(aFail->GetMessageString());
1664 return isCompOfBlocks;
1668 return isCompOfBlocks;
1671 //=============================================================================
1673 * Set of functions, used by CheckCompoundOfBlocks() method
1675 //=============================================================================
1676 void GEOMImpl_IBlocksOperations::AddBlocksFrom (const TopoDS_Shape& theShape,
1677 TopTools_ListOfShape& BLO,
1678 TopTools_ListOfShape& NOT,
1679 TopTools_ListOfShape& EXT,
1680 TopTools_ListOfShape& NOQ)
1682 TopAbs_ShapeEnum aType = theShape.ShapeType();
1684 case TopAbs_COMPOUND:
1685 case TopAbs_COMPSOLID:
1687 TopoDS_Iterator It (theShape);
1688 for (; It.More(); It.Next()) {
1689 AddBlocksFrom(It.Value(), BLO, NOT, EXT, NOQ);
1695 // Check, if there are seam or degenerated edges
1696 BlockFix_CheckTool aTool;
1697 aTool.SetShape(theShape);
1699 if (aTool.NbPossibleBlocks() > 0) {
1700 EXT.Append(theShape);
1702 // Count faces and edges in each face to recognize blocks
1703 TopTools_MapOfShape mapFaces;
1704 Standard_Integer nbFaces = 0;
1705 Standard_Boolean hasNonQuadr = Standard_False;
1706 TopExp_Explorer expF (theShape, TopAbs_FACE);
1708 for (; expF.More(); expF.Next()) {
1709 if (mapFaces.Add(expF.Current())) {
1711 //0021483//if (nbFaces > 6) break;
1714 TopoDS_Shape aF = expF.Current();
1715 TopExp_Explorer wires (aF, TopAbs_WIRE);
1716 if (!wires.More()) {
1717 // no wire in the face
1718 hasNonQuadr = Standard_True;
1719 NOQ.Append(aF);//0021483
1723 TopoDS_Shape aWire = wires.Current();
1726 // multiple wires in the face
1727 hasNonQuadr = Standard_True;
1728 NOQ.Append(aF);//0021483
1733 // Check number of edges in the face
1734 Standard_Integer nbEdges = 0;
1735 TopTools_MapOfShape mapEdges;
1736 TopExp_Explorer expW (aWire, TopAbs_EDGE);
1737 for (; expW.More(); expW.Next()) {
1738 if (mapEdges.Add(expW.Current())) {
1740 if (nbEdges > 4) break;
1744 hasNonQuadr = Standard_True;
1745 NOQ.Append(aF);//0021483
1750 if (nbFaces == 6 && !hasNonQuadr) {
1751 BLO.Append(theShape);
1753 NOT.Append(theShape);
1758 case TopAbs_SHELL: //0021483
1759 case TopAbs_FACE: //0021483
1761 // Count edges in each face
1762 TopTools_MapOfShape mapFaces;
1763 TopExp_Explorer expF (theShape, TopAbs_FACE);
1764 for (; expF.More(); expF.Next()) {
1765 if (mapFaces.Add(expF.Current())) {
1767 TopoDS_Shape aF = expF.Current();
1768 TopExp_Explorer wires (aF, TopAbs_WIRE);
1769 if (!wires.More()) {
1770 // no wire in the face
1771 NOQ.Append(aF);//0021483
1774 TopoDS_Shape aWire = wires.Current();
1777 // multiple wires in the face
1778 NOQ.Append(aF);//0021483
1782 // Check number of edges in the face
1783 Standard_Integer nbEdges = 0;
1784 TopTools_MapOfShape mapEdges;
1785 TopExp_Explorer expW (aWire, TopAbs_EDGE);
1786 for (; expW.More(); expW.Next()) {
1787 if (mapEdges.Add(expW.Current())) {
1789 if (nbEdges > 4) break;
1793 NOQ.Append(aF);//0021483
1800 NOT.Append(theShape);
1804 void AddBlocksFromOld (const TopoDS_Shape& theShape,
1805 TopTools_ListOfShape& BLO,
1806 TopTools_ListOfShape& NOT,
1807 TopTools_ListOfShape& DEG,
1808 TopTools_ListOfShape& SEA)
1810 TopAbs_ShapeEnum aType = theShape.ShapeType();
1812 case TopAbs_COMPOUND:
1813 case TopAbs_COMPSOLID:
1815 TopoDS_Iterator It (theShape);
1816 for (; It.More(); It.Next()) {
1817 AddBlocksFromOld(It.Value(), BLO, NOT, DEG, SEA);
1823 TopTools_MapOfShape mapFaces;
1824 TopExp_Explorer expF (theShape, TopAbs_FACE);
1825 Standard_Integer nbFaces = 0;
1826 Standard_Boolean hasNonQuadr = Standard_False;
1827 Standard_Boolean hasDegenerated = Standard_False;
1828 Standard_Boolean hasSeam = Standard_False;
1829 for (; expF.More(); expF.Next()) {
1830 if (mapFaces.Add(expF.Current())) {
1832 if (nbFaces > 6) break;
1834 // Check number of edges in the face
1835 Standard_Integer nbEdges = 0;
1836 TopTools_MapOfShape mapEdges;
1839 TopoDS_Shape aF = expF.Current();
1840 TopExp_Explorer wires (aF, TopAbs_WIRE);
1841 if (!wires.More()) {
1842 // no wire in the face
1843 hasNonQuadr = Standard_True;
1846 TopoDS_Shape aWire = wires.Current();
1849 // multiple wires in the face
1850 hasNonQuadr = Standard_True;
1855 BRepTools_WireExplorer aWE (TopoDS::Wire(aWire), TopoDS::Face(aF));
1856 for (; aWE.More(); aWE.Next(), nbEdges++) {
1857 if (BRep_Tool::Degenerated(aWE.Current())) {
1858 // degenerated edge found
1859 hasDegenerated = Standard_True;
1862 if (mapEdges.Contains(aWE.Current())) {
1864 hasSeam = Standard_True;
1867 mapEdges.Add(aWE.Current());
1870 hasNonQuadr = Standard_True;
1875 if (hasDegenerated || hasSeam) {
1876 if (hasDegenerated) {
1877 DEG.Append(theShape);
1880 SEA.Append(theShape);
1882 } else if (hasNonQuadr) {
1883 NOT.Append(theShape);
1885 BLO.Append(theShape);
1888 NOT.Append(theShape);
1893 NOT.Append(theShape);
1897 #define REL_NOT_CONNECTED 0
1899 #define REL_NOT_GLUED 2
1900 #define REL_COLLISION_VV 3
1901 #define REL_COLLISION_FF 4
1902 #define REL_COLLISION_EE 5
1903 #define REL_UNKNOWN 6
1905 Standard_Integer BlocksRelation (const TopoDS_Shape& theBlock1,
1906 const TopoDS_Shape& theBlock2)
1908 // Compare bounding boxes before calling BRepExtrema_DistShapeShape
1909 Standard_Real Xmin1, Ymin1, Zmin1, Xmax1, Ymax1, Zmax1;
1910 Standard_Real Xmin2, Ymin2, Zmin2, Xmax2, Ymax2, Zmax2;
1912 BRepBndLib::Add(theBlock1, B1);
1913 BRepBndLib::Add(theBlock2, B2);
1914 B1.Get(Xmin1, Ymin1, Zmin1, Xmax1, Ymax1, Zmax1);
1915 B2.Get(Xmin2, Ymin2, Zmin2, Xmax2, Ymax2, Zmax2);
1916 if (Xmax2 < Xmin1 || Xmax1 < Xmin2 ||
1917 Ymax2 < Ymin1 || Ymax1 < Ymin2 ||
1918 Zmax2 < Zmin1 || Zmax1 < Zmin2) {
1919 return REL_NOT_CONNECTED;
1922 BRepExtrema_DistShapeShape dst (theBlock1, theBlock2);
1923 if (!dst.IsDone()) {
1927 if (dst.Value() > Precision::Confusion()) {
1928 return REL_NOT_CONNECTED;
1931 if (dst.InnerSolution()) {
1932 return REL_COLLISION_VV;
1935 Standard_Integer nbSol = dst.NbSolution();
1936 Standard_Integer relation = REL_OK;
1937 Standard_Integer nbVerts = 0;
1938 Standard_Integer nbEdges = 0;
1939 Standard_Integer sol = 1;
1940 for (; sol <= nbSol; sol++) {
1941 BRepExtrema_SupportType supp1 = dst.SupportTypeShape1(sol);
1942 BRepExtrema_SupportType supp2 = dst.SupportTypeShape2(sol);
1943 if (supp1 == BRepExtrema_IsVertex && supp2 == BRepExtrema_IsVertex) {
1945 } else if (supp1 == BRepExtrema_IsInFace || supp2 == BRepExtrema_IsInFace) {
1946 return REL_COLLISION_FF;
1947 } else if (supp1 == BRepExtrema_IsOnEdge && supp2 == BRepExtrema_IsOnEdge) {
1949 } else if ((supp1 == BRepExtrema_IsOnEdge && supp2 == BRepExtrema_IsVertex) ||
1950 (supp2 == BRepExtrema_IsOnEdge && supp1 == BRepExtrema_IsVertex)) {
1951 relation = REL_COLLISION_EE;
1956 if (relation != REL_OK) {
1960 TColStd_Array1OfInteger vertSol (1, nbVerts);
1961 TopTools_Array1OfShape V1 (1, nbVerts);
1962 TopTools_Array1OfShape V2 (1, nbVerts);
1963 Standard_Integer ivs = 0;
1964 for (sol = 1; sol <= nbSol; sol++) {
1965 if (dst.SupportTypeShape1(sol) == BRepExtrema_IsVertex &&
1966 dst.SupportTypeShape2(sol) == BRepExtrema_IsVertex) {
1967 TopoDS_Vertex Vcur = TopoDS::Vertex(dst.SupportOnShape1(sol));
1968 // Check, that this vertex is far enough from other solution vertices.
1969 Standard_Integer ii = 1;
1970 for (; ii <= ivs; ii++) {
1971 if (BRepTools::Compare(TopoDS::Vertex(V1(ii)), Vcur)) {
1978 V2(ivs) = dst.SupportOnShape2(sol);
1982 // As we deal only with quadrangles,
1983 // 2, 3 or 4 vertex solutions can be found.
1986 return REL_COLLISION_FF;
1988 return REL_NOT_CONNECTED;
1994 // Check sharing of coincident entities.
1995 if (ivs == 2 || ivs == 3) {
1996 // Map vertices and edges of the blocks
1997 TopTools_IndexedDataMapOfShapeListOfShape MVE1, MVE2;
1998 GEOMImpl_Block6Explorer::MapShapesAndAncestors
1999 (theBlock1, TopAbs_VERTEX, TopAbs_EDGE, MVE1);
2000 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2001 (theBlock2, TopAbs_VERTEX, TopAbs_EDGE, MVE2);
2005 TopoDS_Shape anEdge1, anEdge2;
2006 GEOMImpl_Block6Explorer::FindEdge(anEdge1, V1(1), V1(2), MVE1);
2007 if (anEdge1.IsNull()) return REL_UNKNOWN;
2009 GEOMImpl_Block6Explorer::FindEdge(anEdge2, V2(1), V2(2), MVE2);
2010 if (anEdge2.IsNull()) return REL_UNKNOWN;
2012 if (!anEdge1.IsSame(anEdge2)) return REL_NOT_GLUED;
2014 } else { // ivs == 3
2015 // Find common edges
2016 Standard_Integer e1_v1 = 1;
2017 Standard_Integer e1_v2 = 2;
2018 Standard_Integer e2_v1 = 3;
2019 Standard_Integer e2_v2 = 1;
2021 TopoDS_Shape anEdge11, anEdge12;
2022 GEOMImpl_Block6Explorer::FindEdge(anEdge11, V1(e1_v1), V1(e1_v2), MVE1);
2023 if (anEdge11.IsNull()) {
2026 GEOMImpl_Block6Explorer::FindEdge(anEdge11, V1(e1_v1), V1(e1_v2), MVE1);
2027 if (anEdge11.IsNull()) return REL_UNKNOWN;
2029 GEOMImpl_Block6Explorer::FindEdge(anEdge12, V1(e2_v1), V1(e2_v2), MVE1);
2030 if (anEdge12.IsNull()) {
2032 GEOMImpl_Block6Explorer::FindEdge(anEdge12, V1(e2_v1), V1(e2_v2), MVE1);
2033 if (anEdge12.IsNull()) return REL_UNKNOWN;
2036 TopoDS_Shape anEdge21, anEdge22;
2037 GEOMImpl_Block6Explorer::FindEdge(anEdge21, V2(e1_v1), V2(e1_v2), MVE2);
2038 if (anEdge21.IsNull()) return REL_UNKNOWN;
2039 GEOMImpl_Block6Explorer::FindEdge(anEdge22, V2(e2_v1), V2(e2_v2), MVE2);
2040 if (anEdge22.IsNull()) return REL_UNKNOWN;
2042 // Check of edges coincidence (with some precision) have to be done here
2043 // if (!anEdge11.IsEqual(anEdge21)) return REL_UNKNOWN;
2044 // if (!anEdge12.IsEqual(anEdge22)) return REL_UNKNOWN;
2046 // Check of edges sharing
2047 if (!anEdge11.IsSame(anEdge21)) return REL_NOT_GLUED;
2048 if (!anEdge12.IsSame(anEdge22)) return REL_NOT_GLUED;
2053 // Map vertices and faces of the blocks
2054 TopTools_IndexedDataMapOfShapeListOfShape MVF1, MVF2;
2055 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2056 (theBlock1, TopAbs_VERTEX, TopAbs_FACE, MVF1);
2057 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2058 (theBlock2, TopAbs_VERTEX, TopAbs_FACE, MVF2);
2060 TopoDS_Shape aFace1, aFace2;
2061 GEOMImpl_Block6Explorer::FindFace(aFace1, V1(1), V1(2), V1(3), V1(4), MVF1);
2062 if (aFace1.IsNull()) return REL_UNKNOWN;
2063 GEOMImpl_Block6Explorer::FindFace(aFace2, V2(1), V2(2), V2(3), V2(4), MVF2);
2064 if (aFace2.IsNull()) return REL_UNKNOWN;
2066 // Check of faces coincidence (with some precision) have to be done here
2067 // if (!aFace1.IsEqual(aFace2)) return REL_UNKNOWN;
2069 // Check of faces sharing
2070 if (!aFace1.IsSame(aFace2)) return REL_NOT_GLUED;
2076 void FindConnected (const Standard_Integer theBlockIndex,
2077 const TColStd_Array2OfInteger& theRelations,
2078 TColStd_MapOfInteger& theProcessedMap,
2079 TColStd_MapOfInteger& theConnectedMap)
2081 theConnectedMap.Add(theBlockIndex);
2082 theProcessedMap.Add(theBlockIndex);
2084 Standard_Integer nbBlocks = theRelations.ColLength();
2085 Standard_Integer col = 1;
2086 for (; col <= nbBlocks; col++) {
2087 if (theRelations(theBlockIndex, col) == REL_OK ||
2088 theRelations(theBlockIndex, col) == REL_NOT_GLUED) {
2089 if (!theProcessedMap.Contains(col)) {
2090 FindConnected(col, theRelations, theProcessedMap, theConnectedMap);
2096 Standard_Boolean HasAnyConnection (const Standard_Integer theBlockIndex,
2097 const TColStd_MapOfInteger& theWith,
2098 const TColStd_Array2OfInteger& theRelations,
2099 TColStd_MapOfInteger& theProcessedMap)
2101 theProcessedMap.Add(theBlockIndex);
2103 Standard_Integer nbBlocks = theRelations.ColLength();
2104 Standard_Integer col = 1;
2105 for (; col <= nbBlocks; col++) {
2106 if (theRelations(theBlockIndex, col) != REL_NOT_CONNECTED) {
2107 if (!theProcessedMap.Contains(col)) {
2108 if (theWith.Contains(col))
2109 return Standard_True;
2110 if (HasAnyConnection(col, theWith, theRelations, theProcessedMap))
2111 return Standard_True;
2116 return Standard_False;
2119 //=============================================================================
2121 * CheckCompoundOfBlocksOld
2123 //=============================================================================
2124 Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocksOld
2125 (Handle(GEOM_Object) theCompound,
2126 std::list<BCError>& theErrors)
2130 if (theCompound.IsNull()) return Standard_False;
2131 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2133 Standard_Boolean isCompOfBlocks = Standard_True;
2135 // Map sub-shapes and their indices
2136 TopTools_IndexedMapOfShape anIndices;
2137 TopExp::MapShapes(aBlockOrComp, anIndices);
2139 // 1. Report non-blocks
2140 TopTools_ListOfShape NOT; // Not blocks
2141 TopTools_ListOfShape DEG; // Hexahedral solids, having degenerated edges
2142 TopTools_ListOfShape SEA; // Hexahedral solids, having seam edges
2143 TopTools_ListOfShape BLO; // All blocks from the given compound
2144 AddBlocksFromOld(aBlockOrComp, BLO, NOT, DEG, SEA);
2146 if (NOT.Extent() > 0) {
2147 isCompOfBlocks = Standard_False;
2149 anErr.error = NOT_BLOCK;
2150 TopTools_ListIteratorOfListOfShape it (NOT);
2151 for (; it.More(); it.Next()) {
2152 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
2154 theErrors.push_back(anErr);
2157 if (DEG.Extent() > 0 || SEA.Extent() > 0) {
2158 isCompOfBlocks = Standard_False;
2160 anErr.error = EXTRA_EDGE;
2162 TopTools_ListIteratorOfListOfShape itDEG (DEG);
2163 for (; itDEG.More(); itDEG.Next()) {
2164 anErr.incriminated.push_back(anIndices.FindIndex(itDEG.Value()));
2167 TopTools_ListIteratorOfListOfShape itSEA (SEA);
2168 for (; itSEA.More(); itSEA.Next()) {
2169 anErr.incriminated.push_back(anIndices.FindIndex(itSEA.Value()));
2172 theErrors.push_back(anErr);
2175 Standard_Integer nbBlocks = BLO.Extent();
2176 if (nbBlocks == 0) {
2177 isCompOfBlocks = Standard_False;
2179 return isCompOfBlocks;
2181 if (nbBlocks == 1) {
2183 return isCompOfBlocks;
2186 // Convert list of blocks into array for easy and fast access
2187 Standard_Integer ibl = 1;
2188 TopTools_Array1OfShape aBlocks (1, nbBlocks);
2189 TopTools_ListIteratorOfListOfShape BLOit (BLO);
2190 for (; BLOit.More(); BLOit.Next(), ibl++) {
2191 aBlocks.SetValue(ibl, BLOit.Value());
2194 // 2. Find relations between all blocks,
2195 // report connection errors (NOT_GLUED and INVALID_CONNECTION)
2196 TColStd_Array2OfInteger aRelations (1, nbBlocks, 1, nbBlocks);
2197 aRelations.Init(REL_NOT_CONNECTED);
2199 Standard_Integer row = 1;
2200 for (row = 1; row <= nbBlocks; row++) {
2201 TopoDS_Shape aBlock = aBlocks.Value(row);
2203 Standard_Integer col = row + 1;
2204 for (; col <= nbBlocks; col++) {
2205 Standard_Integer aRel = BlocksRelation(aBlock, aBlocks.Value(col));
2206 if (aRel != REL_NOT_CONNECTED) {
2207 aRelations.SetValue(row, col, aRel);
2208 aRelations.SetValue(col, row, aRel);
2209 if (aRel == REL_NOT_GLUED) {
2210 // report connection error
2211 isCompOfBlocks = Standard_False;
2213 anErr.error = NOT_GLUED;
2214 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row)));
2215 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col)));
2216 theErrors.push_back(anErr);
2217 } else if (aRel == REL_COLLISION_VV ||
2218 aRel == REL_COLLISION_FF ||
2219 aRel == REL_COLLISION_EE ||
2220 aRel == REL_UNKNOWN) {
2221 // report connection error
2222 isCompOfBlocks = Standard_False;
2224 anErr.error = INVALID_CONNECTION;
2225 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row)));
2226 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col)));
2227 theErrors.push_back(anErr);
2234 // 3. Find largest set of connected (good connection or not glued) blocks
2235 TColStd_MapOfInteger aProcessedMap;
2236 TColStd_MapOfInteger aLargestSet;
2237 TColStd_MapOfInteger aCurrentSet;
2238 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2239 if (!aProcessedMap.Contains(ibl)) {
2240 aCurrentSet.Clear();
2241 FindConnected(ibl, aRelations, aProcessedMap, aCurrentSet);
2242 if (aCurrentSet.Extent() > aLargestSet.Extent()) {
2243 aLargestSet = aCurrentSet;
2248 // 4. Report all blocks, isolated from <aLargestSet>
2250 anErr.error = NOT_CONNECTED;
2251 Standard_Boolean hasIsolated = Standard_False;
2252 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2253 if (!aLargestSet.Contains(ibl)) {
2254 aProcessedMap.Clear();
2255 if (!HasAnyConnection(ibl, aLargestSet, aRelations, aProcessedMap)) {
2256 // report connection absence
2257 hasIsolated = Standard_True;
2258 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(ibl)));
2263 isCompOfBlocks = Standard_False;
2264 theErrors.push_back(anErr);
2268 return isCompOfBlocks;
2271 //=============================================================================
2275 //=============================================================================
2276 TCollection_AsciiString GEOMImpl_IBlocksOperations::PrintBCErrors
2277 (Handle(GEOM_Object) theCompound,
2278 const std::list<BCError>& theErrors)
2280 TCollection_AsciiString aDescr;
2282 std::list<BCError>::const_iterator errIt = theErrors.begin();
2284 for (; errIt != theErrors.end(); i++, errIt++) {
2285 BCError errStruct = *errIt;
2287 switch (errStruct.error) {
2289 aDescr += "\n\tNot a Blocks: ";
2292 aDescr += "\n\tHexahedral solids with degenerated and/or seam edges: ";
2294 case INVALID_CONNECTION:
2295 aDescr += "\n\tInvalid connection between two blocks: ";
2298 aDescr += "\n\tBlocks, not connected with main body: ";
2301 aDescr += "\n\tNot glued blocks: ";
2307 std::list<int> sshList = errStruct.incriminated;
2308 std::list<int>::iterator sshIt = sshList.begin();
2310 for (; sshIt != sshList.end(); jj++, sshIt++) {
2313 aDescr += TCollection_AsciiString(*sshIt);
2320 //=============================================================================
2322 * CheckCompoundOfBlocks
2324 //=============================================================================
2325 Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocks
2326 (Handle(GEOM_Object) theCompound,
2327 std::list<BCError>& theErrors)
2331 if (theCompound.IsNull()) return Standard_False;
2332 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2334 Standard_Boolean isCompOfBlocks = Standard_True;
2336 // Map sub-shapes and their indices
2337 TopTools_IndexedMapOfShape anIndices;
2338 TopExp::MapShapes(aBlockOrComp, anIndices);
2340 // 1. Separate blocks from non-blocks
2341 TopTools_ListOfShape NOT; // Not blocks
2342 TopTools_ListOfShape EXT; // Hexahedral solids, having degenerated and/or seam edges
2343 TopTools_ListOfShape BLO; // All blocks from the given compound
2344 TopTools_ListOfShape NOQ; // All non-quadrangular faces
2345 AddBlocksFrom(aBlockOrComp, BLO, NOT, EXT, NOQ);
2347 // Report non-blocks
2348 if (NOT.Extent() > 0) {
2349 isCompOfBlocks = Standard_False;
2351 anErr.error = NOT_BLOCK;
2352 TopTools_ListIteratorOfListOfShape it (NOT);
2353 for (; it.More(); it.Next()) {
2354 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
2356 theErrors.push_back(anErr);
2359 // Report solids, having degenerated and/or seam edges
2360 if (EXT.Extent() > 0) {
2361 isCompOfBlocks = Standard_False;
2363 anErr.error = EXTRA_EDGE;
2364 TopTools_ListIteratorOfListOfShape it (EXT);
2365 for (; it.More(); it.Next()) {
2366 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
2368 theErrors.push_back(anErr);
2371 Standard_Integer nbBlocks = BLO.Extent();
2372 if (nbBlocks == 0) {
2373 isCompOfBlocks = Standard_False;
2375 return isCompOfBlocks;
2377 if (nbBlocks == 1) {
2379 return isCompOfBlocks;
2382 // Prepare data for 2. and 3.
2383 TColStd_Array2OfInteger aRelations (1, nbBlocks, 1, nbBlocks);
2384 aRelations.Init(REL_NOT_CONNECTED);
2386 TopTools_IndexedMapOfShape mapBlocks;
2389 TopoDS_Compound aComp;
2390 BB.MakeCompound(aComp);
2392 TopTools_ListIteratorOfListOfShape BLOit (BLO);
2393 for (; BLOit.More(); BLOit.Next()) {
2394 mapBlocks.Add(BLOit.Value());
2395 BB.Add(aComp, BLOit.Value());
2398 // 2. Find glued blocks (having shared faces)
2399 TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
2400 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2401 (aComp, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
2403 Standard_Integer prevInd = 0, curInd = 0;
2404 Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
2405 for (; ind <= nbFaces; ind++) {
2406 const TopTools_ListOfShape& aGluedBlocks = mapFaceBlocks.FindFromIndex(ind);
2407 if (aGluedBlocks.Extent() > 1) { // Shared face found
2408 TopTools_ListIteratorOfListOfShape aGluedBlocksIt (aGluedBlocks);
2409 TopoDS_Shape prevBlock, curBlock;
2410 for (; aGluedBlocksIt.More(); aGluedBlocksIt.Next()) {
2411 curBlock = aGluedBlocksIt.Value();
2412 if (!prevBlock.IsNull()) {
2413 prevInd = mapBlocks.FindIndex(prevBlock);
2414 curInd = mapBlocks.FindIndex(curBlock);
2415 aRelations.SetValue(prevInd, curInd, REL_OK);
2416 aRelations.SetValue(curInd, prevInd, REL_OK);
2418 prevBlock = curBlock;
2423 // 3. Find not glued blocks
2424 GEOMAlgo_GlueAnalyser aGD;
2426 aGD.SetShape(aComp);
2427 aGD.SetTolerance(Precision::Confusion());
2428 aGD.SetCheckGeometry(Standard_True);
2431 Standard_Integer iErr, iWrn;
2432 iErr = aGD.ErrorStatus();
2434 SetErrorCode("Error in GEOMAlgo_GlueAnalyser");
2435 return isCompOfBlocks;
2437 iWrn = aGD.WarningStatus();
2439 MESSAGE("Warning in GEOMAlgo_GlueAnalyser");
2442 // Report not glued blocks
2443 if (aGD.HasSolidsToGlue()) {
2444 isCompOfBlocks = Standard_False;
2445 Standard_Integer aSx1Ind, aSx2Ind;
2447 const GEOMAlgo_ListOfCoupleOfShapes& aLCS = aGD.SolidsToGlue();
2448 GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS (aLCS);
2449 for (; aItCS.More(); aItCS.Next()) {
2450 const GEOMAlgo_CoupleOfShapes& aCS = aItCS.Value();
2451 const TopoDS_Shape& aSx1 = aCS.Shape1();
2452 const TopoDS_Shape& aSx2 = aCS.Shape2();
2454 aSx1Ind = mapBlocks.FindIndex(aSx1);
2455 aSx2Ind = mapBlocks.FindIndex(aSx2);
2456 aRelations.SetValue(aSx1Ind, aSx2Ind, NOT_GLUED);
2457 aRelations.SetValue(aSx2Ind, aSx1Ind, NOT_GLUED);
2460 anErr.error = NOT_GLUED;
2461 anErr.incriminated.push_back(anIndices.FindIndex(aSx1));
2462 anErr.incriminated.push_back(anIndices.FindIndex(aSx2));
2463 theErrors.push_back(anErr);
2467 // 4. Find largest set of connected (good connection or not glued) blocks
2468 Standard_Integer ibl = 1;
2469 TColStd_MapOfInteger aProcessedMap;
2470 TColStd_MapOfInteger aLargestSet;
2471 TColStd_MapOfInteger aCurrentSet;
2472 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2473 if (!aProcessedMap.Contains(ibl)) {
2474 aCurrentSet.Clear();
2475 FindConnected(ibl, aRelations, aProcessedMap, aCurrentSet);
2476 if (aCurrentSet.Extent() > aLargestSet.Extent()) {
2477 aLargestSet = aCurrentSet;
2482 // 5. Report all blocks, isolated from <aLargestSet>
2484 anErr.error = NOT_CONNECTED;
2485 Standard_Boolean hasIsolated = Standard_False;
2486 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2487 if (!aLargestSet.Contains(ibl)) {
2488 aProcessedMap.Clear();
2489 if (!HasAnyConnection(ibl, aLargestSet, aRelations, aProcessedMap)) {
2490 // report connection absence
2491 hasIsolated = Standard_True;
2492 anErr.incriminated.push_back(anIndices.FindIndex(mapBlocks.FindKey(ibl)));
2497 isCompOfBlocks = Standard_False;
2498 theErrors.push_back(anErr);
2502 return isCompOfBlocks;
2505 //=============================================================================
2509 //=============================================================================
2510 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetNonBlocks
2511 (Handle(GEOM_Object) theShape,
2512 Handle(GEOM_Object)& theNonQuads)
2516 if (theShape.IsNull()) return NULL;
2517 TopoDS_Shape aShape = theShape->GetValue();
2519 // Separate blocks from non-blocks
2520 TopTools_ListOfShape BLO; // All blocks from the given compound
2521 TopTools_ListOfShape NOT; // Not blocks
2522 TopTools_ListOfShape EXT; // Hexahedral solids, having degenerated and/or seam edges
2523 TopTools_ListOfShape NOQ; // All non-quadrangular faces
2524 AddBlocksFrom(aShape, BLO, NOT, EXT, NOQ);
2526 if (NOT.IsEmpty() && EXT.IsEmpty() && NOQ.IsEmpty()) {
2527 SetErrorCode("NOT_FOUND_ANY");
2531 // Map sub-shapes and their indices
2532 TopTools_IndexedMapOfShape anIndices;
2533 TopExp::MapShapes(aShape, anIndices);
2536 Handle(GEOM_Object) aNonBlocks;
2537 if (NOT.Extent() > 0 || EXT.Extent() > 0) {
2538 Handle(TColStd_HArray1OfInteger) anArray =
2539 new TColStd_HArray1OfInteger (1, NOT.Extent() + EXT.Extent());
2540 Standard_Integer ii = 1;
2541 TopTools_ListIteratorOfListOfShape it1 (NOT);
2542 for (; it1.More(); it1.Next(), ii++) {
2543 anArray->SetValue(ii, anIndices.FindIndex(it1.Value()));
2545 TopTools_ListIteratorOfListOfShape it2 (EXT);
2546 for (; it2.More(); it2.Next(), ii++) {
2547 anArray->SetValue(ii, anIndices.FindIndex(it2.Value()));
2550 aNonBlocks = GetEngine()->AddSubShape(theShape, anArray);
2551 if (aNonBlocks.IsNull()) {
2552 SetErrorCode("Error in algorithm: result found, but cannot be returned.");
2555 aNonBlocks->SetType(GEOM_GROUP);
2556 TDF_Label aFreeLabel = aNonBlocks->GetFreeLabel();
2557 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)TopAbs_SOLID);
2561 if (NOQ.Extent() > 0) {
2562 Handle(TColStd_HArray1OfInteger) anArray =
2563 new TColStd_HArray1OfInteger (1, NOQ.Extent());
2564 Standard_Integer ii = 1;
2565 TopTools_ListIteratorOfListOfShape it1 (NOQ);
2566 for (; it1.More(); it1.Next(), ii++) {
2567 anArray->SetValue(ii, anIndices.FindIndex(it1.Value()));
2570 theNonQuads = GetEngine()->AddSubShape(theShape, anArray);
2571 if (theNonQuads.IsNull()) {
2572 SetErrorCode("Error in algorithm: result found, but cannot be returned.");
2575 theNonQuads->SetType(GEOM_GROUP);
2576 TDF_Label aFreeLabel = theNonQuads->GetFreeLabel();
2577 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)TopAbs_FACE);
2580 //Make a Python command
2581 Handle(GEOM_Function) aMainShape = theShape->GetLastFunction();
2582 GEOM::TPythonDump pd (aMainShape, /*append=*/true);
2584 if (aNonBlocks.IsNull())
2585 pd << "no_bad_solids";
2589 if (theNonQuads.IsNull())
2590 pd << "no_bad_faces";
2593 pd << ") = geompy.GetNonBlocks(" << theShape << ")";
2599 //=============================================================================
2603 //=============================================================================
2604 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::RemoveExtraEdges
2605 (Handle(GEOM_Object) theObject,
2606 const Standard_Integer theOptimumNbFaces)
2610 if (theObject.IsNull()) return NULL;
2612 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2613 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be fixed
2615 //Add a new Copy object
2616 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2619 Handle(GEOM_Function) aFunction =
2620 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_REMOVE_EXTRA);
2622 //Check if the function is set correctly
2623 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2625 GEOMImpl_IBlockTrsf aTI (aFunction);
2626 aTI.SetOriginal(aLastFunction);
2627 aTI.SetOptimumNbFaces(theOptimumNbFaces);
2629 //Compute the fixed shape
2631 #if OCC_VERSION_LARGE > 0x06010000
2634 if (!GetSolver()->ComputeFunction(aFunction)) {
2635 SetErrorCode("Block driver failed to remove extra edges of the given shape");
2639 catch (Standard_Failure) {
2640 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2641 SetErrorCode(aFail->GetMessageString());
2645 //Make a Python command
2646 std::string doUnionFaces = (theOptimumNbFaces < 0) ? "False" : "True";
2647 GEOM::TPythonDump(aFunction) << aCopy << " = geompy.RemoveExtraEdges("
2648 << theObject << ", " << doUnionFaces.data() << ")";
2654 //=============================================================================
2658 //=============================================================================
2659 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::UnionFaces
2660 (Handle(GEOM_Object) theObject)
2664 if (theObject.IsNull()) return NULL;
2666 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2667 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be fixed
2669 //Add a new Copy object
2670 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2673 Handle(GEOM_Function) aFunction =
2674 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_UNION_FACES);
2676 //Check if the function is set correctly
2677 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2679 GEOMImpl_IBlockTrsf aTI (aFunction);
2680 aTI.SetOriginal(aLastFunction);
2682 //Compute the fixed shape
2684 #if OCC_VERSION_LARGE > 0x06010000
2687 if (!GetSolver()->ComputeFunction(aFunction)) {
2688 SetErrorCode("Block driver failed to remove extra edges of the given shape");
2692 catch (Standard_Failure) {
2693 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2694 SetErrorCode(aFail->GetMessageString());
2698 //Make a Python command
2699 GEOM::TPythonDump(aFunction) << aCopy << " = geompy.UnionFaces("
2700 << theObject << ")";
2706 //=============================================================================
2710 //=============================================================================
2711 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::CheckAndImprove
2712 (Handle(GEOM_Object) theObject)
2716 if (theObject.IsNull()) return NULL;
2718 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2719 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be fixed
2721 //Add a new Copy object
2722 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2725 Handle(GEOM_Function) aFunction =
2726 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_COMPOUND_IMPROVE);
2728 //Check if the function is set correctly
2729 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2731 GEOMImpl_IBlockTrsf aTI (aFunction);
2732 aTI.SetOriginal(aLastFunction);
2734 // -1 means do not unite faces on common surface (?except case of seam edge between them?)
2735 //aTI.SetOptimumNbFaces(-1);
2736 aTI.SetOptimumNbFaces(6);
2738 //Compute the fixed shape
2740 #if OCC_VERSION_LARGE > 0x06010000
2743 if (!GetSolver()->ComputeFunction(aFunction)) {
2744 SetErrorCode("Block driver failed to improve the given blocks compound");
2748 catch (Standard_Failure) {
2749 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2750 SetErrorCode(aFail->GetMessageString());
2754 //Make a Python command
2755 GEOM::TPythonDump(aFunction) << aCopy
2756 << " = geompy.CheckAndImprove(" << theObject << ")";
2762 //=============================================================================
2764 * ExplodeCompoundOfBlocks
2766 //=============================================================================
2767 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::ExplodeCompoundOfBlocks
2768 (Handle(GEOM_Object) theCompound,
2769 const Standard_Integer theMinNbFaces,
2770 const Standard_Integer theMaxNbFaces)
2774 if (theCompound.IsNull()) return NULL;
2775 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2776 if (aBlockOrComp.IsNull()) return NULL;
2778 Handle(TColStd_HSequenceOfTransient) aBlocks = new TColStd_HSequenceOfTransient;
2779 Handle(GEOM_Object) anObj;
2780 Handle(GEOM_Function) aFunction;
2782 TopTools_MapOfShape mapShape;
2783 TCollection_AsciiString anAsciiList, anEntry;
2786 TopTools_IndexedMapOfShape anIndices;
2787 TopExp::MapShapes(aBlockOrComp, anIndices);
2788 Handle(TColStd_HArray1OfInteger) anArray;
2792 #if OCC_VERSION_LARGE > 0x06010000
2795 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2796 for (; exp.More(); exp.Next()) {
2797 if (mapShape.Add(exp.Current())) {
2798 TopoDS_Shape aSolid = exp.Current();
2800 TopTools_MapOfShape mapFaces;
2801 TopExp_Explorer expF (aSolid, TopAbs_FACE);
2802 Standard_Integer nbFaces = 0;
2803 for (; expF.More(); expF.Next()) {
2804 if (mapFaces.Add(expF.Current())) {
2809 if (theMinNbFaces <= nbFaces && nbFaces <= theMaxNbFaces) {
2810 anArray = new TColStd_HArray1OfInteger(1,1);
2811 anArray->SetValue(1, anIndices.FindIndex(aSolid));
2812 anObj = GetEngine()->AddSubShape(theCompound, anArray);
2813 aBlocks->Append(anObj);
2815 //Make a Python command
2816 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2817 anAsciiList += anEntry + ", ";
2822 catch (Standard_Failure) {
2823 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2824 SetErrorCode(aFail->GetMessageString());
2828 if (aBlocks->IsEmpty()) {
2829 SetErrorCode("There are no specified blocks in the given shape");
2833 anAsciiList.Trunc(anAsciiList.Length() - 2);
2835 //The explode doesn't change object so no new function is required.
2836 aFunction = theCompound->GetLastFunction();
2838 //Make a Python command
2839 GEOM::TPythonDump(aFunction, /*append=*/true)
2840 << "[" << anAsciiList.ToCString() << "] = geompy.MakeBlockExplode("
2841 << theCompound << ", " << theMinNbFaces << ", " << theMaxNbFaces << ")";
2847 //=============================================================================
2851 //=============================================================================
2852 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetBlockNearPoint
2853 (Handle(GEOM_Object) theCompound,
2854 Handle(GEOM_Object) thePoint)
2859 Handle(GEOM_Object) aResult;
2862 if (theCompound.IsNull() || thePoint.IsNull()) return NULL;
2864 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2865 if (aBlockOrComp.IsNull()) {
2866 SetErrorCode("Compound is null");
2869 if (aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
2870 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
2871 SetErrorCode("Shape to find block in is not a compound");
2875 TopoDS_Shape anArg = thePoint->GetValue();
2876 if (anArg.IsNull()) {
2877 SetErrorCode("Point is null");
2880 if (anArg.ShapeType() != TopAbs_VERTEX) {
2881 SetErrorCode("Shape for block identification is not a vertex");
2885 //Compute the Block value
2887 #if OCC_VERSION_LARGE > 0x06010000
2890 TopoDS_Shape aShape;
2892 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
2893 gp_Pnt aPnt = BRep_Tool::Pnt(aVert);
2894 Standard_Real PX, PY, PZ;
2895 aPnt.Coord(PX, PY, PZ);
2897 // 1. Classify the point relatively each block
2898 Standard_Integer nearest = 2, nbFound = 0;
2899 TopTools_DataMapOfShapeInteger mapShapeDist;
2900 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2901 for (; exp.More(); exp.Next()) {
2902 TopoDS_Shape aSolid = exp.Current();
2904 if (!mapShapeDist.IsBound(aSolid)) {
2905 Standard_Integer aDistance = 2;
2907 // 1.a. Classify relatively Bounding box
2908 Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
2910 BRepBndLib::Add(aSolid, BB);
2911 BB.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
2912 if (PX < Xmin || Xmax < PX ||
2913 PY < Ymin || Ymax < PY ||
2914 PZ < Zmin || Zmax < PZ) {
2915 // OUT of bounding box
2918 // 1.b. Classify relatively the solid itself
2919 BRepClass3d_SolidClassifier SC (aSolid, aPnt, Precision::Confusion());
2920 if (SC.State() == TopAbs_IN) {
2922 } else if (SC.State() == TopAbs_ON) {
2929 if (aDistance < nearest) {
2930 nearest = aDistance;
2934 // A first found block, containing the point inside, will be returned.
2935 // It is the solution, if there are no intersecting blocks in the compound.
2936 if (nearest == -1) break;
2938 } else if (aDistance == nearest) {
2943 mapShapeDist.Bind(aSolid, aDistance);
2944 } // if (!mapShapeDist.IsBound(aSolid))
2947 // 2. Define block, containing the point or having minimum distance to it
2950 // The point is on boundary of some blocks and there are
2951 // no blocks, having the point inside their volume
2952 SetErrorCode("Multiple blocks near the given point are found");
2955 } else if (nearest == 1) {
2956 // The point is outside some blocks and there are
2957 // no blocks, having the point inside or on boundary.
2958 // We will get a nearest block
2959 Standard_Real minDist = RealLast();
2960 TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
2961 for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
2962 if (mapShapeDistIter.Value() == 1) {
2963 TopoDS_Shape aSolid = mapShapeDistIter.Key();
2964 BRepExtrema_DistShapeShape aDistTool (aVert, aSolid);
2965 if (!aDistTool.IsDone()) {
2966 SetErrorCode("Can not find a distance from the given point to one of blocks");
2969 Standard_Real aDist = aDistTool.Value();
2970 if (aDist < minDist) {
2976 } else { // nearest == -1
2977 // // The point is inside some blocks.
2978 // // We will get a block with nearest center
2979 // Standard_Real minDist = RealLast();
2980 // TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
2981 // for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
2982 // if (mapShapeDistIter.Value() == -1) {
2983 // TopoDS_Shape aSolid = mapShapeDistIter.Key();
2984 // GProp_GProps aSystem;
2985 // BRepGProp::VolumeProperties(aSolid, aSystem);
2986 // gp_Pnt aCenterMass = aSystem.CentreOfMass();
2988 // Standard_Real aDist = aCenterMass.Distance(aPnt);
2989 // if (aDist < minDist) {
2996 } // if (nbFound > 1)
2999 SetErrorCode("There are no blocks near the given point");
3002 TopTools_IndexedMapOfShape anIndices;
3003 TopExp::MapShapes(aBlockOrComp, anIndices);
3004 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
3005 anArray->SetValue(1, anIndices.FindIndex(aShape));
3006 aResult = GetEngine()->AddSubShape(theCompound, anArray);
3009 catch (Standard_Failure) {
3010 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3011 SetErrorCode(aFail->GetMessageString());
3015 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
3017 //Make a Python command
3018 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetBlockNearPoint("
3019 << theCompound << ", " << thePoint << ")";
3025 //=============================================================================
3029 //=============================================================================
3030 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetBlockByParts
3031 (Handle(GEOM_Object) theCompound,
3032 const Handle(TColStd_HSequenceOfTransient)& theParts)
3036 Handle(GEOM_Object) aResult;
3038 if (theCompound.IsNull() || theParts.IsNull()) return NULL;
3039 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
3040 if (aBlockOrComp.IsNull()) return NULL;
3043 Standard_Integer argi, aLen = theParts->Length();
3044 TopTools_Array1OfShape anArgs (1, aLen);
3045 TCollection_AsciiString anEntry, aPartsDescr;
3046 for (argi = 1; argi <= aLen; argi++) {
3047 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theParts->Value(argi));
3048 Handle(GEOM_Function) aRef = anObj->GetLastFunction();
3049 if (aRef.IsNull()) return NULL;
3051 TopoDS_Shape anArg = aRef->GetValue();
3052 if (anArg.IsNull()) {
3053 SetErrorCode("Null shape is given as argument");
3056 anArgs(argi) = anArg;
3058 // For Python command
3059 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
3060 if (argi > 1) aPartsDescr += ", ";
3061 aPartsDescr += anEntry;
3064 //Compute the Block value
3066 #if OCC_VERSION_LARGE > 0x06010000
3069 // 1. Explode compound on solids
3070 TopTools_MapOfShape mapShape;
3071 Standard_Integer nbSolids = 0;
3072 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
3073 for (; exp.More(); exp.Next()) {
3074 if (mapShape.Add(exp.Current())) {
3080 Standard_Integer ind = 1;
3081 TopTools_Array1OfShape aSolids (1, nbSolids);
3082 TColStd_Array1OfInteger aNbParts (1, nbSolids);
3083 for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next(), ind++) {
3084 if (mapShape.Add(exp.Current())) {
3085 TopoDS_Shape aSolid = exp.Current();
3086 aSolids(ind) = aSolid;
3089 // 2. Define quantity of parts, contained in each solid
3090 TopTools_IndexedMapOfShape aSubShapes;
3091 TopExp::MapShapes(aSolid, aSubShapes);
3092 for (argi = 1; argi <= aLen; argi++) {
3093 if (aSubShapes.Contains(anArgs(argi))) {
3100 // 3. Define solid, containing maximum quantity of parts
3101 Standard_Integer maxNb = 0, nbFound = 0;
3102 TopoDS_Shape aShape;
3103 for (ind = 1; ind <= nbSolids; ind++) {
3104 if (aNbParts(ind) > maxNb) {
3105 maxNb = aNbParts(ind);
3106 aShape = aSolids(ind);
3108 } else if (aNbParts(ind) == maxNb) {
3114 SetErrorCode("Multiple blocks, containing maximum quantity of the given parts, are found");
3116 } else if (nbFound == 0) {
3117 SetErrorCode("There are no blocks, containing the given parts");
3120 TopTools_IndexedMapOfShape anIndices;
3121 TopExp::MapShapes(aBlockOrComp, anIndices);
3122 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
3123 anArray->SetValue(1, anIndices.FindIndex(aShape));
3124 aResult = GetEngine()->AddSubShape(theCompound, anArray);
3126 } catch (Standard_Failure) {
3127 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3128 SetErrorCode(aFail->GetMessageString());
3132 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
3134 //Make a Python command
3135 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetBlockByParts("
3136 << theCompound << ", [" << aPartsDescr.ToCString() << "])";
3142 //=============================================================================
3146 //=============================================================================
3147 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::GetBlocksByParts
3148 (Handle(GEOM_Object) theCompound,
3149 const Handle(TColStd_HSequenceOfTransient)& theParts)
3153 if (theCompound.IsNull() || theParts.IsNull()) return NULL;
3154 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
3155 if (aBlockOrComp.IsNull()) return NULL;
3157 Handle(TColStd_HSequenceOfTransient) aBlocks = new TColStd_HSequenceOfTransient;
3158 Handle(GEOM_Object) anObj;
3159 Handle(GEOM_Function) aFunction;
3162 Standard_Integer argi, aLen = theParts->Length();
3163 TopTools_Array1OfShape anArgs (1, aLen);
3164 TCollection_AsciiString anEntry, aPartsDescr, anAsciiList;
3166 for (argi = 1; argi <= aLen; argi++) {
3167 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theParts->Value(argi));
3168 Handle(GEOM_Function) aRef = anObj->GetLastFunction();
3169 if (aRef.IsNull()) return NULL;
3171 TopoDS_Shape anArg = aRef->GetValue();
3172 if (anArg.IsNull()) {
3173 SetErrorCode("Null shape is given as argument");
3176 anArgs(argi) = anArg;
3178 // For Python command
3179 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
3180 aPartsDescr += anEntry + ", ";
3185 #if OCC_VERSION_LARGE > 0x06010000
3188 TopTools_MapOfShape mapShape;
3189 Standard_Integer nbSolids = 0;
3190 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
3191 for (; exp.More(); exp.Next()) {
3192 if (mapShape.Add(exp.Current())) {
3198 Standard_Integer ind = 1;
3199 TopTools_Array1OfShape aSolids (1, nbSolids);
3200 TColStd_Array1OfInteger aNbParts (1, nbSolids);
3201 for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next(), ind++) {
3202 if (mapShape.Add(exp.Current())) {
3203 TopoDS_Shape aSolid = exp.Current();
3204 aSolids(ind) = aSolid;
3207 // 2. Define quantity of parts, contained in each solid
3208 TopTools_IndexedMapOfShape aSubShapes;
3209 TopExp::MapShapes(aSolid, aSubShapes);
3210 for (argi = 1; argi <= aLen; argi++) {
3211 if (aSubShapes.Contains(anArgs(argi))) {
3218 // 3. Define solid, containing maximum quantity of parts
3219 Standard_Integer maxNb = 0, nbFound = 0;
3220 for (ind = 1; ind <= nbSolids; ind++) {
3221 if (aNbParts(ind) > maxNb) {
3222 maxNb = aNbParts(ind);
3224 } else if (aNbParts(ind) == maxNb) {
3230 SetErrorCode("There are no blocks, containing the given parts");
3235 TopTools_IndexedMapOfShape anIndices;
3236 TopExp::MapShapes(aBlockOrComp, anIndices);
3237 Handle(TColStd_HArray1OfInteger) anArray;
3239 for (ind = 1; ind <= nbSolids; ind++) {
3240 if (aNbParts(ind) == maxNb) {
3241 anArray = new TColStd_HArray1OfInteger(1,1);
3242 anArray->SetValue(1, anIndices.FindIndex(aSolids(ind)));
3243 anObj = GetEngine()->AddSubShape(theCompound, anArray);
3244 aBlocks->Append(anObj);
3246 // For Python command
3247 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
3248 anAsciiList += anEntry + ", ";
3249 if (aFunction.IsNull())
3250 aFunction = anObj->GetLastFunction();
3254 catch (Standard_Failure) {
3255 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3256 SetErrorCode(aFail->GetMessageString());
3260 //Make a Python command
3261 aPartsDescr.Trunc(aPartsDescr.Length() - 2);
3262 anAsciiList.Trunc(anAsciiList.Length() - 2);
3264 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3265 << "] = geompy.GetBlocksByParts(" << theCompound
3266 << ", [" << aPartsDescr.ToCString() << "])";
3272 //=============================================================================
3274 * MakeMultiTransformation1D
3276 //=============================================================================
3277 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeMultiTransformation1D
3278 (Handle(GEOM_Object) theObject,
3279 const Standard_Integer theDirFace1,
3280 const Standard_Integer theDirFace2,
3281 const Standard_Integer theNbTimes)
3285 if (theObject.IsNull()) return NULL;
3287 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
3288 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be moved
3290 //Add a new Copy object
3291 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
3293 //Add a translate function
3294 Handle(GEOM_Function) aFunction =
3295 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_MULTI_TRANSFORM_1D);
3297 //Check if the function is set correctly
3298 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
3300 GEOMImpl_IBlockTrsf aTI (aFunction);
3301 aTI.SetOriginal(aLastFunction);
3302 aTI.SetFace1U(theDirFace1);
3303 aTI.SetFace2U(theDirFace2);
3304 aTI.SetNbIterU(theNbTimes);
3306 //Compute the transformation
3308 #if OCC_VERSION_LARGE > 0x06010000
3311 if (!GetSolver()->ComputeFunction(aFunction)) {
3312 SetErrorCode("Block driver failed to make multi-transformation");
3316 catch (Standard_Failure) {
3317 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3318 SetErrorCode(aFail->GetMessageString());
3322 //Make a Python command
3323 GEOM::TPythonDump(aFunction) << aCopy << " = geompy.MakeMultiTransformation1D("
3324 << theObject << ", " << theDirFace1 << ", " << theDirFace2 << ", " << theNbTimes << ")";
3330 //=============================================================================
3332 * MakeMultiTransformation2D
3334 //=============================================================================
3335 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeMultiTransformation2D
3336 (Handle(GEOM_Object) theObject,
3337 const Standard_Integer theDirFace1U,
3338 const Standard_Integer theDirFace2U,
3339 const Standard_Integer theNbTimesU,
3340 const Standard_Integer theDirFace1V,
3341 const Standard_Integer theDirFace2V,
3342 const Standard_Integer theNbTimesV)
3346 if (theObject.IsNull()) return NULL;
3348 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
3349 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be moved
3351 //Add a new Copy object
3352 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
3354 //Add a translate function
3355 Handle(GEOM_Function) aFunction =
3356 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_MULTI_TRANSFORM_2D);
3358 //Check if the function is set correctly
3359 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
3361 GEOMImpl_IBlockTrsf aTI (aFunction);
3362 aTI.SetOriginal(aLastFunction);
3363 aTI.SetFace1U(theDirFace1U);
3364 aTI.SetFace2U(theDirFace2U);
3365 aTI.SetNbIterU(theNbTimesU);
3366 aTI.SetFace1V(theDirFace1V);
3367 aTI.SetFace2V(theDirFace2V);
3368 aTI.SetNbIterV(theNbTimesV);
3370 //Compute the transformation
3372 #if OCC_VERSION_LARGE > 0x06010000
3375 if (!GetSolver()->ComputeFunction(aFunction)) {
3376 SetErrorCode("Block driver failed to make multi-transformation");
3380 catch (Standard_Failure) {
3381 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3382 SetErrorCode(aFail->GetMessageString());
3386 //Make a Python command
3387 GEOM::TPythonDump(aFunction) << aCopy << " = geompy.MakeMultiTransformation2D("
3388 << theObject << ", " << theDirFace1U << ", " << theDirFace2U << ", " << theNbTimesU
3389 << ", " << theDirFace1V << ", " << theDirFace2V << ", " << theNbTimesV << ")";
3395 //=============================================================================
3399 //=============================================================================
3400 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::Propagate
3401 (Handle(GEOM_Object) theShape)
3405 if (theShape.IsNull()) return NULL;
3407 TopoDS_Shape aShape = theShape->GetValue();
3408 if (aShape.IsNull()) return NULL;
3410 TopTools_IndexedMapOfShape anIndices;
3411 TopExp::MapShapes(aShape, anIndices);
3413 TopTools_IndexedDataMapOfShapeListOfShape MEW;
3414 GEOMImpl_Block6Explorer::MapShapesAndAncestors
3415 (aShape, TopAbs_EDGE, TopAbs_WIRE, MEW);
3416 Standard_Integer ie, nbEdges = MEW.Extent();
3419 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
3421 TopTools_MapOfShape mapAcceptedEdges;
3422 TCollection_AsciiString aListRes, anEntry;
3424 // Sort shapes in current chain (Mantis issue 21053)
3425 TopTools_DataMapOfShapeListOfShape aMapChains;
3426 TopTools_ListOfShape aFirstInChains;
3428 for (ie = 1; ie <= nbEdges; ie++) {
3429 TopoDS_Shape curE = MEW.FindKey(ie);
3431 if (mapAcceptedEdges.Contains(curE)) continue;
3434 TopTools_ListOfShape currentChain;
3435 TopTools_ListOfShape listPrevEdges;
3437 currentChain.Append(curE);
3438 listPrevEdges.Append(curE);
3439 mapAcceptedEdges.Add(curE);
3441 // Collect all edges pass by pass
3442 while (listPrevEdges.Extent() > 0) {
3443 // List of edges, added to chain on this cycle pass
3444 TopTools_ListOfShape listCurEdges;
3446 // Find the next portion of edges
3447 TopTools_ListIteratorOfListOfShape itE (listPrevEdges);
3448 for (; itE.More(); itE.Next()) {
3449 TopoDS_Shape anE = itE.Value();
3451 // Iterate on faces, having edge <anE>
3452 TopTools_ListIteratorOfListOfShape itW (MEW.FindFromKey(anE));
3453 for (; itW.More(); itW.Next()) {
3454 TopoDS_Shape aW = itW.Value();
3455 TopoDS_Shape anOppE;
3457 BRepTools_WireExplorer aWE (TopoDS::Wire(aW));
3458 Standard_Integer nb = 1, found = 0;
3459 TopTools_Array1OfShape anEdges (1,4);
3460 for (; aWE.More(); aWE.Next(), nb++) {
3465 anEdges(nb) = aWE.Current();
3466 if (anEdges(nb).IsSame(anE)) found = nb;
3469 if (nb == 5 && found > 0) {
3470 // Quadrangle face found, get an opposite edge
3471 Standard_Integer opp = found + 2;
3472 if (opp > 4) opp -= 4;
3473 anOppE = anEdges(opp);
3475 if (!mapAcceptedEdges.Contains(anOppE)) {
3476 // Add found edge to the chain
3477 currentChain.Append(anOppE);
3478 listCurEdges.Append(anOppE);
3479 mapAcceptedEdges.Add(anOppE);
3481 } // if (nb == 5 && found > 0)
3482 } // for (; itF.More(); itF.Next())
3483 } // for (; itE.More(); itE.Next())
3485 listPrevEdges = listCurEdges;
3486 } // while (listPrevEdges.Extent() > 0)
3488 // Sort shapes in current chain (Mantis issue 21053)
3489 GEOMUtils::SortShapes(currentChain, Standard_False);
3490 aFirstInChains.Append(currentChain.First());
3491 aMapChains.Bind(currentChain.First(), currentChain);
3494 // Sort chains (Mantis issue 21053)
3495 GEOMUtils::SortShapes(aFirstInChains, Standard_False);
3497 // Store sorted chains in the document
3498 TopTools_ListIteratorOfListOfShape aChainsIt (aFirstInChains);
3499 for (; aChainsIt.More(); aChainsIt.Next()) {
3500 TopoDS_Shape aFirstInChain = aChainsIt.Value();
3501 const TopTools_ListOfShape& currentChain = aMapChains.Find(aFirstInChain);
3503 // Store the chain in the document
3504 Handle(TColStd_HArray1OfInteger) anArray =
3505 new TColStd_HArray1OfInteger (1, currentChain.Extent());
3507 // Fill array of sub-shape indices
3508 TopTools_ListIteratorOfListOfShape itSub (currentChain);
3509 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
3510 int id = anIndices.FindIndex(itSub.Value());
3511 anArray->SetValue(index, id);
3514 // Add a new group object
3515 Handle(GEOM_Object) aChain = GetEngine()->AddSubShape(theShape, anArray);
3518 aChain->SetType(GEOM_GROUP);
3520 // Set a sub-shape type
3521 TDF_Label aFreeLabel = aChain->GetFreeLabel();
3522 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)TopAbs_EDGE);
3524 // Add the chain to the result
3525 aSeq->Append(aChain);
3527 //Make a Python command
3528 TDF_Tool::Entry(aChain->GetEntry(), anEntry);
3529 aListRes += anEntry + ", ";
3532 if (aSeq->IsEmpty()) {
3533 SetErrorCode("There are no quadrangle faces in the shape");
3537 aListRes.Trunc(aListRes.Length() - 2);
3539 // The Propagation doesn't change object so no new function is required.
3540 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
3542 // Make a Python command
3543 GEOM::TPythonDump(aFunction, /*append=*/true)
3544 << "[" << aListRes.ToCString() << "] = geompy.Propagate(" << theShape << ")";