1 // Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
24 #pragma warning( disable:4786 )
27 #include <Standard_Stream.hxx>
29 #include <GEOMImpl_IBlocksOperations.hxx>
31 #include <GEOMImpl_Types.hxx>
33 #include <GEOMImpl_BlockDriver.hxx>
34 #include <GEOMImpl_IBlocks.hxx>
35 #include <GEOMImpl_IBlockTrsf.hxx>
36 #include <GEOMImpl_CopyDriver.hxx>
37 #include <GEOMImpl_Block6Explorer.hxx>
38 #include <GEOMImpl_IShapesOperations.hxx>
40 #include <GEOM_Function.hxx>
41 #include <GEOM_PythonDump.hxx>
43 #include <GEOMAlgo_GlueAnalyser.hxx>
44 #include <GEOMAlgo_CoupleOfShapes.hxx>
45 #include <GEOMAlgo_ListOfCoupleOfShapes.hxx>
46 #include <GEOMAlgo_ListIteratorOfListOfCoupleOfShapes.hxx>
47 #include <BlockFix_CheckTool.hxx>
49 #include <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 // The GetPoint() doesn't change object so no new function is required.
639 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
641 // Make a Python command
642 GEOM::TPythonDump(aFunction, /*append=*/true)
643 << aResult << " = geompy.GetVertexNearPoint("
644 << theShape << ", " << thePoint << ")";
650 //=============================================================================
654 //=============================================================================
655 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetEdge
656 (Handle(GEOM_Object) theShape,
657 Handle(GEOM_Object) thePoint1,
658 Handle(GEOM_Object) thePoint2)
663 Handle(GEOM_Object) aResult;
666 if (theShape.IsNull() || thePoint1.IsNull() || thePoint2.IsNull()) return NULL;
668 TopoDS_Shape aBlockOrComp = theShape->GetValue();
669 if (aBlockOrComp.IsNull()) {
670 SetErrorCode("Given shape is null");
674 TopoDS_Shape anArg1 = thePoint1->GetValue();
675 TopoDS_Shape anArg2 = thePoint2->GetValue();
676 if (anArg1.IsNull() || anArg2.IsNull()) {
677 SetErrorCode("Null shape is given as argument");
680 if (anArg1.ShapeType() != TopAbs_VERTEX ||
681 anArg2.ShapeType() != TopAbs_VERTEX) {
682 SetErrorCode("Element for edge identification is not a vertex");
686 //Compute the Edge value
688 #if OCC_VERSION_LARGE > 0x06010000
691 TopTools_IndexedDataMapOfShapeListOfShape MVE;
692 GEOMImpl_Block6Explorer::MapShapesAndAncestors
693 (aBlockOrComp, TopAbs_VERTEX, TopAbs_EDGE, MVE);
696 Standard_Integer ish, ext = MVE.Extent();
698 if (MVE.Contains(anArg1)) {
701 for (ish = 1; ish <= ext; ish++) {
702 TopoDS_Shape aShi = MVE.FindKey(ish);
703 if (BRepTools::Compare(TopoDS::Vertex(anArg1), TopoDS::Vertex(aShi))) {
710 if (MVE.Contains(anArg2)) {
713 for (ish = 1; ish <= ext; ish++) {
714 TopoDS_Shape aShi = MVE.FindKey(ish);
715 if (BRepTools::Compare(TopoDS::Vertex(anArg2), TopoDS::Vertex(aShi))) {
722 if (V1.IsNull() || V2.IsNull()) {
723 SetErrorCode("The given vertex does not belong to the shape");
728 Standard_Integer isFound =
729 GEOMImpl_Block6Explorer::FindEdge(anEdge, V1, V2, MVE, Standard_True);
731 SetErrorCode("The given vertices do not belong to one edge of the given shape");
733 } else if (isFound > 1) {
734 SetErrorCode("Multiple edges found by the given vertices of the shape");
737 TopTools_IndexedMapOfShape anIndices;
738 TopExp::MapShapes(aBlockOrComp, anIndices);
739 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
740 anArray->SetValue(1, anIndices.FindIndex(anEdge));
741 aResult = GetEngine()->AddSubShape(theShape, anArray);
743 } catch (Standard_Failure) {
744 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
745 SetErrorCode(aFail->GetMessageString());
749 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
751 //Make a Python command
752 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetEdge("
753 << theShape << ", " << thePoint1 << ", " << thePoint2 << ")";
759 //=============================================================================
763 //=============================================================================
764 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetEdgeNearPoint
765 (Handle(GEOM_Object) theShape,
766 Handle(GEOM_Object) thePoint)
771 Handle(GEOM_Object) aResult;
774 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
776 TopoDS_Shape aBlockOrComp = theShape->GetValue();
777 if (aBlockOrComp.IsNull()) {
778 SetErrorCode("Given shape is null");
782 TopoDS_Shape anArg = thePoint->GetValue();
783 if (anArg.IsNull()) {
784 SetErrorCode("Null shape is given as argument");
787 if (anArg.ShapeType() != TopAbs_VERTEX) {
788 SetErrorCode("Element for edge identification is not a vertex");
792 //Compute the Edge value
794 #if OCC_VERSION_LARGE > 0x06010000
799 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
801 // 1. Explode blocks on edges
802 TopTools_MapOfShape mapShape;
803 Standard_Integer nbEdges = 0;
804 TopExp_Explorer exp (aBlockOrComp, TopAbs_EDGE);
805 for (; exp.More(); exp.Next()) {
806 if (mapShape.Add(exp.Current())) {
812 SetErrorCode("Given shape contains no edges");
817 Standard_Integer ind = 1;
818 TopTools_Array1OfShape anEdges (1, nbEdges);
819 TColStd_Array1OfReal aDistances (1, nbEdges);
820 for (exp.Init(aBlockOrComp, TopAbs_EDGE); exp.More(); exp.Next()) {
821 if (mapShape.Add(exp.Current())) {
822 TopoDS_Shape anEdge = exp.Current();
823 anEdges(ind) = anEdge;
825 // 2. Classify the point relatively each edge
826 BRepExtrema_DistShapeShape aDistTool (aVert, anEdges(ind));
827 if (!aDistTool.IsDone()) {
828 SetErrorCode("Can not find a distance from the given point to one of edges");
831 aDistances(ind) = aDistTool.Value();
836 // 3. Define edge, having minimum distance to the point
837 Standard_Real nearest = RealLast(), nbFound = 0;
838 Standard_Real prec = Precision::Confusion();
839 for (ind = 1; ind <= nbEdges; ind++) {
840 if (Abs(aDistances(ind) - nearest) < prec) {
842 } else if (aDistances(ind) < nearest) {
843 nearest = aDistances(ind);
844 aShape = anEdges(ind);
850 SetErrorCode("Multiple edges near the given point are found");
852 } else if (nbFound == 0) {
853 SetErrorCode("There are no edges near the given point");
856 TopTools_IndexedMapOfShape anIndices;
857 TopExp::MapShapes(aBlockOrComp, anIndices);
858 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
859 anArray->SetValue(1, anIndices.FindIndex(aShape));
860 aResult = GetEngine()->AddSubShape(theShape, anArray);
863 catch (Standard_Failure) {
864 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
865 SetErrorCode(aFail->GetMessageString());
869 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
871 //Make a Python command
872 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetEdgeNearPoint("
873 << theShape << ", " << thePoint << ")";
879 //=============================================================================
883 //=============================================================================
884 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByPoints
885 (Handle(GEOM_Object) theShape,
886 Handle(GEOM_Object) thePoint1,
887 Handle(GEOM_Object) thePoint2,
888 Handle(GEOM_Object) thePoint3,
889 Handle(GEOM_Object) thePoint4)
894 Handle(GEOM_Object) aResult;
897 if (theShape.IsNull() ||
898 thePoint1.IsNull() || thePoint2.IsNull() ||
899 thePoint3.IsNull() || thePoint4.IsNull()) return NULL;
901 TopoDS_Shape aBlockOrComp = theShape->GetValue();
902 if (aBlockOrComp.IsNull()) {
903 SetErrorCode("Block or compound is null");
907 TopoDS_Shape anArg1 = thePoint1->GetValue();
908 TopoDS_Shape anArg2 = thePoint2->GetValue();
909 TopoDS_Shape anArg3 = thePoint3->GetValue();
910 TopoDS_Shape anArg4 = thePoint4->GetValue();
911 if (anArg1.IsNull() || anArg2.IsNull() ||
912 anArg3.IsNull() || anArg4.IsNull()) {
913 SetErrorCode("Null shape is given as argument");
916 if (anArg1.ShapeType() != TopAbs_VERTEX ||
917 anArg2.ShapeType() != TopAbs_VERTEX ||
918 anArg3.ShapeType() != TopAbs_VERTEX ||
919 anArg4.ShapeType() != TopAbs_VERTEX) {
920 SetErrorCode("Element for face identification is not a vertex");
924 //Compute the Face value
926 #if OCC_VERSION_LARGE > 0x06010000
931 TopTools_IndexedDataMapOfShapeListOfShape MVF;
932 GEOMImpl_Block6Explorer::MapShapesAndAncestors(aBlockOrComp, TopAbs_VERTEX, TopAbs_FACE, MVF);
934 TopoDS_Shape V1,V2,V3,V4;
935 Standard_Integer ish, ext = MVF.Extent();
937 if (MVF.Contains(anArg1)) {
940 for (ish = 1; ish <= ext; ish++) {
941 TopoDS_Shape aShi = MVF.FindKey(ish);
942 if (BRepTools::Compare(TopoDS::Vertex(anArg1), TopoDS::Vertex(aShi))) {
949 if (MVF.Contains(anArg2)) {
952 for (ish = 1; ish <= ext; ish++) {
953 TopoDS_Shape aShi = MVF.FindKey(ish);
954 if (BRepTools::Compare(TopoDS::Vertex(anArg2), TopoDS::Vertex(aShi))) {
961 if (MVF.Contains(anArg3)) {
964 for (ish = 1; ish <= ext; ish++) {
965 TopoDS_Shape aShi = MVF.FindKey(ish);
966 if (BRepTools::Compare(TopoDS::Vertex(anArg3), TopoDS::Vertex(aShi))) {
973 if (MVF.Contains(anArg4)) {
976 for (ish = 1; ish <= ext; ish++) {
977 TopoDS_Shape aShi = MVF.FindKey(ish);
978 if (BRepTools::Compare(TopoDS::Vertex(anArg4), TopoDS::Vertex(aShi))) {
985 if (V1.IsNull() || V2.IsNull() || V3.IsNull() || V4.IsNull()) {
986 SetErrorCode("The given vertex does not belong to the shape");
990 Standard_Integer isFound =
991 GEOMImpl_Block6Explorer::FindFace(aShape, V1, V2, V3, V4, MVF, Standard_True);
993 SetErrorCode("The given vertices do not belong to one face of the given shape");
995 } else if (isFound > 1) {
996 SetErrorCode("The given vertices belong to several faces of the given shape");
999 TopTools_IndexedMapOfShape anIndices;
1000 TopExp::MapShapes(aBlockOrComp, anIndices);
1001 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1002 anArray->SetValue(1, anIndices.FindIndex(aShape));
1003 aResult = GetEngine()->AddSubShape(theShape, anArray);
1006 catch (Standard_Failure) {
1007 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1008 SetErrorCode(aFail->GetMessageString());
1012 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1014 //Make a Python command
1015 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByPoints("
1016 << theShape << ", " << thePoint1 << ", " << thePoint2
1017 << ", " << thePoint3 << ", " << thePoint4 << ")";
1023 //=============================================================================
1027 //=============================================================================
1028 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByEdges
1029 (Handle(GEOM_Object) theShape,
1030 Handle(GEOM_Object) theEdge1,
1031 Handle(GEOM_Object) theEdge2)
1036 Handle(GEOM_Object) aResult;
1039 if (theShape.IsNull() || theEdge1.IsNull() || theEdge2.IsNull()) return NULL;
1041 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1042 if (aBlockOrComp.IsNull()) {
1043 SetErrorCode("Block or compound is null");
1047 TopoDS_Shape anArg1 = theEdge1->GetValue();
1048 TopoDS_Shape anArg2 = theEdge2->GetValue();
1049 if (anArg1.IsNull() || anArg2.IsNull()) {
1050 SetErrorCode("Null shape is given as argument");
1053 if (anArg1.ShapeType() != TopAbs_EDGE ||
1054 anArg2.ShapeType() != TopAbs_EDGE) {
1055 SetErrorCode("Element for face identification is not an edge");
1059 //Compute the Face value
1061 #if OCC_VERSION_LARGE > 0x06010000
1064 TopoDS_Shape aShape;
1066 TopTools_IndexedDataMapOfShapeListOfShape MEF;
1067 GEOMImpl_Block6Explorer::MapShapesAndAncestors(aBlockOrComp, TopAbs_EDGE, TopAbs_FACE, MEF);
1070 Standard_Integer ish, ext = MEF.Extent();
1072 if (MEF.Contains(anArg1)) {
1075 for (ish = 1; ish <= ext; ish++) {
1076 TopoDS_Shape aShi = MEF.FindKey(ish);
1077 if (GEOMImpl_Block6Explorer::IsSimilarEdges(anArg1, aShi)) {
1083 if (MEF.Contains(anArg2)) {
1086 for (ish = 1; ish <= ext; ish++) {
1087 TopoDS_Shape aShi = MEF.FindKey(ish);
1088 if (GEOMImpl_Block6Explorer::IsSimilarEdges(anArg2, aShi)) {
1094 if (E1.IsNull() || E2.IsNull()) {
1095 SetErrorCode("The given edge does not belong to the shape");
1099 const TopTools_ListOfShape& aFacesOfE1 = MEF.FindFromKey(E1);
1100 const TopTools_ListOfShape& aFacesOfE2 = MEF.FindFromKey(E2);
1102 Standard_Integer isFound = 0;
1103 TopTools_ListIteratorOfListOfShape anIterF1 (aFacesOfE1);
1104 for (; anIterF1.More(); anIterF1.Next()) {
1106 TopTools_ListIteratorOfListOfShape anIterF2 (aFacesOfE2);
1107 for (; anIterF2.More(); anIterF2.Next()) {
1109 if (anIterF1.Value().IsSame(anIterF2.Value())) {
1112 // Store the face, defined by two edges
1113 aShape = anIterF1.Value();
1118 SetErrorCode("The given edges do not belong to one face of the given shape");
1120 } else if (isFound > 1) {
1121 SetErrorCode("The given edges belong to several faces of the given shape");
1124 TopTools_IndexedMapOfShape anIndices;
1125 TopExp::MapShapes(aBlockOrComp, anIndices);
1126 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1127 anArray->SetValue(1, anIndices.FindIndex(aShape));
1128 aResult = GetEngine()->AddSubShape(theShape, anArray);
1131 catch (Standard_Failure) {
1132 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1133 SetErrorCode(aFail->GetMessageString());
1137 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1139 //Make a Python command
1140 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByEdges("
1141 << theShape << ", " << theEdge1 << ", " << theEdge2 << ")";
1147 //=============================================================================
1151 //=============================================================================
1152 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetOppositeFace
1153 (Handle(GEOM_Object) theShape,
1154 Handle(GEOM_Object) theFace)
1159 Handle(GEOM_Object) aResult;
1162 if (theShape.IsNull() || theFace.IsNull()) return NULL;
1164 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1165 if (aBlockOrComp.IsNull()) {
1166 SetErrorCode("Block is null");
1169 if (aBlockOrComp.ShapeType() != TopAbs_SOLID) {
1170 SetErrorCode("Shape is not a block");
1174 TopoDS_Shape anArg = theFace->GetValue();
1175 if (anArg.IsNull()) {
1176 SetErrorCode("Null shape is given as argument");
1179 if (anArg.ShapeType() != TopAbs_FACE) {
1180 SetErrorCode("Element for face identification is not a face");
1184 //Compute the Face value
1186 #if OCC_VERSION_LARGE > 0x06010000
1189 TopoDS_Shape aShape;
1191 GEOMImpl_Block6Explorer aBlockTool;
1192 aBlockTool.InitByBlockAndFace(aBlockOrComp, anArg);
1193 aShape = aBlockTool.GetFace(2);
1195 TopTools_IndexedMapOfShape anIndices;
1196 TopExp::MapShapes(aBlockOrComp, anIndices);
1197 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1198 anArray->SetValue(1, anIndices.FindIndex(aShape));
1199 aResult = GetEngine()->AddSubShape(theShape, anArray);
1201 catch (Standard_Failure) {
1202 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1203 SetErrorCode(aFail->GetMessageString());
1207 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1209 //Make a Python command
1210 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetOppositeFace("
1211 << theShape << ", " << theFace << ")";
1217 //=============================================================================
1221 //=============================================================================
1222 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceNearPoint
1223 (Handle(GEOM_Object) theShape,
1224 Handle(GEOM_Object) thePoint)
1229 Handle(GEOM_Object) aResult;
1232 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
1234 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1235 if (aBlockOrComp.IsNull()) {
1236 SetErrorCode("Block or compound is null");
1240 TopoDS_Shape anArg = thePoint->GetValue();
1241 if (anArg.IsNull()) {
1242 SetErrorCode("Null shape is given as argument");
1245 if (anArg.ShapeType() != TopAbs_VERTEX) {
1246 SetErrorCode("Element for face identification is not a vertex");
1250 //Compute the Face value
1252 #if OCC_VERSION_LARGE > 0x06010000
1255 TopoDS_Shape aShape;
1257 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
1258 gp_Pnt aPnt = BRep_Tool::Pnt(aVert);
1259 Standard_Real PX, PY, PZ;
1260 aPnt.Coord(PX, PY, PZ);
1262 // 1. Classify the point relatively each face
1263 Standard_Integer nearest = 2, nbFound = 0;
1264 TopTools_DataMapOfShapeInteger mapShapeDist;
1265 TopExp_Explorer exp (aBlockOrComp, TopAbs_FACE);
1266 for (; exp.More(); exp.Next()) {
1267 TopoDS_Shape aFace = exp.Current();
1269 if (!mapShapeDist.IsBound(aFace)) {
1270 Standard_Integer aDistance = 2;
1272 // 1.a. Classify relatively Surface
1273 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aFace));
1274 Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf);
1275 gp_Pnt2d p2dOnSurf = aSurfAna->ValueOfUV(aPnt, Precision::Confusion());
1276 gp_Pnt p3dOnSurf = aSurfAna->Value(p2dOnSurf);
1277 Standard_Real aDist = p3dOnSurf.Distance(aPnt);
1278 if (aDist > Precision::Confusion()) {
1282 // 1.b. Classify relatively the face itself
1283 BRepClass_FaceClassifier FC (TopoDS::Face(aFace), p2dOnSurf, Precision::Confusion());
1284 if (FC.State() == TopAbs_IN) {
1286 } else if (FC.State() == TopAbs_ON) {
1293 if (aDistance < nearest) {
1294 nearest = aDistance;
1298 // A first found face, containing the point inside, will be returned.
1299 // It is the solution, if there are no
1300 // coincident or intersecting faces in the compound.
1301 if (nearest == -1) break;
1303 } else if (aDistance == nearest) {
1308 mapShapeDist.Bind(aFace, aDistance);
1309 } // if (!mapShapeDist.IsBound(aFace))
1312 // 2. Define face, containing the point or having minimum distance to it
1315 // The point is on boundary of some faces and there are
1316 // no faces, having the point inside
1317 SetErrorCode("Multiple faces near the given point are found");
1320 } else if (nearest == 1) {
1321 // The point is outside some faces and there are
1322 // no faces, having the point inside or on boundary.
1323 // We will get a nearest face
1324 Standard_Real bigReal = RealLast();
1325 Standard_Real minDist = bigReal;
1326 TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
1327 for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
1328 if (mapShapeDistIter.Value() == 1) {
1329 TopoDS_Shape aFace = mapShapeDistIter.Key();
1330 Standard_Real aDist = bigReal;
1332 // 2.a. Fast check of distance - if point projection on surface is on face
1333 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aFace));
1334 Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf);
1335 gp_Pnt2d p2dOnSurf = aSurfAna->ValueOfUV(aPnt, Precision::Confusion());
1336 gp_Pnt p3dOnSurf = aSurfAna->Value(p2dOnSurf);
1337 aDist = p3dOnSurf.Distance(aPnt);
1339 BRepClass_FaceClassifier FC (TopoDS::Face(aFace), p2dOnSurf, Precision::Confusion());
1340 if (FC.State() == TopAbs_OUT) {
1341 if (aDist < minDist) {
1342 // 2.b. Slow check - if point projection on surface is outside of face
1343 BRepExtrema_DistShapeShape aDistTool (aVert, aFace);
1344 if (!aDistTool.IsDone()) {
1345 SetErrorCode("Can not find a distance from the given point to one of faces");
1348 aDist = aDistTool.Value();
1354 if (aDist < minDist) {
1360 } else { // nearest == -1
1361 // // The point is inside some faces.
1362 // // We will get a face with nearest center
1363 // Standard_Real minDist = RealLast();
1364 // TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
1365 // for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
1366 // if (mapShapeDistIter.Value() == -1) {
1367 // TopoDS_Shape aFace = mapShapeDistIter.Key();
1368 // GProp_GProps aSystem;
1369 // BRepGProp::SurfaceProperties(aFace, aSystem);
1370 // gp_Pnt aCenterMass = aSystem.CentreOfMass();
1372 // Standard_Real aDist = aCenterMass.Distance(aPnt);
1373 // if (aDist < minDist) {
1380 } // if (nbFound > 1)
1383 SetErrorCode("There are no faces near the given point");
1386 TopTools_IndexedMapOfShape anIndices;
1387 TopExp::MapShapes(aBlockOrComp, anIndices);
1388 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1389 anArray->SetValue(1, anIndices.FindIndex(aShape));
1390 aResult = GetEngine()->AddSubShape(theShape, anArray);
1393 catch (Standard_Failure) {
1394 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1395 SetErrorCode(aFail->GetMessageString());
1399 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1401 //Make a Python command
1402 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceNearPoint("
1403 << theShape << ", " << thePoint << ")";
1409 //=============================================================================
1413 //=============================================================================
1414 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByNormale
1415 (Handle(GEOM_Object) theShape,
1416 Handle(GEOM_Object) theVector)
1421 Handle(GEOM_Object) aResult;
1424 if (theShape.IsNull() || theVector.IsNull()) return NULL;
1426 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1427 if (aBlockOrComp.IsNull()) {
1428 SetErrorCode("Block or compound is null");
1432 TopoDS_Shape anArg = theVector->GetValue();
1433 if (anArg.IsNull()) {
1434 SetErrorCode("Null shape is given as argument");
1437 if (anArg.ShapeType() != TopAbs_EDGE) {
1438 SetErrorCode("Element for normale identification is not an edge");
1442 //Compute the Face value
1444 #if OCC_VERSION_LARGE > 0x06010000
1447 TopoDS_Shape aShape;
1449 TopoDS_Edge anEdge = TopoDS::Edge(anArg);
1450 TopoDS_Vertex V1, V2;
1451 TopExp::Vertices(anEdge, V1, V2, Standard_True);
1452 gp_Pnt P1 = BRep_Tool::Pnt(V1);
1453 gp_Pnt P2 = BRep_Tool::Pnt(V2);
1454 gp_Vec aVec (P1, P2);
1455 if (aVec.Magnitude() < Precision::Confusion()) {
1456 SetErrorCode("Vector with null magnitude is given");
1460 Standard_Real minAngle = RealLast();
1461 TopTools_MapOfShape mapShape;
1462 TopExp_Explorer exp (aBlockOrComp, TopAbs_FACE);
1463 for (; exp.More(); exp.Next()) {
1464 if (mapShape.Add(exp.Current())) {
1465 TopoDS_Face aFace = TopoDS::Face(exp.Current());
1466 BRepAdaptor_Surface SF (aFace);
1468 Standard_Real u, v, x;
1470 // find a point on the surface to get normal direction in
1471 u = SF.FirstUParameter();
1472 x = SF.LastUParameter();
1473 if (Precision::IsInfinite(u)) {
1474 u = (Precision::IsInfinite(x)) ? 0. : x;
1475 } else if (!Precision::IsInfinite(x)) {
1479 v = SF.FirstVParameter();
1480 x = SF.LastVParameter();
1481 if (Precision::IsInfinite(v)) {
1482 v = (Precision::IsInfinite(x)) ? 0. : x;
1483 } else if (!Precision::IsInfinite(x)) {
1487 // compute the normal direction
1489 SF.D1(u,v,P1,Vec1,Vec2);
1490 gp_Vec V = Vec1.Crossed(Vec2);
1492 if (V.Magnitude() < Precision::Confusion()) {
1493 SetErrorCode("Normal vector of a face has null magnitude");
1497 // consider the face orientation
1498 if (aFace.Orientation() == TopAbs_REVERSED ||
1499 aFace.Orientation() == TopAbs_INTERNAL) {
1503 // compute the angle and compare with the minimal one
1504 Standard_Real anAngle = aVec.Angle(V);
1505 if (anAngle < minAngle) {
1512 if (aShape.IsNull()) {
1513 SetErrorCode("Failed to find a face by the given normale");
1516 TopTools_IndexedMapOfShape anIndices;
1517 TopExp::MapShapes(aBlockOrComp, anIndices);
1518 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1519 anArray->SetValue(1, anIndices.FindIndex(aShape));
1520 aResult = GetEngine()->AddSubShape(theShape, anArray);
1523 catch (Standard_Failure) {
1524 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1525 SetErrorCode(aFail->GetMessageString());
1529 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1531 //Make a Python command
1532 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByNormale("
1533 << theShape << ", " << theVector << ")";
1539 //=============================================================================
1541 * GetShapesNearPoint
1543 //=============================================================================
1544 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetShapesNearPoint
1545 (Handle(GEOM_Object) theShape,
1546 Handle(GEOM_Object) thePoint,
1547 const Standard_Integer theShapeType,
1548 const Standard_Real theConstTolerance)
1553 Handle(GEOM_Object) aResult;
1556 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
1558 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1559 if (aBlockOrComp.IsNull()) {
1560 SetErrorCode("Block or compound is null");
1564 TopoDS_Shape anArg = thePoint->GetValue();
1565 if (anArg.IsNull()) {
1566 SetErrorCode("Null shape is given as argument");
1569 if (anArg.ShapeType() != TopAbs_VERTEX) {
1570 SetErrorCode("Element for face identification is not a vertex");
1574 if (theShapeType < TopAbs_SOLID || TopAbs_VERTEX < theShapeType) {
1575 SetErrorCode("Invalid type of result is requested");
1579 Standard_Real theTolerance = theConstTolerance;
1580 if (theTolerance < Precision::Confusion()) {
1581 theTolerance = Precision::Confusion();
1584 // Compute the result
1586 #if OCC_VERSION_LARGE > 0x06010000
1589 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
1591 TopTools_MapOfShape mapShape;
1592 Standard_Integer nbEdges = 0;
1593 TopExp_Explorer exp (aBlockOrComp, TopAbs_ShapeEnum(theShapeType));
1594 for (; exp.More(); exp.Next()) {
1595 if (mapShape.Add(exp.Current())) {
1601 SetErrorCode("Given shape contains no sub-shapes of requested type");
1605 // Calculate distances and find min
1607 Standard_Integer ind = 1;
1608 Standard_Real aMinDist = RealLast();
1609 TopTools_Array1OfShape anEdges (1, nbEdges);
1610 TColStd_Array1OfReal aDistances (1, nbEdges);
1611 for (exp.Init(aBlockOrComp, TopAbs_ShapeEnum(theShapeType)); exp.More(); exp.Next()) {
1612 if (mapShape.Add(exp.Current())) {
1613 TopoDS_Shape anEdge = exp.Current();
1614 anEdges(ind) = anEdge;
1616 BRepExtrema_DistShapeShape aDistTool (aVert, anEdges(ind));
1617 if (!aDistTool.IsDone()) {
1618 SetErrorCode("Can not find a distance from the given point to one of sub-shapes");
1621 aDistances(ind) = aDistTool.Value();
1622 if (aDistances(ind) < aMinDist) {
1623 aMinDist = aDistances(ind);
1629 if (aMinDist < RealLast()) {
1630 // Collect sub-shapes with distance < (aMinDist + theTolerance)
1631 int nbSubShapes = 0;
1632 TopTools_Array1OfShape aNearShapes (1, nbEdges);
1633 for (ind = 1; ind <= nbEdges; ind++) {
1634 if (aDistances(ind) < aMinDist + theTolerance) {
1636 aNearShapes(nbSubShapes) = anEdges(ind);
1641 TopTools_IndexedMapOfShape anIndices;
1642 TopExp::MapShapes(aBlockOrComp, anIndices);
1643 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger (1, nbSubShapes);
1644 for (ind = 1; ind <= nbSubShapes; ind++) {
1645 anArray->SetValue(ind, anIndices.FindIndex(aNearShapes(ind)));
1647 aResult = GetEngine()->AddSubShape(theShape, anArray);
1650 catch (Standard_Failure) {
1651 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1652 SetErrorCode(aFail->GetMessageString());
1656 if (aResult.IsNull())
1659 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
1661 //Make a Python command
1662 GEOM::TPythonDump(aFunction)
1663 << aResult << " = geompy.GetShapesNearPoint(" << theShape << ", " << thePoint
1664 << ", " << TopAbs_ShapeEnum(theShapeType) << ", " << theTolerance << ")";
1670 //=============================================================================
1672 * IsCompoundOfBlocks
1674 //=============================================================================
1675 Standard_Boolean GEOMImpl_IBlocksOperations::IsCompoundOfBlocks
1676 (Handle(GEOM_Object) theCompound,
1677 const Standard_Integer theMinNbFaces,
1678 const Standard_Integer theMaxNbFaces,
1679 Standard_Integer& theNbBlocks)
1682 Standard_Boolean isCompOfBlocks = Standard_False;
1685 if (theCompound.IsNull()) return isCompOfBlocks;
1686 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
1689 isCompOfBlocks = Standard_True;
1691 #if OCC_VERSION_LARGE > 0x06010000
1694 TopTools_MapOfShape mapShape;
1695 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
1696 for (; exp.More(); exp.Next()) {
1697 if (mapShape.Add(exp.Current())) {
1698 TopoDS_Shape aSolid = exp.Current();
1700 TopTools_MapOfShape mapFaces;
1701 TopExp_Explorer expF (aSolid, TopAbs_FACE);
1702 Standard_Integer nbFaces = 0;
1703 for (; expF.More(); expF.Next()) {
1704 if (mapFaces.Add(expF.Current())) {
1706 if (nbFaces > theMaxNbFaces) {
1707 isCompOfBlocks = Standard_False;
1712 if (nbFaces < theMinNbFaces || theMaxNbFaces < nbFaces) {
1713 isCompOfBlocks = Standard_False;
1720 catch (Standard_Failure) {
1721 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1722 SetErrorCode(aFail->GetMessageString());
1723 return isCompOfBlocks;
1727 return isCompOfBlocks;
1730 //=============================================================================
1732 * Set of functions, used by CheckCompoundOfBlocks() method
1734 //=============================================================================
1735 void GEOMImpl_IBlocksOperations::AddBlocksFrom (const TopoDS_Shape& theShape,
1736 TopTools_ListOfShape& BLO,
1737 TopTools_ListOfShape& NOT,
1738 TopTools_ListOfShape& EXT)
1740 TopAbs_ShapeEnum aType = theShape.ShapeType();
1742 case TopAbs_COMPOUND:
1743 case TopAbs_COMPSOLID:
1745 TopoDS_Iterator It (theShape);
1746 for (; It.More(); It.Next()) {
1747 AddBlocksFrom(It.Value(), BLO, NOT, EXT);
1753 // Check, if there are seam or degenerated edges
1754 BlockFix_CheckTool aTool;
1755 aTool.SetShape(theShape);
1757 if (aTool.NbPossibleBlocks() > 0) {
1758 EXT.Append(theShape);
1760 // Count faces and edges in each face to recognize blocks
1761 TopTools_MapOfShape mapFaces;
1762 Standard_Integer nbFaces = 0;
1763 Standard_Boolean hasNonQuadr = Standard_False;
1764 TopExp_Explorer expF (theShape, TopAbs_FACE);
1766 for (; expF.More(); expF.Next()) {
1767 if (mapFaces.Add(expF.Current())) {
1769 if (nbFaces > 6) break;
1772 TopoDS_Shape aF = expF.Current();
1773 TopExp_Explorer wires (aF, TopAbs_WIRE);
1774 if (!wires.More()) {
1775 // no wire in the face
1776 hasNonQuadr = Standard_True;
1779 TopoDS_Shape aWire = wires.Current();
1782 // multiple wires in the face
1783 hasNonQuadr = Standard_True;
1787 // Check number of edges in the face
1788 Standard_Integer nbEdges = 0;
1789 TopTools_MapOfShape mapEdges;
1790 TopExp_Explorer expW (aWire, TopAbs_EDGE);
1791 for (; expW.More(); expW.Next()) {
1792 if (mapEdges.Add(expW.Current())) {
1794 if (nbEdges > 4) break;
1798 hasNonQuadr = Standard_True;
1803 if (nbFaces == 6 && !hasNonQuadr) {
1804 BLO.Append(theShape);
1806 NOT.Append(theShape);
1812 NOT.Append(theShape);
1816 void AddBlocksFromOld (const TopoDS_Shape& theShape,
1817 TopTools_ListOfShape& BLO,
1818 TopTools_ListOfShape& NOT,
1819 TopTools_ListOfShape& DEG,
1820 TopTools_ListOfShape& SEA)
1822 TopAbs_ShapeEnum aType = theShape.ShapeType();
1824 case TopAbs_COMPOUND:
1825 case TopAbs_COMPSOLID:
1827 TopoDS_Iterator It (theShape);
1828 for (; It.More(); It.Next()) {
1829 AddBlocksFromOld(It.Value(), BLO, NOT, DEG, SEA);
1835 TopTools_MapOfShape mapFaces;
1836 TopExp_Explorer expF (theShape, TopAbs_FACE);
1837 Standard_Integer nbFaces = 0;
1838 Standard_Boolean hasNonQuadr = Standard_False;
1839 Standard_Boolean hasDegenerated = Standard_False;
1840 Standard_Boolean hasSeam = Standard_False;
1841 for (; expF.More(); expF.Next()) {
1842 if (mapFaces.Add(expF.Current())) {
1844 if (nbFaces > 6) break;
1846 // Check number of edges in the face
1847 Standard_Integer nbEdges = 0;
1848 TopTools_MapOfShape mapEdges;
1851 TopoDS_Shape aF = expF.Current();
1852 TopExp_Explorer wires (aF, TopAbs_WIRE);
1853 if (!wires.More()) {
1854 // no wire in the face
1855 hasNonQuadr = Standard_True;
1858 TopoDS_Shape aWire = wires.Current();
1861 // multiple wires in the face
1862 hasNonQuadr = Standard_True;
1867 BRepTools_WireExplorer aWE (TopoDS::Wire(aWire), TopoDS::Face(aF));
1868 for (; aWE.More(); aWE.Next(), nbEdges++) {
1869 if (BRep_Tool::Degenerated(aWE.Current())) {
1870 // degenerated edge found
1871 hasDegenerated = Standard_True;
1874 if (mapEdges.Contains(aWE.Current())) {
1876 hasSeam = Standard_True;
1879 mapEdges.Add(aWE.Current());
1882 hasNonQuadr = Standard_True;
1887 if (hasDegenerated || hasSeam) {
1888 if (hasDegenerated) {
1889 DEG.Append(theShape);
1892 SEA.Append(theShape);
1894 } else if (hasNonQuadr) {
1895 NOT.Append(theShape);
1897 BLO.Append(theShape);
1900 NOT.Append(theShape);
1905 NOT.Append(theShape);
1909 #define REL_NOT_CONNECTED 0
1911 #define REL_NOT_GLUED 2
1912 #define REL_COLLISION_VV 3
1913 #define REL_COLLISION_FF 4
1914 #define REL_COLLISION_EE 5
1915 #define REL_UNKNOWN 6
1917 Standard_Integer BlocksRelation (const TopoDS_Shape& theBlock1,
1918 const TopoDS_Shape& theBlock2)
1920 // Compare bounding boxes before calling BRepExtrema_DistShapeShape
1921 Standard_Real Xmin1, Ymin1, Zmin1, Xmax1, Ymax1, Zmax1;
1922 Standard_Real Xmin2, Ymin2, Zmin2, Xmax2, Ymax2, Zmax2;
1924 BRepBndLib::Add(theBlock1, B1);
1925 BRepBndLib::Add(theBlock2, B2);
1926 B1.Get(Xmin1, Ymin1, Zmin1, Xmax1, Ymax1, Zmax1);
1927 B2.Get(Xmin2, Ymin2, Zmin2, Xmax2, Ymax2, Zmax2);
1928 if (Xmax2 < Xmin1 || Xmax1 < Xmin2 ||
1929 Ymax2 < Ymin1 || Ymax1 < Ymin2 ||
1930 Zmax2 < Zmin1 || Zmax1 < Zmin2) {
1931 return REL_NOT_CONNECTED;
1934 BRepExtrema_DistShapeShape dst (theBlock1, theBlock2);
1935 if (!dst.IsDone()) {
1939 if (dst.Value() > Precision::Confusion()) {
1940 return REL_NOT_CONNECTED;
1943 if (dst.InnerSolution()) {
1944 return REL_COLLISION_VV;
1947 Standard_Integer nbSol = dst.NbSolution();
1948 Standard_Integer relation = REL_OK;
1949 Standard_Integer nbVerts = 0;
1950 Standard_Integer nbEdges = 0;
1951 Standard_Integer sol = 1;
1952 for (; sol <= nbSol; sol++) {
1953 BRepExtrema_SupportType supp1 = dst.SupportTypeShape1(sol);
1954 BRepExtrema_SupportType supp2 = dst.SupportTypeShape2(sol);
1955 if (supp1 == BRepExtrema_IsVertex && supp2 == BRepExtrema_IsVertex) {
1957 } else if (supp1 == BRepExtrema_IsInFace || supp2 == BRepExtrema_IsInFace) {
1958 return REL_COLLISION_FF;
1959 } else if (supp1 == BRepExtrema_IsOnEdge && supp2 == BRepExtrema_IsOnEdge) {
1961 } else if ((supp1 == BRepExtrema_IsOnEdge && supp2 == BRepExtrema_IsVertex) ||
1962 (supp2 == BRepExtrema_IsOnEdge && supp1 == BRepExtrema_IsVertex)) {
1963 relation = REL_COLLISION_EE;
1968 if (relation != REL_OK) {
1972 TColStd_Array1OfInteger vertSol (1, nbVerts);
1973 TopTools_Array1OfShape V1 (1, nbVerts);
1974 TopTools_Array1OfShape V2 (1, nbVerts);
1975 Standard_Integer ivs = 0;
1976 for (sol = 1; sol <= nbSol; sol++) {
1977 if (dst.SupportTypeShape1(sol) == BRepExtrema_IsVertex &&
1978 dst.SupportTypeShape2(sol) == BRepExtrema_IsVertex) {
1979 TopoDS_Vertex Vcur = TopoDS::Vertex(dst.SupportOnShape1(sol));
1980 // Check, that this vertex is far enough from other solution vertices.
1981 Standard_Integer ii = 1;
1982 for (; ii <= ivs; ii++) {
1983 if (BRepTools::Compare(TopoDS::Vertex(V1(ii)), Vcur)) {
1990 V2(ivs) = dst.SupportOnShape2(sol);
1994 // As we deal only with quadrangles,
1995 // 2, 3 or 4 vertex solutions can be found.
1998 return REL_COLLISION_FF;
2000 return REL_NOT_CONNECTED;
2006 // Check sharing of coincident entities.
2007 if (ivs == 2 || ivs == 3) {
2008 // Map vertices and edges of the blocks
2009 TopTools_IndexedDataMapOfShapeListOfShape MVE1, MVE2;
2010 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2011 (theBlock1, TopAbs_VERTEX, TopAbs_EDGE, MVE1);
2012 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2013 (theBlock2, TopAbs_VERTEX, TopAbs_EDGE, MVE2);
2017 TopoDS_Shape anEdge1, anEdge2;
2018 GEOMImpl_Block6Explorer::FindEdge(anEdge1, V1(1), V1(2), MVE1);
2019 if (anEdge1.IsNull()) return REL_UNKNOWN;
2021 GEOMImpl_Block6Explorer::FindEdge(anEdge2, V2(1), V2(2), MVE2);
2022 if (anEdge2.IsNull()) return REL_UNKNOWN;
2024 if (!anEdge1.IsSame(anEdge2)) return REL_NOT_GLUED;
2026 } else { // ivs == 3
2027 // Find common edges
2028 Standard_Integer e1_v1 = 1;
2029 Standard_Integer e1_v2 = 2;
2030 Standard_Integer e2_v1 = 3;
2031 Standard_Integer e2_v2 = 1;
2033 TopoDS_Shape anEdge11, anEdge12;
2034 GEOMImpl_Block6Explorer::FindEdge(anEdge11, V1(e1_v1), V1(e1_v2), MVE1);
2035 if (anEdge11.IsNull()) {
2038 GEOMImpl_Block6Explorer::FindEdge(anEdge11, V1(e1_v1), V1(e1_v2), MVE1);
2039 if (anEdge11.IsNull()) return REL_UNKNOWN;
2041 GEOMImpl_Block6Explorer::FindEdge(anEdge12, V1(e2_v1), V1(e2_v2), MVE1);
2042 if (anEdge12.IsNull()) {
2044 GEOMImpl_Block6Explorer::FindEdge(anEdge12, V1(e2_v1), V1(e2_v2), MVE1);
2045 if (anEdge12.IsNull()) return REL_UNKNOWN;
2048 TopoDS_Shape anEdge21, anEdge22;
2049 GEOMImpl_Block6Explorer::FindEdge(anEdge21, V2(e1_v1), V2(e1_v2), MVE2);
2050 if (anEdge21.IsNull()) return REL_UNKNOWN;
2051 GEOMImpl_Block6Explorer::FindEdge(anEdge22, V2(e2_v1), V2(e2_v2), MVE2);
2052 if (anEdge22.IsNull()) return REL_UNKNOWN;
2054 // Check of edges coincidence (with some precision) have to be done here
2055 // if (!anEdge11.IsEqual(anEdge21)) return REL_UNKNOWN;
2056 // if (!anEdge12.IsEqual(anEdge22)) return REL_UNKNOWN;
2058 // Check of edges sharing
2059 if (!anEdge11.IsSame(anEdge21)) return REL_NOT_GLUED;
2060 if (!anEdge12.IsSame(anEdge22)) return REL_NOT_GLUED;
2065 // Map vertices and faces of the blocks
2066 TopTools_IndexedDataMapOfShapeListOfShape MVF1, MVF2;
2067 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2068 (theBlock1, TopAbs_VERTEX, TopAbs_FACE, MVF1);
2069 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2070 (theBlock2, TopAbs_VERTEX, TopAbs_FACE, MVF2);
2072 TopoDS_Shape aFace1, aFace2;
2073 GEOMImpl_Block6Explorer::FindFace(aFace1, V1(1), V1(2), V1(3), V1(4), MVF1);
2074 if (aFace1.IsNull()) return REL_UNKNOWN;
2075 GEOMImpl_Block6Explorer::FindFace(aFace2, V2(1), V2(2), V2(3), V2(4), MVF2);
2076 if (aFace2.IsNull()) return REL_UNKNOWN;
2078 // Check of faces coincidence (with some precision) have to be done here
2079 // if (!aFace1.IsEqual(aFace2)) return REL_UNKNOWN;
2081 // Check of faces sharing
2082 if (!aFace1.IsSame(aFace2)) return REL_NOT_GLUED;
2088 void FindConnected (const Standard_Integer theBlockIndex,
2089 const TColStd_Array2OfInteger& theRelations,
2090 TColStd_MapOfInteger& theProcessedMap,
2091 TColStd_MapOfInteger& theConnectedMap)
2093 theConnectedMap.Add(theBlockIndex);
2094 theProcessedMap.Add(theBlockIndex);
2096 Standard_Integer nbBlocks = theRelations.ColLength();
2097 Standard_Integer col = 1;
2098 for (; col <= nbBlocks; col++) {
2099 if (theRelations(theBlockIndex, col) == REL_OK ||
2100 theRelations(theBlockIndex, col) == REL_NOT_GLUED) {
2101 if (!theProcessedMap.Contains(col)) {
2102 FindConnected(col, theRelations, theProcessedMap, theConnectedMap);
2108 Standard_Boolean HasAnyConnection (const Standard_Integer theBlockIndex,
2109 const TColStd_MapOfInteger& theWith,
2110 const TColStd_Array2OfInteger& theRelations,
2111 TColStd_MapOfInteger& theProcessedMap)
2113 theProcessedMap.Add(theBlockIndex);
2115 Standard_Integer nbBlocks = theRelations.ColLength();
2116 Standard_Integer col = 1;
2117 for (; col <= nbBlocks; col++) {
2118 if (theRelations(theBlockIndex, col) != REL_NOT_CONNECTED) {
2119 if (!theProcessedMap.Contains(col)) {
2120 if (theWith.Contains(col))
2121 return Standard_True;
2122 if (HasAnyConnection(col, theWith, theRelations, theProcessedMap))
2123 return Standard_True;
2128 return Standard_False;
2131 //=============================================================================
2133 * CheckCompoundOfBlocksOld
2135 //=============================================================================
2136 Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocksOld
2137 (Handle(GEOM_Object) theCompound,
2138 std::list<BCError>& theErrors)
2142 if (theCompound.IsNull()) return Standard_False;
2143 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2145 Standard_Boolean isCompOfBlocks = Standard_True;
2147 // Map sub-shapes and their indices
2148 TopTools_IndexedMapOfShape anIndices;
2149 TopExp::MapShapes(aBlockOrComp, anIndices);
2151 // 1. Report non-blocks
2152 TopTools_ListOfShape NOT; // Not blocks
2153 TopTools_ListOfShape DEG; // Hexahedral solids, having degenerated edges
2154 TopTools_ListOfShape SEA; // Hexahedral solids, having seam edges
2155 TopTools_ListOfShape BLO; // All blocks from the given compound
2156 AddBlocksFromOld(aBlockOrComp, BLO, NOT, DEG, SEA);
2158 if (NOT.Extent() > 0) {
2159 isCompOfBlocks = Standard_False;
2161 anErr.error = NOT_BLOCK;
2162 TopTools_ListIteratorOfListOfShape it (NOT);
2163 for (; it.More(); it.Next()) {
2164 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
2166 theErrors.push_back(anErr);
2169 if (DEG.Extent() > 0 || SEA.Extent() > 0) {
2170 isCompOfBlocks = Standard_False;
2172 anErr.error = EXTRA_EDGE;
2174 TopTools_ListIteratorOfListOfShape itDEG (DEG);
2175 for (; itDEG.More(); itDEG.Next()) {
2176 anErr.incriminated.push_back(anIndices.FindIndex(itDEG.Value()));
2179 TopTools_ListIteratorOfListOfShape itSEA (SEA);
2180 for (; itSEA.More(); itSEA.Next()) {
2181 anErr.incriminated.push_back(anIndices.FindIndex(itSEA.Value()));
2184 theErrors.push_back(anErr);
2187 Standard_Integer nbBlocks = BLO.Extent();
2188 if (nbBlocks == 0) {
2189 isCompOfBlocks = Standard_False;
2191 return isCompOfBlocks;
2193 if (nbBlocks == 1) {
2195 return isCompOfBlocks;
2198 // Convert list of blocks into array for easy and fast access
2199 Standard_Integer ibl = 1;
2200 TopTools_Array1OfShape aBlocks (1, nbBlocks);
2201 TopTools_ListIteratorOfListOfShape BLOit (BLO);
2202 for (; BLOit.More(); BLOit.Next(), ibl++) {
2203 aBlocks.SetValue(ibl, BLOit.Value());
2206 // 2. Find relations between all blocks,
2207 // report connection errors (NOT_GLUED and INVALID_CONNECTION)
2208 TColStd_Array2OfInteger aRelations (1, nbBlocks, 1, nbBlocks);
2209 aRelations.Init(REL_NOT_CONNECTED);
2211 Standard_Integer row = 1;
2212 for (row = 1; row <= nbBlocks; row++) {
2213 TopoDS_Shape aBlock = aBlocks.Value(row);
2215 Standard_Integer col = row + 1;
2216 for (; col <= nbBlocks; col++) {
2217 Standard_Integer aRel = BlocksRelation(aBlock, aBlocks.Value(col));
2218 if (aRel != REL_NOT_CONNECTED) {
2219 aRelations.SetValue(row, col, aRel);
2220 aRelations.SetValue(col, row, aRel);
2221 if (aRel == REL_NOT_GLUED) {
2222 // report connection error
2223 isCompOfBlocks = Standard_False;
2225 anErr.error = NOT_GLUED;
2226 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row)));
2227 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col)));
2228 theErrors.push_back(anErr);
2229 } else if (aRel == REL_COLLISION_VV ||
2230 aRel == REL_COLLISION_FF ||
2231 aRel == REL_COLLISION_EE ||
2232 aRel == REL_UNKNOWN) {
2233 // report connection error
2234 isCompOfBlocks = Standard_False;
2236 anErr.error = INVALID_CONNECTION;
2237 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row)));
2238 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col)));
2239 theErrors.push_back(anErr);
2246 // 3. Find largest set of connected (good connection or not glued) blocks
2247 TColStd_MapOfInteger aProcessedMap;
2248 TColStd_MapOfInteger aLargestSet;
2249 TColStd_MapOfInteger aCurrentSet;
2250 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2251 if (!aProcessedMap.Contains(ibl)) {
2252 aCurrentSet.Clear();
2253 FindConnected(ibl, aRelations, aProcessedMap, aCurrentSet);
2254 if (aCurrentSet.Extent() > aLargestSet.Extent()) {
2255 aLargestSet = aCurrentSet;
2260 // 4. Report all blocks, isolated from <aLargestSet>
2262 anErr.error = NOT_CONNECTED;
2263 Standard_Boolean hasIsolated = Standard_False;
2264 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2265 if (!aLargestSet.Contains(ibl)) {
2266 aProcessedMap.Clear();
2267 if (!HasAnyConnection(ibl, aLargestSet, aRelations, aProcessedMap)) {
2268 // report connection absence
2269 hasIsolated = Standard_True;
2270 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(ibl)));
2275 isCompOfBlocks = Standard_False;
2276 theErrors.push_back(anErr);
2280 return isCompOfBlocks;
2283 //=============================================================================
2287 //=============================================================================
2288 TCollection_AsciiString GEOMImpl_IBlocksOperations::PrintBCErrors
2289 (Handle(GEOM_Object) theCompound,
2290 const std::list<BCError>& theErrors)
2292 TCollection_AsciiString aDescr;
2294 std::list<BCError>::const_iterator errIt = theErrors.begin();
2296 for (; errIt != theErrors.end(); i++, errIt++) {
2297 BCError errStruct = *errIt;
2299 switch (errStruct.error) {
2301 aDescr += "\n\tNot a Blocks: ";
2304 aDescr += "\n\tHexahedral solids with degenerated and/or seam edges: ";
2306 case INVALID_CONNECTION:
2307 aDescr += "\n\tInvalid connection between two blocks: ";
2310 aDescr += "\n\tBlocks, not connected with main body: ";
2313 aDescr += "\n\tNot glued blocks: ";
2319 std::list<int> sshList = errStruct.incriminated;
2320 std::list<int>::iterator sshIt = sshList.begin();
2322 for (; sshIt != sshList.end(); jj++, sshIt++) {
2325 aDescr += TCollection_AsciiString(*sshIt);
2332 //=============================================================================
2334 * CheckCompoundOfBlocks
2336 //=============================================================================
2337 Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocks
2338 (Handle(GEOM_Object) theCompound,
2339 std::list<BCError>& theErrors)
2343 if (theCompound.IsNull()) return Standard_False;
2344 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2346 Standard_Boolean isCompOfBlocks = Standard_True;
2348 // Map sub-shapes and their indices
2349 TopTools_IndexedMapOfShape anIndices;
2350 TopExp::MapShapes(aBlockOrComp, anIndices);
2352 // 1. Separate blocks from non-blocks
2353 TopTools_ListOfShape NOT; // Not blocks
2354 TopTools_ListOfShape EXT; // Hexahedral solids, having degenerated and/or seam edges
2355 TopTools_ListOfShape BLO; // All blocks from the given compound
2356 AddBlocksFrom(aBlockOrComp, BLO, NOT, EXT);
2358 // Report non-blocks
2359 if (NOT.Extent() > 0) {
2360 isCompOfBlocks = Standard_False;
2362 anErr.error = NOT_BLOCK;
2363 TopTools_ListIteratorOfListOfShape it (NOT);
2364 for (; it.More(); it.Next()) {
2365 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
2367 theErrors.push_back(anErr);
2370 // Report solids, having degenerated and/or seam edges
2371 if (EXT.Extent() > 0) {
2372 isCompOfBlocks = Standard_False;
2374 anErr.error = EXTRA_EDGE;
2375 TopTools_ListIteratorOfListOfShape it (EXT);
2376 for (; it.More(); it.Next()) {
2377 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
2379 theErrors.push_back(anErr);
2382 Standard_Integer nbBlocks = BLO.Extent();
2383 if (nbBlocks == 0) {
2384 isCompOfBlocks = Standard_False;
2386 return isCompOfBlocks;
2388 if (nbBlocks == 1) {
2390 return isCompOfBlocks;
2393 // Prepare data for 2. and 3.
2394 TColStd_Array2OfInteger aRelations (1, nbBlocks, 1, nbBlocks);
2395 aRelations.Init(REL_NOT_CONNECTED);
2397 TopTools_IndexedMapOfShape mapBlocks;
2400 TopoDS_Compound aComp;
2401 BB.MakeCompound(aComp);
2403 TopTools_ListIteratorOfListOfShape BLOit (BLO);
2404 for (; BLOit.More(); BLOit.Next()) {
2405 mapBlocks.Add(BLOit.Value());
2406 BB.Add(aComp, BLOit.Value());
2409 // 2. Find glued blocks (having shared faces)
2410 TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
2411 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2412 (aComp, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
2414 Standard_Integer prevInd = 0, curInd = 0;
2415 Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
2416 for (; ind <= nbFaces; ind++) {
2417 const TopTools_ListOfShape& aGluedBlocks = mapFaceBlocks.FindFromIndex(ind);
2418 if (aGluedBlocks.Extent() > 1) { // Shared face found
2419 TopTools_ListIteratorOfListOfShape aGluedBlocksIt (aGluedBlocks);
2420 TopoDS_Shape prevBlock, curBlock;
2421 for (; aGluedBlocksIt.More(); aGluedBlocksIt.Next()) {
2422 curBlock = aGluedBlocksIt.Value();
2423 if (!prevBlock.IsNull()) {
2424 prevInd = mapBlocks.FindIndex(prevBlock);
2425 curInd = mapBlocks.FindIndex(curBlock);
2426 aRelations.SetValue(prevInd, curInd, REL_OK);
2427 aRelations.SetValue(curInd, prevInd, REL_OK);
2429 prevBlock = curBlock;
2434 // 3. Find not glued blocks
2435 GEOMAlgo_GlueAnalyser aGD;
2437 aGD.SetShape(aComp);
2438 aGD.SetTolerance(Precision::Confusion());
2439 aGD.SetCheckGeometry(Standard_True);
2442 Standard_Integer iErr, iWrn;
2443 iErr = aGD.ErrorStatus();
2445 SetErrorCode("Error in GEOMAlgo_GlueAnalyser");
2446 return isCompOfBlocks;
2448 iWrn = aGD.WarningStatus();
2450 MESSAGE("Warning in GEOMAlgo_GlueAnalyser");
2453 // Report not glued blocks
2454 if (aGD.HasSolidsToGlue()) {
2455 isCompOfBlocks = Standard_False;
2456 Standard_Integer aSx1Ind, aSx2Ind;
2458 const GEOMAlgo_ListOfCoupleOfShapes& aLCS = aGD.SolidsToGlue();
2459 GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS (aLCS);
2460 for (; aItCS.More(); aItCS.Next()) {
2461 const GEOMAlgo_CoupleOfShapes& aCS = aItCS.Value();
2462 const TopoDS_Shape& aSx1 = aCS.Shape1();
2463 const TopoDS_Shape& aSx2 = aCS.Shape2();
2465 aSx1Ind = mapBlocks.FindIndex(aSx1);
2466 aSx2Ind = mapBlocks.FindIndex(aSx2);
2467 aRelations.SetValue(aSx1Ind, aSx2Ind, NOT_GLUED);
2468 aRelations.SetValue(aSx2Ind, aSx1Ind, NOT_GLUED);
2471 anErr.error = NOT_GLUED;
2472 anErr.incriminated.push_back(anIndices.FindIndex(aSx1));
2473 anErr.incriminated.push_back(anIndices.FindIndex(aSx2));
2474 theErrors.push_back(anErr);
2478 // 4. Find largest set of connected (good connection or not glued) blocks
2479 Standard_Integer ibl = 1;
2480 TColStd_MapOfInteger aProcessedMap;
2481 TColStd_MapOfInteger aLargestSet;
2482 TColStd_MapOfInteger aCurrentSet;
2483 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2484 if (!aProcessedMap.Contains(ibl)) {
2485 aCurrentSet.Clear();
2486 FindConnected(ibl, aRelations, aProcessedMap, aCurrentSet);
2487 if (aCurrentSet.Extent() > aLargestSet.Extent()) {
2488 aLargestSet = aCurrentSet;
2493 // 5. Report all blocks, isolated from <aLargestSet>
2495 anErr.error = NOT_CONNECTED;
2496 Standard_Boolean hasIsolated = Standard_False;
2497 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2498 if (!aLargestSet.Contains(ibl)) {
2499 aProcessedMap.Clear();
2500 if (!HasAnyConnection(ibl, aLargestSet, aRelations, aProcessedMap)) {
2501 // report connection absence
2502 hasIsolated = Standard_True;
2503 anErr.incriminated.push_back(anIndices.FindIndex(mapBlocks.FindKey(ibl)));
2508 isCompOfBlocks = Standard_False;
2509 theErrors.push_back(anErr);
2513 return isCompOfBlocks;
2516 //=============================================================================
2520 //=============================================================================
2521 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::RemoveExtraEdges
2522 (Handle(GEOM_Object) theObject,
2523 const Standard_Integer theOptimumNbFaces)
2527 if (theObject.IsNull()) return NULL;
2529 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2530 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be fixed
2532 //Add a new Copy object
2533 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2536 Handle(GEOM_Function) aFunction =
2537 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_REMOVE_EXTRA);
2539 //Check if the function is set correctly
2540 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2542 GEOMImpl_IBlockTrsf aTI (aFunction);
2543 aTI.SetOriginal(aLastFunction);
2544 aTI.SetOptimumNbFaces(theOptimumNbFaces);
2546 //Compute the fixed shape
2548 #if OCC_VERSION_LARGE > 0x06010000
2551 if (!GetSolver()->ComputeFunction(aFunction)) {
2552 SetErrorCode("Block driver failed to remove extra edges of the given shape");
2556 catch (Standard_Failure) {
2557 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2558 SetErrorCode(aFail->GetMessageString());
2562 //Make a Python command
2563 std::string doUnionFaces = (theOptimumNbFaces < 0) ? "False" : "True";
2564 GEOM::TPythonDump(aFunction) << aCopy << " = geompy.RemoveExtraEdges("
2565 << theObject << ", " << doUnionFaces.data() << ")";
2571 //=============================================================================
2575 //=============================================================================
2576 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::CheckAndImprove
2577 (Handle(GEOM_Object) theObject)
2581 if (theObject.IsNull()) return NULL;
2583 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2584 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be fixed
2586 //Add a new Copy object
2587 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2590 Handle(GEOM_Function) aFunction =
2591 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_COMPOUND_IMPROVE);
2593 //Check if the function is set correctly
2594 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2596 GEOMImpl_IBlockTrsf aTI (aFunction);
2597 aTI.SetOriginal(aLastFunction);
2599 // -1 means do not unite faces on common surface (?except case of seam edge between them?)
2600 //aTI.SetOptimumNbFaces(-1);
2601 aTI.SetOptimumNbFaces(6);
2603 //Compute the fixed shape
2605 #if OCC_VERSION_LARGE > 0x06010000
2608 if (!GetSolver()->ComputeFunction(aFunction)) {
2609 SetErrorCode("Block driver failed to improve the given blocks compound");
2613 catch (Standard_Failure) {
2614 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2615 SetErrorCode(aFail->GetMessageString());
2619 //Make a Python command
2620 GEOM::TPythonDump(aFunction) << aCopy
2621 << " = geompy.CheckAndImprove(" << theObject << ")";
2627 //=============================================================================
2629 * ExplodeCompoundOfBlocks
2631 //=============================================================================
2632 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::ExplodeCompoundOfBlocks
2633 (Handle(GEOM_Object) theCompound,
2634 const Standard_Integer theMinNbFaces,
2635 const Standard_Integer theMaxNbFaces)
2639 if (theCompound.IsNull()) return NULL;
2640 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2641 if (aBlockOrComp.IsNull()) return NULL;
2643 Handle(TColStd_HSequenceOfTransient) aBlocks = new TColStd_HSequenceOfTransient;
2644 Handle(GEOM_Object) anObj;
2645 Handle(GEOM_Function) aFunction;
2647 TopTools_MapOfShape mapShape;
2648 TCollection_AsciiString anAsciiList, anEntry;
2651 TopTools_IndexedMapOfShape anIndices;
2652 TopExp::MapShapes(aBlockOrComp, anIndices);
2653 Handle(TColStd_HArray1OfInteger) anArray;
2657 #if OCC_VERSION_LARGE > 0x06010000
2660 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2661 for (; exp.More(); exp.Next()) {
2662 if (mapShape.Add(exp.Current())) {
2663 TopoDS_Shape aSolid = exp.Current();
2665 TopTools_MapOfShape mapFaces;
2666 TopExp_Explorer expF (aSolid, TopAbs_FACE);
2667 Standard_Integer nbFaces = 0;
2668 for (; expF.More(); expF.Next()) {
2669 if (mapFaces.Add(expF.Current())) {
2674 if (theMinNbFaces <= nbFaces && nbFaces <= theMaxNbFaces) {
2675 anArray = new TColStd_HArray1OfInteger(1,1);
2676 anArray->SetValue(1, anIndices.FindIndex(aSolid));
2677 anObj = GetEngine()->AddSubShape(theCompound, anArray);
2678 aBlocks->Append(anObj);
2680 //Make a Python command
2681 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2682 anAsciiList += anEntry + ", ";
2687 catch (Standard_Failure) {
2688 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2689 SetErrorCode(aFail->GetMessageString());
2693 if (aBlocks->IsEmpty()) {
2694 SetErrorCode("There are no specified blocks in the given shape");
2698 anAsciiList.Trunc(anAsciiList.Length() - 2);
2700 //The explode doesn't change object so no new function is required.
2701 aFunction = theCompound->GetLastFunction();
2703 //Make a Python command
2704 GEOM::TPythonDump(aFunction, /*append=*/true)
2705 << "[" << anAsciiList.ToCString() << "] = geompy.MakeBlockExplode("
2706 << theCompound << ", " << theMinNbFaces << ", " << theMaxNbFaces << ")";
2712 //=============================================================================
2716 //=============================================================================
2717 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetBlockNearPoint
2718 (Handle(GEOM_Object) theCompound,
2719 Handle(GEOM_Object) thePoint)
2724 Handle(GEOM_Object) aResult;
2727 if (theCompound.IsNull() || thePoint.IsNull()) return NULL;
2729 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2730 if (aBlockOrComp.IsNull()) {
2731 SetErrorCode("Compound is null");
2734 if (aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
2735 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
2736 SetErrorCode("Shape to find block in is not a compound");
2740 TopoDS_Shape anArg = thePoint->GetValue();
2741 if (anArg.IsNull()) {
2742 SetErrorCode("Point is null");
2745 if (anArg.ShapeType() != TopAbs_VERTEX) {
2746 SetErrorCode("Shape for block identification is not a vertex");
2750 //Compute the Block value
2752 #if OCC_VERSION_LARGE > 0x06010000
2755 TopoDS_Shape aShape;
2757 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
2758 gp_Pnt aPnt = BRep_Tool::Pnt(aVert);
2759 Standard_Real PX, PY, PZ;
2760 aPnt.Coord(PX, PY, PZ);
2762 // 1. Classify the point relatively each block
2763 Standard_Integer nearest = 2, nbFound = 0;
2764 TopTools_DataMapOfShapeInteger mapShapeDist;
2765 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2766 for (; exp.More(); exp.Next()) {
2767 TopoDS_Shape aSolid = exp.Current();
2769 if (!mapShapeDist.IsBound(aSolid)) {
2770 Standard_Integer aDistance = 2;
2772 // 1.a. Classify relatively Bounding box
2773 Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
2775 BRepBndLib::Add(aSolid, BB);
2776 BB.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
2777 if (PX < Xmin || Xmax < PX ||
2778 PY < Ymin || Ymax < PY ||
2779 PZ < Zmin || Zmax < PZ) {
2780 // OUT of bounding box
2783 // 1.b. Classify relatively the solid itself
2784 BRepClass3d_SolidClassifier SC (aSolid, aPnt, Precision::Confusion());
2785 if (SC.State() == TopAbs_IN) {
2787 } else if (SC.State() == TopAbs_ON) {
2794 if (aDistance < nearest) {
2795 nearest = aDistance;
2799 // A first found block, containing the point inside, will be returned.
2800 // It is the solution, if there are no intersecting blocks in the compound.
2801 if (nearest == -1) break;
2803 } else if (aDistance == nearest) {
2808 mapShapeDist.Bind(aSolid, aDistance);
2809 } // if (!mapShapeDist.IsBound(aSolid))
2812 // 2. Define block, containing the point or having minimum distance to it
2815 // The point is on boundary of some blocks and there are
2816 // no blocks, having the point inside their volume
2817 SetErrorCode("Multiple blocks near the given point are found");
2820 } else if (nearest == 1) {
2821 // The point is outside some blocks and there are
2822 // no blocks, having the point inside or on boundary.
2823 // We will get a nearest block
2824 Standard_Real minDist = RealLast();
2825 TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
2826 for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
2827 if (mapShapeDistIter.Value() == 1) {
2828 TopoDS_Shape aSolid = mapShapeDistIter.Key();
2829 BRepExtrema_DistShapeShape aDistTool (aVert, aSolid);
2830 if (!aDistTool.IsDone()) {
2831 SetErrorCode("Can not find a distance from the given point to one of blocks");
2834 Standard_Real aDist = aDistTool.Value();
2835 if (aDist < minDist) {
2841 } else { // nearest == -1
2842 // // The point is inside some blocks.
2843 // // We will get a block with nearest center
2844 // Standard_Real minDist = RealLast();
2845 // TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
2846 // for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
2847 // if (mapShapeDistIter.Value() == -1) {
2848 // TopoDS_Shape aSolid = mapShapeDistIter.Key();
2849 // GProp_GProps aSystem;
2850 // BRepGProp::VolumeProperties(aSolid, aSystem);
2851 // gp_Pnt aCenterMass = aSystem.CentreOfMass();
2853 // Standard_Real aDist = aCenterMass.Distance(aPnt);
2854 // if (aDist < minDist) {
2861 } // if (nbFound > 1)
2864 SetErrorCode("There are no blocks near the given point");
2867 TopTools_IndexedMapOfShape anIndices;
2868 TopExp::MapShapes(aBlockOrComp, anIndices);
2869 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2870 anArray->SetValue(1, anIndices.FindIndex(aShape));
2871 aResult = GetEngine()->AddSubShape(theCompound, anArray);
2874 catch (Standard_Failure) {
2875 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2876 SetErrorCode(aFail->GetMessageString());
2880 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
2882 //Make a Python command
2883 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetBlockNearPoint("
2884 << theCompound << ", " << thePoint << ")";
2890 //=============================================================================
2894 //=============================================================================
2895 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetBlockByParts
2896 (Handle(GEOM_Object) theCompound,
2897 const Handle(TColStd_HSequenceOfTransient)& theParts)
2901 Handle(GEOM_Object) aResult;
2903 if (theCompound.IsNull() || theParts.IsNull()) return NULL;
2904 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2905 if (aBlockOrComp.IsNull()) return NULL;
2908 Standard_Integer argi, aLen = theParts->Length();
2909 TopTools_Array1OfShape anArgs (1, aLen);
2910 TCollection_AsciiString anEntry, aPartsDescr;
2911 for (argi = 1; argi <= aLen; argi++) {
2912 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theParts->Value(argi));
2913 Handle(GEOM_Function) aRef = anObj->GetLastFunction();
2914 if (aRef.IsNull()) return NULL;
2916 TopoDS_Shape anArg = aRef->GetValue();
2917 if (anArg.IsNull()) {
2918 SetErrorCode("Null shape is given as argument");
2921 anArgs(argi) = anArg;
2923 // For Python command
2924 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2925 if (argi > 1) aPartsDescr += ", ";
2926 aPartsDescr += anEntry;
2929 //Compute the Block value
2931 #if OCC_VERSION_LARGE > 0x06010000
2934 // 1. Explode compound on solids
2935 TopTools_MapOfShape mapShape;
2936 Standard_Integer nbSolids = 0;
2937 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2938 for (; exp.More(); exp.Next()) {
2939 if (mapShape.Add(exp.Current())) {
2945 Standard_Integer ind = 1;
2946 TopTools_Array1OfShape aSolids (1, nbSolids);
2947 TColStd_Array1OfInteger aNbParts (1, nbSolids);
2948 for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next(), ind++) {
2949 if (mapShape.Add(exp.Current())) {
2950 TopoDS_Shape aSolid = exp.Current();
2951 aSolids(ind) = aSolid;
2954 // 2. Define quantity of parts, contained in each solid
2955 TopTools_IndexedMapOfShape aSubShapes;
2956 TopExp::MapShapes(aSolid, aSubShapes);
2957 for (argi = 1; argi <= aLen; argi++) {
2958 if (aSubShapes.Contains(anArgs(argi))) {
2965 // 3. Define solid, containing maximum quantity of parts
2966 Standard_Integer maxNb = 0, nbFound = 0;
2967 TopoDS_Shape aShape;
2968 for (ind = 1; ind <= nbSolids; ind++) {
2969 if (aNbParts(ind) > maxNb) {
2970 maxNb = aNbParts(ind);
2971 aShape = aSolids(ind);
2973 } else if (aNbParts(ind) == maxNb) {
2979 SetErrorCode("Multiple blocks, containing maximum quantity of the given parts, are found");
2981 } else if (nbFound == 0) {
2982 SetErrorCode("There are no blocks, containing the given parts");
2985 TopTools_IndexedMapOfShape anIndices;
2986 TopExp::MapShapes(aBlockOrComp, anIndices);
2987 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2988 anArray->SetValue(1, anIndices.FindIndex(aShape));
2989 aResult = GetEngine()->AddSubShape(theCompound, anArray);
2991 } catch (Standard_Failure) {
2992 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2993 SetErrorCode(aFail->GetMessageString());
2997 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
2999 //Make a Python command
3000 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetBlockByParts("
3001 << theCompound << ", [" << aPartsDescr.ToCString() << "])";
3007 //=============================================================================
3011 //=============================================================================
3012 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::GetBlocksByParts
3013 (Handle(GEOM_Object) theCompound,
3014 const Handle(TColStd_HSequenceOfTransient)& theParts)
3018 if (theCompound.IsNull() || theParts.IsNull()) return NULL;
3019 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
3020 if (aBlockOrComp.IsNull()) return NULL;
3022 Handle(TColStd_HSequenceOfTransient) aBlocks = new TColStd_HSequenceOfTransient;
3023 Handle(GEOM_Object) anObj;
3024 Handle(GEOM_Function) aFunction;
3027 Standard_Integer argi, aLen = theParts->Length();
3028 TopTools_Array1OfShape anArgs (1, aLen);
3029 TCollection_AsciiString anEntry, aPartsDescr, anAsciiList;
3031 for (argi = 1; argi <= aLen; argi++) {
3032 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theParts->Value(argi));
3033 Handle(GEOM_Function) aRef = anObj->GetLastFunction();
3034 if (aRef.IsNull()) return NULL;
3036 TopoDS_Shape anArg = aRef->GetValue();
3037 if (anArg.IsNull()) {
3038 SetErrorCode("Null shape is given as argument");
3041 anArgs(argi) = anArg;
3043 // For Python command
3044 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
3045 aPartsDescr += anEntry + ", ";
3050 #if OCC_VERSION_LARGE > 0x06010000
3053 TopTools_MapOfShape mapShape;
3054 Standard_Integer nbSolids = 0;
3055 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
3056 for (; exp.More(); exp.Next()) {
3057 if (mapShape.Add(exp.Current())) {
3063 Standard_Integer ind = 1;
3064 TopTools_Array1OfShape aSolids (1, nbSolids);
3065 TColStd_Array1OfInteger aNbParts (1, nbSolids);
3066 for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next(), ind++) {
3067 if (mapShape.Add(exp.Current())) {
3068 TopoDS_Shape aSolid = exp.Current();
3069 aSolids(ind) = aSolid;
3072 // 2. Define quantity of parts, contained in each solid
3073 TopTools_IndexedMapOfShape aSubShapes;
3074 TopExp::MapShapes(aSolid, aSubShapes);
3075 for (argi = 1; argi <= aLen; argi++) {
3076 if (aSubShapes.Contains(anArgs(argi))) {
3083 // 3. Define solid, containing maximum quantity of parts
3084 Standard_Integer maxNb = 0, nbFound = 0;
3085 for (ind = 1; ind <= nbSolids; ind++) {
3086 if (aNbParts(ind) > maxNb) {
3087 maxNb = aNbParts(ind);
3089 } else if (aNbParts(ind) == maxNb) {
3095 SetErrorCode("There are no blocks, containing the given parts");
3100 TopTools_IndexedMapOfShape anIndices;
3101 TopExp::MapShapes(aBlockOrComp, anIndices);
3102 Handle(TColStd_HArray1OfInteger) anArray;
3104 for (ind = 1; ind <= nbSolids; ind++) {
3105 if (aNbParts(ind) == maxNb) {
3106 anArray = new TColStd_HArray1OfInteger(1,1);
3107 anArray->SetValue(1, anIndices.FindIndex(aSolids(ind)));
3108 anObj = GetEngine()->AddSubShape(theCompound, anArray);
3109 aBlocks->Append(anObj);
3111 // For Python command
3112 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
3113 anAsciiList += anEntry + ", ";
3114 if (aFunction.IsNull())
3115 aFunction = anObj->GetLastFunction();
3119 catch (Standard_Failure) {
3120 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3121 SetErrorCode(aFail->GetMessageString());
3125 //Make a Python command
3126 aPartsDescr.Trunc(aPartsDescr.Length() - 2);
3127 anAsciiList.Trunc(anAsciiList.Length() - 2);
3129 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3130 << "] = geompy.GetBlocksByParts(" << theCompound
3131 << ", [" << aPartsDescr.ToCString() << "])";
3137 //=============================================================================
3139 * MakeMultiTransformation1D
3141 //=============================================================================
3142 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeMultiTransformation1D
3143 (Handle(GEOM_Object) theObject,
3144 const Standard_Integer theDirFace1,
3145 const Standard_Integer theDirFace2,
3146 const Standard_Integer theNbTimes)
3150 if (theObject.IsNull()) return NULL;
3152 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
3153 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be moved
3155 //Add a new Copy object
3156 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
3158 //Add a translate function
3159 Handle(GEOM_Function) aFunction =
3160 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_MULTI_TRANSFORM_1D);
3162 //Check if the function is set correctly
3163 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
3165 GEOMImpl_IBlockTrsf aTI (aFunction);
3166 aTI.SetOriginal(aLastFunction);
3167 aTI.SetFace1U(theDirFace1);
3168 aTI.SetFace2U(theDirFace2);
3169 aTI.SetNbIterU(theNbTimes);
3171 //Compute the transformation
3173 #if OCC_VERSION_LARGE > 0x06010000
3176 if (!GetSolver()->ComputeFunction(aFunction)) {
3177 SetErrorCode("Block driver failed to make multi-transformation");
3181 catch (Standard_Failure) {
3182 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3183 SetErrorCode(aFail->GetMessageString());
3187 //Make a Python command
3188 GEOM::TPythonDump(aFunction) << aCopy << " = geompy.MakeMultiTransformation1D("
3189 << theObject << ", " << theDirFace1 << ", " << theDirFace2 << ", " << theNbTimes << ")";
3195 //=============================================================================
3197 * MakeMultiTransformation2D
3199 //=============================================================================
3200 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeMultiTransformation2D
3201 (Handle(GEOM_Object) theObject,
3202 const Standard_Integer theDirFace1U,
3203 const Standard_Integer theDirFace2U,
3204 const Standard_Integer theNbTimesU,
3205 const Standard_Integer theDirFace1V,
3206 const Standard_Integer theDirFace2V,
3207 const Standard_Integer theNbTimesV)
3211 if (theObject.IsNull()) return NULL;
3213 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
3214 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be moved
3216 //Add a new Copy object
3217 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
3219 //Add a translate function
3220 Handle(GEOM_Function) aFunction =
3221 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_MULTI_TRANSFORM_2D);
3223 //Check if the function is set correctly
3224 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
3226 GEOMImpl_IBlockTrsf aTI (aFunction);
3227 aTI.SetOriginal(aLastFunction);
3228 aTI.SetFace1U(theDirFace1U);
3229 aTI.SetFace2U(theDirFace2U);
3230 aTI.SetNbIterU(theNbTimesU);
3231 aTI.SetFace1V(theDirFace1V);
3232 aTI.SetFace2V(theDirFace2V);
3233 aTI.SetNbIterV(theNbTimesV);
3235 //Compute the transformation
3237 #if OCC_VERSION_LARGE > 0x06010000
3240 if (!GetSolver()->ComputeFunction(aFunction)) {
3241 SetErrorCode("Block driver failed to make multi-transformation");
3245 catch (Standard_Failure) {
3246 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3247 SetErrorCode(aFail->GetMessageString());
3251 //Make a Python command
3252 GEOM::TPythonDump(aFunction) << aCopy << " = geompy.MakeMultiTransformation2D("
3253 << theObject << ", " << theDirFace1U << ", " << theDirFace2U << ", " << theNbTimesU
3254 << ", " << theDirFace1V << ", " << theDirFace2V << ", " << theNbTimesV << ")";
3260 //=============================================================================
3264 //=============================================================================
3265 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::Propagate
3266 (Handle(GEOM_Object) theShape)
3270 if (theShape.IsNull()) return NULL;
3272 TopoDS_Shape aShape = theShape->GetValue();
3273 if (aShape.IsNull()) return NULL;
3275 TopTools_IndexedMapOfShape anIndices;
3276 TopExp::MapShapes(aShape, anIndices);
3278 TopTools_IndexedDataMapOfShapeListOfShape MEW;
3279 GEOMImpl_Block6Explorer::MapShapesAndAncestors
3280 (aShape, TopAbs_EDGE, TopAbs_WIRE, MEW);
3281 Standard_Integer ie, nbEdges = MEW.Extent();
3284 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
3286 TopTools_MapOfShape mapAcceptedEdges;
3287 TCollection_AsciiString aListRes, anEntry;
3289 // Sort shapes in current chain (Mantis issue 21053)
3290 TopTools_DataMapOfShapeListOfShape aMapChains;
3291 TopTools_ListOfShape aFirstInChains;
3293 for (ie = 1; ie <= nbEdges; ie++) {
3294 TopoDS_Shape curE = MEW.FindKey(ie);
3296 if (mapAcceptedEdges.Contains(curE)) continue;
3299 TopTools_ListOfShape currentChain;
3300 TopTools_ListOfShape listPrevEdges;
3302 currentChain.Append(curE);
3303 listPrevEdges.Append(curE);
3304 mapAcceptedEdges.Add(curE);
3306 // Collect all edges pass by pass
3307 while (listPrevEdges.Extent() > 0) {
3308 // List of edges, added to chain on this cycle pass
3309 TopTools_ListOfShape listCurEdges;
3311 // Find the next portion of edges
3312 TopTools_ListIteratorOfListOfShape itE (listPrevEdges);
3313 for (; itE.More(); itE.Next()) {
3314 TopoDS_Shape anE = itE.Value();
3316 // Iterate on faces, having edge <anE>
3317 TopTools_ListIteratorOfListOfShape itW (MEW.FindFromKey(anE));
3318 for (; itW.More(); itW.Next()) {
3319 TopoDS_Shape aW = itW.Value();
3320 TopoDS_Shape anOppE;
3322 BRepTools_WireExplorer aWE (TopoDS::Wire(aW));
3323 Standard_Integer nb = 1, found = 0;
3324 TopTools_Array1OfShape anEdges (1,4);
3325 for (; aWE.More(); aWE.Next(), nb++) {
3330 anEdges(nb) = aWE.Current();
3331 if (anEdges(nb).IsSame(anE)) found = nb;
3334 if (nb == 5 && found > 0) {
3335 // Quadrangle face found, get an opposite edge
3336 Standard_Integer opp = found + 2;
3337 if (opp > 4) opp -= 4;
3338 anOppE = anEdges(opp);
3340 if (!mapAcceptedEdges.Contains(anOppE)) {
3341 // Add found edge to the chain
3342 currentChain.Append(anOppE);
3343 listCurEdges.Append(anOppE);
3344 mapAcceptedEdges.Add(anOppE);
3346 } // if (nb == 5 && found > 0)
3347 } // for (; itF.More(); itF.Next())
3348 } // for (; itE.More(); itE.Next())
3350 listPrevEdges = listCurEdges;
3351 } // while (listPrevEdges.Extent() > 0)
3353 // Sort shapes in current chain (Mantis issue 21053)
3354 GEOMImpl_IShapesOperations::SortShapes(currentChain, Standard_False);
3355 aFirstInChains.Append(currentChain.First());
3356 aMapChains.Bind(currentChain.First(), currentChain);
3359 // Sort chains (Mantis issue 21053)
3360 GEOMImpl_IShapesOperations::SortShapes(aFirstInChains, Standard_False);
3362 // Store sorted chains in the document
3363 TopTools_ListIteratorOfListOfShape aChainsIt (aFirstInChains);
3364 for (; aChainsIt.More(); aChainsIt.Next()) {
3365 TopoDS_Shape aFirstInChain = aChainsIt.Value();
3366 const TopTools_ListOfShape& currentChain = aMapChains.Find(aFirstInChain);
3368 // Store the chain in the document
3369 Handle(TColStd_HArray1OfInteger) anArray =
3370 new TColStd_HArray1OfInteger (1, currentChain.Extent());
3372 // Fill array of sub-shape indices
3373 TopTools_ListIteratorOfListOfShape itSub (currentChain);
3374 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
3375 int id = anIndices.FindIndex(itSub.Value());
3376 anArray->SetValue(index, id);
3379 // Add a new group object
3380 Handle(GEOM_Object) aChain = GetEngine()->AddSubShape(theShape, anArray);
3383 aChain->SetType(GEOM_GROUP);
3385 // Set a sub-shape type
3386 TDF_Label aFreeLabel = aChain->GetFreeLabel();
3387 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)TopAbs_EDGE);
3389 // Add the chain to the result
3390 aSeq->Append(aChain);
3392 //Make a Python command
3393 TDF_Tool::Entry(aChain->GetEntry(), anEntry);
3394 aListRes += anEntry + ", ";
3397 if (aSeq->IsEmpty()) {
3398 SetErrorCode("There are no quadrangle faces in the shape");
3402 aListRes.Trunc(aListRes.Length() - 2);
3404 // The Propagation doesn't change object so no new function is required.
3405 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
3407 // Make a Python command
3408 GEOM::TPythonDump(aFunction, /*append=*/true)
3409 << "[" << aListRes.ToCString() << "] = geompy.Propagate(" << theShape << ")";