3 #include "GEOMImpl_IBlocksOperations.hxx"
5 #include "GEOMImpl_Types.hxx"
7 #include "GEOMImpl_BlockDriver.hxx"
8 #include "GEOMImpl_IBlocks.hxx"
9 #include "GEOMImpl_IBlockTrsf.hxx"
10 #include "GEOMImpl_CopyDriver.hxx"
11 #include "GEOMImpl_Block6Explorer.hxx"
13 #include "GEOM_Function.hxx"
15 #include "GEOMAlgo_GlueAnalyser.hxx"
16 #include "GEOMAlgo_CoupleOfShapes.hxx"
17 #include "GEOMAlgo_ListOfCoupleOfShapes.hxx"
18 #include "GEOMAlgo_ListIteratorOfListOfCoupleOfShapes.hxx"
19 #include "BlockFix_CheckTool.hxx"
21 #include "utilities.h"
23 #include "Utils_ExceptHandlers.hxx"
25 #include <TFunction_DriverTable.hxx>
26 #include <TFunction_Driver.hxx>
27 #include <TFunction_Logbook.hxx>
28 #include <TDataStd_Integer.hxx>
29 #include <TDF_Tool.hxx>
31 #include <BRep_Tool.hxx>
32 #include <BRep_Builder.hxx>
33 #include <BRepTools.hxx>
34 #include <BRepTools_WireExplorer.hxx>
35 #include <BRepGProp.hxx>
36 #include <BRepBndLib.hxx>
37 #include <BRepAdaptor_Surface.hxx>
38 #include <BRepClass_FaceClassifier.hxx>
39 #include <BRepClass3d_SolidClassifier.hxx>
40 #include <BRepExtrema_DistShapeShape.hxx>
44 #include <TopoDS_Edge.hxx>
45 #include <TopoDS_Vertex.hxx>
46 #include <TopoDS_Compound.hxx>
47 #include <TopoDS_Iterator.hxx>
49 #include <TopExp_Explorer.hxx>
50 #include <TopTools_MapOfShape.hxx>
51 #include <TopTools_Array1OfShape.hxx>
52 #include <TopTools_IndexedMapOfShape.hxx>
53 #include <TopTools_DataMapOfShapeInteger.hxx>
54 #include <TopTools_ListIteratorOfListOfShape.hxx>
55 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
56 #include <TopTools_DataMapIteratorOfDataMapOfShapeInteger.hxx>
58 #include <Bnd_Box.hxx>
59 #include <GProp_GProps.hxx>
61 #include <Geom_Surface.hxx>
62 #include <ShapeAnalysis_Surface.hxx>
64 #include <TColStd_MapOfInteger.hxx>
65 #include <TColStd_Array1OfReal.hxx>
66 #include <TColStd_Array1OfInteger.hxx>
67 #include <TColStd_Array2OfInteger.hxx>
69 //#include <OSD_Timer.hxx>
71 #include <Precision.hxx>
73 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
75 //=============================================================================
79 //=============================================================================
80 GEOMImpl_IBlocksOperations::GEOMImpl_IBlocksOperations (GEOM_Engine* theEngine, int theDocID)
81 : GEOM_IOperations(theEngine, theDocID)
83 MESSAGE("GEOMImpl_IBlocksOperations::GEOMImpl_IBlocksOperations");
86 //=============================================================================
90 //=============================================================================
91 GEOMImpl_IBlocksOperations::~GEOMImpl_IBlocksOperations()
93 MESSAGE("GEOMImpl_IBlocksOperations::~GEOMImpl_IBlocksOperations");
97 //=============================================================================
101 //=============================================================================
102 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad
103 (Handle(GEOM_Object) theEdge1, Handle(GEOM_Object) theEdge2,
104 Handle(GEOM_Object) theEdge3, Handle(GEOM_Object) theEdge4)
108 if (theEdge1.IsNull() || theEdge2.IsNull() ||
109 theEdge3.IsNull() || theEdge4.IsNull()) return NULL;
111 //Add a new Face object
112 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
114 //Add a new Face function
115 Handle(GEOM_Function) aFunction =
116 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_FOUR_EDGES);
118 //Check if the function is set correctly
119 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
121 GEOMImpl_IBlocks aPI (aFunction);
123 Handle(GEOM_Function) aRef1 = theEdge1->GetLastFunction();
124 Handle(GEOM_Function) aRef2 = theEdge2->GetLastFunction();
125 Handle(GEOM_Function) aRef3 = theEdge3->GetLastFunction();
126 Handle(GEOM_Function) aRef4 = theEdge4->GetLastFunction();
127 if (aRef1.IsNull() || aRef2.IsNull() ||
128 aRef3.IsNull() || aRef4.IsNull()) return NULL;
130 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
131 aShapesSeq->Append(aRef1);
132 aShapesSeq->Append(aRef2);
133 aShapesSeq->Append(aRef3);
134 aShapesSeq->Append(aRef4);
136 aPI.SetShapes(aShapesSeq);
138 //Compute the Face value
140 if (!GetSolver()->ComputeFunction(aFunction)) {
141 SetErrorCode("Block driver failed to compute a face");
145 catch (Standard_Failure) {
146 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
147 SetErrorCode(aFail->GetMessageString());
151 //Make a Python command
152 TCollection_AsciiString anEntry, aDescr;
153 TDF_Tool::Entry(aFace->GetEntry(), anEntry);
154 aDescr += anEntry + " = geompy.MakeQuad(";
155 TDF_Tool::Entry(theEdge1->GetEntry(), anEntry);
156 aDescr += anEntry + ", ";
157 TDF_Tool::Entry(theEdge2->GetEntry(), anEntry);
158 aDescr += anEntry + ", ";
159 TDF_Tool::Entry(theEdge3->GetEntry(), anEntry);
160 aDescr += anEntry + ", ";
161 TDF_Tool::Entry(theEdge4->GetEntry(), anEntry);
162 aDescr += anEntry + ")";
164 aFunction->SetDescription(aDescr);
170 //=============================================================================
174 //=============================================================================
175 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad2Edges
176 (Handle(GEOM_Object) theEdge1, Handle(GEOM_Object) theEdge2)
180 if (theEdge1.IsNull() || theEdge2.IsNull()) return NULL;
182 //Add a new Face object
183 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
185 //Add a new Face function
186 Handle(GEOM_Function) aFunction =
187 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_TWO_EDGES);
189 //Check if the function is set correctly
190 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
192 GEOMImpl_IBlocks aPI (aFunction);
194 Handle(GEOM_Function) aRef1 = theEdge1->GetLastFunction();
195 Handle(GEOM_Function) aRef2 = theEdge2->GetLastFunction();
196 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
198 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
199 aShapesSeq->Append(aRef1);
200 aShapesSeq->Append(aRef2);
202 aPI.SetShapes(aShapesSeq);
204 //Compute the Face value
206 if (!GetSolver()->ComputeFunction(aFunction)) {
207 SetErrorCode("Block driver failed to compute a face");
211 catch (Standard_Failure) {
212 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
213 SetErrorCode(aFail->GetMessageString());
217 //Make a Python command
218 TCollection_AsciiString anEntry, aDescr;
219 TDF_Tool::Entry(aFace->GetEntry(), anEntry);
220 aDescr += anEntry + " = geompy.MakeQuad2Edges(";
221 TDF_Tool::Entry(theEdge1->GetEntry(), anEntry);
222 aDescr += anEntry + ", ";
223 TDF_Tool::Entry(theEdge2->GetEntry(), anEntry);
224 aDescr += anEntry + ")";
226 aFunction->SetDescription(aDescr);
232 //=============================================================================
236 //=============================================================================
237 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad4Vertices
238 (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2,
239 Handle(GEOM_Object) thePnt3, Handle(GEOM_Object) thePnt4)
243 if (thePnt1.IsNull() || thePnt2.IsNull() ||
244 thePnt3.IsNull() || thePnt4.IsNull()) return NULL;
246 //Add a new Face object
247 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
249 //Add a new Face function
250 Handle(GEOM_Function) aFunction =
251 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_FOUR_PNT);
253 //Check if the function is set correctly
254 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
256 GEOMImpl_IBlocks aPI (aFunction);
258 Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
259 Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
260 Handle(GEOM_Function) aRef3 = thePnt3->GetLastFunction();
261 Handle(GEOM_Function) aRef4 = thePnt4->GetLastFunction();
262 if (aRef1.IsNull() || aRef2.IsNull() ||
263 aRef3.IsNull() || aRef4.IsNull()) return NULL;
265 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
266 aShapesSeq->Append(aRef1);
267 aShapesSeq->Append(aRef2);
268 aShapesSeq->Append(aRef3);
269 aShapesSeq->Append(aRef4);
271 aPI.SetShapes(aShapesSeq);
273 //Compute the Face value
275 if (!GetSolver()->ComputeFunction(aFunction)) {
276 SetErrorCode("Block driver failed to compute a face");
280 catch (Standard_Failure) {
281 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
282 SetErrorCode(aFail->GetMessageString());
286 //Make a Python command
287 TCollection_AsciiString anEntry, aDescr;
288 TDF_Tool::Entry(aFace->GetEntry(), anEntry);
289 aDescr += anEntry + " = geompy.MakeQuad4Vertices(";
290 TDF_Tool::Entry(thePnt1->GetEntry(), anEntry);
291 aDescr += anEntry + ", ";
292 TDF_Tool::Entry(thePnt2->GetEntry(), anEntry);
293 aDescr += anEntry + ", ";
294 TDF_Tool::Entry(thePnt3->GetEntry(), anEntry);
295 aDescr += anEntry + ", ";
296 TDF_Tool::Entry(thePnt4->GetEntry(), anEntry);
297 aDescr += anEntry + ")";
299 aFunction->SetDescription(aDescr);
305 //=============================================================================
309 //=============================================================================
310 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeHexa
311 (Handle(GEOM_Object) theFace1, Handle(GEOM_Object) theFace2,
312 Handle(GEOM_Object) theFace3, Handle(GEOM_Object) theFace4,
313 Handle(GEOM_Object) theFace5, Handle(GEOM_Object) theFace6)
317 if (theFace1.IsNull() || theFace2.IsNull() ||
318 theFace3.IsNull() || theFace4.IsNull() ||
319 theFace5.IsNull() || theFace6.IsNull()) return NULL;
321 //Add a new Solid object
322 Handle(GEOM_Object) aBlock = GetEngine()->AddObject(GetDocID(), GEOM_BLOCK);
324 //Add a new Block function
325 Handle(GEOM_Function) aFunction =
326 aBlock->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_SIX_FACES);
328 //Check if the function is set correctly
329 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
331 GEOMImpl_IBlocks aPI (aFunction);
333 Handle(GEOM_Function) aRef1 = theFace1->GetLastFunction();
334 Handle(GEOM_Function) aRef2 = theFace2->GetLastFunction();
335 Handle(GEOM_Function) aRef3 = theFace3->GetLastFunction();
336 Handle(GEOM_Function) aRef4 = theFace4->GetLastFunction();
337 Handle(GEOM_Function) aRef5 = theFace5->GetLastFunction();
338 Handle(GEOM_Function) aRef6 = theFace6->GetLastFunction();
339 if (aRef1.IsNull() || aRef2.IsNull() ||
340 aRef3.IsNull() || aRef4.IsNull() ||
341 aRef5.IsNull() || aRef6.IsNull()) return NULL;
343 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
344 aShapesSeq->Append(aRef1);
345 aShapesSeq->Append(aRef2);
346 aShapesSeq->Append(aRef3);
347 aShapesSeq->Append(aRef4);
348 aShapesSeq->Append(aRef5);
349 aShapesSeq->Append(aRef6);
351 aPI.SetShapes(aShapesSeq);
353 //Compute the Block value
355 if (!GetSolver()->ComputeFunction(aFunction)) {
356 SetErrorCode("Block driver failed to compute a block");
360 catch (Standard_Failure) {
361 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
362 SetErrorCode(aFail->GetMessageString());
366 //Make a Python command
367 TCollection_AsciiString anEntry, aDescr;
368 TDF_Tool::Entry(aBlock->GetEntry(), anEntry);
369 aDescr += anEntry + " = geompy.MakeHexa(";
370 TDF_Tool::Entry(theFace1->GetEntry(), anEntry);
371 aDescr += anEntry + ", ";
372 TDF_Tool::Entry(theFace2->GetEntry(), anEntry);
373 aDescr += anEntry + ", ";
374 TDF_Tool::Entry(theFace3->GetEntry(), anEntry);
375 aDescr += anEntry + ", ";
376 TDF_Tool::Entry(theFace4->GetEntry(), anEntry);
377 aDescr += anEntry + ", ";
378 TDF_Tool::Entry(theFace5->GetEntry(), anEntry);
379 aDescr += anEntry + ", ";
380 TDF_Tool::Entry(theFace6->GetEntry(), anEntry);
381 aDescr += anEntry + ")";
383 aFunction->SetDescription(aDescr);
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 (!GetSolver()->ComputeFunction(aFunction)) {
426 SetErrorCode("Block driver failed to compute a block");
430 catch (Standard_Failure) {
431 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
432 SetErrorCode(aFail->GetMessageString());
436 //Make a Python command
437 TCollection_AsciiString anEntry, aDescr;
438 TDF_Tool::Entry(aBlock->GetEntry(), anEntry);
439 aDescr += anEntry + " = geompy.MakeHexa2Faces(";
440 TDF_Tool::Entry(theFace1->GetEntry(), anEntry);
441 aDescr += anEntry + ", ";
442 TDF_Tool::Entry(theFace2->GetEntry(), anEntry);
443 aDescr += anEntry + ")";
445 aFunction->SetDescription(aDescr);
451 //=============================================================================
455 //=============================================================================
456 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeBlockCompound
457 (Handle(GEOM_Object) theCompound)
461 if (theCompound.IsNull()) return NULL;
464 Handle(GEOM_Object) aBlockComp = GetEngine()->AddObject(GetDocID(), GEOM_COMPOUND);
466 //Add a new BlocksComp function
467 Handle(GEOM_Function) aFunction =
468 aBlockComp->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_COMPOUND_GLUE);
470 //Check if the function is set correctly
471 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
473 GEOMImpl_IBlocks aPI (aFunction);
475 Handle(GEOM_Function) aRef1 = theCompound->GetLastFunction();
476 if (aRef1.IsNull()) return NULL;
478 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
479 aShapesSeq->Append(aRef1);
481 aPI.SetShapes(aShapesSeq);
483 //Compute the Blocks Compound value
485 if (!GetSolver()->ComputeFunction(aFunction)) {
486 SetErrorCode("Block driver failed to compute a blocks compound");
490 catch (Standard_Failure) {
491 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
492 SetErrorCode(aFail->GetMessageString());
496 //Make a Python command
497 TCollection_AsciiString anEntry, aDescr;
498 TDF_Tool::Entry(aBlockComp->GetEntry(), anEntry);
499 aDescr += anEntry + " = geompy.BlocksOp.MakeBlockCompound(";
500 TDF_Tool::Entry(theCompound->GetEntry(), anEntry);
501 aDescr += anEntry + ")";
503 aFunction->SetDescription(aDescr);
509 //=============================================================================
513 //=============================================================================
514 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetPoint
515 (Handle(GEOM_Object) theShape,
516 const Standard_Real theX,
517 const Standard_Real theY,
518 const Standard_Real theZ,
519 const Standard_Real theEpsilon)
524 Handle(GEOM_Object) aResult;
527 if (theShape.IsNull()) return NULL;
529 TopoDS_Shape aBlockOrComp = theShape->GetValue();
530 if (aBlockOrComp.IsNull()) {
531 SetErrorCode("Block or compound is null");
534 if (aBlockOrComp.ShapeType() != TopAbs_SOLID &&
535 aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
536 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
537 SetErrorCode("Shape is neither a block, nor a compound of blocks");
541 //Compute the Vertex value
542 gp_Pnt P (theX, theY, theZ);
543 Standard_Real eps = Max(theEpsilon, Precision::Confusion());
546 Standard_Integer isFound = 0;
547 TopTools_MapOfShape mapShape;
548 TopExp_Explorer exp (aBlockOrComp, TopAbs_VERTEX);
550 for (; exp.More(); exp.Next()) {
551 if (mapShape.Add(exp.Current())) {
552 TopoDS_Vertex aVi = TopoDS::Vertex(exp.Current());
553 gp_Pnt aPi = BRep_Tool::Pnt(aVi);
554 if (aPi.Distance(P) < eps) {
562 SetErrorCode("Vertex has not been found");
564 } else if (isFound > 1) {
565 SetErrorCode("Multiple vertices found by the given coordinates and epsilon");
568 TopTools_IndexedMapOfShape anIndices;
569 TopExp::MapShapes(aBlockOrComp, anIndices);
570 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
571 anArray->SetValue(1, anIndices.FindIndex(V));
572 aResult = GetEngine()->AddSubShape(theShape, anArray);
575 //The GetPoint() doesn't change object so no new function is required.
576 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
578 //Make a Python command
579 TCollection_AsciiString anEntry, aDescr;
580 TDF_Tool::Entry(aResult->GetEntry(), anEntry);
581 aDescr += anEntry + " = geompy.GetPoint(";
582 TDF_Tool::Entry(theShape->GetEntry(), anEntry);
583 aDescr += anEntry + ", ";
584 aDescr += TCollection_AsciiString(theX) + ", ";
585 aDescr += TCollection_AsciiString(theY) + ", ";
586 aDescr += TCollection_AsciiString(theZ) + ", ";
587 aDescr += TCollection_AsciiString(theEpsilon) + ")";
589 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n\t";
591 aFunction->SetDescription(aNewDescr);
597 //=============================================================================
601 //=============================================================================
602 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetEdge
603 (Handle(GEOM_Object) theShape,
604 Handle(GEOM_Object) thePoint1,
605 Handle(GEOM_Object) thePoint2)
610 Handle(GEOM_Object) aResult;
613 if (theShape.IsNull() || thePoint1.IsNull() || thePoint2.IsNull()) return NULL;
615 TopoDS_Shape aBlockOrComp = theShape->GetValue();
616 if (aBlockOrComp.IsNull()) {
617 SetErrorCode("Block or compound is null");
620 if (aBlockOrComp.ShapeType() != TopAbs_SOLID &&
621 aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
622 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
623 SetErrorCode("Shape is neither a block, nor a compound of blocks");
627 TopoDS_Shape anArg1 = thePoint1->GetValue();
628 TopoDS_Shape anArg2 = thePoint2->GetValue();
629 if (anArg1.IsNull() || anArg2.IsNull()) {
630 SetErrorCode("Null shape is given as argument");
633 if (anArg1.ShapeType() != TopAbs_VERTEX ||
634 anArg2.ShapeType() != TopAbs_VERTEX) {
635 SetErrorCode("Element for edge identification is not a vertex");
639 //Compute the Edge value
641 TopTools_IndexedDataMapOfShapeListOfShape MVE;
642 GEOMImpl_Block6Explorer::MapShapesAndAncestors
643 (aBlockOrComp, TopAbs_VERTEX, TopAbs_EDGE, MVE);
646 Standard_Integer ish, ext = MVE.Extent();
648 if (MVE.Contains(anArg1)) {
651 for (ish = 1; ish <= ext; ish++) {
652 TopoDS_Shape aShi = MVE.FindKey(ish);
653 if (BRepTools::Compare(TopoDS::Vertex(anArg1), TopoDS::Vertex(aShi))) {
660 if (MVE.Contains(anArg2)) {
663 for (ish = 1; ish <= ext; ish++) {
664 TopoDS_Shape aShi = MVE.FindKey(ish);
665 if (BRepTools::Compare(TopoDS::Vertex(anArg2), TopoDS::Vertex(aShi))) {
672 if (V1.IsNull() || V2.IsNull()) {
673 SetErrorCode("The given vertex does not belong to the shape");
678 Standard_Integer isFound =
679 GEOMImpl_Block6Explorer::FindEdge(anEdge, V1, V2, MVE, Standard_True);
681 SetErrorCode("The given vertices do not belong to one edge of the given shape");
683 } else if (isFound > 1) {
684 SetErrorCode("Multiple edges found by the given vertices of the shape");
687 TopTools_IndexedMapOfShape anIndices;
688 TopExp::MapShapes(aBlockOrComp, anIndices);
689 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
690 anArray->SetValue(1, anIndices.FindIndex(anEdge));
691 aResult = GetEngine()->AddSubShape(theShape, anArray);
693 } catch (Standard_Failure) {
694 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
695 SetErrorCode(aFail->GetMessageString());
699 //The GetEdge() doesn't change object so no new function is required.
700 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
702 //Make a Python command
703 TCollection_AsciiString anEntry, aDescr;
704 TDF_Tool::Entry(aResult->GetEntry(), anEntry);
705 aDescr += anEntry + " = geompy.GetEdge(";
706 TDF_Tool::Entry(theShape->GetEntry(), anEntry);
707 aDescr += anEntry + ", ";
708 TDF_Tool::Entry(thePoint1->GetEntry(), anEntry);
709 aDescr += anEntry + ", ";
710 TDF_Tool::Entry(thePoint2->GetEntry(), anEntry);
711 aDescr += anEntry + ")";
713 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n\t";
715 aFunction->SetDescription(aNewDescr);
721 //=============================================================================
725 //=============================================================================
726 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetEdgeNearPoint
727 (Handle(GEOM_Object) theShape,
728 Handle(GEOM_Object) thePoint)
733 Handle(GEOM_Object) aResult;
736 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
738 TopoDS_Shape aBlockOrComp = theShape->GetValue();
739 if (aBlockOrComp.IsNull()) {
740 SetErrorCode("Block or compound is null");
743 if (aBlockOrComp.ShapeType() != TopAbs_SOLID &&
744 aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
745 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
746 SetErrorCode("Shape is neither a block, nor a compound of blocks");
750 TopoDS_Shape anArg = thePoint->GetValue();
751 if (anArg.IsNull()) {
752 SetErrorCode("Null shape is given as argument");
755 if (anArg.ShapeType() != TopAbs_VERTEX) {
756 SetErrorCode("Element for edge identification is not a vertex");
760 //Compute the Edge value
764 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
766 // 1. Explode blocks on edges
767 TopTools_MapOfShape mapShape;
768 Standard_Integer nbEdges = 0;
769 TopExp_Explorer exp (aBlockOrComp, TopAbs_EDGE);
770 for (; exp.More(); exp.Next()) {
771 if (mapShape.Add(exp.Current())) {
777 Standard_Integer ind = 1;
778 TopTools_Array1OfShape anEdges (1, nbEdges);
779 TColStd_Array1OfReal aDistances (1, nbEdges);
780 for (exp.Init(aBlockOrComp, TopAbs_EDGE); exp.More(); exp.Next()) {
781 if (mapShape.Add(exp.Current())) {
782 TopoDS_Shape anEdge = exp.Current();
783 anEdges(ind) = anEdge;
785 // 2. Classify the point relatively each edge
786 BRepExtrema_DistShapeShape aDistTool (aVert, anEdges(ind));
787 if (!aDistTool.IsDone()) {
788 SetErrorCode("Can not find a distance from the given point to one of edges");
791 aDistances(ind) = aDistTool.Value();
796 // 3. Define edge, having minimum distance to the point
797 Standard_Real nearest = RealLast(), nbFound = 0;
798 Standard_Real prec = Precision::Confusion();
799 for (ind = 1; ind <= nbEdges; ind++) {
800 if (Abs(aDistances(ind) - nearest) < prec) {
802 } else if (aDistances(ind) < nearest) {
803 nearest = aDistances(ind);
804 aShape = anEdges(ind);
810 SetErrorCode("Multiple edges near the given point are found");
812 } else if (nbFound == 0) {
813 SetErrorCode("There are no edges near the given point");
816 TopTools_IndexedMapOfShape anIndices;
817 TopExp::MapShapes(aBlockOrComp, anIndices);
818 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
819 anArray->SetValue(1, anIndices.FindIndex(aShape));
820 aResult = GetEngine()->AddSubShape(theShape, anArray);
823 catch (Standard_Failure) {
824 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
825 SetErrorCode(aFail->GetMessageString());
829 //The GetEdgeNearPoint() doesn't change object so no new function is required.
830 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
832 //Make a Python command
833 TCollection_AsciiString anEntry, aDescr;
834 TDF_Tool::Entry(aResult->GetEntry(), anEntry);
835 aDescr += anEntry + " = geompy.GetEdgeNearPoint(";
836 TDF_Tool::Entry(theShape->GetEntry(), anEntry);
837 aDescr += anEntry + ", ";
838 TDF_Tool::Entry(thePoint->GetEntry(), anEntry);
839 aDescr += anEntry + ")";
841 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n\t";
843 aFunction->SetDescription(aNewDescr);
849 //=============================================================================
853 //=============================================================================
854 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByPoints
855 (Handle(GEOM_Object) theShape,
856 Handle(GEOM_Object) thePoint1,
857 Handle(GEOM_Object) thePoint2,
858 Handle(GEOM_Object) thePoint3,
859 Handle(GEOM_Object) thePoint4)
864 Handle(GEOM_Object) aResult;
867 if (theShape.IsNull() ||
868 thePoint1.IsNull() || thePoint2.IsNull() ||
869 thePoint3.IsNull() || thePoint4.IsNull()) return NULL;
871 TopoDS_Shape aBlockOrComp = theShape->GetValue();
872 if (aBlockOrComp.IsNull()) {
873 SetErrorCode("Block or compound is null");
876 if (aBlockOrComp.ShapeType() != TopAbs_SOLID &&
877 aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
878 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
879 SetErrorCode("Shape is neither a block, nor a compound of blocks");
883 TopoDS_Shape anArg1 = thePoint1->GetValue();
884 TopoDS_Shape anArg2 = thePoint2->GetValue();
885 TopoDS_Shape anArg3 = thePoint3->GetValue();
886 TopoDS_Shape anArg4 = thePoint4->GetValue();
887 if (anArg1.IsNull() || anArg2.IsNull() ||
888 anArg3.IsNull() || anArg4.IsNull()) {
889 SetErrorCode("Null shape is given as argument");
892 if (anArg1.ShapeType() != TopAbs_VERTEX ||
893 anArg2.ShapeType() != TopAbs_VERTEX ||
894 anArg3.ShapeType() != TopAbs_VERTEX ||
895 anArg4.ShapeType() != TopAbs_VERTEX) {
896 SetErrorCode("Element for face identification is not a vertex");
900 //Compute the Face value
904 TopTools_IndexedDataMapOfShapeListOfShape MVF;
905 GEOMImpl_Block6Explorer::MapShapesAndAncestors(aBlockOrComp, TopAbs_VERTEX, TopAbs_FACE, MVF);
907 TopoDS_Shape V1,V2,V3,V4;
908 Standard_Integer ish, ext = MVF.Extent();
910 if (MVF.Contains(anArg1)) {
913 for (ish = 1; ish <= ext; ish++) {
914 TopoDS_Shape aShi = MVF.FindKey(ish);
915 if (BRepTools::Compare(TopoDS::Vertex(anArg1), TopoDS::Vertex(aShi))) {
922 if (MVF.Contains(anArg2)) {
925 for (ish = 1; ish <= ext; ish++) {
926 TopoDS_Shape aShi = MVF.FindKey(ish);
927 if (BRepTools::Compare(TopoDS::Vertex(anArg2), TopoDS::Vertex(aShi))) {
934 if (MVF.Contains(anArg3)) {
937 for (ish = 1; ish <= ext; ish++) {
938 TopoDS_Shape aShi = MVF.FindKey(ish);
939 if (BRepTools::Compare(TopoDS::Vertex(anArg3), TopoDS::Vertex(aShi))) {
946 if (MVF.Contains(anArg4)) {
949 for (ish = 1; ish <= ext; ish++) {
950 TopoDS_Shape aShi = MVF.FindKey(ish);
951 if (BRepTools::Compare(TopoDS::Vertex(anArg4), TopoDS::Vertex(aShi))) {
958 if (V1.IsNull() || V2.IsNull() || V3.IsNull() || V4.IsNull()) {
959 SetErrorCode("The given vertex does not belong to the shape");
963 Standard_Integer isFound =
964 GEOMImpl_Block6Explorer::FindFace(aShape, V1, V2, V3, V4, MVF, Standard_True);
966 SetErrorCode("The given vertices do not belong to one face of the given shape");
968 } else if (isFound > 1) {
969 SetErrorCode("The given vertices belong to several faces of the given shape");
972 TopTools_IndexedMapOfShape anIndices;
973 TopExp::MapShapes(aBlockOrComp, anIndices);
974 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
975 anArray->SetValue(1, anIndices.FindIndex(aShape));
976 aResult = GetEngine()->AddSubShape(theShape, anArray);
979 catch (Standard_Failure) {
980 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
981 SetErrorCode(aFail->GetMessageString());
985 //The GetFaceByPoints() doesn't change object so no new function is required.
986 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
988 //Make a Python command
989 TCollection_AsciiString anEntry, aDescr;
990 TDF_Tool::Entry(aResult->GetEntry(), anEntry);
991 aDescr += anEntry + " = geompy.GetFaceByPoints(";
992 TDF_Tool::Entry(theShape->GetEntry(), anEntry);
993 aDescr += anEntry + ", ";
994 TDF_Tool::Entry(thePoint1->GetEntry(), anEntry);
995 aDescr += anEntry + ", ";
996 TDF_Tool::Entry(thePoint2->GetEntry(), anEntry);
997 aDescr += anEntry + ", ";
998 TDF_Tool::Entry(thePoint3->GetEntry(), anEntry);
999 aDescr += anEntry + ", ";
1000 TDF_Tool::Entry(thePoint4->GetEntry(), anEntry);
1001 aDescr += anEntry + ")";
1003 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n\t";
1004 aNewDescr += aDescr;
1005 aFunction->SetDescription(aNewDescr);
1011 //=============================================================================
1015 //=============================================================================
1016 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByEdges
1017 (Handle(GEOM_Object) theShape,
1018 Handle(GEOM_Object) theEdge1,
1019 Handle(GEOM_Object) theEdge2)
1024 Handle(GEOM_Object) aResult;
1027 if (theShape.IsNull() || theEdge1.IsNull() || theEdge2.IsNull()) return NULL;
1029 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1030 if (aBlockOrComp.IsNull()) {
1031 SetErrorCode("Block or compound is null");
1034 if (aBlockOrComp.ShapeType() != TopAbs_SOLID &&
1035 aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
1036 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
1037 SetErrorCode("Shape is neither a block, nor a compound of blocks");
1041 TopoDS_Shape anArg1 = theEdge1->GetValue();
1042 TopoDS_Shape anArg2 = theEdge2->GetValue();
1043 if (anArg1.IsNull() || anArg2.IsNull()) {
1044 SetErrorCode("Null shape is given as argument");
1047 if (anArg1.ShapeType() != TopAbs_EDGE ||
1048 anArg2.ShapeType() != TopAbs_EDGE) {
1049 SetErrorCode("Element for face identification is not an edge");
1053 //Compute the Face value
1055 TopoDS_Shape aShape;
1057 TopTools_IndexedDataMapOfShapeListOfShape MEF;
1058 GEOMImpl_Block6Explorer::MapShapesAndAncestors(aBlockOrComp, TopAbs_EDGE, TopAbs_FACE, MEF);
1061 Standard_Integer ish, ext = MEF.Extent();
1063 if (MEF.Contains(anArg1)) {
1066 for (ish = 1; ish <= ext; ish++) {
1067 TopoDS_Shape aShi = MEF.FindKey(ish);
1068 if (GEOMImpl_Block6Explorer::IsSimilarEdges(anArg1, aShi)) {
1074 if (MEF.Contains(anArg2)) {
1077 for (ish = 1; ish <= ext; ish++) {
1078 TopoDS_Shape aShi = MEF.FindKey(ish);
1079 if (GEOMImpl_Block6Explorer::IsSimilarEdges(anArg2, aShi)) {
1085 if (E1.IsNull() || E2.IsNull()) {
1086 SetErrorCode("The given edge does not belong to the shape");
1090 const TopTools_ListOfShape& aFacesOfE1 = MEF.FindFromKey(E1);
1091 const TopTools_ListOfShape& aFacesOfE2 = MEF.FindFromKey(E2);
1093 Standard_Integer isFound = 0;
1094 TopTools_ListIteratorOfListOfShape anIterF1 (aFacesOfE1);
1095 for (; anIterF1.More(); anIterF1.Next()) {
1097 TopTools_ListIteratorOfListOfShape anIterF2 (aFacesOfE2);
1098 for (; anIterF2.More(); anIterF2.Next()) {
1100 if (anIterF1.Value().IsSame(anIterF2.Value())) {
1103 // Store the face, defined by two edges
1104 aShape = anIterF1.Value();
1109 SetErrorCode("The given edges do not belong to one face of the given shape");
1111 } else if (isFound > 1) {
1112 SetErrorCode("The given edges belong to several faces of the given shape");
1115 TopTools_IndexedMapOfShape anIndices;
1116 TopExp::MapShapes(aBlockOrComp, anIndices);
1117 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1118 anArray->SetValue(1, anIndices.FindIndex(aShape));
1119 aResult = GetEngine()->AddSubShape(theShape, anArray);
1122 catch (Standard_Failure) {
1123 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1124 SetErrorCode(aFail->GetMessageString());
1128 //The GetFaceByEdges() doesn't change object so no new function is required.
1129 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1131 //Make a Python command
1132 TCollection_AsciiString anEntry, aDescr;
1133 TDF_Tool::Entry(aResult->GetEntry(), anEntry);
1134 aDescr += anEntry + " = geompy.GetFaceByEdges(";
1135 TDF_Tool::Entry(theShape->GetEntry(), anEntry);
1136 aDescr += anEntry + ", ";
1137 TDF_Tool::Entry(theEdge1->GetEntry(), anEntry);
1138 aDescr += anEntry + ", ";
1139 TDF_Tool::Entry(theEdge2->GetEntry(), anEntry);
1140 aDescr += anEntry + ")";
1142 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n\t";
1143 aNewDescr += aDescr;
1144 aFunction->SetDescription(aNewDescr);
1150 //=============================================================================
1154 //=============================================================================
1155 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetOppositeFace
1156 (Handle(GEOM_Object) theShape,
1157 Handle(GEOM_Object) theFace)
1162 Handle(GEOM_Object) aResult;
1165 if (theShape.IsNull() || theFace.IsNull()) return NULL;
1167 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1168 if (aBlockOrComp.IsNull()) {
1169 SetErrorCode("Block is null");
1172 if (aBlockOrComp.ShapeType() != TopAbs_SOLID) {
1173 SetErrorCode("Shape is not a block");
1177 TopoDS_Shape anArg = theFace->GetValue();
1178 if (anArg.IsNull()) {
1179 SetErrorCode("Null shape is given as argument");
1182 if (anArg.ShapeType() != TopAbs_FACE) {
1183 SetErrorCode("Element for face identification is not a face");
1187 //Compute the Face value
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 //The GetOppositeFace() doesn't change object so no new function is required.
1208 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1210 //Make a Python command
1211 TCollection_AsciiString anEntry, aDescr;
1212 TDF_Tool::Entry(aResult->GetEntry(), anEntry);
1213 aDescr += anEntry + " = geompy.GetOppositeFace(";
1214 TDF_Tool::Entry(theShape->GetEntry(), anEntry);
1215 aDescr += anEntry + ", ";
1216 TDF_Tool::Entry(theFace->GetEntry(), anEntry);
1217 aDescr += anEntry + ")";
1219 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n\t";
1220 aNewDescr += aDescr;
1221 aFunction->SetDescription(aNewDescr);
1227 //=============================================================================
1231 //=============================================================================
1232 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceNearPoint
1233 (Handle(GEOM_Object) theShape,
1234 Handle(GEOM_Object) thePoint)
1236 // OSD_Timer timer1, timer2, timer3, timer4, timer5;
1242 Handle(GEOM_Object) aResult;
1245 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
1247 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1248 if (aBlockOrComp.IsNull()) {
1249 SetErrorCode("Block or compound is null");
1252 if (aBlockOrComp.ShapeType() != TopAbs_SOLID &&
1253 aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
1254 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
1255 SetErrorCode("Shape is neither a block, nor a compound of blocks");
1259 TopoDS_Shape anArg = thePoint->GetValue();
1260 if (anArg.IsNull()) {
1261 SetErrorCode("Null shape is given as argument");
1264 if (anArg.ShapeType() != TopAbs_VERTEX) {
1265 SetErrorCode("Element for face identification is not a vertex");
1269 //Compute the Face value
1271 TopoDS_Shape aShape;
1273 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
1274 gp_Pnt aPnt = BRep_Tool::Pnt(aVert);
1275 Standard_Real PX, PY, PZ;
1276 aPnt.Coord(PX, PY, PZ);
1281 // 1. Classify the point relatively each face
1282 Standard_Integer nearest = 2, nbFound = 0;
1283 TopTools_DataMapOfShapeInteger mapShapeDist;
1284 TopExp_Explorer exp (aBlockOrComp, TopAbs_FACE);
1285 for (; exp.More(); exp.Next()) {
1286 TopoDS_Shape aFace = exp.Current();
1288 if (!mapShapeDist.IsBound(aFace)) {
1289 Standard_Integer aDistance = 2;
1291 // 1.a. Classify relatively Surface
1292 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aFace));
1293 Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf);
1294 gp_Pnt2d p2dOnSurf = aSurfAna->ValueOfUV(aPnt, Precision::Confusion());
1295 gp_Pnt p3dOnSurf = aSurfAna->Value(p2dOnSurf);
1296 Standard_Real aDist = p3dOnSurf.Distance(aPnt);
1297 if (aDist > Precision::Confusion()) {
1301 // 1.b. Classify relatively the face itself
1302 BRepClass_FaceClassifier FC (TopoDS::Face(aFace), p2dOnSurf, Precision::Confusion());
1303 if (FC.State() == TopAbs_IN) {
1305 } else if (FC.State() == TopAbs_ON) {
1312 if (aDistance < nearest) {
1313 nearest = aDistance;
1317 // A first found face, containing the point inside, will be returned.
1318 // It is the solution, if there are no
1319 // coincident or intersecting faces in the compound.
1320 if (nearest == -1) break;
1322 } else if (aDistance == nearest) {
1327 mapShapeDist.Bind(aFace, aDistance);
1328 } // if (!mapShapeDist.IsBound(aFace))
1334 // 2. Define face, containing the point or having minimum distance to it
1337 // The point is on boundary of some faces and there are
1338 // no faces, having the point inside
1339 SetErrorCode("Multiple faces near the given point are found");
1342 } else if (nearest == 1) {
1343 // The point is outside some faces and there are
1344 // no faces, having the point inside or on boundary.
1345 // We will get a nearest face
1346 Standard_Real bigReal = RealLast();
1347 Standard_Real minDist = bigReal;
1348 TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
1349 for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
1350 if (mapShapeDistIter.Value() == 1) {
1351 TopoDS_Shape aFace = mapShapeDistIter.Key();
1352 Standard_Real aDist = bigReal;
1354 // 2.a. Fast check of distance - if point projection on surface is on face
1355 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aFace));
1356 Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf);
1357 gp_Pnt2d p2dOnSurf = aSurfAna->ValueOfUV(aPnt, Precision::Confusion());
1358 gp_Pnt p3dOnSurf = aSurfAna->Value(p2dOnSurf);
1359 aDist = p3dOnSurf.Distance(aPnt);
1361 BRepClass_FaceClassifier FC (TopoDS::Face(aFace), p2dOnSurf, Precision::Confusion());
1362 if (FC.State() == TopAbs_OUT) {
1363 if (aDist < minDist) {
1364 // 2.b. Slow check - if point projection on surface is outside of face
1365 BRepExtrema_DistShapeShape aDistTool (aVert, aFace);
1366 if (!aDistTool.IsDone()) {
1367 SetErrorCode("Can not find a distance from the given point to one of faces");
1370 aDist = aDistTool.Value();
1376 if (aDist < minDist) {
1382 } else { // nearest == -1
1383 // // The point is inside some faces.
1384 // // We will get a face with nearest center
1385 // Standard_Real minDist = RealLast();
1386 // TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
1387 // for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
1388 // if (mapShapeDistIter.Value() == -1) {
1389 // TopoDS_Shape aFace = mapShapeDistIter.Key();
1390 // GProp_GProps aSystem;
1391 // BRepGProp::SurfaceProperties(aFace, aSystem);
1392 // gp_Pnt aCenterMass = aSystem.CentreOfMass();
1394 // Standard_Real aDist = aCenterMass.Distance(aPnt);
1395 // if (aDist < minDist) {
1402 } // if (nbFound > 1)
1408 SetErrorCode("There are no faces near the given point");
1411 TopTools_IndexedMapOfShape anIndices;
1412 TopExp::MapShapes(aBlockOrComp, anIndices);
1413 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1414 anArray->SetValue(1, anIndices.FindIndex(aShape));
1415 aResult = GetEngine()->AddSubShape(theShape, anArray);
1420 catch (Standard_Failure) {
1421 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1422 SetErrorCode(aFail->GetMessageString());
1428 //The GetFaceNearPoint() doesn't change object so no new function is required.
1429 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1431 //Make a Python command
1432 TCollection_AsciiString anEntry, aDescr;
1433 TDF_Tool::Entry(aResult->GetEntry(), anEntry);
1434 aDescr += anEntry + " = geompy.GetFaceNearPoint(";
1435 TDF_Tool::Entry(theShape->GetEntry(), anEntry);
1436 aDescr += anEntry + ", ";
1437 TDF_Tool::Entry(thePoint->GetEntry(), anEntry);
1438 aDescr += anEntry + ")";
1440 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n\t";
1441 aNewDescr += aDescr;
1442 aFunction->SetDescription(aNewDescr);
1448 // cout << "Show current face times:" << endl;
1458 //=============================================================================
1462 //=============================================================================
1463 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByNormale
1464 (Handle(GEOM_Object) theShape,
1465 Handle(GEOM_Object) theVector)
1470 Handle(GEOM_Object) aResult;
1473 if (theShape.IsNull() || theVector.IsNull()) return NULL;
1475 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1476 if (aBlockOrComp.IsNull()) {
1477 SetErrorCode("Block or compound is null");
1480 if (aBlockOrComp.ShapeType() != TopAbs_SOLID &&
1481 aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
1482 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
1483 SetErrorCode("Shape is neither a block, nor a compound of blocks");
1487 TopoDS_Shape anArg = theVector->GetValue();
1488 if (anArg.IsNull()) {
1489 SetErrorCode("Null shape is given as argument");
1492 if (anArg.ShapeType() != TopAbs_EDGE) {
1493 SetErrorCode("Element for normale identification is not an edge");
1497 //Compute the Face value
1499 TopoDS_Shape aShape;
1501 TopoDS_Edge anEdge = TopoDS::Edge(anArg);
1502 TopoDS_Vertex V1, V2;
1503 TopExp::Vertices(anEdge, V1, V2, Standard_True);
1504 gp_Pnt P1 = BRep_Tool::Pnt(V1);
1505 gp_Pnt P2 = BRep_Tool::Pnt(V2);
1506 gp_Vec aVec (P1, P2);
1507 if (aVec.Magnitude() < Precision::Confusion()) {
1508 SetErrorCode("Vector with null magnitude is given");
1512 Standard_Real minAngle = RealLast();
1513 TopTools_MapOfShape mapShape;
1514 TopExp_Explorer exp (aBlockOrComp, TopAbs_FACE);
1515 for (; exp.More(); exp.Next()) {
1516 if (mapShape.Add(exp.Current())) {
1517 TopoDS_Face aFace = TopoDS::Face(exp.Current());
1518 BRepAdaptor_Surface SF (aFace);
1520 Standard_Real u, v, x;
1522 // find a point on the surface to get normal direction in
1523 u = SF.FirstUParameter();
1524 x = SF.LastUParameter();
1525 if (Precision::IsInfinite(u)) {
1526 u = (Precision::IsInfinite(x)) ? 0. : x;
1527 } else if (!Precision::IsInfinite(x)) {
1531 v = SF.FirstVParameter();
1532 x = SF.LastVParameter();
1533 if (Precision::IsInfinite(v)) {
1534 v = (Precision::IsInfinite(x)) ? 0. : x;
1535 } else if (!Precision::IsInfinite(x)) {
1539 // compute the normal direction
1541 SF.D1(u,v,P1,Vec1,Vec2);
1542 gp_Vec V = Vec1.Crossed(Vec2);
1544 if (V.Magnitude() < Precision::Confusion()) {
1545 SetErrorCode("Normal vector of a face has null magnitude");
1549 // consider the face orientation
1550 if (aFace.Orientation() == TopAbs_REVERSED ||
1551 aFace.Orientation() == TopAbs_INTERNAL) {
1555 // compute the angle and compare with the minimal one
1556 Standard_Real anAngle = aVec.Angle(V);
1557 if (anAngle < minAngle) {
1564 if (aShape.IsNull()) {
1565 SetErrorCode("Failed to find a face by the given normale");
1568 TopTools_IndexedMapOfShape anIndices;
1569 TopExp::MapShapes(aBlockOrComp, anIndices);
1570 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1571 anArray->SetValue(1, anIndices.FindIndex(aShape));
1572 aResult = GetEngine()->AddSubShape(theShape, anArray);
1575 catch (Standard_Failure) {
1576 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1577 SetErrorCode(aFail->GetMessageString());
1581 //The GetFaceByNormale() doesn't change object so no new function is required.
1582 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1584 //Make a Python command
1585 TCollection_AsciiString anEntry, aDescr;
1586 TDF_Tool::Entry(aResult->GetEntry(), anEntry);
1587 aDescr += anEntry + " = geompy.GetFaceByNormale(";
1588 TDF_Tool::Entry(theShape->GetEntry(), anEntry);
1589 aDescr += anEntry + ", ";
1590 TDF_Tool::Entry(theVector->GetEntry(), anEntry);
1591 aDescr += anEntry + ")";
1593 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n\t";
1594 aNewDescr += aDescr;
1595 aFunction->SetDescription(aNewDescr);
1601 //=============================================================================
1603 * IsCompoundOfBlocks
1605 //=============================================================================
1606 Standard_Boolean GEOMImpl_IBlocksOperations::IsCompoundOfBlocks
1607 (Handle(GEOM_Object) theCompound,
1608 const Standard_Integer theMinNbFaces,
1609 const Standard_Integer theMaxNbFaces,
1610 Standard_Integer& theNbBlocks)
1613 Standard_Boolean isCompOfBlocks = Standard_False;
1616 if (theCompound.IsNull()) return isCompOfBlocks;
1617 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
1620 isCompOfBlocks = Standard_True;
1622 TopTools_MapOfShape mapShape;
1623 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
1624 for (; exp.More(); exp.Next()) {
1625 if (mapShape.Add(exp.Current())) {
1626 TopoDS_Shape aSolid = exp.Current();
1628 TopTools_MapOfShape mapFaces;
1629 TopExp_Explorer expF (aSolid, TopAbs_FACE);
1630 Standard_Integer nbFaces = 0;
1631 for (; expF.More(); expF.Next()) {
1632 if (mapFaces.Add(expF.Current())) {
1634 if (nbFaces > theMaxNbFaces) {
1635 isCompOfBlocks = Standard_False;
1640 if (nbFaces < theMinNbFaces || theMaxNbFaces < nbFaces) {
1641 isCompOfBlocks = Standard_False;
1648 catch (Standard_Failure) {
1649 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1650 SetErrorCode(aFail->GetMessageString());
1651 return isCompOfBlocks;
1655 return isCompOfBlocks;
1658 //=============================================================================
1660 * Set of functions, used by CheckCompoundOfBlocks() method
1662 //=============================================================================
1663 void GEOMImpl_IBlocksOperations::AddBlocksFrom (const TopoDS_Shape& theShape,
1664 TopTools_ListOfShape& BLO,
1665 TopTools_ListOfShape& NOT,
1666 TopTools_ListOfShape& EXT)
1668 TopAbs_ShapeEnum aType = theShape.ShapeType();
1670 case TopAbs_COMPOUND:
1671 case TopAbs_COMPSOLID:
1673 TopoDS_Iterator It (theShape);
1674 for (; It.More(); It.Next()) {
1675 AddBlocksFrom(It.Value(), BLO, NOT, EXT);
1681 // Check, if there are seam or degenerated edges
1682 BlockFix_CheckTool aTool;
1683 aTool.SetShape(theShape);
1685 if (aTool.NbPossibleBlocks() > 0) {
1686 EXT.Append(theShape);
1688 // Count faces and edges in each face to recognize blocks
1689 TopTools_MapOfShape mapFaces;
1690 Standard_Integer nbFaces = 0;
1691 Standard_Boolean hasNonQuadr = Standard_False;
1692 TopExp_Explorer expF (theShape, TopAbs_FACE);
1694 for (; expF.More(); expF.Next()) {
1695 if (mapFaces.Add(expF.Current())) {
1697 if (nbFaces > 6) break;
1700 TopoDS_Shape aF = expF.Current();
1701 TopExp_Explorer wires (aF, TopAbs_WIRE);
1702 if (!wires.More()) {
1703 // no wire in the face
1704 hasNonQuadr = Standard_True;
1707 TopoDS_Shape aWire = wires.Current();
1710 // multiple wires in the face
1711 hasNonQuadr = Standard_True;
1715 // Check number of edges in the face
1716 Standard_Integer nbEdges = 0;
1717 TopTools_MapOfShape mapEdges;
1718 TopExp_Explorer expW (aWire, TopAbs_EDGE);
1719 for (; expW.More(); expW.Next()) {
1720 if (mapEdges.Add(expW.Current())) {
1722 if (nbEdges > 4) break;
1726 hasNonQuadr = Standard_True;
1731 if (nbFaces == 6 && !hasNonQuadr) {
1732 BLO.Append(theShape);
1734 NOT.Append(theShape);
1740 NOT.Append(theShape);
1744 void AddBlocksFromOld (const TopoDS_Shape& theShape,
1745 TopTools_ListOfShape& BLO,
1746 TopTools_ListOfShape& NOT,
1747 TopTools_ListOfShape& DEG,
1748 TopTools_ListOfShape& SEA)
1750 TopAbs_ShapeEnum aType = theShape.ShapeType();
1752 case TopAbs_COMPOUND:
1753 case TopAbs_COMPSOLID:
1755 TopoDS_Iterator It (theShape);
1756 for (; It.More(); It.Next()) {
1757 AddBlocksFromOld(It.Value(), BLO, NOT, DEG, SEA);
1763 TopTools_MapOfShape mapFaces;
1764 TopExp_Explorer expF (theShape, TopAbs_FACE);
1765 Standard_Integer nbFaces = 0;
1766 Standard_Boolean hasNonQuadr = Standard_False;
1767 Standard_Boolean hasDegenerated = Standard_False;
1768 Standard_Boolean hasSeam = Standard_False;
1769 for (; expF.More(); expF.Next()) {
1770 if (mapFaces.Add(expF.Current())) {
1772 if (nbFaces > 6) break;
1774 // Check number of edges in the face
1775 Standard_Integer nbEdges = 0;
1776 TopTools_MapOfShape mapEdges;
1779 TopoDS_Shape aF = expF.Current();
1780 TopExp_Explorer wires (aF, TopAbs_WIRE);
1781 if (!wires.More()) {
1782 // no wire in the face
1783 hasNonQuadr = Standard_True;
1786 TopoDS_Shape aWire = wires.Current();
1789 // multiple wires in the face
1790 hasNonQuadr = Standard_True;
1795 BRepTools_WireExplorer aWE (TopoDS::Wire(aWire), TopoDS::Face(aF));
1796 for (; aWE.More(); aWE.Next(), nbEdges++) {
1797 if (BRep_Tool::Degenerated(aWE.Current())) {
1798 // degenerated edge found
1799 hasDegenerated = Standard_True;
1802 if (mapEdges.Contains(aWE.Current())) {
1804 hasSeam = Standard_True;
1807 mapEdges.Add(aWE.Current());
1810 hasNonQuadr = Standard_True;
1815 if (hasDegenerated || hasSeam) {
1816 if (hasDegenerated) {
1817 DEG.Append(theShape);
1820 SEA.Append(theShape);
1822 } else if (hasNonQuadr) {
1823 NOT.Append(theShape);
1825 BLO.Append(theShape);
1828 NOT.Append(theShape);
1833 NOT.Append(theShape);
1837 #define REL_NOT_CONNECTED 0
1839 #define REL_NOT_GLUED 2
1840 #define REL_COLLISION_VV 3
1841 #define REL_COLLISION_FF 4
1842 #define REL_COLLISION_EE 5
1843 #define REL_UNKNOWN 6
1845 Standard_Integer BlocksRelation (const TopoDS_Shape& theBlock1,
1846 const TopoDS_Shape& theBlock2)
1848 // Compare bounding boxes before calling BRepExtrema_DistShapeShape
1849 Standard_Real Xmin1, Ymin1, Zmin1, Xmax1, Ymax1, Zmax1;
1850 Standard_Real Xmin2, Ymin2, Zmin2, Xmax2, Ymax2, Zmax2;
1852 BRepBndLib::Add(theBlock1, B1);
1853 BRepBndLib::Add(theBlock2, B2);
1854 B1.Get(Xmin1, Ymin1, Zmin1, Xmax1, Ymax1, Zmax1);
1855 B2.Get(Xmin2, Ymin2, Zmin2, Xmax2, Ymax2, Zmax2);
1856 if (Xmax2 < Xmin1 || Xmax1 < Xmin2 ||
1857 Ymax2 < Ymin1 || Ymax1 < Ymin2 ||
1858 Zmax2 < Zmin1 || Zmax1 < Zmin2) {
1859 return REL_NOT_CONNECTED;
1862 BRepExtrema_DistShapeShape dst (theBlock1, theBlock2);
1863 if (!dst.IsDone()) {
1867 if (dst.Value() > Precision::Confusion()) {
1868 return REL_NOT_CONNECTED;
1871 if (dst.InnerSolution()) {
1872 return REL_COLLISION_VV;
1875 Standard_Integer nbSol = dst.NbSolution();
1876 Standard_Integer relation = REL_OK;
1877 Standard_Integer nbVerts = 0;
1878 Standard_Integer nbEdges = 0;
1879 Standard_Integer sol = 1;
1880 for (; sol <= nbSol; sol++) {
1881 BRepExtrema_SupportType supp1 = dst.SupportTypeShape1(sol);
1882 BRepExtrema_SupportType supp2 = dst.SupportTypeShape2(sol);
1883 if (supp1 == BRepExtrema_IsVertex && supp2 == BRepExtrema_IsVertex) {
1885 } else if (supp1 == BRepExtrema_IsInFace || supp2 == BRepExtrema_IsInFace) {
1886 return REL_COLLISION_FF;
1887 } else if (supp1 == BRepExtrema_IsOnEdge && supp2 == BRepExtrema_IsOnEdge) {
1889 } else if ((supp1 == BRepExtrema_IsOnEdge && supp2 == BRepExtrema_IsVertex) ||
1890 (supp2 == BRepExtrema_IsOnEdge && supp1 == BRepExtrema_IsVertex)) {
1891 relation = REL_COLLISION_EE;
1896 if (relation != REL_OK) {
1900 TColStd_Array1OfInteger vertSol (1, nbVerts);
1901 TopTools_Array1OfShape V1 (1, nbVerts);
1902 TopTools_Array1OfShape V2 (1, nbVerts);
1903 Standard_Integer ivs = 0;
1904 for (sol = 1; sol <= nbSol; sol++) {
1905 if (dst.SupportTypeShape1(sol) == BRepExtrema_IsVertex &&
1906 dst.SupportTypeShape2(sol) == BRepExtrema_IsVertex) {
1907 TopoDS_Vertex Vcur = TopoDS::Vertex(dst.SupportOnShape1(sol));
1908 // Check, that this vertex is far enough from other solution vertices.
1909 Standard_Integer ii = 1;
1910 for (; ii <= ivs; ii++) {
1911 if (BRepTools::Compare(TopoDS::Vertex(V1(ii)), Vcur)) {
1918 V2(ivs) = dst.SupportOnShape2(sol);
1922 // As we deal only with quadrangles,
1923 // 2, 3 or 4 vertex solutions can be found.
1926 return REL_COLLISION_FF;
1928 return REL_NOT_CONNECTED;
1934 // Check sharing of coincident entities.
1935 if (ivs == 2 || ivs == 3) {
1936 // Map vertices and edges of the blocks
1937 TopTools_IndexedDataMapOfShapeListOfShape MVE1, MVE2;
1938 GEOMImpl_Block6Explorer::MapShapesAndAncestors
1939 (theBlock1, TopAbs_VERTEX, TopAbs_EDGE, MVE1);
1940 GEOMImpl_Block6Explorer::MapShapesAndAncestors
1941 (theBlock2, TopAbs_VERTEX, TopAbs_EDGE, MVE2);
1945 TopoDS_Shape anEdge1, anEdge2;
1946 GEOMImpl_Block6Explorer::FindEdge(anEdge1, V1(1), V1(2), MVE1);
1947 if (anEdge1.IsNull()) return REL_UNKNOWN;
1949 GEOMImpl_Block6Explorer::FindEdge(anEdge2, V2(1), V2(2), MVE2);
1950 if (anEdge2.IsNull()) return REL_UNKNOWN;
1952 if (!anEdge1.IsSame(anEdge2)) return REL_NOT_GLUED;
1954 } else { // ivs == 3
1955 // Find common edges
1956 Standard_Integer e1_v1 = 1;
1957 Standard_Integer e1_v2 = 2;
1958 Standard_Integer e2_v1 = 3;
1959 Standard_Integer e2_v2 = 1;
1961 TopoDS_Shape anEdge11, anEdge12;
1962 GEOMImpl_Block6Explorer::FindEdge(anEdge11, V1(e1_v1), V1(e1_v2), MVE1);
1963 if (anEdge11.IsNull()) {
1966 GEOMImpl_Block6Explorer::FindEdge(anEdge11, V1(e1_v1), V1(e1_v2), MVE1);
1967 if (anEdge11.IsNull()) return REL_UNKNOWN;
1969 GEOMImpl_Block6Explorer::FindEdge(anEdge12, V1(e2_v1), V1(e2_v2), MVE1);
1970 if (anEdge12.IsNull()) {
1972 GEOMImpl_Block6Explorer::FindEdge(anEdge12, V1(e2_v1), V1(e2_v2), MVE1);
1973 if (anEdge12.IsNull()) return REL_UNKNOWN;
1976 TopoDS_Shape anEdge21, anEdge22;
1977 GEOMImpl_Block6Explorer::FindEdge(anEdge21, V2(e1_v1), V2(e1_v2), MVE2);
1978 if (anEdge21.IsNull()) return REL_UNKNOWN;
1979 GEOMImpl_Block6Explorer::FindEdge(anEdge22, V2(e2_v1), V2(e2_v2), MVE2);
1980 if (anEdge22.IsNull()) return REL_UNKNOWN;
1982 // Check of edges coincidence (with some precision) have to be done here
1983 // if (!anEdge11.IsEqual(anEdge21)) return REL_UNKNOWN;
1984 // if (!anEdge12.IsEqual(anEdge22)) return REL_UNKNOWN;
1986 // Check of edges sharing
1987 if (!anEdge11.IsSame(anEdge21)) return REL_NOT_GLUED;
1988 if (!anEdge12.IsSame(anEdge22)) return REL_NOT_GLUED;
1993 // Map vertices and faces of the blocks
1994 TopTools_IndexedDataMapOfShapeListOfShape MVF1, MVF2;
1995 GEOMImpl_Block6Explorer::MapShapesAndAncestors
1996 (theBlock1, TopAbs_VERTEX, TopAbs_FACE, MVF1);
1997 GEOMImpl_Block6Explorer::MapShapesAndAncestors
1998 (theBlock2, TopAbs_VERTEX, TopAbs_FACE, MVF2);
2000 TopoDS_Shape aFace1, aFace2;
2001 GEOMImpl_Block6Explorer::FindFace(aFace1, V1(1), V1(2), V1(3), V1(4), MVF1);
2002 if (aFace1.IsNull()) return REL_UNKNOWN;
2003 GEOMImpl_Block6Explorer::FindFace(aFace2, V2(1), V2(2), V2(3), V2(4), MVF2);
2004 if (aFace2.IsNull()) return REL_UNKNOWN;
2006 // Check of faces coincidence (with some precision) have to be done here
2007 // if (!aFace1.IsEqual(aFace2)) return REL_UNKNOWN;
2009 // Check of faces sharing
2010 if (!aFace1.IsSame(aFace2)) return REL_NOT_GLUED;
2016 void FindConnected (const Standard_Integer theBlockIndex,
2017 const TColStd_Array2OfInteger& theRelations,
2018 TColStd_MapOfInteger& theProcessedMap,
2019 TColStd_MapOfInteger& theConnectedMap)
2021 theConnectedMap.Add(theBlockIndex);
2022 theProcessedMap.Add(theBlockIndex);
2024 Standard_Integer nbBlocks = theRelations.ColLength();
2025 Standard_Integer col = 1;
2026 for (; col <= nbBlocks; col++) {
2027 if (theRelations(theBlockIndex, col) == REL_OK ||
2028 theRelations(theBlockIndex, col) == REL_NOT_GLUED) {
2029 if (!theProcessedMap.Contains(col)) {
2030 FindConnected(col, theRelations, theProcessedMap, theConnectedMap);
2036 Standard_Boolean HasAnyConnection (const Standard_Integer theBlockIndex,
2037 const TColStd_MapOfInteger& theWith,
2038 const TColStd_Array2OfInteger& theRelations,
2039 TColStd_MapOfInteger& theProcessedMap)
2041 theProcessedMap.Add(theBlockIndex);
2043 Standard_Integer nbBlocks = theRelations.ColLength();
2044 Standard_Integer col = 1;
2045 for (; col <= nbBlocks; col++) {
2046 if (theRelations(theBlockIndex, col) != REL_NOT_CONNECTED) {
2047 if (!theProcessedMap.Contains(col)) {
2048 if (theWith.Contains(col))
2049 return Standard_True;
2050 if (HasAnyConnection(col, theWith, theRelations, theProcessedMap))
2051 return Standard_True;
2056 return Standard_False;
2059 //=============================================================================
2061 * CheckCompoundOfBlocksOld
2063 //=============================================================================
2064 Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocksOld
2065 (Handle(GEOM_Object) theCompound,
2066 list<BCError>& theErrors)
2070 if (theCompound.IsNull()) return Standard_False;
2071 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2073 Standard_Boolean isCompOfBlocks = Standard_True;
2075 // Map sub-shapes and their indices
2076 TopTools_IndexedMapOfShape anIndices;
2077 TopExp::MapShapes(aBlockOrComp, anIndices);
2079 // 1. Report non-blocks
2080 TopTools_ListOfShape NOT; // Not blocks
2081 TopTools_ListOfShape DEG; // Hexahedral solids, having degenerated edges
2082 TopTools_ListOfShape SEA; // Hexahedral solids, having seam edges
2083 TopTools_ListOfShape BLO; // All blocks from the given compound
2084 AddBlocksFromOld(aBlockOrComp, BLO, NOT, DEG, SEA);
2086 if (NOT.Extent() > 0) {
2087 isCompOfBlocks = Standard_False;
2089 anErr.error = NOT_BLOCK;
2090 TopTools_ListIteratorOfListOfShape it (NOT);
2091 for (; it.More(); it.Next()) {
2092 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
2094 theErrors.push_back(anErr);
2097 if (DEG.Extent() > 0 || SEA.Extent() > 0) {
2098 isCompOfBlocks = Standard_False;
2100 anErr.error = EXTRA_EDGE;
2102 TopTools_ListIteratorOfListOfShape itDEG (DEG);
2103 for (; itDEG.More(); itDEG.Next()) {
2104 anErr.incriminated.push_back(anIndices.FindIndex(itDEG.Value()));
2107 TopTools_ListIteratorOfListOfShape itSEA (SEA);
2108 for (; itSEA.More(); itSEA.Next()) {
2109 anErr.incriminated.push_back(anIndices.FindIndex(itSEA.Value()));
2112 theErrors.push_back(anErr);
2115 Standard_Integer nbBlocks = BLO.Extent();
2116 if (nbBlocks == 0) {
2117 isCompOfBlocks = Standard_False;
2119 return isCompOfBlocks;
2121 if (nbBlocks == 1) {
2123 return isCompOfBlocks;
2126 // Convert list of blocks into array for easy and fast access
2127 Standard_Integer ibl = 1;
2128 TopTools_Array1OfShape aBlocks (1, nbBlocks);
2129 TopTools_ListIteratorOfListOfShape BLOit (BLO);
2130 for (; BLOit.More(); BLOit.Next(), ibl++) {
2131 aBlocks.SetValue(ibl, BLOit.Value());
2134 // 2. Find relations between all blocks,
2135 // report connection errors (NOT_GLUED and INVALID_CONNECTION)
2136 TColStd_Array2OfInteger aRelations (1, nbBlocks, 1, nbBlocks);
2137 aRelations.Init(REL_NOT_CONNECTED);
2139 Standard_Integer row = 1;
2140 for (row = 1; row <= nbBlocks; row++) {
2141 TopoDS_Shape aBlock = aBlocks.Value(row);
2143 Standard_Integer col = row + 1;
2144 for (; col <= nbBlocks; col++) {
2145 Standard_Integer aRel = BlocksRelation(aBlock, aBlocks.Value(col));
2146 if (aRel != REL_NOT_CONNECTED) {
2147 aRelations.SetValue(row, col, aRel);
2148 aRelations.SetValue(col, row, aRel);
2149 if (aRel == REL_NOT_GLUED) {
2150 // report connection error
2151 isCompOfBlocks = Standard_False;
2153 anErr.error = NOT_GLUED;
2154 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row)));
2155 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col)));
2156 theErrors.push_back(anErr);
2157 } else if (aRel == REL_COLLISION_VV ||
2158 aRel == REL_COLLISION_FF ||
2159 aRel == REL_COLLISION_EE ||
2160 aRel == REL_UNKNOWN) {
2161 // report connection error
2162 isCompOfBlocks = Standard_False;
2164 anErr.error = INVALID_CONNECTION;
2165 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row)));
2166 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col)));
2167 theErrors.push_back(anErr);
2174 // 3. Find largest set of connected (good connection or not glued) blocks
2175 TColStd_MapOfInteger aProcessedMap;
2176 TColStd_MapOfInteger aLargestSet;
2177 TColStd_MapOfInteger aCurrentSet;
2178 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2179 if (!aProcessedMap.Contains(ibl)) {
2180 aCurrentSet.Clear();
2181 FindConnected(ibl, aRelations, aProcessedMap, aCurrentSet);
2182 if (aCurrentSet.Extent() > aLargestSet.Extent()) {
2183 aLargestSet = aCurrentSet;
2188 // 4. Report all blocks, isolated from <aLargestSet>
2190 anErr.error = NOT_CONNECTED;
2191 Standard_Boolean hasIsolated = Standard_False;
2192 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2193 if (!aLargestSet.Contains(ibl)) {
2194 aProcessedMap.Clear();
2195 if (!HasAnyConnection(ibl, aLargestSet, aRelations, aProcessedMap)) {
2196 // report connection absence
2197 hasIsolated = Standard_True;
2198 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(ibl)));
2203 isCompOfBlocks = Standard_False;
2204 theErrors.push_back(anErr);
2208 return isCompOfBlocks;
2211 //=============================================================================
2215 //=============================================================================
2216 TCollection_AsciiString GEOMImpl_IBlocksOperations::PrintBCErrors
2217 (Handle(GEOM_Object) theCompound,
2218 const list<BCError>& theErrors)
2220 TCollection_AsciiString aDescr;
2222 list<BCError>::const_iterator errIt = theErrors.begin();
2224 for (; errIt != theErrors.end(); i++, errIt++) {
2225 BCError errStruct = *errIt;
2227 switch (errStruct.error) {
2229 aDescr += "\n\tNot a Blocks: ";
2232 aDescr += "\n\tHexahedral solids with degenerated and/or seam edges: ";
2234 case INVALID_CONNECTION:
2235 aDescr += "\n\tInvalid connection between two blocks: ";
2238 aDescr += "\n\tBlocks, not connected with main body: ";
2241 aDescr += "\n\tNot glued blocks: ";
2247 list<int> sshList = errStruct.incriminated;
2248 list<int>::iterator sshIt = sshList.begin();
2250 for (; sshIt != sshList.end(); jj++, sshIt++) {
2253 aDescr += TCollection_AsciiString(*sshIt);
2260 //=============================================================================
2262 * CheckCompoundOfBlocks
2264 //=============================================================================
2265 Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocks
2266 (Handle(GEOM_Object) theCompound,
2267 list<BCError>& theErrors)
2271 if (theCompound.IsNull()) return Standard_False;
2272 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2274 Standard_Boolean isCompOfBlocks = Standard_True;
2276 // Map sub-shapes and their indices
2277 TopTools_IndexedMapOfShape anIndices;
2278 TopExp::MapShapes(aBlockOrComp, anIndices);
2280 // 1. Separate blocks from non-blocks
2281 TopTools_ListOfShape NOT; // Not blocks
2282 TopTools_ListOfShape EXT; // Hexahedral solids, having degenerated and/or seam edges
2283 TopTools_ListOfShape BLO; // All blocks from the given compound
2284 AddBlocksFrom(aBlockOrComp, BLO, NOT, EXT);
2286 // Report non-blocks
2287 if (NOT.Extent() > 0) {
2288 isCompOfBlocks = Standard_False;
2290 anErr.error = NOT_BLOCK;
2291 TopTools_ListIteratorOfListOfShape it (NOT);
2292 for (; it.More(); it.Next()) {
2293 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
2295 theErrors.push_back(anErr);
2298 // Report solids, having degenerated and/or seam edges
2299 if (EXT.Extent() > 0) {
2300 isCompOfBlocks = Standard_False;
2302 anErr.error = EXTRA_EDGE;
2303 TopTools_ListIteratorOfListOfShape it (EXT);
2304 for (; it.More(); it.Next()) {
2305 anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
2307 theErrors.push_back(anErr);
2310 Standard_Integer nbBlocks = BLO.Extent();
2311 if (nbBlocks == 0) {
2312 isCompOfBlocks = Standard_False;
2314 return isCompOfBlocks;
2316 if (nbBlocks == 1) {
2318 return isCompOfBlocks;
2321 // Prepare data for 2. and 3.
2322 TColStd_Array2OfInteger aRelations (1, nbBlocks, 1, nbBlocks);
2323 aRelations.Init(REL_NOT_CONNECTED);
2325 TopTools_IndexedMapOfShape mapBlocks;
2328 TopoDS_Compound aComp;
2329 BB.MakeCompound(aComp);
2331 TopTools_ListIteratorOfListOfShape BLOit (BLO);
2332 for (; BLOit.More(); BLOit.Next()) {
2333 mapBlocks.Add(BLOit.Value());
2334 BB.Add(aComp, BLOit.Value());
2337 // 2. Find glued blocks (having shared faces)
2338 TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
2339 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2340 (aComp, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
2342 Standard_Integer prevInd = 0, curInd = 0;
2343 Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
2344 for (; ind <= nbFaces; ind++) {
2345 const TopTools_ListOfShape& aGluedBlocks = mapFaceBlocks.FindFromIndex(ind);
2346 if (aGluedBlocks.Extent() > 1) { // Shared face found
2347 TopTools_ListIteratorOfListOfShape aGluedBlocksIt (aGluedBlocks);
2348 TopoDS_Shape prevBlock, curBlock;
2349 for (; aGluedBlocksIt.More(); aGluedBlocksIt.Next()) {
2350 curBlock = aGluedBlocksIt.Value();
2351 if (!prevBlock.IsNull()) {
2352 prevInd = mapBlocks.FindIndex(prevBlock);
2353 curInd = mapBlocks.FindIndex(curBlock);
2354 aRelations.SetValue(prevInd, curInd, REL_OK);
2355 aRelations.SetValue(curInd, prevInd, REL_OK);
2357 prevBlock = curBlock;
2362 // 3. Find not glued blocks
2363 GEOMAlgo_GlueAnalyser aGD;
2365 aGD.SetShape(aComp);
2366 aGD.SetTolerance(Precision::Confusion());
2367 aGD.SetCheckGeometry(Standard_True);
2370 Standard_Integer iErr, iWrn;
2371 iErr = aGD.ErrorStatus();
2373 SetErrorCode("Error in GEOMAlgo_GlueAnalyser");
2374 return isCompOfBlocks;
2376 iWrn = aGD.WarningStatus();
2378 MESSAGE("Warning in GEOMAlgo_GlueAnalyser");
2381 // Report not glued blocks
2382 if (aGD.HasSolidsToGlue()) {
2383 isCompOfBlocks = Standard_False;
2384 Standard_Integer aSx1Ind, aSx2Ind;
2386 const GEOMAlgo_ListOfCoupleOfShapes& aLCS = aGD.SolidsToGlue();
2387 GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS (aLCS);
2388 for (; aItCS.More(); aItCS.Next()) {
2389 const GEOMAlgo_CoupleOfShapes& aCS = aItCS.Value();
2390 const TopoDS_Shape& aSx1 = aCS.Shape1();
2391 const TopoDS_Shape& aSx2 = aCS.Shape2();
2393 aSx1Ind = mapBlocks.FindIndex(aSx1);
2394 aSx2Ind = mapBlocks.FindIndex(aSx2);
2395 aRelations.SetValue(aSx1Ind, aSx2Ind, NOT_GLUED);
2396 aRelations.SetValue(aSx2Ind, aSx1Ind, NOT_GLUED);
2399 anErr.error = NOT_GLUED;
2400 anErr.incriminated.push_back(anIndices.FindIndex(aSx1));
2401 anErr.incriminated.push_back(anIndices.FindIndex(aSx2));
2402 theErrors.push_back(anErr);
2406 // 4. Find largest set of connected (good connection or not glued) blocks
2407 Standard_Integer ibl = 1;
2408 TColStd_MapOfInteger aProcessedMap;
2409 TColStd_MapOfInteger aLargestSet;
2410 TColStd_MapOfInteger aCurrentSet;
2411 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2412 if (!aProcessedMap.Contains(ibl)) {
2413 aCurrentSet.Clear();
2414 FindConnected(ibl, aRelations, aProcessedMap, aCurrentSet);
2415 if (aCurrentSet.Extent() > aLargestSet.Extent()) {
2416 aLargestSet = aCurrentSet;
2421 // 5. Report all blocks, isolated from <aLargestSet>
2423 anErr.error = NOT_CONNECTED;
2424 Standard_Boolean hasIsolated = Standard_False;
2425 for (ibl = 1; ibl <= nbBlocks; ibl++) {
2426 if (!aLargestSet.Contains(ibl)) {
2427 aProcessedMap.Clear();
2428 if (!HasAnyConnection(ibl, aLargestSet, aRelations, aProcessedMap)) {
2429 // report connection absence
2430 hasIsolated = Standard_True;
2431 anErr.incriminated.push_back(anIndices.FindIndex(mapBlocks.FindKey(ibl)));
2436 isCompOfBlocks = Standard_False;
2437 theErrors.push_back(anErr);
2441 return isCompOfBlocks;
2444 //=============================================================================
2448 //=============================================================================
2449 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::RemoveExtraEdges
2450 (Handle(GEOM_Object) theObject)
2454 if (theObject.IsNull()) return NULL;
2456 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2457 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be fixed
2459 //Add a new Copy object
2460 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2463 Handle(GEOM_Function) aFunction =
2464 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_REMOVE_EXTRA);
2466 //Check if the function is set correctly
2467 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2469 GEOMImpl_IBlockTrsf aTI (aFunction);
2470 aTI.SetOriginal(aLastFunction);
2472 //Compute the fixed shape
2474 if (!GetSolver()->ComputeFunction(aFunction)) {
2475 SetErrorCode("Block driver failed to remove extra edges of the given shape");
2479 catch (Standard_Failure) {
2480 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2481 SetErrorCode(aFail->GetMessageString());
2485 //Make a Python command
2486 TCollection_AsciiString anEntry, aDescr;
2487 TDF_Tool::Entry(aCopy->GetEntry(), anEntry);
2488 aDescr += anEntry + " = geompy.RemoveExtraEdges(";
2489 TDF_Tool::Entry(theObject->GetEntry(), anEntry);
2490 aDescr += anEntry + ")";
2492 aFunction->SetDescription(aDescr);
2498 //=============================================================================
2502 //=============================================================================
2503 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::CheckAndImprove
2504 (Handle(GEOM_Object) theObject)
2508 if (theObject.IsNull()) return NULL;
2510 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2511 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be fixed
2513 //Add a new Copy object
2514 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2517 Handle(GEOM_Function) aFunction =
2518 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_COMPOUND_IMPROVE);
2520 //Check if the function is set correctly
2521 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2523 GEOMImpl_IBlockTrsf aTI (aFunction);
2524 aTI.SetOriginal(aLastFunction);
2526 //Compute the fixed shape
2528 if (!GetSolver()->ComputeFunction(aFunction)) {
2529 SetErrorCode("Block driver failed to improve the given blocks compound");
2533 catch (Standard_Failure) {
2534 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2535 SetErrorCode(aFail->GetMessageString());
2539 //Make a Python command
2540 TCollection_AsciiString anEntry, aDescr;
2541 TDF_Tool::Entry(aCopy->GetEntry(), anEntry);
2542 aDescr += anEntry + " = geompy.CheckAndImprove(";
2543 TDF_Tool::Entry(theObject->GetEntry(), anEntry);
2544 aDescr += anEntry + ")";
2546 aFunction->SetDescription(aDescr);
2552 //=============================================================================
2554 * ExplodeCompoundOfBlocks
2556 //=============================================================================
2557 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::ExplodeCompoundOfBlocks
2558 (Handle(GEOM_Object) theCompound,
2559 const Standard_Integer theMinNbFaces,
2560 const Standard_Integer theMaxNbFaces)
2564 if (theCompound.IsNull()) return NULL;
2565 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2566 if (aBlockOrComp.IsNull()) return NULL;
2568 Handle(TColStd_HSequenceOfTransient) aBlocks = new TColStd_HSequenceOfTransient;
2569 Handle(GEOM_Object) anObj;
2570 Handle(GEOM_Function) aFunction;
2572 TopTools_MapOfShape mapShape;
2573 TCollection_AsciiString anAsciiList = "[", anEntry;
2576 TopTools_IndexedMapOfShape anIndices;
2577 TopExp::MapShapes(aBlockOrComp, anIndices);
2578 Handle(TColStd_HArray1OfInteger) anArray;
2582 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2583 for (; exp.More(); exp.Next()) {
2584 if (mapShape.Add(exp.Current())) {
2585 TopoDS_Shape aSolid = exp.Current();
2587 TopTools_MapOfShape mapFaces;
2588 TopExp_Explorer expF (aSolid, TopAbs_FACE);
2589 Standard_Integer nbFaces = 0;
2590 for (; expF.More(); expF.Next()) {
2591 if (mapFaces.Add(expF.Current())) {
2596 if (theMinNbFaces <= nbFaces && nbFaces <= theMaxNbFaces) {
2597 anArray = new TColStd_HArray1OfInteger(1,1);
2598 anArray->SetValue(1, anIndices.FindIndex(aSolid));
2599 anObj = GetEngine()->AddSubShape(theCompound, anArray);
2600 aBlocks->Append(anObj);
2602 //Make a Python command
2603 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2604 anAsciiList += anEntry;
2610 catch (Standard_Failure) {
2611 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2612 SetErrorCode(aFail->GetMessageString());
2616 if (aBlocks->IsEmpty()) {
2617 SetErrorCode("There are no specified blocks in the given shape");
2621 anAsciiList.Trunc(anAsciiList.Length() - 1);
2624 //The explode doesn't change object so no new function is required.
2625 aFunction = theCompound->GetLastFunction();
2627 //Make a Python command
2628 TCollection_AsciiString aDescr (anAsciiList);
2629 aDescr += " = geompy.MakeBlockExplode(";
2630 TDF_Tool::Entry(theCompound->GetEntry(), anEntry);
2631 aDescr += anEntry + ", ";
2632 aDescr += TCollection_AsciiString(theMinNbFaces) + ", ";
2633 aDescr += TCollection_AsciiString(theMaxNbFaces) + ")";
2635 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n\t";
2636 aNewDescr += aDescr;
2637 aFunction->SetDescription(aNewDescr);
2643 //=============================================================================
2647 //=============================================================================
2648 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetBlockNearPoint
2649 (Handle(GEOM_Object) theCompound,
2650 Handle(GEOM_Object) thePoint)
2655 Handle(GEOM_Object) aResult;
2658 if (theCompound.IsNull() || thePoint.IsNull()) return NULL;
2660 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2661 if (aBlockOrComp.IsNull()) {
2662 SetErrorCode("Compound is null");
2665 if (aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
2666 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
2667 SetErrorCode("Shape to find block in is not a compound");
2671 TopoDS_Shape anArg = thePoint->GetValue();
2672 if (anArg.IsNull()) {
2673 SetErrorCode("Point is null");
2676 if (anArg.ShapeType() != TopAbs_VERTEX) {
2677 SetErrorCode("Shape for block identification is not a vertex");
2681 //Compute the Block value
2683 TopoDS_Shape aShape;
2685 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
2686 gp_Pnt aPnt = BRep_Tool::Pnt(aVert);
2687 Standard_Real PX, PY, PZ;
2688 aPnt.Coord(PX, PY, PZ);
2690 // 1. Classify the point relatively each block
2691 Standard_Integer nearest = 2, nbFound = 0;
2692 TopTools_DataMapOfShapeInteger mapShapeDist;
2693 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2694 for (; exp.More(); exp.Next()) {
2695 TopoDS_Shape aSolid = exp.Current();
2697 if (!mapShapeDist.IsBound(aSolid)) {
2698 Standard_Integer aDistance = 2;
2700 // 1.a. Classify relatively Bounding box
2701 Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
2703 BRepBndLib::Add(aSolid, BB);
2704 BB.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
2705 if (PX < Xmin || Xmax < PX ||
2706 PY < Ymin || Ymax < PY ||
2707 PZ < Zmin || Zmax < PZ) {
2708 // OUT of bounding box
2711 // 1.b. Classify relatively the solid itself
2712 BRepClass3d_SolidClassifier SC (aSolid, aPnt, Precision::Confusion());
2713 if (SC.State() == TopAbs_IN) {
2715 } else if (SC.State() == TopAbs_ON) {
2722 if (aDistance < nearest) {
2723 nearest = aDistance;
2727 // A first found block, containing the point inside, will be returned.
2728 // It is the solution, if there are no intersecting blocks in the compound.
2729 if (nearest == -1) break;
2731 } else if (aDistance == nearest) {
2736 mapShapeDist.Bind(aSolid, aDistance);
2737 } // if (!mapShapeDist.IsBound(aSolid))
2740 // 2. Define block, containing the point or having minimum distance to it
2743 // The point is on boundary of some blocks and there are
2744 // no blocks, having the point inside their volume
2745 SetErrorCode("Multiple blocks near the given point are found");
2748 } else if (nearest == 1) {
2749 // The point is outside some blocks and there are
2750 // no blocks, having the point inside or on boundary.
2751 // We will get a nearest block
2752 Standard_Real minDist = RealLast();
2753 TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
2754 for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
2755 if (mapShapeDistIter.Value() == 1) {
2756 TopoDS_Shape aSolid = mapShapeDistIter.Key();
2757 BRepExtrema_DistShapeShape aDistTool (aVert, aSolid);
2758 if (!aDistTool.IsDone()) {
2759 SetErrorCode("Can not find a distance from the given point to one of blocks");
2762 Standard_Real aDist = aDistTool.Value();
2763 if (aDist < minDist) {
2769 } else { // nearest == -1
2770 // // The point is inside some blocks.
2771 // // We will get a block with nearest center
2772 // Standard_Real minDist = RealLast();
2773 // TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
2774 // for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
2775 // if (mapShapeDistIter.Value() == -1) {
2776 // TopoDS_Shape aSolid = mapShapeDistIter.Key();
2777 // GProp_GProps aSystem;
2778 // BRepGProp::VolumeProperties(aSolid, aSystem);
2779 // gp_Pnt aCenterMass = aSystem.CentreOfMass();
2781 // Standard_Real aDist = aCenterMass.Distance(aPnt);
2782 // if (aDist < minDist) {
2789 } // if (nbFound > 1)
2792 SetErrorCode("There are no blocks near the given point");
2795 TopTools_IndexedMapOfShape anIndices;
2796 TopExp::MapShapes(aBlockOrComp, anIndices);
2797 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2798 anArray->SetValue(1, anIndices.FindIndex(aShape));
2799 aResult = GetEngine()->AddSubShape(theCompound, anArray);
2802 catch (Standard_Failure) {
2803 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2804 SetErrorCode(aFail->GetMessageString());
2808 //The GetBlockNearPoint() doesn't change object so no new function is required.
2809 Handle(GEOM_Function) aFunction = theCompound->GetLastFunction();
2811 //Make a Python command
2812 TCollection_AsciiString anEntry, aDescr;
2813 TDF_Tool::Entry(aResult->GetEntry(), anEntry);
2814 aDescr += anEntry + " = geompy.GetBlockNearPoint(";
2815 TDF_Tool::Entry(theCompound->GetEntry(), anEntry);
2816 aDescr += anEntry + ", ";
2817 TDF_Tool::Entry(thePoint->GetEntry(), anEntry);
2818 aDescr += anEntry + ")";
2820 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n\t";
2821 aNewDescr += aDescr;
2822 aFunction->SetDescription(aNewDescr);
2828 //=============================================================================
2832 //=============================================================================
2833 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetBlockByParts
2834 (Handle(GEOM_Object) theCompound,
2835 const Handle(TColStd_HSequenceOfTransient)& theParts)
2839 Handle(GEOM_Object) aResult;
2841 if (theCompound.IsNull() || theParts.IsNull()) return NULL;
2842 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2843 if (aBlockOrComp.IsNull()) return NULL;
2846 Standard_Integer argi, aLen = theParts->Length();
2847 TopTools_Array1OfShape anArgs (1, aLen);
2848 TCollection_AsciiString anEntry, aPartsDescr;
2849 for (argi = 1; argi <= aLen; argi++) {
2850 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theParts->Value(argi));
2851 Handle(GEOM_Function) aRef = anObj->GetLastFunction();
2852 if (aRef.IsNull()) return NULL;
2854 TopoDS_Shape anArg = aRef->GetValue();
2855 if (anArg.IsNull()) {
2856 SetErrorCode("Null shape is given as argument");
2859 anArgs(argi) = anArg;
2861 // For Python command
2862 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2863 if (argi > 1) aPartsDescr += ", ";
2864 aPartsDescr += anEntry;
2867 //Compute the Block value
2869 // 1. Explode compound on solids
2870 TopTools_MapOfShape mapShape;
2871 Standard_Integer nbSolids = 0;
2872 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2873 for (; exp.More(); exp.Next()) {
2874 if (mapShape.Add(exp.Current())) {
2880 Standard_Integer ind = 1;
2881 TopTools_Array1OfShape aSolids (1, nbSolids);
2882 TColStd_Array1OfInteger aNbParts (1, nbSolids);
2883 for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next(), ind++) {
2884 if (mapShape.Add(exp.Current())) {
2885 TopoDS_Shape aSolid = exp.Current();
2886 aSolids(ind) = aSolid;
2889 // 2. Define quantity of parts, contained in each solid
2890 TopTools_IndexedMapOfShape aSubShapes;
2891 TopExp::MapShapes(aSolid, aSubShapes);
2892 for (argi = 1; argi <= aLen; argi++) {
2893 if (aSubShapes.Contains(anArgs(argi))) {
2900 // 3. Define solid, containing maximum quantity of parts
2901 Standard_Integer maxNb = 0, nbFound = 0;
2902 TopoDS_Shape aShape;
2903 for (ind = 1; ind <= nbSolids; ind++) {
2904 if (aNbParts(ind) > maxNb) {
2905 maxNb = aNbParts(ind);
2906 aShape = aSolids(ind);
2908 } else if (aNbParts(ind) == maxNb) {
2914 SetErrorCode("Multiple blocks, containing maximum quantity of the given parts, are found");
2916 } else if (nbFound == 0) {
2917 SetErrorCode("There are no blocks, containing the given parts");
2920 TopTools_IndexedMapOfShape anIndices;
2921 TopExp::MapShapes(aBlockOrComp, anIndices);
2922 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2923 anArray->SetValue(1, anIndices.FindIndex(aShape));
2924 aResult = GetEngine()->AddSubShape(theCompound, anArray);
2926 } catch (Standard_Failure) {
2927 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2928 SetErrorCode(aFail->GetMessageString());
2932 //The GetBlockByParts() doesn't change object so no new function is required.
2933 Handle(GEOM_Function) aFunction = theCompound->GetLastFunction();
2935 //Make a Python command
2936 TDF_Tool::Entry(aResult->GetEntry(), anEntry);
2937 TCollection_AsciiString aDescr (anEntry);
2938 aDescr += " = geompy.GetBlockByParts(";
2939 TDF_Tool::Entry(theCompound->GetEntry(), anEntry);
2940 aDescr += anEntry + ", [";
2941 aDescr += aPartsDescr + "])";
2943 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n\t";
2944 aNewDescr += aDescr;
2945 aFunction->SetDescription(aNewDescr);
2951 //=============================================================================
2955 //=============================================================================
2956 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::GetBlocksByParts
2957 (Handle(GEOM_Object) theCompound,
2958 const Handle(TColStd_HSequenceOfTransient)& theParts)
2962 if (theCompound.IsNull() || theParts.IsNull()) return NULL;
2963 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2964 if (aBlockOrComp.IsNull()) return NULL;
2966 Handle(TColStd_HSequenceOfTransient) aBlocks = new TColStd_HSequenceOfTransient;
2967 Handle(GEOM_Object) anObj;
2968 Handle(GEOM_Function) aFunction;
2971 Standard_Integer argi, aLen = theParts->Length();
2972 TopTools_Array1OfShape anArgs (1, aLen);
2973 TCollection_AsciiString anEntry, aPartsDescr, anAsciiList = "[";
2974 for (argi = 1; argi <= aLen; argi++) {
2975 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theParts->Value(argi));
2976 Handle(GEOM_Function) aRef = anObj->GetLastFunction();
2977 if (aRef.IsNull()) return NULL;
2979 TopoDS_Shape anArg = aRef->GetValue();
2980 if (anArg.IsNull()) {
2981 SetErrorCode("Null shape is given as argument");
2984 anArgs(argi) = anArg;
2986 // For Python command
2987 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2988 if (argi > 1) aPartsDescr += ", ";
2989 aPartsDescr += anEntry;
2994 TopTools_MapOfShape mapShape;
2995 Standard_Integer nbSolids = 0;
2996 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2997 for (; exp.More(); exp.Next()) {
2998 if (mapShape.Add(exp.Current())) {
3004 Standard_Integer ind = 1;
3005 TopTools_Array1OfShape aSolids (1, nbSolids);
3006 TColStd_Array1OfInteger aNbParts (1, nbSolids);
3007 for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next(), ind++) {
3008 if (mapShape.Add(exp.Current())) {
3009 TopoDS_Shape aSolid = exp.Current();
3010 aSolids(ind) = aSolid;
3013 // 2. Define quantity of parts, contained in each solid
3014 TopTools_IndexedMapOfShape aSubShapes;
3015 TopExp::MapShapes(aSolid, aSubShapes);
3016 for (argi = 1; argi <= aLen; argi++) {
3017 if (aSubShapes.Contains(anArgs(argi))) {
3024 // 3. Define solid, containing maximum quantity of parts
3025 Standard_Integer maxNb = 0, nbFound = 0;
3026 for (ind = 1; ind <= nbSolids; ind++) {
3027 if (aNbParts(ind) > maxNb) {
3028 maxNb = aNbParts(ind);
3030 } else if (aNbParts(ind) == maxNb) {
3036 SetErrorCode("There are no blocks, containing the given parts");
3041 TopTools_IndexedMapOfShape anIndices;
3042 TopExp::MapShapes(aBlockOrComp, anIndices);
3043 Handle(TColStd_HArray1OfInteger) anArray;
3045 for (ind = 1; ind <= nbSolids; ind++) {
3046 if (aNbParts(ind) == maxNb) {
3047 anArray = new TColStd_HArray1OfInteger(1,1);
3048 anArray->SetValue(1, anIndices.FindIndex(aSolids(ind)));
3049 anObj = GetEngine()->AddSubShape(theCompound, anArray);
3050 aBlocks->Append(anObj);
3052 //Make a Python command
3053 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
3054 anAsciiList += anEntry;
3059 catch (Standard_Failure) {
3060 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3061 SetErrorCode(aFail->GetMessageString());
3065 anAsciiList.Trunc(anAsciiList.Length() - 1);
3068 //The GetBlocksByParts() doesn't change object so no new function is required.
3069 aFunction = theCompound->GetLastFunction();
3071 //Make a Python command
3072 TCollection_AsciiString aDescr (anAsciiList);
3073 aDescr += " = geompy.GetBlocksByParts(";
3074 TDF_Tool::Entry(theCompound->GetEntry(), anEntry);
3075 aDescr += anEntry + ", [";
3076 aDescr += aPartsDescr + "])";
3078 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n\t";
3079 aNewDescr += aDescr;
3080 aFunction->SetDescription(aNewDescr);
3086 //=============================================================================
3088 * MakeMultiTransformation1D
3090 //=============================================================================
3091 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeMultiTransformation1D
3092 (Handle(GEOM_Object) theObject,
3093 const Standard_Integer theDirFace1,
3094 const Standard_Integer theDirFace2,
3095 const Standard_Integer theNbTimes)
3099 if (theObject.IsNull()) return NULL;
3101 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
3102 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be moved
3104 //Add a new Copy object
3105 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
3107 //Add a translate function
3108 Handle(GEOM_Function) aFunction =
3109 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_MULTI_TRANSFORM_1D);
3111 //Check if the function is set correctly
3112 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
3114 GEOMImpl_IBlockTrsf aTI (aFunction);
3115 aTI.SetOriginal(aLastFunction);
3116 aTI.SetFace1U(theDirFace1);
3117 aTI.SetFace2U(theDirFace2);
3118 aTI.SetNbIterU(theNbTimes);
3120 //Compute the transformation
3122 if (!GetSolver()->ComputeFunction(aFunction)) {
3123 SetErrorCode("Block driver failed to make multi-transformation");
3127 catch (Standard_Failure) {
3128 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3129 SetErrorCode(aFail->GetMessageString());
3133 //Make a Python command
3134 TCollection_AsciiString anEntry, aDescr;
3135 TDF_Tool::Entry(aCopy->GetEntry(), anEntry);
3136 aDescr += anEntry + " = geompy.MakeMultiTransformation1D(";
3137 TDF_Tool::Entry(theObject->GetEntry(), anEntry);
3138 aDescr += anEntry + ", ";
3139 aDescr += TCollection_AsciiString(theDirFace1) + ", ";
3140 aDescr += TCollection_AsciiString(theDirFace2) + ", ";
3141 aDescr += TCollection_AsciiString(theNbTimes) + ") ";
3143 aFunction->SetDescription(aDescr);
3149 //=============================================================================
3151 * MakeMultiTransformation2D
3153 //=============================================================================
3154 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeMultiTransformation2D
3155 (Handle(GEOM_Object) theObject,
3156 const Standard_Integer theDirFace1U,
3157 const Standard_Integer theDirFace2U,
3158 const Standard_Integer theNbTimesU,
3159 const Standard_Integer theDirFace1V,
3160 const Standard_Integer theDirFace2V,
3161 const Standard_Integer theNbTimesV)
3165 if (theObject.IsNull()) return NULL;
3167 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
3168 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be moved
3170 //Add a new Copy object
3171 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
3173 //Add a translate function
3174 Handle(GEOM_Function) aFunction =
3175 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_MULTI_TRANSFORM_2D);
3177 //Check if the function is set correctly
3178 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
3180 GEOMImpl_IBlockTrsf aTI (aFunction);
3181 aTI.SetOriginal(aLastFunction);
3182 aTI.SetFace1U(theDirFace1U);
3183 aTI.SetFace2U(theDirFace2U);
3184 aTI.SetNbIterU(theNbTimesU);
3185 aTI.SetFace1V(theDirFace1V);
3186 aTI.SetFace2V(theDirFace2V);
3187 aTI.SetNbIterV(theNbTimesV);
3189 //Compute the transformation
3191 if (!GetSolver()->ComputeFunction(aFunction)) {
3192 SetErrorCode("Block driver failed to make multi-transformation");
3196 catch (Standard_Failure) {
3197 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3198 SetErrorCode(aFail->GetMessageString());
3202 //Make a Python command
3203 TCollection_AsciiString anEntry, aDescr;
3204 TDF_Tool::Entry(aCopy->GetEntry(), anEntry);
3205 aDescr += anEntry + " = geompy.MakeMultiTransformation2D(";
3206 TDF_Tool::Entry(theObject->GetEntry(), anEntry);
3207 aDescr += anEntry + ", ";
3208 aDescr += TCollection_AsciiString(theDirFace1U) + ", ";
3209 aDescr += TCollection_AsciiString(theDirFace2U) + ", ";
3210 aDescr += TCollection_AsciiString(theNbTimesU) + ", ";
3211 aDescr += TCollection_AsciiString(theDirFace1V) + ", ";
3212 aDescr += TCollection_AsciiString(theDirFace2V) + ", ";
3213 aDescr += TCollection_AsciiString(theNbTimesV) + ") ";
3215 aFunction->SetDescription(aDescr);
3221 //=============================================================================
3225 //=============================================================================
3226 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::Propagate
3227 (Handle(GEOM_Object) theShape)
3231 if (theShape.IsNull()) return NULL;
3233 TopoDS_Shape aShape = theShape->GetValue();
3234 if (aShape.IsNull()) return NULL;
3236 TopTools_IndexedMapOfShape anIndices;
3237 TopExp::MapShapes(aShape, anIndices);
3239 TopTools_IndexedDataMapOfShapeListOfShape MEW;
3240 GEOMImpl_Block6Explorer::MapShapesAndAncestors
3241 (aShape, TopAbs_EDGE, TopAbs_WIRE, MEW);
3242 Standard_Integer ie, nbEdges = MEW.Extent();
3245 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
3247 TopTools_MapOfShape mapAcceptedEdges;
3249 for (ie = 1; ie <= nbEdges; ie++) {
3250 TopoDS_Shape curE = MEW.FindKey(ie);
3252 if (mapAcceptedEdges.Contains(curE)) continue;
3255 TopTools_ListOfShape currentChain;
3256 TopTools_ListOfShape listPrevEdges;
3258 currentChain.Append(curE);
3259 listPrevEdges.Append(curE);
3260 mapAcceptedEdges.Add(curE);
3262 // Collect all edges pass by pass
3263 while (listPrevEdges.Extent() > 0) {
3264 // List of edges, added to chain on this cycle pass
3265 TopTools_ListOfShape listCurEdges;
3267 // Find the next portion of edges
3268 TopTools_ListIteratorOfListOfShape itE (listPrevEdges);
3269 for (; itE.More(); itE.Next()) {
3270 TopoDS_Shape anE = itE.Value();
3272 // Iterate on faces, having edge <anE>
3273 TopTools_ListIteratorOfListOfShape itW (MEW.FindFromKey(anE));
3274 for (; itW.More(); itW.Next()) {
3275 TopoDS_Shape aW = itW.Value();
3276 TopoDS_Shape anOppE;
3278 BRepTools_WireExplorer aWE (TopoDS::Wire(aW));
3279 Standard_Integer nb = 1, found = 0;
3280 TopTools_Array1OfShape anEdges (1,4);
3281 for (; aWE.More(); aWE.Next(), nb++) {
3286 anEdges(nb) = aWE.Current();
3287 if (anEdges(nb).IsSame(anE)) found = nb;
3290 if (nb == 5 && found > 0) {
3291 // Quadrangle face found, get an opposite edge
3292 Standard_Integer opp = found + 2;
3293 if (opp > 4) opp -= 4;
3294 anOppE = anEdges(opp);
3296 if (!mapAcceptedEdges.Contains(anOppE)) {
3297 // Add found edge to the chain
3298 currentChain.Append(anOppE);
3299 listCurEdges.Append(anOppE);
3300 mapAcceptedEdges.Add(anOppE);
3302 } // if (nb == 5 && found > 0)
3303 } // for (; itF.More(); itF.Next())
3304 } // for (; itE.More(); itE.Next())
3306 listPrevEdges = listCurEdges;
3307 } // while (listPrevEdges.Extent() > 0)
3309 // Store the chain in the document
3310 Handle(TColStd_HArray1OfInteger) anArray =
3311 new TColStd_HArray1OfInteger (1, currentChain.Extent());
3313 // Fill array of sub-shape indices
3314 TopTools_ListIteratorOfListOfShape itSub (currentChain);
3315 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
3316 int id = anIndices.FindIndex(itSub.Value());
3317 anArray->SetValue(index, id);
3320 // Add a new group object
3321 Handle(GEOM_Object) aChain = GetEngine()->AddSubShape(theShape, anArray);
3324 aChain->SetType(GEOM_GROUP);
3326 // Set a sub shape type
3327 TDF_Label aFreeLabel = aChain->GetFreeLabel();
3328 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)TopAbs_EDGE);
3330 // Add the chain to the result
3331 aSeq->Append(aChain);
3334 if (aSeq->IsEmpty()) {
3335 SetErrorCode("There are no quadrangle faces in the shape");
3339 // The Propagation doesn't change object so no new function is required.
3340 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
3342 // Make a Python command
3343 TCollection_AsciiString aDescr
3344 ("\n\tlistPropagationChains = IShapesOperations.Propagate(");
3345 TCollection_AsciiString anEntry;
3346 TDF_Tool::Entry(theShape->GetEntry(), anEntry);
3347 aDescr += (anEntry + ")");
3349 TCollection_AsciiString anOldDescr = aFunction->GetDescription();
3350 anOldDescr = anOldDescr + aDescr;
3351 aFunction->SetDescription(anOldDescr);