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 "utilities.h"
17 #include "Utils_ExceptHandlers.hxx"
19 #include <TFunction_DriverTable.hxx>
20 #include <TFunction_Driver.hxx>
21 #include <TFunction_Logbook.hxx>
22 #include <TDF_Tool.hxx>
24 #include <BRep_Tool.hxx>
25 #include <BRepTools.hxx>
26 #include <BRepGProp.hxx>
27 #include <BRepBndLib.hxx>
28 #include <BRepAdaptor_Surface.hxx>
29 #include <BRepClass_FaceClassifier.hxx>
30 #include <BRepClass3d_SolidClassifier.hxx>
31 #include <BRepExtrema_DistShapeShape.hxx>
35 #include <TopoDS_Edge.hxx>
36 #include <TopoDS_Vertex.hxx>
37 #include <TopoDS_Iterator.hxx>
39 #include <TopExp_Explorer.hxx>
40 #include <TopTools_MapOfShape.hxx>
41 #include <TopTools_Array1OfShape.hxx>
42 #include <TopTools_IndexedMapOfShape.hxx>
43 #include <TopTools_ListIteratorOfListOfShape.hxx>
44 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
46 #include <Bnd_Box.hxx>
47 #include <Precision.hxx>
48 #include <GProp_GProps.hxx>
49 #include <TColStd_MapOfInteger.hxx>
50 #include <TColStd_Array1OfReal.hxx>
51 #include <TColStd_Array1OfInteger.hxx>
52 #include <TColStd_Array2OfInteger.hxx>
54 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
56 //=============================================================================
60 //=============================================================================
61 GEOMImpl_IBlocksOperations::GEOMImpl_IBlocksOperations (GEOM_Engine* theEngine, int theDocID)
62 : GEOM_IOperations(theEngine, theDocID)
64 MESSAGE("GEOMImpl_IBlocksOperations::GEOMImpl_IBlocksOperations");
67 //=============================================================================
71 //=============================================================================
72 GEOMImpl_IBlocksOperations::~GEOMImpl_IBlocksOperations()
74 MESSAGE("GEOMImpl_IBlocksOperations::~GEOMImpl_IBlocksOperations");
78 //=============================================================================
82 //=============================================================================
83 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad
84 (Handle(GEOM_Object) theEdge1, Handle(GEOM_Object) theEdge2,
85 Handle(GEOM_Object) theEdge3, Handle(GEOM_Object) theEdge4)
89 if (theEdge1.IsNull() || theEdge2.IsNull() ||
90 theEdge3.IsNull() || theEdge4.IsNull()) return NULL;
92 //Add a new Face object
93 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
95 //Add a new Face function
96 Handle(GEOM_Function) aFunction =
97 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_FOUR_EDGES);
99 //Check if the function is set correctly
100 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
102 GEOMImpl_IBlocks aPI (aFunction);
104 Handle(GEOM_Function) aRef1 = theEdge1->GetLastFunction();
105 Handle(GEOM_Function) aRef2 = theEdge2->GetLastFunction();
106 Handle(GEOM_Function) aRef3 = theEdge3->GetLastFunction();
107 Handle(GEOM_Function) aRef4 = theEdge4->GetLastFunction();
108 if (aRef1.IsNull() || aRef2.IsNull() ||
109 aRef3.IsNull() || aRef4.IsNull()) return NULL;
111 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
112 aShapesSeq->Append(aRef1);
113 aShapesSeq->Append(aRef2);
114 aShapesSeq->Append(aRef3);
115 aShapesSeq->Append(aRef4);
117 aPI.SetShapes(aShapesSeq);
119 //Compute the Face value
121 if (!GetSolver()->ComputeFunction(aFunction)) {
122 SetErrorCode("Block driver failed to compute a face");
126 catch (Standard_Failure) {
127 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
128 SetErrorCode(aFail->GetMessageString());
132 //Make a Python command
133 TCollection_AsciiString anEntry, aDescr;
134 TDF_Tool::Entry(aFace->GetEntry(), anEntry);
135 aDescr += anEntry + " = IBlocksOperations.MakeQuad(";
136 TDF_Tool::Entry(theEdge1->GetEntry(), anEntry);
137 aDescr += anEntry + ", ";
138 TDF_Tool::Entry(theEdge2->GetEntry(), anEntry);
139 aDescr += anEntry + ", ";
140 TDF_Tool::Entry(theEdge3->GetEntry(), anEntry);
141 aDescr += anEntry + ", ";
142 TDF_Tool::Entry(theEdge4->GetEntry(), anEntry);
143 aDescr += anEntry + ")";
145 aFunction->SetDescription(aDescr);
151 //=============================================================================
155 //=============================================================================
156 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad2Edges
157 (Handle(GEOM_Object) theEdge1, Handle(GEOM_Object) theEdge2)
161 if (theEdge1.IsNull() || theEdge2.IsNull()) return NULL;
163 //Add a new Face object
164 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
166 //Add a new Face function
167 Handle(GEOM_Function) aFunction =
168 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_TWO_EDGES);
170 //Check if the function is set correctly
171 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
173 GEOMImpl_IBlocks aPI (aFunction);
175 Handle(GEOM_Function) aRef1 = theEdge1->GetLastFunction();
176 Handle(GEOM_Function) aRef2 = theEdge2->GetLastFunction();
177 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
179 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
180 aShapesSeq->Append(aRef1);
181 aShapesSeq->Append(aRef2);
183 aPI.SetShapes(aShapesSeq);
185 //Compute the Face value
187 if (!GetSolver()->ComputeFunction(aFunction)) {
188 SetErrorCode("Block driver failed to compute a face");
192 catch (Standard_Failure) {
193 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
194 SetErrorCode(aFail->GetMessageString());
198 //Make a Python command
199 TCollection_AsciiString anEntry, aDescr;
200 TDF_Tool::Entry(aFace->GetEntry(), anEntry);
201 aDescr += anEntry + " = IBlocksOperations.MakeQuad2Edges(";
202 TDF_Tool::Entry(theEdge1->GetEntry(), anEntry);
203 aDescr += anEntry + ", ";
204 TDF_Tool::Entry(theEdge2->GetEntry(), anEntry);
205 aDescr += anEntry + ")";
207 aFunction->SetDescription(aDescr);
213 //=============================================================================
217 //=============================================================================
218 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad4Vertices
219 (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2,
220 Handle(GEOM_Object) thePnt3, Handle(GEOM_Object) thePnt4)
224 if (thePnt1.IsNull() || thePnt2.IsNull() ||
225 thePnt3.IsNull() || thePnt4.IsNull()) return NULL;
227 //Add a new Face object
228 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
230 //Add a new Face function
231 Handle(GEOM_Function) aFunction =
232 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_FOUR_PNT);
234 //Check if the function is set correctly
235 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
237 GEOMImpl_IBlocks aPI (aFunction);
239 Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
240 Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
241 Handle(GEOM_Function) aRef3 = thePnt3->GetLastFunction();
242 Handle(GEOM_Function) aRef4 = thePnt4->GetLastFunction();
243 if (aRef1.IsNull() || aRef2.IsNull() ||
244 aRef3.IsNull() || aRef4.IsNull()) return NULL;
246 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
247 aShapesSeq->Append(aRef1);
248 aShapesSeq->Append(aRef2);
249 aShapesSeq->Append(aRef3);
250 aShapesSeq->Append(aRef4);
252 aPI.SetShapes(aShapesSeq);
254 //Compute the Face value
256 if (!GetSolver()->ComputeFunction(aFunction)) {
257 SetErrorCode("Block driver failed to compute a face");
261 catch (Standard_Failure) {
262 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
263 SetErrorCode(aFail->GetMessageString());
267 //Make a Python command
268 TCollection_AsciiString anEntry, aDescr;
269 TDF_Tool::Entry(aFace->GetEntry(), anEntry);
270 aDescr += anEntry + " = IBlocksOperations.MakeQuad4Vertices(";
271 TDF_Tool::Entry(thePnt1->GetEntry(), anEntry);
272 aDescr += anEntry + ", ";
273 TDF_Tool::Entry(thePnt2->GetEntry(), anEntry);
274 aDescr += anEntry + ", ";
275 TDF_Tool::Entry(thePnt3->GetEntry(), anEntry);
276 aDescr += anEntry + ", ";
277 TDF_Tool::Entry(thePnt4->GetEntry(), anEntry);
278 aDescr += anEntry + ")";
280 aFunction->SetDescription(aDescr);
286 //=============================================================================
290 //=============================================================================
291 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeHexa
292 (Handle(GEOM_Object) theFace1, Handle(GEOM_Object) theFace2,
293 Handle(GEOM_Object) theFace3, Handle(GEOM_Object) theFace4,
294 Handle(GEOM_Object) theFace5, Handle(GEOM_Object) theFace6)
298 if (theFace1.IsNull() || theFace2.IsNull() ||
299 theFace3.IsNull() || theFace4.IsNull() ||
300 theFace5.IsNull() || theFace6.IsNull()) return NULL;
302 //Add a new Solid object
303 Handle(GEOM_Object) aBlock = GetEngine()->AddObject(GetDocID(), GEOM_BLOCK);
305 //Add a new Block function
306 Handle(GEOM_Function) aFunction =
307 aBlock->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_SIX_FACES);
309 //Check if the function is set correctly
310 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
312 GEOMImpl_IBlocks aPI (aFunction);
314 Handle(GEOM_Function) aRef1 = theFace1->GetLastFunction();
315 Handle(GEOM_Function) aRef2 = theFace2->GetLastFunction();
316 Handle(GEOM_Function) aRef3 = theFace3->GetLastFunction();
317 Handle(GEOM_Function) aRef4 = theFace4->GetLastFunction();
318 Handle(GEOM_Function) aRef5 = theFace5->GetLastFunction();
319 Handle(GEOM_Function) aRef6 = theFace6->GetLastFunction();
320 if (aRef1.IsNull() || aRef2.IsNull() ||
321 aRef3.IsNull() || aRef4.IsNull() ||
322 aRef5.IsNull() || aRef6.IsNull()) return NULL;
324 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
325 aShapesSeq->Append(aRef1);
326 aShapesSeq->Append(aRef2);
327 aShapesSeq->Append(aRef3);
328 aShapesSeq->Append(aRef4);
329 aShapesSeq->Append(aRef5);
330 aShapesSeq->Append(aRef6);
332 aPI.SetShapes(aShapesSeq);
334 //Compute the Block value
336 if (!GetSolver()->ComputeFunction(aFunction)) {
337 SetErrorCode("Block driver failed to compute a block");
341 catch (Standard_Failure) {
342 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
343 SetErrorCode(aFail->GetMessageString());
347 //Make a Python command
348 TCollection_AsciiString anEntry, aDescr;
349 TDF_Tool::Entry(aBlock->GetEntry(), anEntry);
350 aDescr += anEntry + " = IBlocksOperations.MakeHexa(";
351 TDF_Tool::Entry(theFace1->GetEntry(), anEntry);
352 aDescr += anEntry + ", ";
353 TDF_Tool::Entry(theFace2->GetEntry(), anEntry);
354 aDescr += anEntry + ", ";
355 TDF_Tool::Entry(theFace3->GetEntry(), anEntry);
356 aDescr += anEntry + ", ";
357 TDF_Tool::Entry(theFace4->GetEntry(), anEntry);
358 aDescr += anEntry + ", ";
359 TDF_Tool::Entry(theFace5->GetEntry(), anEntry);
360 aDescr += anEntry + ", ";
361 TDF_Tool::Entry(theFace6->GetEntry(), anEntry);
362 aDescr += anEntry + ")";
364 aFunction->SetDescription(aDescr);
370 //=============================================================================
374 //=============================================================================
375 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeHexa2Faces
376 (Handle(GEOM_Object) theFace1, Handle(GEOM_Object) theFace2)
380 if (theFace1.IsNull() || theFace2.IsNull()) return NULL;
382 //Add a new Solid object
383 Handle(GEOM_Object) aBlock = GetEngine()->AddObject(GetDocID(), GEOM_BLOCK);
385 //Add a new Block function
386 Handle(GEOM_Function) aFunction =
387 aBlock->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_TWO_FACES);
389 //Check if the function is set correctly
390 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
392 GEOMImpl_IBlocks aPI (aFunction);
394 Handle(GEOM_Function) aRef1 = theFace1->GetLastFunction();
395 Handle(GEOM_Function) aRef2 = theFace2->GetLastFunction();
396 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
398 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
399 aShapesSeq->Append(aRef1);
400 aShapesSeq->Append(aRef2);
402 aPI.SetShapes(aShapesSeq);
404 //Compute the Block value
406 if (!GetSolver()->ComputeFunction(aFunction)) {
407 SetErrorCode("Block driver failed to compute a block");
411 catch (Standard_Failure) {
412 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
413 SetErrorCode(aFail->GetMessageString());
417 //Make a Python command
418 TCollection_AsciiString anEntry, aDescr;
419 TDF_Tool::Entry(aBlock->GetEntry(), anEntry);
420 aDescr += anEntry + " = IBlocksOperations.MakeHexa2Faces(";
421 TDF_Tool::Entry(theFace1->GetEntry(), anEntry);
422 aDescr += anEntry + ", ";
423 TDF_Tool::Entry(theFace2->GetEntry(), anEntry);
424 aDescr += anEntry + ")";
426 aFunction->SetDescription(aDescr);
432 //=============================================================================
436 //=============================================================================
437 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeBlockCompound
438 (Handle(GEOM_Object) theCompound)
442 if (theCompound.IsNull()) return NULL;
445 Handle(GEOM_Object) aBlockComp = GetEngine()->AddObject(GetDocID(), GEOM_COMPOUND);
447 //Add a new BlocksComp function
448 Handle(GEOM_Function) aFunction =
449 aBlockComp->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_COMPOUND_GLUE);
451 //Check if the function is set correctly
452 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
454 GEOMImpl_IBlocks aPI (aFunction);
456 Handle(GEOM_Function) aRef1 = theCompound->GetLastFunction();
457 if (aRef1.IsNull()) return NULL;
459 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
460 aShapesSeq->Append(aRef1);
462 aPI.SetShapes(aShapesSeq);
464 //Compute the Blocks Compound value
466 if (!GetSolver()->ComputeFunction(aFunction)) {
467 SetErrorCode("Block driver failed to compute a blocks compound");
471 catch (Standard_Failure) {
472 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
473 SetErrorCode(aFail->GetMessageString());
477 //Make a Python command
478 TCollection_AsciiString anEntry, aDescr;
479 TDF_Tool::Entry(aBlockComp->GetEntry(), anEntry);
480 aDescr += anEntry + " = IBlocksOperations.MakeBlockCompound(";
481 TDF_Tool::Entry(theCompound->GetEntry(), anEntry);
482 aDescr += anEntry + ")";
484 aFunction->SetDescription(aDescr);
490 //=============================================================================
494 //=============================================================================
495 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetPoint
496 (Handle(GEOM_Object) theShape,
497 const Standard_Real theX,
498 const Standard_Real theY,
499 const Standard_Real theZ,
500 const Standard_Real theEpsilon)
505 Handle(GEOM_Object) aResult;
508 if (theShape.IsNull()) return NULL;
510 TopoDS_Shape aBlockOrComp = theShape->GetValue();
511 if (aBlockOrComp.IsNull()) {
512 SetErrorCode("Block or compound is null");
515 if (aBlockOrComp.ShapeType() != TopAbs_SOLID &&
516 aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
517 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
518 SetErrorCode("Shape is neither a block, nor a compound of blocks");
522 //Compute the Vertex value
523 gp_Pnt P (theX, theY, theZ);
524 Standard_Real eps = Max(theEpsilon, Precision::Confusion());
527 Standard_Integer isFound = 0;
528 TopTools_MapOfShape mapShape;
529 TopExp_Explorer exp (aBlockOrComp, TopAbs_VERTEX);
531 for (; exp.More(); exp.Next()) {
532 if (mapShape.Add(exp.Current())) {
533 TopoDS_Vertex aVi = TopoDS::Vertex(exp.Current());
534 gp_Pnt aPi = BRep_Tool::Pnt(aVi);
535 if (aPi.Distance(P) < eps) {
543 SetErrorCode("Vertex has not been found");
545 } else if (isFound > 1) {
546 SetErrorCode("Multiple vertices found by the given coordinates and epsilon");
549 TopTools_IndexedMapOfShape anIndices;
550 TopExp::MapShapes(aBlockOrComp, anIndices);
551 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
552 anArray->SetValue(1, anIndices.FindIndex(V));
553 aResult = GetEngine()->AddSubShape(theShape, anArray);
556 //The GetPoint() doesn't change object so no new function is required.
557 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
559 //Make a Python command
560 TCollection_AsciiString anEntry, aDescr;
561 TDF_Tool::Entry(aResult->GetEntry(), anEntry);
562 aDescr += anEntry + " = IBlocksOperations.GetPoint(";
563 TDF_Tool::Entry(theShape->GetEntry(), anEntry);
564 aDescr += anEntry + ", ";
565 aDescr += TCollection_AsciiString(theX) + ", ";
566 aDescr += TCollection_AsciiString(theY) + ", ";
567 aDescr += TCollection_AsciiString(theZ) + ", ";
568 aDescr += TCollection_AsciiString(theEpsilon) + ")";
570 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n";
572 aFunction->SetDescription(aNewDescr);
578 //=============================================================================
582 //=============================================================================
583 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetEdge
584 (Handle(GEOM_Object) theShape,
585 Handle(GEOM_Object) thePoint1,
586 Handle(GEOM_Object) thePoint2)
591 Handle(GEOM_Object) aResult;
594 if (theShape.IsNull() || thePoint1.IsNull() || thePoint2.IsNull()) return NULL;
596 TopoDS_Shape aBlockOrComp = theShape->GetValue();
597 if (aBlockOrComp.IsNull()) {
598 SetErrorCode("Block or compound is null");
601 if (aBlockOrComp.ShapeType() != TopAbs_SOLID &&
602 aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
603 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
604 SetErrorCode("Shape is neither a block, nor a compound of blocks");
608 TopoDS_Shape anArg1 = thePoint1->GetValue();
609 TopoDS_Shape anArg2 = thePoint2->GetValue();
610 if (anArg1.IsNull() || anArg2.IsNull()) {
611 SetErrorCode("Null shape is given as argument");
614 if (anArg1.ShapeType() != TopAbs_VERTEX ||
615 anArg2.ShapeType() != TopAbs_VERTEX) {
616 SetErrorCode("Element for edge identification is not a vertex");
620 //Compute the Edge value
622 TopTools_IndexedDataMapOfShapeListOfShape MVE;
623 GEOMImpl_Block6Explorer::MapShapesAndAncestors
624 (aBlockOrComp, TopAbs_VERTEX, TopAbs_EDGE, MVE);
627 Standard_Integer ish, ext = MVE.Extent();
629 if (MVE.Contains(anArg1)) {
632 for (ish = 1; ish <= ext; ish++) {
633 TopoDS_Shape aShi = MVE.FindKey(ish);
634 if (BRepTools::Compare(TopoDS::Vertex(anArg1), TopoDS::Vertex(aShi))) {
641 if (MVE.Contains(anArg2)) {
644 for (ish = 1; ish <= ext; ish++) {
645 TopoDS_Shape aShi = MVE.FindKey(ish);
646 if (BRepTools::Compare(TopoDS::Vertex(anArg2), TopoDS::Vertex(aShi))) {
653 if (V1.IsNull() || V2.IsNull()) {
654 SetErrorCode("The given vertex does not belong to the shape");
659 Standard_Integer isFound =
660 GEOMImpl_Block6Explorer::FindEdge(anEdge, V1, V2, MVE, Standard_True);
662 SetErrorCode("The given vertices do not belong to one edge of the given shape");
664 } else if (isFound > 1) {
665 SetErrorCode("Multiple edges found by the given vertices of the shape");
668 TopTools_IndexedMapOfShape anIndices;
669 TopExp::MapShapes(aBlockOrComp, anIndices);
670 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
671 anArray->SetValue(1, anIndices.FindIndex(anEdge));
672 aResult = GetEngine()->AddSubShape(theShape, anArray);
674 } catch (Standard_Failure) {
675 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
676 SetErrorCode(aFail->GetMessageString());
680 //The GetEdge() doesn't change object so no new function is required.
681 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
683 //Make a Python command
684 TCollection_AsciiString anEntry, aDescr;
685 TDF_Tool::Entry(aResult->GetEntry(), anEntry);
686 aDescr += anEntry + " = IBlocksOperations.GetEdge(";
687 TDF_Tool::Entry(theShape->GetEntry(), anEntry);
688 aDescr += anEntry + ", ";
689 TDF_Tool::Entry(thePoint1->GetEntry(), anEntry);
690 aDescr += anEntry + ", ";
691 TDF_Tool::Entry(thePoint2->GetEntry(), anEntry);
692 aDescr += anEntry + ")";
694 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n";
696 aFunction->SetDescription(aNewDescr);
702 //=============================================================================
706 //=============================================================================
707 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetEdgeNearPoint
708 (Handle(GEOM_Object) theShape,
709 Handle(GEOM_Object) thePoint)
714 Handle(GEOM_Object) aResult;
717 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
719 TopoDS_Shape aBlockOrComp = theShape->GetValue();
720 if (aBlockOrComp.IsNull()) {
721 SetErrorCode("Block or compound is null");
724 if (aBlockOrComp.ShapeType() != TopAbs_SOLID &&
725 aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
726 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
727 SetErrorCode("Shape is neither a block, nor a compound of blocks");
731 TopoDS_Shape anArg = thePoint->GetValue();
732 if (anArg.IsNull()) {
733 SetErrorCode("Null shape is given as argument");
736 if (anArg.ShapeType() != TopAbs_VERTEX) {
737 SetErrorCode("Element for edge identification is not a vertex");
741 //Compute the Edge value
745 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
747 // 1. Explode blocks on edges
748 TopTools_MapOfShape mapShape;
749 Standard_Integer nbEdges = 0;
750 TopExp_Explorer exp (aBlockOrComp, TopAbs_EDGE);
751 for (; exp.More(); exp.Next()) {
752 if (mapShape.Add(exp.Current())) {
758 Standard_Integer ind = 1;
759 TopTools_Array1OfShape anEdges (1, nbEdges);
760 TColStd_Array1OfReal aDistances (1, nbEdges);
761 for (exp.Init(aBlockOrComp, TopAbs_EDGE); exp.More(); exp.Next()) {
762 if (mapShape.Add(exp.Current())) {
763 TopoDS_Shape anEdge = exp.Current();
764 anEdges(ind) = anEdge;
766 // 2. Classify the point relatively each edge
767 BRepExtrema_DistShapeShape aDistTool (aVert, anEdges(ind));
768 if (!aDistTool.IsDone()) {
769 SetErrorCode("Can not find a distance from the given point to one of edges");
772 aDistances(ind) = aDistTool.Value();
777 // 3. Define edge, having minimum distance to the point
778 Standard_Real nearest = RealLast(), nbFound = 0;
779 Standard_Real prec = Precision::Confusion();
780 for (ind = 1; ind <= nbEdges; ind++) {
781 if (Abs(aDistances(ind) - nearest) < prec) {
783 } else if (aDistances(ind) < nearest) {
784 nearest = aDistances(ind);
785 aShape = anEdges(ind);
791 SetErrorCode("Multiple edges near the given point are found");
793 } else if (nbFound == 0) {
794 SetErrorCode("There are no edges near the given point");
797 TopTools_IndexedMapOfShape anIndices;
798 TopExp::MapShapes(aBlockOrComp, anIndices);
799 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
800 anArray->SetValue(1, anIndices.FindIndex(aShape));
801 aResult = GetEngine()->AddSubShape(theShape, anArray);
804 catch (Standard_Failure) {
805 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
806 SetErrorCode(aFail->GetMessageString());
810 //The GetEdgeNearPoint() doesn't change object so no new function is required.
811 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
813 //Make a Python command
814 TCollection_AsciiString anEntry, aDescr;
815 TDF_Tool::Entry(aResult->GetEntry(), anEntry);
816 aDescr += anEntry + " = IBlocksOperations.GetEdgeNearPoint(";
817 TDF_Tool::Entry(theShape->GetEntry(), anEntry);
818 aDescr += anEntry + ", ";
819 TDF_Tool::Entry(thePoint->GetEntry(), anEntry);
820 aDescr += anEntry + ")";
822 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n";
824 aFunction->SetDescription(aNewDescr);
830 //=============================================================================
834 //=============================================================================
835 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByPoints
836 (Handle(GEOM_Object) theShape,
837 Handle(GEOM_Object) thePoint1,
838 Handle(GEOM_Object) thePoint2,
839 Handle(GEOM_Object) thePoint3,
840 Handle(GEOM_Object) thePoint4)
845 Handle(GEOM_Object) aResult;
848 if (theShape.IsNull() ||
849 thePoint1.IsNull() || thePoint2.IsNull() ||
850 thePoint3.IsNull() || thePoint4.IsNull()) return NULL;
852 TopoDS_Shape aBlockOrComp = theShape->GetValue();
853 if (aBlockOrComp.IsNull()) {
854 SetErrorCode("Block or compound is null");
857 if (aBlockOrComp.ShapeType() != TopAbs_SOLID &&
858 aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
859 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
860 SetErrorCode("Shape is neither a block, nor a compound of blocks");
864 TopoDS_Shape anArg1 = thePoint1->GetValue();
865 TopoDS_Shape anArg2 = thePoint2->GetValue();
866 TopoDS_Shape anArg3 = thePoint3->GetValue();
867 TopoDS_Shape anArg4 = thePoint4->GetValue();
868 if (anArg1.IsNull() || anArg2.IsNull() ||
869 anArg3.IsNull() || anArg4.IsNull()) {
870 SetErrorCode("Null shape is given as argument");
873 if (anArg1.ShapeType() != TopAbs_VERTEX ||
874 anArg2.ShapeType() != TopAbs_VERTEX ||
875 anArg3.ShapeType() != TopAbs_VERTEX ||
876 anArg4.ShapeType() != TopAbs_VERTEX) {
877 SetErrorCode("Element for face identification is not a vertex");
881 //Compute the Face value
885 TopTools_IndexedDataMapOfShapeListOfShape MVF;
886 GEOMImpl_Block6Explorer::MapShapesAndAncestors(aBlockOrComp, TopAbs_VERTEX, TopAbs_FACE, MVF);
888 TopoDS_Shape V1,V2,V3,V4;
889 Standard_Integer ish, ext = MVF.Extent();
891 if (MVF.Contains(anArg1)) {
894 for (ish = 1; ish <= ext; ish++) {
895 TopoDS_Shape aShi = MVF.FindKey(ish);
896 if (BRepTools::Compare(TopoDS::Vertex(anArg1), TopoDS::Vertex(aShi))) {
903 if (MVF.Contains(anArg2)) {
906 for (ish = 1; ish <= ext; ish++) {
907 TopoDS_Shape aShi = MVF.FindKey(ish);
908 if (BRepTools::Compare(TopoDS::Vertex(anArg2), TopoDS::Vertex(aShi))) {
915 if (MVF.Contains(anArg3)) {
918 for (ish = 1; ish <= ext; ish++) {
919 TopoDS_Shape aShi = MVF.FindKey(ish);
920 if (BRepTools::Compare(TopoDS::Vertex(anArg3), TopoDS::Vertex(aShi))) {
927 if (MVF.Contains(anArg4)) {
930 for (ish = 1; ish <= ext; ish++) {
931 TopoDS_Shape aShi = MVF.FindKey(ish);
932 if (BRepTools::Compare(TopoDS::Vertex(anArg4), TopoDS::Vertex(aShi))) {
939 if (V1.IsNull() || V2.IsNull() || V3.IsNull() || V4.IsNull()) {
940 SetErrorCode("The given vertex does not belong to the shape");
944 Standard_Integer isFound =
945 GEOMImpl_Block6Explorer::FindFace(aShape, V1, V2, V3, V4, MVF, Standard_True);
947 SetErrorCode("The given vertices do not belong to one face of the given shape");
949 } else if (isFound > 1) {
950 SetErrorCode("The given vertices belong to several faces of the given shape");
953 TopTools_IndexedMapOfShape anIndices;
954 TopExp::MapShapes(aBlockOrComp, anIndices);
955 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
956 anArray->SetValue(1, anIndices.FindIndex(aShape));
957 aResult = GetEngine()->AddSubShape(theShape, anArray);
960 catch (Standard_Failure) {
961 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
962 SetErrorCode(aFail->GetMessageString());
966 //The GetFaceByPoints() doesn't change object so no new function is required.
967 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
969 //Make a Python command
970 TCollection_AsciiString anEntry, aDescr;
971 TDF_Tool::Entry(aResult->GetEntry(), anEntry);
972 aDescr += anEntry + " = IBlocksOperations.GetFaceByPoints(";
973 TDF_Tool::Entry(theShape->GetEntry(), anEntry);
974 aDescr += anEntry + ", ";
975 TDF_Tool::Entry(thePoint1->GetEntry(), anEntry);
976 aDescr += anEntry + ", ";
977 TDF_Tool::Entry(thePoint2->GetEntry(), anEntry);
978 aDescr += anEntry + ", ";
979 TDF_Tool::Entry(thePoint3->GetEntry(), anEntry);
980 aDescr += anEntry + ", ";
981 TDF_Tool::Entry(thePoint4->GetEntry(), anEntry);
982 aDescr += anEntry + ")";
984 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n";
986 aFunction->SetDescription(aNewDescr);
992 //=============================================================================
996 //=============================================================================
997 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByEdges
998 (Handle(GEOM_Object) theShape,
999 Handle(GEOM_Object) theEdge1,
1000 Handle(GEOM_Object) theEdge2)
1005 Handle(GEOM_Object) aResult;
1008 if (theShape.IsNull() || theEdge1.IsNull() || theEdge2.IsNull()) return NULL;
1010 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1011 if (aBlockOrComp.IsNull()) {
1012 SetErrorCode("Block or compound is null");
1015 if (aBlockOrComp.ShapeType() != TopAbs_SOLID &&
1016 aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
1017 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
1018 SetErrorCode("Shape is neither a block, nor a compound of blocks");
1022 TopoDS_Shape anArg1 = theEdge1->GetValue();
1023 TopoDS_Shape anArg2 = theEdge2->GetValue();
1024 if (anArg1.IsNull() || anArg2.IsNull()) {
1025 SetErrorCode("Null shape is given as argument");
1028 if (anArg1.ShapeType() != TopAbs_EDGE ||
1029 anArg2.ShapeType() != TopAbs_EDGE) {
1030 SetErrorCode("Element for face identification is not an edge");
1034 //Compute the Face value
1036 TopoDS_Shape aShape;
1038 TopTools_IndexedDataMapOfShapeListOfShape MEF;
1039 GEOMImpl_Block6Explorer::MapShapesAndAncestors(aBlockOrComp, TopAbs_EDGE, TopAbs_FACE, MEF);
1042 Standard_Integer ish, ext = MEF.Extent();
1044 if (MEF.Contains(anArg1)) {
1047 for (ish = 1; ish <= ext; ish++) {
1048 TopoDS_Shape aShi = MEF.FindKey(ish);
1049 if (GEOMImpl_Block6Explorer::IsSimilarEdges(anArg1, aShi)) {
1055 if (MEF.Contains(anArg2)) {
1058 for (ish = 1; ish <= ext; ish++) {
1059 TopoDS_Shape aShi = MEF.FindKey(ish);
1060 if (GEOMImpl_Block6Explorer::IsSimilarEdges(anArg2, aShi)) {
1066 if (E1.IsNull() || E2.IsNull()) {
1067 SetErrorCode("The given edge does not belong to the shape");
1071 const TopTools_ListOfShape& aFacesOfE1 = MEF.FindFromKey(E1);
1072 const TopTools_ListOfShape& aFacesOfE2 = MEF.FindFromKey(E2);
1074 Standard_Integer isFound = 0;
1075 TopTools_ListIteratorOfListOfShape anIterF1 (aFacesOfE1);
1076 for (; anIterF1.More(); anIterF1.Next()) {
1078 TopTools_ListIteratorOfListOfShape anIterF2 (aFacesOfE2);
1079 for (; anIterF2.More(); anIterF2.Next()) {
1081 if (anIterF1.Value().IsSame(anIterF2.Value())) {
1084 // Store the face, defined by two edges
1085 aShape = anIterF1.Value();
1090 SetErrorCode("The given edges do not belong to one face of the given shape");
1092 } else if (isFound > 1) {
1093 SetErrorCode("The given edges belong to several faces of the given shape");
1096 TopTools_IndexedMapOfShape anIndices;
1097 TopExp::MapShapes(aBlockOrComp, anIndices);
1098 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1099 anArray->SetValue(1, anIndices.FindIndex(aShape));
1100 aResult = GetEngine()->AddSubShape(theShape, anArray);
1103 catch (Standard_Failure) {
1104 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1105 SetErrorCode(aFail->GetMessageString());
1109 //The GetFaceByEdges() doesn't change object so no new function is required.
1110 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1112 //Make a Python command
1113 TCollection_AsciiString anEntry, aDescr;
1114 TDF_Tool::Entry(aResult->GetEntry(), anEntry);
1115 aDescr += anEntry + " = IBlocksOperations.GetFaceByEdges(";
1116 TDF_Tool::Entry(theShape->GetEntry(), anEntry);
1117 aDescr += anEntry + ", ";
1118 TDF_Tool::Entry(theEdge1->GetEntry(), anEntry);
1119 aDescr += anEntry + ", ";
1120 TDF_Tool::Entry(theEdge2->GetEntry(), anEntry);
1121 aDescr += anEntry + ")";
1123 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n";
1124 aNewDescr += aDescr;
1125 aFunction->SetDescription(aNewDescr);
1131 //=============================================================================
1135 //=============================================================================
1136 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetOppositeFace
1137 (Handle(GEOM_Object) theShape,
1138 Handle(GEOM_Object) theFace)
1143 Handle(GEOM_Object) aResult;
1146 if (theShape.IsNull() || theFace.IsNull()) return NULL;
1148 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1149 if (aBlockOrComp.IsNull()) {
1150 SetErrorCode("Block is null");
1153 if (aBlockOrComp.ShapeType() != TopAbs_SOLID) {
1154 SetErrorCode("Shape is not a block");
1158 TopoDS_Shape anArg = theFace->GetValue();
1159 if (anArg.IsNull()) {
1160 SetErrorCode("Null shape is given as argument");
1163 if (anArg.ShapeType() != TopAbs_FACE) {
1164 SetErrorCode("Element for face identification is not a face");
1168 //Compute the Face value
1170 TopoDS_Shape aShape;
1172 GEOMImpl_Block6Explorer aBlockTool;
1173 aBlockTool.InitByBlockAndFace(aBlockOrComp, anArg);
1174 aShape = aBlockTool.GetFace(2);
1176 TopTools_IndexedMapOfShape anIndices;
1177 TopExp::MapShapes(aBlockOrComp, anIndices);
1178 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1179 anArray->SetValue(1, anIndices.FindIndex(aShape));
1180 aResult = GetEngine()->AddSubShape(theShape, anArray);
1182 catch (Standard_Failure) {
1183 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1184 SetErrorCode(aFail->GetMessageString());
1188 //The GetOppositeFace() doesn't change object so no new function is required.
1189 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1191 //Make a Python command
1192 TCollection_AsciiString anEntry, aDescr;
1193 TDF_Tool::Entry(aResult->GetEntry(), anEntry);
1194 aDescr += anEntry + " = IBlocksOperations.GetOppositeFace(";
1195 TDF_Tool::Entry(theShape->GetEntry(), anEntry);
1196 aDescr += anEntry + ", ";
1197 TDF_Tool::Entry(theFace->GetEntry(), anEntry);
1198 aDescr += anEntry + ")";
1200 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n";
1201 aNewDescr += aDescr;
1202 aFunction->SetDescription(aNewDescr);
1208 //=============================================================================
1212 //=============================================================================
1213 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceNearPoint
1214 (Handle(GEOM_Object) theShape,
1215 Handle(GEOM_Object) thePoint)
1220 Handle(GEOM_Object) aResult;
1223 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
1225 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1226 if (aBlockOrComp.IsNull()) {
1227 SetErrorCode("Block or compound is null");
1230 if (aBlockOrComp.ShapeType() != TopAbs_SOLID &&
1231 aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
1232 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
1233 SetErrorCode("Shape is neither a block, nor a compound of blocks");
1237 TopoDS_Shape anArg = thePoint->GetValue();
1238 if (anArg.IsNull()) {
1239 SetErrorCode("Null shape is given as argument");
1242 if (anArg.ShapeType() != TopAbs_VERTEX) {
1243 SetErrorCode("Element for face identification is not a vertex");
1247 //Compute the Face value
1249 TopoDS_Shape aShape;
1251 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
1252 gp_Pnt aPnt = BRep_Tool::Pnt(aVert);
1254 // 1. Explode blocks on faces
1255 TopTools_MapOfShape mapShape;
1256 Standard_Integer nbFaces = 0;
1257 TopExp_Explorer exp (aBlockOrComp, TopAbs_FACE);
1258 for (; exp.More(); exp.Next()) {
1259 if (mapShape.Add(exp.Current())) {
1265 Standard_Integer ind = 1;
1266 TopTools_Array1OfShape aFaces (1, nbFaces);
1267 TColStd_Array1OfInteger aDistances (1, nbFaces);
1268 for (exp.Init(aBlockOrComp, TopAbs_FACE); exp.More(); exp.Next()) {
1269 if (mapShape.Add(exp.Current())) {
1270 TopoDS_Shape aFace = exp.Current();
1271 aFaces(ind) = aFace;
1273 // 2. Classify the point relatively each face
1274 BRepClass_FaceClassifier FC (TopoDS::Face(aFace), aPnt, Precision::Confusion());
1275 if (FC.State() == TopAbs_IN) {
1276 aDistances(ind) = -1;
1277 } else if (FC.State() == TopAbs_ON) {
1278 aDistances(ind) = 0;
1280 aDistances(ind) = 1;
1286 // 3. Define face, containing the point or having minimum distance to it
1287 Standard_Integer nearest = 2, nbFound = 0;
1288 for (ind = 1; ind <= nbFaces; ind++) {
1289 if (aDistances(ind) < nearest) {
1290 nearest = aDistances(ind);
1291 aShape = aFaces(ind);
1293 } else if (aDistances(ind) == nearest) {
1300 // The point is on boundary of some faces and there are
1301 // no faces, having the point inside
1302 SetErrorCode("Multiple faces near the given point are found");
1305 } else if (nearest == 1) {
1306 // The point is outside some faces and there are
1307 // no faces, having the point inside or on boundary.
1308 // We will get a nearest face
1309 Standard_Real minDist = RealLast();
1310 for (ind = 1; ind <= nbFaces; ind++) {
1311 if (aDistances(ind) == 1) {
1312 BRepExtrema_DistShapeShape aDistTool (aVert, aFaces(ind));
1313 if (!aDistTool.IsDone()) {
1314 SetErrorCode("Can not find a distance from the given point to one of faces");
1317 Standard_Real aDist = aDistTool.Value();
1318 if (aDist < minDist) {
1320 aShape = aFaces(ind);
1324 } else { // nearest == -1
1325 // The point is inside some faces.
1326 // We will get a face with nearest center
1327 Standard_Real minDist = RealLast();
1328 for (ind = 1; ind <= nbFaces; ind++) {
1329 if (aDistances(ind) == -1) {
1330 GProp_GProps aSystem;
1331 BRepGProp::SurfaceProperties(aFaces(ind), aSystem);
1332 gp_Pnt aCenterMass = aSystem.CentreOfMass();
1334 Standard_Real aDist = aCenterMass.Distance(aPnt);
1335 if (aDist < minDist) {
1337 aShape = aFaces(ind);
1345 SetErrorCode("There are no faces near the given point");
1348 TopTools_IndexedMapOfShape anIndices;
1349 TopExp::MapShapes(aBlockOrComp, anIndices);
1350 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1351 anArray->SetValue(1, anIndices.FindIndex(aShape));
1352 aResult = GetEngine()->AddSubShape(theShape, anArray);
1355 catch (Standard_Failure) {
1356 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1357 SetErrorCode(aFail->GetMessageString());
1361 //The GetFaceNearPoint() doesn't change object so no new function is required.
1362 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1364 //Make a Python command
1365 TCollection_AsciiString anEntry, aDescr;
1366 TDF_Tool::Entry(aResult->GetEntry(), anEntry);
1367 aDescr += anEntry + " = IBlocksOperations.GetFaceNearPoint(";
1368 TDF_Tool::Entry(theShape->GetEntry(), anEntry);
1369 aDescr += anEntry + ", ";
1370 TDF_Tool::Entry(thePoint->GetEntry(), anEntry);
1371 aDescr += anEntry + ")";
1373 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n";
1374 aNewDescr += aDescr;
1375 aFunction->SetDescription(aNewDescr);
1381 //=============================================================================
1385 //=============================================================================
1386 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByNormale
1387 (Handle(GEOM_Object) theShape,
1388 Handle(GEOM_Object) theVector)
1393 Handle(GEOM_Object) aResult;
1396 if (theShape.IsNull() || theVector.IsNull()) return NULL;
1398 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1399 if (aBlockOrComp.IsNull()) {
1400 SetErrorCode("Block or compound is null");
1403 if (aBlockOrComp.ShapeType() != TopAbs_SOLID &&
1404 aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
1405 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
1406 SetErrorCode("Shape is neither a block, nor a compound of blocks");
1410 TopoDS_Shape anArg = theVector->GetValue();
1411 if (anArg.IsNull()) {
1412 SetErrorCode("Null shape is given as argument");
1415 if (anArg.ShapeType() != TopAbs_EDGE) {
1416 SetErrorCode("Element for normale identification is not an edge");
1420 //Compute the Face value
1422 TopoDS_Shape aShape;
1424 TopoDS_Edge anEdge = TopoDS::Edge(anArg);
1425 TopoDS_Vertex V1, V2;
1426 TopExp::Vertices(anEdge, V1, V2, Standard_True);
1427 gp_Pnt P1 = BRep_Tool::Pnt(V1);
1428 gp_Pnt P2 = BRep_Tool::Pnt(V2);
1429 gp_Vec aVec (P1, P2);
1430 if (aVec.Magnitude() < Precision::Confusion()) {
1431 SetErrorCode("Vector with null magnitude is given");
1435 Standard_Real minAngle = RealLast();
1436 TopTools_MapOfShape mapShape;
1437 TopExp_Explorer exp (aBlockOrComp, TopAbs_FACE);
1438 for (; exp.More(); exp.Next()) {
1439 if (mapShape.Add(exp.Current())) {
1440 TopoDS_Face aFace = TopoDS::Face(exp.Current());
1441 BRepAdaptor_Surface SF (aFace);
1443 Standard_Real u, v, x;
1445 // find a point on the surface to get normal direction in
1446 u = SF.FirstUParameter();
1447 x = SF.LastUParameter();
1448 if (Precision::IsInfinite(u)) {
1449 u = (Precision::IsInfinite(x)) ? 0. : x;
1450 } else if (!Precision::IsInfinite(x)) {
1454 v = SF.FirstVParameter();
1455 x = SF.LastVParameter();
1456 if (Precision::IsInfinite(v)) {
1457 v = (Precision::IsInfinite(x)) ? 0. : x;
1458 } else if (!Precision::IsInfinite(x)) {
1462 // compute the normal direction
1464 SF.D1(u,v,P1,Vec1,Vec2);
1465 gp_Vec V = Vec1.Crossed(Vec2);
1467 if (V.Magnitude() < Precision::Confusion()) {
1468 SetErrorCode("Normal vector of a face has null magnitude");
1472 // consider the face orientation
1473 if (aFace.Orientation() == TopAbs_REVERSED ||
1474 aFace.Orientation() == TopAbs_INTERNAL) {
1478 // compute the angle and compare with the minimal one
1479 Standard_Real anAngle = aVec.Angle(V);
1480 if (anAngle < minAngle) {
1487 if (aShape.IsNull()) {
1488 SetErrorCode("Failed to find a face by the given normale");
1491 TopTools_IndexedMapOfShape anIndices;
1492 TopExp::MapShapes(aBlockOrComp, anIndices);
1493 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1494 anArray->SetValue(1, anIndices.FindIndex(aShape));
1495 aResult = GetEngine()->AddSubShape(theShape, anArray);
1498 catch (Standard_Failure) {
1499 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1500 SetErrorCode(aFail->GetMessageString());
1504 //The GetFaceByNormale() doesn't change object so no new function is required.
1505 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1507 //Make a Python command
1508 TCollection_AsciiString anEntry, aDescr;
1509 TDF_Tool::Entry(aResult->GetEntry(), anEntry);
1510 aDescr += anEntry + " = IBlocksOperations.GetFaceByNormale(";
1511 TDF_Tool::Entry(theShape->GetEntry(), anEntry);
1512 aDescr += anEntry + ", ";
1513 TDF_Tool::Entry(theVector->GetEntry(), anEntry);
1514 aDescr += anEntry + ")";
1516 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n";
1517 aNewDescr += aDescr;
1518 aFunction->SetDescription(aNewDescr);
1524 //=============================================================================
1526 * IsCompoundOfBlocks
1528 //=============================================================================
1529 Standard_Boolean GEOMImpl_IBlocksOperations::IsCompoundOfBlocks
1530 (Handle(GEOM_Object) theCompound,
1531 const Standard_Integer theMinNbFaces,
1532 const Standard_Integer theMaxNbFaces,
1533 Standard_Integer& theNbBlocks)
1536 Standard_Boolean isCompOfBlocks = Standard_False;
1539 if (theCompound.IsNull()) return isCompOfBlocks;
1540 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
1543 isCompOfBlocks = Standard_True;
1545 TopTools_MapOfShape mapShape;
1546 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
1547 for (; exp.More(); exp.Next()) {
1548 if (mapShape.Add(exp.Current())) {
1549 TopoDS_Shape aSolid = exp.Current();
1551 TopTools_MapOfShape mapFaces;
1552 TopExp_Explorer expF (aSolid, TopAbs_FACE);
1553 Standard_Integer nbFaces = 0;
1554 for (; expF.More(); expF.Next()) {
1555 if (mapFaces.Add(expF.Current())) {
1557 if (nbFaces > theMaxNbFaces) {
1558 isCompOfBlocks = Standard_False;
1563 if (nbFaces < theMinNbFaces || theMaxNbFaces < nbFaces) {
1564 isCompOfBlocks = Standard_False;
1571 catch (Standard_Failure) {
1572 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1573 SetErrorCode(aFail->GetMessageString());
1574 return isCompOfBlocks;
1578 return isCompOfBlocks;
1581 //=============================================================================
1583 * Set of functions, used by CheckCompoundOfBlocks() method
1585 //=============================================================================
1586 void AddBlocksFrom (const TopoDS_Shape& theShape,
1587 TopTools_ListOfShape& BLO,
1588 TopTools_ListOfShape& NOT)
1590 TopAbs_ShapeEnum aType = theShape.ShapeType();
1592 case TopAbs_COMPOUND:
1593 case TopAbs_COMPSOLID:
1595 TopoDS_Iterator It (theShape);
1596 for (; It.More(); It.Next()) {
1597 AddBlocksFrom(It.Value(), BLO, NOT);
1603 TopTools_MapOfShape mapFaces;
1604 TopExp_Explorer expF (theShape, TopAbs_FACE);
1605 Standard_Integer nbFaces = 0;
1606 Standard_Integer nbEdges = 0;
1607 for (; expF.More(); expF.Next()) {
1608 if (mapFaces.Add(expF.Current())) {
1610 if (nbFaces > 6) break;
1612 // Check number of edges in the face
1613 TopoDS_Shape aF = expF.Current();
1614 TopExp_Explorer expE (aF, TopAbs_EDGE);
1616 for (; expE.More(); expE.Next()) {
1618 if (nbEdges > 4) break;
1620 if (nbEdges != 4) break;
1623 if (nbFaces == 6 && nbEdges == 4) {
1624 BLO.Append(theShape);
1626 NOT.Append(theShape);
1631 NOT.Append(theShape);
1635 #define REL_NOT_CONNECTED 0
1637 #define REL_NOT_GLUED 2
1638 #define REL_COLLISION_VV 3
1639 #define REL_COLLISION_FF 4
1640 #define REL_COLLISION_EE 5
1641 #define REL_UNKNOWN 6
1643 Standard_Integer BlocksRelation (const TopoDS_Shape& theBlock1,
1644 const TopoDS_Shape& theBlock2)
1646 // Compare bounding boxes before calling BRepExtrema_DistShapeShape
1647 Standard_Real Xmin1, Ymin1, Zmin1, Xmax1, Ymax1, Zmax1;
1648 Standard_Real Xmin2, Ymin2, Zmin2, Xmax2, Ymax2, Zmax2;
1650 BRepBndLib::Add(theBlock1, B1);
1651 BRepBndLib::Add(theBlock2, B2);
1652 // BRepBndLib::AddClose(theBlock1, B1);
1653 // BRepBndLib::AddClose(theBlock2, B2);
1654 B1.Get(Xmin1, Ymin1, Zmin1, Xmax1, Ymax1, Zmax1);
1655 B2.Get(Xmin2, Ymin2, Zmin2, Xmax2, Ymax2, Zmax2);
1656 if (Xmax2 < Xmin1 || Xmax1 < Xmin2 ||
1657 Ymax2 < Ymin1 || Ymax1 < Ymin2 ||
1658 Zmax2 < Zmin1 || Zmax1 < Zmin2) {
1659 // Standard_Real prec = Precision::Confusion();
1660 // if (prec < Xmin1 - Xmax2 || prec < Xmin2 - Xmax1 ||
1661 // prec < Ymin1 - Ymax2 || prec < Ymin2 - Ymax1 ||
1662 // prec < Zmin1 - Zmax2 || prec < Zmin2 - Zmax1) {
1663 return REL_NOT_CONNECTED;
1667 BRepExtrema_DistShapeShape dst (theBlock1, theBlock2);
1668 if (!dst.IsDone()) {
1672 if (dst.Value() > Precision::Confusion()) {
1673 return REL_NOT_CONNECTED;
1676 if (dst.InnerSolution()) {
1677 return REL_COLLISION_VV;
1680 Standard_Integer nbSol = dst.NbSolution();
1681 Standard_Integer relation = REL_OK;
1682 Standard_Integer nbVerts = 0;
1683 Standard_Integer nbEdges = 0;
1684 Standard_Integer sol = 1;
1685 for (; sol <= nbSol; sol++) {
1686 BRepExtrema_SupportType supp1 = dst.SupportTypeShape1(sol);
1687 BRepExtrema_SupportType supp2 = dst.SupportTypeShape2(sol);
1688 if (supp1 == BRepExtrema_IsVertex && supp2 == BRepExtrema_IsVertex) {
1690 } else if (supp1 == BRepExtrema_IsInFace || supp2 == BRepExtrema_IsInFace) {
1691 return REL_COLLISION_FF;
1692 } else if (supp1 == BRepExtrema_IsOnEdge && supp2 == BRepExtrema_IsOnEdge) {
1694 } else if ((supp1 == BRepExtrema_IsOnEdge && supp2 == BRepExtrema_IsVertex) ||
1695 (supp2 == BRepExtrema_IsOnEdge && supp1 == BRepExtrema_IsVertex)) {
1696 relation = REL_COLLISION_EE;
1701 if (relation != REL_OK) {
1705 TColStd_Array1OfInteger vertSol (1, nbVerts);
1706 TopTools_Array1OfShape V1 (1, nbVerts);
1707 TopTools_Array1OfShape V2 (1, nbVerts);
1708 Standard_Integer ivs = 0;
1709 for (sol = 1; sol <= nbSol; sol++) {
1710 if (dst.SupportTypeShape1(sol) == BRepExtrema_IsVertex &&
1711 dst.SupportTypeShape2(sol) == BRepExtrema_IsVertex) {
1712 TopoDS_Vertex Vcur = TopoDS::Vertex(dst.SupportOnShape1(sol));
1713 // Check, that this vertex is far enough from other solution vertices.
1714 Standard_Integer ii = 1;
1715 for (; ii <= ivs; ii++) {
1716 if (BRepTools::Compare(TopoDS::Vertex(V1(ii)), Vcur)) {
1723 V2(ivs) = dst.SupportOnShape2(sol);
1727 // As we deal only with quadrangles,
1728 // 2, 3 or 4 vertex solutions can be found.
1731 return REL_COLLISION_FF;
1733 return REL_NOT_CONNECTED;
1739 // Check sharing of coincident entities.
1740 if (ivs == 2 || ivs == 3) {
1741 // Map vertices and edges of the blocks
1742 TopTools_IndexedDataMapOfShapeListOfShape MVE1, MVE2;
1743 GEOMImpl_Block6Explorer::MapShapesAndAncestors
1744 (theBlock1, TopAbs_VERTEX, TopAbs_EDGE, MVE1);
1745 GEOMImpl_Block6Explorer::MapShapesAndAncestors
1746 (theBlock2, TopAbs_VERTEX, TopAbs_EDGE, MVE2);
1750 TopoDS_Shape anEdge1, anEdge2;
1751 GEOMImpl_Block6Explorer::FindEdge(anEdge1, V1(1), V1(2), MVE1);
1752 if (anEdge1.IsNull()) return REL_UNKNOWN;
1754 GEOMImpl_Block6Explorer::FindEdge(anEdge2, V2(1), V2(2), MVE2);
1755 if (anEdge2.IsNull()) return REL_UNKNOWN;
1757 if (!anEdge1.IsSame(anEdge2)) return REL_NOT_GLUED;
1759 } else { // ivs == 3
1760 // Find common edges
1761 Standard_Integer e1_v1 = 1;
1762 Standard_Integer e1_v2 = 2;
1763 Standard_Integer e2_v1 = 3;
1764 Standard_Integer e2_v2 = 1;
1766 TopoDS_Shape anEdge11, anEdge12;
1767 GEOMImpl_Block6Explorer::FindEdge(anEdge11, V1(e1_v1), V1(e1_v2), MVE1);
1768 if (anEdge11.IsNull()) {
1771 GEOMImpl_Block6Explorer::FindEdge(anEdge11, V1(e1_v1), V1(e1_v2), MVE1);
1772 if (anEdge11.IsNull()) return REL_UNKNOWN;
1774 GEOMImpl_Block6Explorer::FindEdge(anEdge12, V1(e2_v1), V1(e2_v2), MVE1);
1775 if (anEdge12.IsNull()) {
1777 GEOMImpl_Block6Explorer::FindEdge(anEdge12, V1(e2_v1), V1(e2_v2), MVE1);
1778 if (anEdge12.IsNull()) return REL_UNKNOWN;
1781 TopoDS_Shape anEdge21, anEdge22;
1782 GEOMImpl_Block6Explorer::FindEdge(anEdge21, V2(e1_v1), V2(e1_v2), MVE2);
1783 if (anEdge21.IsNull()) return REL_UNKNOWN;
1784 GEOMImpl_Block6Explorer::FindEdge(anEdge22, V2(e2_v1), V2(e2_v2), MVE2);
1785 if (anEdge22.IsNull()) return REL_UNKNOWN;
1787 // Check of edges coincidence (with some precision) have to be done here
1788 // if (!anEdge11.IsEqual(anEdge21)) return REL_UNKNOWN;
1789 // if (!anEdge12.IsEqual(anEdge22)) return REL_UNKNOWN;
1791 // Check of edges sharing
1792 if (!anEdge11.IsSame(anEdge21)) return REL_NOT_GLUED;
1793 if (!anEdge12.IsSame(anEdge22)) return REL_NOT_GLUED;
1798 // Map vertices and faces of the blocks
1799 TopTools_IndexedDataMapOfShapeListOfShape MVF1, MVF2;
1800 GEOMImpl_Block6Explorer::MapShapesAndAncestors
1801 (theBlock1, TopAbs_VERTEX, TopAbs_FACE, MVF1);
1802 GEOMImpl_Block6Explorer::MapShapesAndAncestors
1803 (theBlock2, TopAbs_VERTEX, TopAbs_FACE, MVF2);
1805 TopoDS_Shape aFace1, aFace2;
1806 GEOMImpl_Block6Explorer::FindFace(aFace1, V1(1), V1(2), V1(3), V1(4), MVF1);
1807 if (aFace1.IsNull()) return REL_UNKNOWN;
1808 GEOMImpl_Block6Explorer::FindFace(aFace2, V2(1), V2(2), V2(3), V2(4), MVF2);
1809 if (aFace2.IsNull()) return REL_UNKNOWN;
1811 // Check of faces coincidence (with some precision) have to be done here
1812 // if (!aFace1.IsEqual(aFace2)) return REL_UNKNOWN;
1814 // Check of faces sharing
1815 if (!aFace1.IsSame(aFace2)) return REL_NOT_GLUED;
1821 void FindConnected (const Standard_Integer theBlockIndex,
1822 const TColStd_Array2OfInteger& theRelations,
1823 TColStd_MapOfInteger& theProcessedMap,
1824 TColStd_MapOfInteger& theConnectedMap)
1826 theConnectedMap.Add(theBlockIndex);
1827 theProcessedMap.Add(theBlockIndex);
1829 Standard_Integer nbBlocks = theRelations.ColLength();
1830 Standard_Integer col = 1;
1831 for (; col <= nbBlocks; col++) {
1832 if (theRelations(theBlockIndex, col) == REL_OK ||
1833 theRelations(theBlockIndex, col) == REL_NOT_GLUED) {
1834 if (!theProcessedMap.Contains(col)) {
1835 FindConnected(col, theRelations, theProcessedMap, theConnectedMap);
1841 Standard_Boolean HasAnyConnection (const Standard_Integer theBlockIndex,
1842 const TColStd_MapOfInteger& theWith,
1843 const TColStd_Array2OfInteger& theRelations,
1844 TColStd_MapOfInteger& theProcessedMap)
1846 theProcessedMap.Add(theBlockIndex);
1848 Standard_Integer nbBlocks = theRelations.ColLength();
1849 Standard_Integer col = 1;
1850 for (; col <= nbBlocks; col++) {
1851 if (theRelations(theBlockIndex, col) != REL_NOT_CONNECTED) {
1852 if (!theProcessedMap.Contains(col)) {
1853 if (theWith.Contains(col))
1854 return Standard_True;
1855 if (HasAnyConnection(col, theWith, theRelations, theProcessedMap))
1856 return Standard_True;
1861 return Standard_False;
1864 //=============================================================================
1866 * CheckCompoundOfBlocks
1868 //=============================================================================
1869 Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocks
1870 (Handle(GEOM_Object) theCompound,
1871 list<BCError>& theErrors)
1875 if (theCompound.IsNull()) return Standard_False;
1876 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
1878 Standard_Boolean isCompOfBlocks = Standard_True;
1880 // Map sub-shapes and their indices
1881 TopTools_IndexedMapOfShape anIndices;
1882 TopExp::MapShapes(aBlockOrComp, anIndices);
1884 // 1. Report non-blocks
1885 TopTools_ListOfShape NOT; // Not blocks
1886 TopTools_ListOfShape BLO; // All blocks from the given compound
1887 AddBlocksFrom(aBlockOrComp, BLO, NOT);
1889 if (NOT.Extent() > 0) {
1890 isCompOfBlocks = Standard_False;
1892 anErr.error = NOT_BLOCK;
1893 TopTools_ListIteratorOfListOfShape NOTit (NOT);
1894 for (; NOTit.More(); NOTit.Next()) {
1895 anErr.incriminated.push_back(anIndices.FindIndex(NOTit.Value()));
1897 theErrors.push_back(anErr);
1900 Standard_Integer nbBlocks = BLO.Extent();
1901 if (nbBlocks == 0) {
1902 isCompOfBlocks = Standard_False;
1904 return isCompOfBlocks;
1906 if (nbBlocks == 1) {
1908 return isCompOfBlocks;
1911 // Convert list of blocks into array for easy and fast access
1912 Standard_Integer ibl = 1;
1913 TopTools_Array1OfShape aBlocks (1, nbBlocks);
1914 TopTools_ListIteratorOfListOfShape BLOit (BLO);
1915 for (; BLOit.More(); BLOit.Next(), ibl++) {
1916 aBlocks.SetValue(ibl, BLOit.Value());
1919 // 2. Find relations between all blocks,
1920 // report connection errors (NOT_GLUED and INVALID_CONNECTION)
1921 TColStd_Array2OfInteger aRelations (1, nbBlocks, 1, nbBlocks);
1922 aRelations.Init(REL_NOT_CONNECTED);
1924 Standard_Integer row = 1;
1925 for (row = 1; row <= nbBlocks; row++) {
1926 TopoDS_Shape aBlock = aBlocks.Value(row);
1928 Standard_Integer col = row + 1;
1929 for (; col <= nbBlocks; col++) {
1930 Standard_Integer aRel = BlocksRelation(aBlock, aBlocks.Value(col));
1931 if (aRel != REL_NOT_CONNECTED) {
1932 aRelations.SetValue(row, col, aRel);
1933 aRelations.SetValue(col, row, aRel);
1934 if (aRel == REL_NOT_GLUED) {
1935 // report connection error
1936 isCompOfBlocks = Standard_False;
1938 anErr.error = NOT_GLUED;
1939 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row)));
1940 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col)));
1941 theErrors.push_back(anErr);
1942 } else if (aRel == REL_COLLISION_VV ||
1943 aRel == REL_COLLISION_FF ||
1944 aRel == REL_COLLISION_EE ||
1945 aRel == REL_UNKNOWN) {
1946 // report connection error
1947 isCompOfBlocks = Standard_False;
1949 anErr.error = INVALID_CONNECTION;
1950 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row)));
1951 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col)));
1952 theErrors.push_back(anErr);
1959 // 3. Find largest set of connected (good connection or not glued) blocks
1960 TColStd_MapOfInteger aProcessedMap;
1961 TColStd_MapOfInteger aLargestSet;
1962 TColStd_MapOfInteger aCurrentSet;
1963 for (ibl = 1; ibl <= nbBlocks; ibl++) {
1964 if (!aProcessedMap.Contains(ibl)) {
1965 FindConnected(ibl, aRelations, aProcessedMap, aCurrentSet);
1966 if (aCurrentSet.Extent() > aLargestSet.Extent()) {
1967 aLargestSet = aCurrentSet;
1972 // 4. Report all blocks, isolated from <aLargestSet>
1974 anErr.error = NOT_CONNECTED;
1975 Standard_Boolean hasIsolated = Standard_False;
1976 for (ibl = 1; ibl <= nbBlocks; ibl++) {
1977 if (!aLargestSet.Contains(ibl)) {
1978 aProcessedMap.Clear();
1979 if (!HasAnyConnection(ibl, aLargestSet, aRelations, aProcessedMap)) {
1980 // report connection absence
1981 hasIsolated = Standard_True;
1982 anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(ibl)));
1987 isCompOfBlocks = Standard_False;
1988 theErrors.push_back(anErr);
1992 return isCompOfBlocks;
1995 //=============================================================================
1999 //=============================================================================
2000 TCollection_AsciiString GEOMImpl_IBlocksOperations::PrintBCErrors
2001 (Handle(GEOM_Object) theCompound,
2002 const list<BCError>& theErrors)
2004 TCollection_AsciiString aDescr;
2006 list<BCError>::const_iterator errIt = theErrors.begin();
2008 for (; errIt != theErrors.end(); i++, errIt++) {
2009 BCError errStruct = *errIt;
2011 switch (errStruct.error) {
2013 aDescr += "\nNot a Blocks: ";
2015 case INVALID_CONNECTION:
2016 aDescr += "\nInvalid connection between two blocks: ";
2019 aDescr += "\nBlocks, not connected with main body: ";
2022 aDescr += "\nNot glued blocks: ";
2028 list<int> sshList = errStruct.incriminated;
2029 list<int>::iterator sshIt = sshList.begin();
2031 for (; sshIt != sshList.end(); jj++, sshIt++) {
2034 aDescr += TCollection_AsciiString(*sshIt);
2041 //=============================================================================
2043 * ExplodeCompoundOfBlocks
2045 //=============================================================================
2046 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::ExplodeCompoundOfBlocks
2047 (Handle(GEOM_Object) theCompound,
2048 const Standard_Integer theMinNbFaces,
2049 const Standard_Integer theMaxNbFaces)
2053 if (theCompound.IsNull()) return NULL;
2054 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2055 if (aBlockOrComp.IsNull()) return NULL;
2057 Handle(TColStd_HSequenceOfTransient) aBlocks = new TColStd_HSequenceOfTransient;
2058 Handle(GEOM_Object) anObj;
2059 Handle(GEOM_Function) aFunction;
2061 TopTools_MapOfShape mapShape;
2062 TCollection_AsciiString anAsciiList = "[", anEntry;
2065 TopTools_IndexedMapOfShape anIndices;
2066 TopExp::MapShapes(aBlockOrComp, anIndices);
2067 Handle(TColStd_HArray1OfInteger) anArray;
2071 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2072 for (; exp.More(); exp.Next()) {
2073 if (mapShape.Add(exp.Current())) {
2074 TopoDS_Shape aSolid = exp.Current();
2076 TopTools_MapOfShape mapFaces;
2077 TopExp_Explorer expF (aSolid, TopAbs_FACE);
2078 Standard_Integer nbFaces = 0;
2079 for (; expF.More(); expF.Next()) {
2080 if (mapFaces.Add(expF.Current())) {
2085 if (theMinNbFaces <= nbFaces && nbFaces <= theMaxNbFaces) {
2086 anArray = new TColStd_HArray1OfInteger(1,1);
2087 anArray->SetValue(1, anIndices.FindIndex(aSolid));
2088 anObj = GetEngine()->AddSubShape(theCompound, anArray);
2089 aBlocks->Append(anObj);
2091 //Make a Python command
2092 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2093 anAsciiList += anEntry;
2099 catch (Standard_Failure) {
2100 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2101 SetErrorCode(aFail->GetMessageString());
2105 if (aBlocks->IsEmpty()) {
2106 SetErrorCode("There are no specified blocks in the given shape");
2110 anAsciiList.Trunc(anAsciiList.Length() - 1);
2113 //The explode doesn't change object so no new function is required.
2114 aFunction = theCompound->GetLastFunction();
2116 //Make a Python command
2117 TCollection_AsciiString aDescr (anAsciiList);
2118 aDescr += " = IBlocksOperations.ExplodeCompoundOfBlocks(";
2119 TDF_Tool::Entry(theCompound->GetEntry(), anEntry);
2120 aDescr += anEntry + ", ";
2121 aDescr += TCollection_AsciiString(theMinNbFaces) + ", ";
2122 aDescr += TCollection_AsciiString(theMaxNbFaces) + ")";
2124 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n";
2125 aNewDescr += aDescr;
2126 aFunction->SetDescription(aNewDescr);
2132 //=============================================================================
2136 //=============================================================================
2137 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetBlockNearPoint
2138 (Handle(GEOM_Object) theCompound,
2139 Handle(GEOM_Object) thePoint)
2144 Handle(GEOM_Object) aResult;
2147 if (theCompound.IsNull() || thePoint.IsNull()) return NULL;
2149 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2150 if (aBlockOrComp.IsNull()) {
2151 SetErrorCode("Compound is null");
2154 if (aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
2155 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
2156 SetErrorCode("Shape is neither a block, nor a compound of blocks");
2160 TopoDS_Shape anArg = thePoint->GetValue();
2161 if (anArg.IsNull()) {
2162 SetErrorCode("Null shape is given as argument");
2165 if (anArg.ShapeType() != TopAbs_VERTEX) {
2166 SetErrorCode("Element for block identification is not a vertex");
2170 //Compute the Block value
2172 TopoDS_Shape aShape;
2173 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
2174 gp_Pnt aPnt = BRep_Tool::Pnt(aVert);
2176 // 1. Explode compound on blocks
2177 TopTools_MapOfShape mapShape;
2178 Standard_Integer nbSolids = 0;
2179 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2180 for (; exp.More(); exp.Next()) {
2181 if (mapShape.Add(exp.Current())) {
2187 Standard_Integer ind = 1;
2188 TopTools_Array1OfShape aSolids (1, nbSolids);
2189 TColStd_Array1OfInteger aDistances (1, nbSolids);
2190 for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next()) {
2191 if (mapShape.Add(exp.Current())) {
2192 TopoDS_Shape aSolid = exp.Current();
2193 aSolids(ind) = aSolid;
2195 // 2. Classify the point relatively each block
2196 BRepClass3d_SolidClassifier SC (aSolid, aPnt, Precision::Confusion());
2197 if (SC.State() == TopAbs_IN) {
2198 aDistances(ind) = -1;
2199 } else if (SC.State() == TopAbs_ON) {
2200 aDistances(ind) = 0;
2202 aDistances(ind) = 1;
2208 // 3. Define block, containing the point or having minimum distance to it
2209 Standard_Integer nearest = 2, nbFound = 0;
2210 for (ind = 1; ind <= nbSolids; ind++) {
2211 if (aDistances(ind) < nearest) {
2212 nearest = aDistances(ind);
2213 aShape = aSolids(ind);
2215 } else if (aDistances(ind) == nearest) {
2222 // The point is on boundary of some blocks and there are
2223 // no blocks, having the point inside their volume
2224 SetErrorCode("Multiple blocks near the given point are found");
2227 } else if (nearest == 1) {
2228 // The point is outside some blocks and there are
2229 // no blocks, having the point inside or on boundary.
2230 // We will get a nearest block
2231 Standard_Real minDist = RealLast();
2232 for (ind = 1; ind <= nbSolids; ind++) {
2233 if (aDistances(ind) == 1) {
2234 BRepExtrema_DistShapeShape aDistTool (aVert, aSolids(ind));
2235 if (!aDistTool.IsDone()) {
2236 SetErrorCode("Can not find a distance from the given point to one of blocks");
2239 Standard_Real aDist = aDistTool.Value();
2240 if (aDist < minDist) {
2242 aShape = aSolids(ind);
2246 } else { // nearest == -1
2247 // The point is inside some blocks.
2248 // We will get a block with nearest center
2249 Standard_Real minDist = RealLast();
2250 for (ind = 1; ind <= nbSolids; ind++) {
2251 if (aDistances(ind) == -1) {
2252 GProp_GProps aSystem;
2253 BRepGProp::VolumeProperties(aSolids(ind), aSystem);
2254 gp_Pnt aCenterMass = aSystem.CentreOfMass();
2256 Standard_Real aDist = aCenterMass.Distance(aPnt);
2257 if (aDist < minDist) {
2259 aShape = aSolids(ind);
2267 SetErrorCode("There are no blocks near the given point");
2270 TopTools_IndexedMapOfShape anIndices;
2271 TopExp::MapShapes(aBlockOrComp, anIndices);
2272 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2273 anArray->SetValue(1, anIndices.FindIndex(aShape));
2274 aResult = GetEngine()->AddSubShape(theCompound, anArray);
2277 catch (Standard_Failure) {
2278 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2279 SetErrorCode(aFail->GetMessageString());
2283 //The GetBlockNearPoint() doesn't change object so no new function is required.
2284 Handle(GEOM_Function) aFunction = theCompound->GetLastFunction();
2286 //Make a Python command
2287 TCollection_AsciiString anEntry, aDescr;
2288 TDF_Tool::Entry(aResult->GetEntry(), anEntry);
2289 aDescr += anEntry + " = IBlocksOperations.GetBlockNearPoint(";
2290 TDF_Tool::Entry(theCompound->GetEntry(), anEntry);
2291 aDescr += anEntry + ", ";
2292 TDF_Tool::Entry(thePoint->GetEntry(), anEntry);
2293 aDescr += anEntry + ")";
2295 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n";
2296 aNewDescr += aDescr;
2297 aFunction->SetDescription(aNewDescr);
2303 //=============================================================================
2307 //=============================================================================
2308 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetBlockByParts
2309 (Handle(GEOM_Object) theCompound,
2310 const Handle(TColStd_HSequenceOfTransient)& theParts)
2314 Handle(GEOM_Object) aResult;
2316 if (theCompound.IsNull() || theParts.IsNull()) return NULL;
2317 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2318 if (aBlockOrComp.IsNull()) return NULL;
2321 Standard_Integer argi, aLen = theParts->Length();
2322 TopTools_Array1OfShape anArgs (1, aLen);
2323 TCollection_AsciiString anEntry, aPartsDescr;
2324 for (argi = 1; argi <= aLen; argi++) {
2325 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theParts->Value(argi));
2326 Handle(GEOM_Function) aRef = anObj->GetLastFunction();
2327 if (aRef.IsNull()) return NULL;
2329 TopoDS_Shape anArg = aRef->GetValue();
2330 if (anArg.IsNull()) {
2331 SetErrorCode("Null shape is given as argument");
2334 anArgs(argi) = anArg;
2336 // For Python command
2337 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2338 if (argi > 1) aPartsDescr += ", ";
2339 aPartsDescr += anEntry;
2342 //Compute the Block value
2344 // 1. Explode compound on solids
2345 TopTools_MapOfShape mapShape;
2346 Standard_Integer nbSolids = 0;
2347 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2348 for (; exp.More(); exp.Next()) {
2349 if (mapShape.Add(exp.Current())) {
2355 Standard_Integer ind = 1;
2356 TopTools_Array1OfShape aSolids (1, nbSolids);
2357 TColStd_Array1OfInteger aNbParts (1, nbSolids);
2358 for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next(), ind++) {
2359 if (mapShape.Add(exp.Current())) {
2360 TopoDS_Shape aSolid = exp.Current();
2361 aSolids(ind) = aSolid;
2364 // 2. Define quantity of parts, contained in each solid
2365 TopTools_IndexedMapOfShape aSubShapes;
2366 TopExp::MapShapes(aSolid, aSubShapes);
2367 for (argi = 1; argi <= aLen; argi++) {
2368 if (aSubShapes.Contains(anArgs(argi))) {
2375 // 3. Define solid, containing maximum quantity of parts
2376 Standard_Integer maxNb = 0, nbFound = 0;
2377 TopoDS_Shape aShape;
2378 for (ind = 1; ind <= nbSolids; ind++) {
2379 if (aNbParts(ind) > maxNb) {
2380 maxNb = aNbParts(ind);
2381 aShape = aSolids(ind);
2383 } else if (aNbParts(ind) == maxNb) {
2389 SetErrorCode("Multiple blocks, containing maximum quantity of the given parts, are found");
2391 } else if (nbFound == 0) {
2392 SetErrorCode("There are no blocks, containing the given parts");
2395 TopTools_IndexedMapOfShape anIndices;
2396 TopExp::MapShapes(aBlockOrComp, anIndices);
2397 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2398 anArray->SetValue(1, anIndices.FindIndex(aShape));
2399 aResult = GetEngine()->AddSubShape(theCompound, anArray);
2401 } catch (Standard_Failure) {
2402 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2403 SetErrorCode(aFail->GetMessageString());
2407 //The GetBlockByParts() doesn't change object so no new function is required.
2408 Handle(GEOM_Function) aFunction = theCompound->GetLastFunction();
2410 //Make a Python command
2411 TDF_Tool::Entry(aResult->GetEntry(), anEntry);
2412 TCollection_AsciiString aDescr (anEntry);
2413 aDescr += " = IBlocksOperations.GetBlockByParts(";
2414 TDF_Tool::Entry(theCompound->GetEntry(), anEntry);
2415 aDescr += anEntry + ", [";
2416 aDescr += aPartsDescr + "])";
2418 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n";
2419 aNewDescr += aDescr;
2420 aFunction->SetDescription(aNewDescr);
2426 //=============================================================================
2430 //=============================================================================
2431 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::GetBlocksByParts
2432 (Handle(GEOM_Object) theCompound,
2433 const Handle(TColStd_HSequenceOfTransient)& theParts)
2437 if (theCompound.IsNull() || theParts.IsNull()) return NULL;
2438 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
2439 if (aBlockOrComp.IsNull()) return NULL;
2441 Handle(TColStd_HSequenceOfTransient) aBlocks = new TColStd_HSequenceOfTransient;
2442 Handle(GEOM_Object) anObj;
2443 Handle(GEOM_Function) aFunction;
2446 Standard_Integer argi, aLen = theParts->Length();
2447 TopTools_Array1OfShape anArgs (1, aLen);
2448 TCollection_AsciiString anEntry, aPartsDescr, anAsciiList = "[";
2449 for (argi = 1; argi <= aLen; argi++) {
2450 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theParts->Value(argi));
2451 Handle(GEOM_Function) aRef = anObj->GetLastFunction();
2452 if (aRef.IsNull()) return NULL;
2454 TopoDS_Shape anArg = aRef->GetValue();
2455 if (anArg.IsNull()) {
2456 SetErrorCode("Null shape is given as argument");
2459 anArgs(argi) = anArg;
2461 // For Python command
2462 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2463 if (argi > 1) aPartsDescr += ", ";
2464 aPartsDescr += anEntry;
2469 TopTools_MapOfShape mapShape;
2470 Standard_Integer nbSolids = 0;
2471 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
2472 for (; exp.More(); exp.Next()) {
2473 if (mapShape.Add(exp.Current())) {
2479 Standard_Integer ind = 1;
2480 TopTools_Array1OfShape aSolids (1, nbSolids);
2481 TColStd_Array1OfInteger aNbParts (1, nbSolids);
2482 for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next(), ind++) {
2483 if (mapShape.Add(exp.Current())) {
2484 TopoDS_Shape aSolid = exp.Current();
2485 aSolids(ind) = aSolid;
2488 // 2. Define quantity of parts, contained in each solid
2489 TopTools_IndexedMapOfShape aSubShapes;
2490 TopExp::MapShapes(aSolid, aSubShapes);
2491 for (argi = 1; argi <= aLen; argi++) {
2492 if (aSubShapes.Contains(anArgs(argi))) {
2499 // 3. Define solid, containing maximum quantity of parts
2500 Standard_Integer maxNb = 0, nbFound = 0;
2501 for (ind = 1; ind <= nbSolids; ind++) {
2502 if (aNbParts(ind) > maxNb) {
2503 maxNb = aNbParts(ind);
2505 } else if (aNbParts(ind) == maxNb) {
2511 SetErrorCode("There are no blocks, containing the given parts");
2516 TopTools_IndexedMapOfShape anIndices;
2517 TopExp::MapShapes(aBlockOrComp, anIndices);
2518 Handle(TColStd_HArray1OfInteger) anArray;
2520 for (ind = 1; ind <= nbSolids; ind++) {
2521 if (aNbParts(ind) == maxNb) {
2522 anArray = new TColStd_HArray1OfInteger(1,1);
2523 anArray->SetValue(1, anIndices.FindIndex(aSolids(ind)));
2524 anObj = GetEngine()->AddSubShape(theCompound, anArray);
2525 aBlocks->Append(anObj);
2527 //Make a Python command
2528 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2529 anAsciiList += anEntry;
2534 catch (Standard_Failure) {
2535 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2536 SetErrorCode(aFail->GetMessageString());
2540 anAsciiList.Trunc(anAsciiList.Length() - 1);
2543 //The GetBlocksByParts() doesn't change object so no new function is required.
2544 aFunction = theCompound->GetLastFunction();
2546 //Make a Python command
2547 TCollection_AsciiString aDescr (anAsciiList);
2548 aDescr += " = IBlocksOperations.GetBlocksByParts(";
2549 TDF_Tool::Entry(theCompound->GetEntry(), anEntry);
2550 aDescr += anEntry + ", [";
2551 aDescr += aPartsDescr + "])";
2553 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n";
2554 aNewDescr += aDescr;
2555 aFunction->SetDescription(aNewDescr);
2561 //=============================================================================
2563 * MakeMultiTransformation1D
2565 //=============================================================================
2566 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeMultiTransformation1D
2567 (Handle(GEOM_Object) theObject,
2568 const Standard_Integer theDirFace1,
2569 const Standard_Integer theDirFace2,
2570 const Standard_Integer theNbTimes)
2574 if (theObject.IsNull()) return NULL;
2576 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2577 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be moved
2579 //Add a new Copy object
2580 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2582 //Add a translate function
2583 Handle(GEOM_Function) aFunction =
2584 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_MULTI_TRANSFORM_1D);
2586 //Check if the function is set correctly
2587 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2589 GEOMImpl_IBlockTrsf aTI (aFunction);
2590 aTI.SetOriginal(aLastFunction);
2591 aTI.SetFace1U(theDirFace1);
2592 aTI.SetFace2U(theDirFace2);
2593 aTI.SetNbIterU(theNbTimes);
2595 //Compute the transformation
2597 if (!GetSolver()->ComputeFunction(aFunction)) {
2598 SetErrorCode("Block driver failed to make multi-transformation");
2602 catch (Standard_Failure) {
2603 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2604 SetErrorCode(aFail->GetMessageString());
2608 //Make a Python command
2609 TCollection_AsciiString anEntry, aDescr;
2610 TDF_Tool::Entry(aCopy->GetEntry(), anEntry);
2611 aDescr += anEntry + " = IBlocksOperations.MakeMultiTransformation1D(";
2612 TDF_Tool::Entry(theObject->GetEntry(), anEntry);
2613 aDescr += anEntry + ", ";
2614 aDescr += TCollection_AsciiString(theDirFace1) + ", ";
2615 aDescr += TCollection_AsciiString(theDirFace2) + ", ";
2616 aDescr += TCollection_AsciiString(theNbTimes) + ") ";
2618 aFunction->SetDescription(aDescr);
2624 //=============================================================================
2626 * MakeMultiTransformation2D
2628 //=============================================================================
2629 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeMultiTransformation2D
2630 (Handle(GEOM_Object) theObject,
2631 const Standard_Integer theDirFace1U,
2632 const Standard_Integer theDirFace2U,
2633 const Standard_Integer theNbTimesU,
2634 const Standard_Integer theDirFace1V,
2635 const Standard_Integer theDirFace2V,
2636 const Standard_Integer theNbTimesV)
2640 if (theObject.IsNull()) return NULL;
2642 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
2643 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be moved
2645 //Add a new Copy object
2646 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
2648 //Add a translate function
2649 Handle(GEOM_Function) aFunction =
2650 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_MULTI_TRANSFORM_2D);
2652 //Check if the function is set correctly
2653 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
2655 GEOMImpl_IBlockTrsf aTI (aFunction);
2656 aTI.SetOriginal(aLastFunction);
2657 aTI.SetFace1U(theDirFace1U);
2658 aTI.SetFace2U(theDirFace2U);
2659 aTI.SetNbIterU(theNbTimesU);
2660 aTI.SetFace1V(theDirFace1V);
2661 aTI.SetFace2V(theDirFace2V);
2662 aTI.SetNbIterV(theNbTimesV);
2664 //Compute the transformation
2666 if (!GetSolver()->ComputeFunction(aFunction)) {
2667 SetErrorCode("Block driver failed to make multi-transformation");
2671 catch (Standard_Failure) {
2672 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2673 SetErrorCode(aFail->GetMessageString());
2677 //Make a Python command
2678 TCollection_AsciiString anEntry, aDescr;
2679 TDF_Tool::Entry(aCopy->GetEntry(), anEntry);
2680 aDescr += anEntry + " = IBlocksOperations.MakeMultiTransformation2D(";
2681 TDF_Tool::Entry(theObject->GetEntry(), anEntry);
2682 aDescr += anEntry + ", ";
2683 aDescr += TCollection_AsciiString(theDirFace1U) + ", ";
2684 aDescr += TCollection_AsciiString(theDirFace2U) + ", ";
2685 aDescr += TCollection_AsciiString(theNbTimesU) + ", ";
2686 aDescr += TCollection_AsciiString(theDirFace1V) + ", ";
2687 aDescr += TCollection_AsciiString(theDirFace2V) + ", ";
2688 aDescr += TCollection_AsciiString(theNbTimesV) + ") ";
2690 aFunction->SetDescription(aDescr);