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 <BRepTools.hxx>
25 #include <BRep_Tool.hxx>
26 #include <BRepClass3d_SolidClassifier.hxx>
27 #include <BRepClass_FaceClassifier.hxx>
28 #include <BRepAdaptor_Surface.hxx>
29 #include <BRepExtrema_DistShapeShape.hxx>
30 #include <BRepGProp.hxx>
33 #include <TopoDS_Edge.hxx>
34 #include <TopoDS_Vertex.hxx>
36 #include <TopExp_Explorer.hxx>
37 #include <TopTools_MapOfShape.hxx>
38 #include <TopTools_Array1OfShape.hxx>
39 #include <TopTools_IndexedMapOfShape.hxx>
40 #include <TopTools_ListIteratorOfListOfShape.hxx>
41 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
43 #include <Precision.hxx>
44 #include <GProp_GProps.hxx>
45 #include <TColStd_Array1OfInteger.hxx>
47 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
49 //=============================================================================
53 //=============================================================================
54 GEOMImpl_IBlocksOperations::GEOMImpl_IBlocksOperations (GEOM_Engine* theEngine, int theDocID)
55 : GEOM_IOperations(theEngine, theDocID)
57 MESSAGE("GEOMImpl_IBlocksOperations::GEOMImpl_IBlocksOperations");
60 //=============================================================================
64 //=============================================================================
65 GEOMImpl_IBlocksOperations::~GEOMImpl_IBlocksOperations()
67 MESSAGE("GEOMImpl_IBlocksOperations::~GEOMImpl_IBlocksOperations");
71 //=============================================================================
73 * MakeQuadFaceFourVertices
75 //=============================================================================
76 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuadFaceFourVertices
77 (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2,
78 Handle(GEOM_Object) thePnt3, Handle(GEOM_Object) thePnt4)
82 if (thePnt1.IsNull() || thePnt2.IsNull() ||
83 thePnt3.IsNull() || thePnt4.IsNull()) return NULL;
85 //Add a new Face object
86 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
88 //Add a new Face function
89 Handle(GEOM_Function) aFunction =
90 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_FOUR_PNT);
92 //Check if the function is set correctly
93 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
95 GEOMImpl_IBlocks aPI (aFunction);
97 Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
98 Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
99 Handle(GEOM_Function) aRef3 = thePnt3->GetLastFunction();
100 Handle(GEOM_Function) aRef4 = thePnt4->GetLastFunction();
101 if (aRef1.IsNull() || aRef2.IsNull() ||
102 aRef3.IsNull() || aRef4.IsNull()) return NULL;
104 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
105 aShapesSeq->Append(aRef1);
106 aShapesSeq->Append(aRef2);
107 aShapesSeq->Append(aRef3);
108 aShapesSeq->Append(aRef4);
110 aPI.SetShapes(aShapesSeq);
112 //Compute the Face value
114 if (!GetSolver()->ComputeFunction(aFunction)) {
115 SetErrorCode("Block driver failed to compute a face");
119 catch (Standard_Failure) {
120 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
121 SetErrorCode(aFail->GetMessageString());
125 //Make a Python command
126 TCollection_AsciiString anEntry, aDescr;
127 TDF_Tool::Entry(aFace->GetEntry(), anEntry);
128 aDescr += (anEntry+" = IBlocksOperations.MakeQuadFaceFourVertices(");
129 TDF_Tool::Entry(thePnt1->GetEntry(), anEntry);
130 aDescr += (anEntry+", ");
131 TDF_Tool::Entry(thePnt2->GetEntry(), anEntry);
132 aDescr += (anEntry+", ");
133 TDF_Tool::Entry(thePnt3->GetEntry(), anEntry);
134 aDescr += (anEntry+", ");
135 TDF_Tool::Entry(thePnt4->GetEntry(), anEntry);
136 aDescr += (anEntry+")");
138 aFunction->SetDescription(aDescr);
144 //=============================================================================
146 * MakeQuadFaceFourEdges
148 //=============================================================================
149 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuadFaceFourEdges
150 (Handle(GEOM_Object) theEdge1, Handle(GEOM_Object) theEdge2,
151 Handle(GEOM_Object) theEdge3, Handle(GEOM_Object) theEdge4)
155 if (theEdge1.IsNull() || theEdge2.IsNull() ||
156 theEdge3.IsNull() || theEdge4.IsNull()) return NULL;
158 //Add a new Face object
159 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
161 //Add a new Face function
162 Handle(GEOM_Function) aFunction =
163 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_FOUR_EDGES);
165 //Check if the function is set correctly
166 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
168 GEOMImpl_IBlocks aPI (aFunction);
170 Handle(GEOM_Function) aRef1 = theEdge1->GetLastFunction();
171 Handle(GEOM_Function) aRef2 = theEdge2->GetLastFunction();
172 Handle(GEOM_Function) aRef3 = theEdge3->GetLastFunction();
173 Handle(GEOM_Function) aRef4 = theEdge4->GetLastFunction();
174 if (aRef1.IsNull() || aRef2.IsNull() ||
175 aRef3.IsNull() || aRef4.IsNull()) return NULL;
177 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
178 aShapesSeq->Append(aRef1);
179 aShapesSeq->Append(aRef2);
180 aShapesSeq->Append(aRef3);
181 aShapesSeq->Append(aRef4);
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.MakeQuadFaceFourEdges(");
202 TDF_Tool::Entry(theEdge1->GetEntry(), anEntry);
203 aDescr += (anEntry+", ");
204 TDF_Tool::Entry(theEdge2->GetEntry(), anEntry);
205 aDescr += (anEntry+", ");
206 TDF_Tool::Entry(theEdge3->GetEntry(), anEntry);
207 aDescr += (anEntry+", ");
208 TDF_Tool::Entry(theEdge4->GetEntry(), anEntry);
209 aDescr += (anEntry+")");
211 aFunction->SetDescription(aDescr);
217 //=============================================================================
219 * MakeQuadFaceTwoEdges
221 //=============================================================================
222 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuadFaceTwoEdges
223 (Handle(GEOM_Object) theEdge1, Handle(GEOM_Object) theEdge2)
227 if (theEdge1.IsNull() || theEdge2.IsNull()) return NULL;
229 //Add a new Face object
230 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
232 //Add a new Face function
233 Handle(GEOM_Function) aFunction =
234 aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_TWO_EDGES);
236 //Check if the function is set correctly
237 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
239 GEOMImpl_IBlocks aPI (aFunction);
241 Handle(GEOM_Function) aRef1 = theEdge1->GetLastFunction();
242 Handle(GEOM_Function) aRef2 = theEdge2->GetLastFunction();
243 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
245 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
246 aShapesSeq->Append(aRef1);
247 aShapesSeq->Append(aRef2);
249 aPI.SetShapes(aShapesSeq);
251 //Compute the Face value
253 if (!GetSolver()->ComputeFunction(aFunction)) {
254 SetErrorCode("Block driver failed to compute a face");
258 catch (Standard_Failure) {
259 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
260 SetErrorCode(aFail->GetMessageString());
264 //Make a Python command
265 TCollection_AsciiString anEntry, aDescr;
266 TDF_Tool::Entry(aFace->GetEntry(), anEntry);
267 aDescr += (anEntry+" = IBlocksOperations.MakeQuadFaceTwoEdges(");
268 TDF_Tool::Entry(theEdge1->GetEntry(), anEntry);
269 aDescr += (anEntry+", ");
270 TDF_Tool::Entry(theEdge2->GetEntry(), anEntry);
271 aDescr += (anEntry+")");
273 aFunction->SetDescription(aDescr);
279 //=============================================================================
281 * MakeHexaSolidSixFaces
283 //=============================================================================
284 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeHexaSolidSixFaces
285 (Handle(GEOM_Object) theFace1, Handle(GEOM_Object) theFace2,
286 Handle(GEOM_Object) theFace3, Handle(GEOM_Object) theFace4,
287 Handle(GEOM_Object) theFace5, Handle(GEOM_Object) theFace6)
291 if (theFace1.IsNull() || theFace2.IsNull() ||
292 theFace3.IsNull() || theFace4.IsNull() ||
293 theFace5.IsNull() || theFace6.IsNull()) return NULL;
295 //Add a new Solid object
296 Handle(GEOM_Object) aBlock = GetEngine()->AddObject(GetDocID(), GEOM_BLOCK);
298 //Add a new Block function
299 Handle(GEOM_Function) aFunction =
300 aBlock->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_SIX_FACES);
302 //Check if the function is set correctly
303 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
305 GEOMImpl_IBlocks aPI (aFunction);
307 Handle(GEOM_Function) aRef1 = theFace1->GetLastFunction();
308 Handle(GEOM_Function) aRef2 = theFace2->GetLastFunction();
309 Handle(GEOM_Function) aRef3 = theFace3->GetLastFunction();
310 Handle(GEOM_Function) aRef4 = theFace4->GetLastFunction();
311 Handle(GEOM_Function) aRef5 = theFace5->GetLastFunction();
312 Handle(GEOM_Function) aRef6 = theFace6->GetLastFunction();
313 if (aRef1.IsNull() || aRef2.IsNull() ||
314 aRef3.IsNull() || aRef4.IsNull() ||
315 aRef5.IsNull() || aRef6.IsNull()) return NULL;
317 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
318 aShapesSeq->Append(aRef1);
319 aShapesSeq->Append(aRef2);
320 aShapesSeq->Append(aRef3);
321 aShapesSeq->Append(aRef4);
322 aShapesSeq->Append(aRef5);
323 aShapesSeq->Append(aRef6);
325 aPI.SetShapes(aShapesSeq);
327 //Compute the Block value
329 if (!GetSolver()->ComputeFunction(aFunction)) {
330 SetErrorCode("Block driver failed to compute a block");
334 catch (Standard_Failure) {
335 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
336 SetErrorCode(aFail->GetMessageString());
340 //Make a Python command
341 TCollection_AsciiString anEntry, aDescr;
342 TDF_Tool::Entry(aBlock->GetEntry(), anEntry);
343 aDescr += (anEntry+" = IBlocksOperations.MakeHexaSolidSixFaces(");
344 TDF_Tool::Entry(theFace1->GetEntry(), anEntry);
345 aDescr += (anEntry+", ");
346 TDF_Tool::Entry(theFace2->GetEntry(), anEntry);
347 aDescr += (anEntry+", ");
348 TDF_Tool::Entry(theFace3->GetEntry(), anEntry);
349 aDescr += (anEntry+", ");
350 TDF_Tool::Entry(theFace4->GetEntry(), anEntry);
351 aDescr += (anEntry+", ");
352 TDF_Tool::Entry(theFace5->GetEntry(), anEntry);
353 aDescr += (anEntry+", ");
354 TDF_Tool::Entry(theFace6->GetEntry(), anEntry);
355 aDescr += (anEntry+")");
357 aFunction->SetDescription(aDescr);
363 //=============================================================================
365 * MakeHexaSolidTwoFaces
367 //=============================================================================
368 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeHexaSolidTwoFaces
369 (Handle(GEOM_Object) theFace1, Handle(GEOM_Object) theFace2)
373 if (theFace1.IsNull() || theFace2.IsNull()) return NULL;
375 //Add a new Solid object
376 Handle(GEOM_Object) aBlock = GetEngine()->AddObject(GetDocID(), GEOM_BLOCK);
378 //Add a new Block function
379 Handle(GEOM_Function) aFunction =
380 aBlock->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_TWO_FACES);
382 //Check if the function is set correctly
383 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
385 GEOMImpl_IBlocks aPI (aFunction);
387 Handle(GEOM_Function) aRef1 = theFace1->GetLastFunction();
388 Handle(GEOM_Function) aRef2 = theFace2->GetLastFunction();
389 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
391 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
392 aShapesSeq->Append(aRef1);
393 aShapesSeq->Append(aRef2);
395 aPI.SetShapes(aShapesSeq);
397 //Compute the Block value
399 if (!GetSolver()->ComputeFunction(aFunction)) {
400 SetErrorCode("Block driver failed to compute a block");
404 catch (Standard_Failure) {
405 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
406 SetErrorCode(aFail->GetMessageString());
410 //Make a Python command
411 TCollection_AsciiString anEntry, aDescr;
412 TDF_Tool::Entry(aBlock->GetEntry(), anEntry);
413 aDescr += (anEntry+" = IBlocksOperations.MakeHexaSolidTwoFaces(");
414 TDF_Tool::Entry(theFace1->GetEntry(), anEntry);
415 aDescr += (anEntry+", ");
416 TDF_Tool::Entry(theFace2->GetEntry(), anEntry);
417 aDescr += (anEntry+")");
419 aFunction->SetDescription(aDescr);
425 //=============================================================================
429 //=============================================================================
430 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetEdge
431 (Handle(GEOM_Object) theShape,
432 Handle(GEOM_Object) thePoint1,
433 Handle(GEOM_Object) thePoint2)
438 Handle(GEOM_Object) aResult;
441 if (theShape.IsNull() || thePoint1.IsNull() || thePoint2.IsNull()) return NULL;
443 TopoDS_Shape aBlockOrComp = theShape->GetValue();
444 if (aBlockOrComp.IsNull()) {
445 SetErrorCode("Block or compound is null");
448 if (aBlockOrComp.ShapeType() != TopAbs_SOLID &&
449 aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
450 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
451 SetErrorCode("Shape is neither a block, nor a compound of blocks");
455 TopoDS_Shape anArg1 = thePoint1->GetValue();
456 TopoDS_Shape anArg2 = thePoint2->GetValue();
457 if (anArg1.IsNull() || anArg2.IsNull()) {
458 SetErrorCode("Null shape is given as argument");
461 if (anArg1.ShapeType() != TopAbs_VERTEX ||
462 anArg2.ShapeType() != TopAbs_VERTEX) {
463 SetErrorCode("Element for edge identification is not a vertex");
467 //Compute the Edge value
469 TopTools_IndexedDataMapOfShapeListOfShape MVE;
470 GEOMImpl_Block6Explorer::MapShapesAndAncestors
471 (aBlockOrComp, TopAbs_VERTEX, TopAbs_EDGE, MVE);
474 Standard_Integer ish, ext = MVE.Extent();
476 if (MVE.Contains(anArg1)) {
479 for (ish = 1; ish <= ext; ish++) {
480 TopoDS_Shape aShi = MVE.FindKey(ish);
481 if (BRepTools::Compare(TopoDS::Vertex(anArg1), TopoDS::Vertex(aShi))) {
488 if (MVE.Contains(anArg2)) {
491 for (ish = 1; ish <= ext; ish++) {
492 TopoDS_Shape aShi = MVE.FindKey(ish);
493 if (BRepTools::Compare(TopoDS::Vertex(anArg2), TopoDS::Vertex(aShi))) {
500 if (V1.IsNull() || V2.IsNull()) {
501 SetErrorCode("The given vertex does not belong to the shape");
505 const TopTools_ListOfShape& anEdgesOfV1 = MVE.FindFromKey(V1);
506 const TopTools_ListOfShape& anEdgesOfV2 = MVE.FindFromKey(V2);
508 Standard_Integer isFound = 0;
509 TopTools_ListIteratorOfListOfShape anIterE1 (anEdgesOfV1);
510 TopTools_MapOfShape mapShape1;
512 for (; anIterE1.More(); anIterE1.Next()) {
514 if (mapShape1.Add(anIterE1.Value())) {
515 TopTools_ListIteratorOfListOfShape anIterE2 (anEdgesOfV2);
516 TopTools_MapOfShape mapShape2;
517 for (; anIterE2.More(); anIterE2.Next()) {
519 if (mapShape2.Add(anIterE2.Value())) {
520 if (anIterE1.Value().IsSame(anIterE2.Value())) {
523 // Store the edge, defined by two vertices
524 anEdge = anIterE1.Value();
531 SetErrorCode("The given vertices do not belong to one edge of the given shape");
533 } else if (isFound > 1) {
534 SetErrorCode("Multiple edges found by the given vertices of the shape");
537 TopTools_IndexedMapOfShape anIndices;
538 TopExp::MapShapes(aBlockOrComp, anIndices);
539 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
540 anArray->SetValue(1, anIndices.FindIndex(anEdge));
541 aResult = GetEngine()->AddSubShape(theShape, anArray);
543 } catch (Standard_Failure) {
544 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
545 SetErrorCode(aFail->GetMessageString());
549 //The GetEdge() doesn't change object so no new function is required.
550 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
552 //Make a Python command
553 TCollection_AsciiString anEntry, aDescr;
554 TDF_Tool::Entry(aResult->GetEntry(), anEntry);
555 aDescr += (anEntry+" = IBlocksOperations.GetEdge(");
556 TDF_Tool::Entry(theShape->GetEntry(), anEntry);
557 aDescr += (anEntry+", ");
558 TDF_Tool::Entry(thePoint1->GetEntry(), anEntry);
559 aDescr += (anEntry+", ");
560 TDF_Tool::Entry(thePoint2->GetEntry(), anEntry);
561 aDescr += (anEntry+")");
563 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n";
565 aFunction->SetDescription(aNewDescr);
571 //=============================================================================
575 //=============================================================================
576 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByPoints
577 (Handle(GEOM_Object) theShape,
578 Handle(GEOM_Object) thePoint1,
579 Handle(GEOM_Object) thePoint2,
580 Handle(GEOM_Object) thePoint3,
581 Handle(GEOM_Object) thePoint4)
586 Handle(GEOM_Object) aResult;
589 if (theShape.IsNull() ||
590 thePoint1.IsNull() || thePoint2.IsNull() ||
591 thePoint3.IsNull() || thePoint4.IsNull()) return NULL;
593 TopoDS_Shape aBlockOrComp = theShape->GetValue();
594 if (aBlockOrComp.IsNull()) {
595 SetErrorCode("Block or compound is null");
598 if (aBlockOrComp.ShapeType() != TopAbs_SOLID &&
599 aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
600 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
601 SetErrorCode("Shape is neither a block, nor a compound of blocks");
605 TopoDS_Shape anArg1 = thePoint1->GetValue();
606 TopoDS_Shape anArg2 = thePoint2->GetValue();
607 TopoDS_Shape anArg3 = thePoint3->GetValue();
608 TopoDS_Shape anArg4 = thePoint4->GetValue();
609 if (anArg1.IsNull() || anArg2.IsNull() ||
610 anArg3.IsNull() || anArg4.IsNull()) {
611 SetErrorCode("Null shape is given as argument");
614 if (anArg1.ShapeType() != TopAbs_VERTEX ||
615 anArg2.ShapeType() != TopAbs_VERTEX ||
616 anArg3.ShapeType() != TopAbs_VERTEX ||
617 anArg4.ShapeType() != TopAbs_VERTEX) {
618 SetErrorCode("Element for face identification is not a vertex");
622 //Compute the Face value
626 TopTools_IndexedDataMapOfShapeListOfShape MVF;
627 GEOMImpl_Block6Explorer::MapShapesAndAncestors(aBlockOrComp, TopAbs_VERTEX, TopAbs_FACE, MVF);
629 TopoDS_Shape V1,V2,V3,V4;
630 Standard_Integer ish, ext = MVF.Extent();
632 if (MVF.Contains(anArg1)) {
635 for (ish = 1; ish <= ext; ish++) {
636 TopoDS_Shape aShi = MVF.FindKey(ish);
637 if (BRepTools::Compare(TopoDS::Vertex(anArg1), TopoDS::Vertex(aShi))) {
644 if (MVF.Contains(anArg2)) {
647 for (ish = 1; ish <= ext; ish++) {
648 TopoDS_Shape aShi = MVF.FindKey(ish);
649 if (BRepTools::Compare(TopoDS::Vertex(anArg2), TopoDS::Vertex(aShi))) {
656 if (MVF.Contains(anArg3)) {
659 for (ish = 1; ish <= ext; ish++) {
660 TopoDS_Shape aShi = MVF.FindKey(ish);
661 if (BRepTools::Compare(TopoDS::Vertex(anArg3), TopoDS::Vertex(aShi))) {
668 if (MVF.Contains(anArg4)) {
671 for (ish = 1; ish <= ext; ish++) {
672 TopoDS_Shape aShi = MVF.FindKey(ish);
673 if (BRepTools::Compare(TopoDS::Vertex(anArg4), TopoDS::Vertex(aShi))) {
680 if (V1.IsNull() || V2.IsNull() || V3.IsNull() || V4.IsNull()) {
681 SetErrorCode("The given vertex does not belong to the shape");
685 const TopTools_ListOfShape& aFacesOfV1 = MVF.FindFromKey(V1);
686 const TopTools_ListOfShape& aFacesOfV2 = MVF.FindFromKey(V2);
687 const TopTools_ListOfShape& aFacesOfV3 = MVF.FindFromKey(V3);
688 const TopTools_ListOfShape& aFacesOfV4 = MVF.FindFromKey(V4);
690 Standard_Integer isFound = 0;
691 TopTools_ListIteratorOfListOfShape anIterF1 (aFacesOfV1);
692 for (; anIterF1.More(); anIterF1.Next()) {
694 TopoDS_Shape aFace = anIterF1.Value();
695 TopTools_ListIteratorOfListOfShape anIterF2 (aFacesOfV2);
696 for (; anIterF2.More(); anIterF2.Next()) {
698 if (aFace.IsSame(anIterF2.Value())) {
699 TopTools_ListIteratorOfListOfShape anIterF3 (aFacesOfV3);
700 for (; anIterF3.More(); anIterF3.Next()) {
702 if (aFace.IsSame(anIterF3.Value())) {
703 TopTools_ListIteratorOfListOfShape anIterF4 (aFacesOfV4);
704 for (; anIterF4.More(); anIterF4.Next()) {
706 if (aFace.IsSame(anIterF4.Value())) {
709 // Store the face, defined by four vertices
719 SetErrorCode("The given vertices do not belong to one face of the given shape");
721 } else if (isFound > 1) {
722 SetErrorCode("The given vertices belong to several faces of the given shape");
725 TopTools_IndexedMapOfShape anIndices;
726 TopExp::MapShapes(aBlockOrComp, anIndices);
727 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
728 anArray->SetValue(1, anIndices.FindIndex(aShape));
729 aResult = GetEngine()->AddSubShape(theShape, anArray);
732 catch (Standard_Failure) {
733 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
734 SetErrorCode(aFail->GetMessageString());
738 //The GetFaceByPoints() doesn't change object so no new function is required.
739 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
741 //Make a Python command
742 TCollection_AsciiString anEntry, aDescr;
743 TDF_Tool::Entry(aResult->GetEntry(), anEntry);
744 aDescr += (anEntry+" = IBlocksOperations.GetFaceByPoints(");
745 TDF_Tool::Entry(theShape->GetEntry(), anEntry);
746 aDescr += (anEntry+", ");
747 TDF_Tool::Entry(thePoint1->GetEntry(), anEntry);
748 aDescr += (anEntry+", ");
749 TDF_Tool::Entry(thePoint2->GetEntry(), anEntry);
750 aDescr += (anEntry+", ");
751 TDF_Tool::Entry(thePoint3->GetEntry(), anEntry);
752 aDescr += (anEntry+", ");
753 TDF_Tool::Entry(thePoint4->GetEntry(), anEntry);
754 aDescr += (anEntry+")");
756 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n";
758 aFunction->SetDescription(aNewDescr);
764 //=============================================================================
768 //=============================================================================
769 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByEdges
770 (Handle(GEOM_Object) theShape,
771 Handle(GEOM_Object) theEdge1,
772 Handle(GEOM_Object) theEdge2)
777 Handle(GEOM_Object) aResult;
780 if (theShape.IsNull() || theEdge1.IsNull() || theEdge2.IsNull()) return NULL;
782 TopoDS_Shape aBlockOrComp = theShape->GetValue();
783 if (aBlockOrComp.IsNull()) {
784 SetErrorCode("Block or compound is null");
787 if (aBlockOrComp.ShapeType() != TopAbs_SOLID &&
788 aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
789 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
790 SetErrorCode("Shape is neither a block, nor a compound of blocks");
794 TopoDS_Shape anArg1 = theEdge1->GetValue();
795 TopoDS_Shape anArg2 = theEdge2->GetValue();
796 if (anArg1.IsNull() || anArg2.IsNull()) {
797 SetErrorCode("Null shape is given as argument");
800 if (anArg1.ShapeType() != TopAbs_EDGE ||
801 anArg2.ShapeType() != TopAbs_EDGE) {
802 SetErrorCode("Element for face identification is not an edge");
806 //Compute the Face value
810 TopTools_IndexedDataMapOfShapeListOfShape MEF;
811 GEOMImpl_Block6Explorer::MapShapesAndAncestors(aBlockOrComp, TopAbs_EDGE, TopAbs_FACE, MEF);
814 Standard_Integer ish, ext = MEF.Extent();
816 if (MEF.Contains(anArg1)) {
819 for (ish = 1; ish <= ext; ish++) {
820 TopoDS_Shape aShi = MEF.FindKey(ish);
821 if (GEOMImpl_Block6Explorer::IsSimilarEdges(anArg1, aShi)) {
827 if (MEF.Contains(anArg2)) {
830 for (ish = 1; ish <= ext; ish++) {
831 TopoDS_Shape aShi = MEF.FindKey(ish);
832 if (GEOMImpl_Block6Explorer::IsSimilarEdges(anArg2, aShi)) {
838 if (E1.IsNull() || E2.IsNull()) {
839 SetErrorCode("The given edge does not belong to the shape");
843 const TopTools_ListOfShape& aFacesOfE1 = MEF.FindFromKey(E1);
844 const TopTools_ListOfShape& aFacesOfE2 = MEF.FindFromKey(E2);
846 Standard_Integer isFound = 0;
847 TopTools_ListIteratorOfListOfShape anIterF1 (aFacesOfE1);
848 for (; anIterF1.More(); anIterF1.Next()) {
850 TopTools_ListIteratorOfListOfShape anIterF2 (aFacesOfE2);
851 for (; anIterF2.More(); anIterF2.Next()) {
853 if (anIterF1.Value().IsSame(anIterF2.Value())) {
856 // Store the face, defined by two edges
857 aShape = anIterF1.Value();
862 SetErrorCode("The given edges do not belong to one face of the given shape");
864 } else if (isFound > 1) {
865 SetErrorCode("The given edges belong to several faces of the given shape");
868 TopTools_IndexedMapOfShape anIndices;
869 TopExp::MapShapes(aBlockOrComp, anIndices);
870 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
871 anArray->SetValue(1, anIndices.FindIndex(aShape));
872 aResult = GetEngine()->AddSubShape(theShape, anArray);
875 catch (Standard_Failure) {
876 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
877 SetErrorCode(aFail->GetMessageString());
881 //The GetFaceByEdges() doesn't change object so no new function is required.
882 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
884 //Make a Python command
885 TCollection_AsciiString anEntry, aDescr;
886 TDF_Tool::Entry(aResult->GetEntry(), anEntry);
887 aDescr += (anEntry+" = IBlocksOperations.GetFaceByEdges(");
888 TDF_Tool::Entry(theShape->GetEntry(), anEntry);
889 aDescr += (anEntry+", ");
890 TDF_Tool::Entry(theEdge1->GetEntry(), anEntry);
891 aDescr += (anEntry+", ");
892 TDF_Tool::Entry(theEdge2->GetEntry(), anEntry);
893 aDescr += (anEntry+")");
895 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n";
897 aFunction->SetDescription(aNewDescr);
903 //=============================================================================
907 //=============================================================================
908 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetOppositeFace
909 (Handle(GEOM_Object) theShape,
910 Handle(GEOM_Object) theFace)
915 Handle(GEOM_Object) aResult;
918 if (theShape.IsNull() || theFace.IsNull()) return NULL;
920 TopoDS_Shape aBlockOrComp = theShape->GetValue();
921 if (aBlockOrComp.IsNull()) {
922 SetErrorCode("Block is null");
925 if (aBlockOrComp.ShapeType() != TopAbs_SOLID) {
926 SetErrorCode("Shape is not a block");
930 TopoDS_Shape anArg = theFace->GetValue();
931 if (anArg.IsNull()) {
932 SetErrorCode("Null shape is given as argument");
935 if (anArg.ShapeType() != TopAbs_FACE) {
936 SetErrorCode("Element for face identification is not a face");
940 //Compute the Face value
944 GEOMImpl_Block6Explorer aBlockTool;
945 aBlockTool.InitByBlockAndFace(aBlockOrComp, anArg);
946 aShape = aBlockTool.GetFace(2);
948 TopTools_IndexedMapOfShape anIndices;
949 TopExp::MapShapes(aBlockOrComp, anIndices);
950 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
951 anArray->SetValue(1, anIndices.FindIndex(aShape));
952 aResult = GetEngine()->AddSubShape(theShape, anArray);
954 catch (Standard_Failure) {
955 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
956 SetErrorCode(aFail->GetMessageString());
960 //The GetOppositeFace() doesn't change object so no new function is required.
961 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
963 //Make a Python command
964 TCollection_AsciiString anEntry, aDescr;
965 TDF_Tool::Entry(aResult->GetEntry(), anEntry);
966 aDescr += (anEntry+" = IBlocksOperations.GetOppositeFace(");
967 TDF_Tool::Entry(theShape->GetEntry(), anEntry);
968 aDescr += (anEntry+", ");
969 TDF_Tool::Entry(theFace->GetEntry(), anEntry);
970 aDescr += (anEntry+")");
972 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n";
974 aFunction->SetDescription(aNewDescr);
980 //=============================================================================
984 //=============================================================================
985 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceNearPoint
986 (Handle(GEOM_Object) theShape,
987 Handle(GEOM_Object) thePoint)
992 Handle(GEOM_Object) aResult;
995 if (theShape.IsNull() || thePoint.IsNull()) return NULL;
997 TopoDS_Shape aBlockOrComp = theShape->GetValue();
998 if (aBlockOrComp.IsNull()) {
999 SetErrorCode("Block or compound is null");
1002 if (aBlockOrComp.ShapeType() != TopAbs_SOLID &&
1003 aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
1004 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
1005 SetErrorCode("Shape is neither a block, nor a compound of blocks");
1009 TopoDS_Shape anArg = thePoint->GetValue();
1010 if (anArg.IsNull()) {
1011 SetErrorCode("Null shape is given as argument");
1014 if (anArg.ShapeType() != TopAbs_VERTEX) {
1015 SetErrorCode("Element for face identification is not a vertex");
1019 //Compute the Face value
1021 TopoDS_Shape aShape;
1023 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
1024 gp_Pnt aPnt = BRep_Tool::Pnt(aVert);
1026 // 1. Explode blocks on faces
1027 TopTools_MapOfShape mapShape;
1028 Standard_Integer nbFaces = 0;
1029 TopExp_Explorer exp (aBlockOrComp, TopAbs_FACE);
1030 for (; exp.More(); exp.Next()) {
1031 if (mapShape.Add(exp.Current())) {
1037 Standard_Integer ind = 1;
1038 TopTools_Array1OfShape aFaces (1, nbFaces);
1039 TColStd_Array1OfInteger aDistances (1, nbFaces);
1040 for (exp.Init(aBlockOrComp, TopAbs_FACE); exp.More(); exp.Next()) {
1041 if (mapShape.Add(exp.Current())) {
1042 TopoDS_Shape aFace = exp.Current();
1043 aFaces(ind) = aFace;
1045 // 2. Classify the point relatively each face
1046 BRepClass_FaceClassifier FC (TopoDS::Face(aFace), aPnt, Precision::Confusion());
1047 if (FC.State() == TopAbs_IN) {
1048 aDistances(ind) = -1;
1049 } else if (FC.State() == TopAbs_ON) {
1050 aDistances(ind) = 0;
1052 aDistances(ind) = 1;
1058 // 3. Define face, containing the point or having minimum distance to it
1059 Standard_Integer nearest = 2, nbFound = 0;
1060 for (ind = 1; ind <= nbFaces; ind++) {
1061 if (aDistances(ind) < nearest) {
1062 nearest = aDistances(ind);
1063 aShape = aFaces(ind);
1065 } else if (aDistances(ind) == nearest) {
1072 // The point is on boundary of some faces and there are
1073 // no faces, having the point inside
1074 SetErrorCode("Multiple faces near the given point are found");
1077 } else if (nearest == 1) {
1078 // The point is outside some faces and there are
1079 // no faces, having the point inside or on boundary.
1080 // We will get a nearest face
1081 Standard_Real minDist = RealLast();
1082 for (ind = 1; ind <= nbFaces; ind++) {
1083 if (aDistances(ind) == 1) {
1084 BRepExtrema_DistShapeShape aDistTool (aVert, aFaces(ind));
1085 if (!aDistTool.IsDone()) {
1086 SetErrorCode("Can not find a distance from the given point to one of faces");
1089 Standard_Real aDist = aDistTool.Value();
1090 if (aDist < minDist) {
1092 aShape = aFaces(ind);
1096 } else { // nearest == -1
1097 // The point is inside some faces.
1098 // We will get a face with nearest center
1099 Standard_Real minDist = RealLast();
1100 for (ind = 1; ind <= nbFaces; ind++) {
1101 if (aDistances(ind) == -1) {
1102 GProp_GProps aSystem;
1103 BRepGProp::SurfaceProperties(aFaces(ind), aSystem);
1104 gp_Pnt aCenterMass = aSystem.CentreOfMass();
1106 Standard_Real aDist = aCenterMass.Distance(aPnt);
1107 if (aDist < minDist) {
1109 aShape = aFaces(ind);
1117 SetErrorCode("There are no faces near the given point");
1120 TopTools_IndexedMapOfShape anIndices;
1121 TopExp::MapShapes(aBlockOrComp, anIndices);
1122 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1123 anArray->SetValue(1, anIndices.FindIndex(aShape));
1124 aResult = GetEngine()->AddSubShape(theShape, anArray);
1127 catch (Standard_Failure) {
1128 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1129 SetErrorCode(aFail->GetMessageString());
1133 //The GetFaceNearPoint() doesn't change object so no new function is required.
1134 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1136 //Make a Python command
1137 TCollection_AsciiString anEntry, aDescr;
1138 TDF_Tool::Entry(aResult->GetEntry(), anEntry);
1139 aDescr += (anEntry+" = IBlocksOperations.GetFaceNearPoint(");
1140 TDF_Tool::Entry(theShape->GetEntry(), anEntry);
1141 aDescr += (anEntry+", ");
1142 TDF_Tool::Entry(thePoint->GetEntry(), anEntry);
1143 aDescr += (anEntry+")");
1145 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n";
1146 aNewDescr += aDescr;
1147 aFunction->SetDescription(aNewDescr);
1153 //=============================================================================
1157 //=============================================================================
1158 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByNormale
1159 (Handle(GEOM_Object) theShape,
1160 Handle(GEOM_Object) theVector)
1165 Handle(GEOM_Object) aResult;
1168 if (theShape.IsNull() || theVector.IsNull()) return NULL;
1170 TopoDS_Shape aBlockOrComp = theShape->GetValue();
1171 if (aBlockOrComp.IsNull()) {
1172 SetErrorCode("Block or compound is null");
1175 if (aBlockOrComp.ShapeType() != TopAbs_SOLID &&
1176 aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
1177 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
1178 SetErrorCode("Shape is neither a block, nor a compound of blocks");
1182 TopoDS_Shape anArg = theVector->GetValue();
1183 if (anArg.IsNull()) {
1184 SetErrorCode("Null shape is given as argument");
1187 if (anArg.ShapeType() != TopAbs_EDGE) {
1188 SetErrorCode("Element for normale identification is not an edge");
1192 //Compute the Face value
1194 TopoDS_Shape aShape;
1196 TopoDS_Edge anEdge = TopoDS::Edge(anArg);
1197 TopoDS_Vertex V1, V2;
1198 TopExp::Vertices(anEdge, V1, V2, Standard_True);
1199 gp_Pnt P1 = BRep_Tool::Pnt(V1);
1200 gp_Pnt P2 = BRep_Tool::Pnt(V2);
1201 gp_Vec aVec (P1, P2);
1202 if (aVec.Magnitude() < Precision::Confusion()) {
1203 SetErrorCode("Vector with null magnitude is given");
1207 Standard_Real minAngle = RealLast();
1208 TopTools_MapOfShape mapShape;
1209 Standard_Integer nbFaces = 0;
1210 TopExp_Explorer exp (aBlockOrComp, TopAbs_FACE);
1211 for (; exp.More(); exp.Next()) {
1212 if (mapShape.Add(exp.Current())) {
1213 TopoDS_Face aFace = TopoDS::Face(exp.Current());
1214 BRepAdaptor_Surface SF (aFace);
1216 Standard_Real u, v, x;
1218 // find a point on the surface to get normal direction in
1219 u = SF.FirstUParameter();
1220 x = SF.LastUParameter();
1221 if (Precision::IsInfinite(u)) {
1222 u = (Precision::IsInfinite(x)) ? 0. : x;
1223 } else if (!Precision::IsInfinite(x)) {
1227 v = SF.FirstVParameter();
1228 x = SF.LastVParameter();
1229 if (Precision::IsInfinite(v)) {
1230 v = (Precision::IsInfinite(x)) ? 0. : x;
1231 } else if (!Precision::IsInfinite(x)) {
1235 // compute the normal direction
1237 SF.D1(u,v,P1,Vec1,Vec2);
1238 gp_Vec V = Vec1.Crossed(Vec2);
1240 if (V.Magnitude() < Precision::Confusion()) {
1241 SetErrorCode("Normal vector of a face has null magnitude");
1245 // consider the face orientation
1246 if (aFace.Orientation() == TopAbs_REVERSED ||
1247 aFace.Orientation() == TopAbs_INTERNAL) {
1251 // compute the angle and compare with the minimal one
1252 Standard_Real anAngle = aVec.Angle(V);
1253 if (anAngle < minAngle) {
1260 if (aShape.IsNull()) {
1261 SetErrorCode("Failed to find a face by the given normale");
1264 TopTools_IndexedMapOfShape anIndices;
1265 TopExp::MapShapes(aBlockOrComp, anIndices);
1266 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1267 anArray->SetValue(1, anIndices.FindIndex(aShape));
1268 aResult = GetEngine()->AddSubShape(theShape, anArray);
1271 catch (Standard_Failure) {
1272 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1273 SetErrorCode(aFail->GetMessageString());
1277 //The GetFaceByNormale() doesn't change object so no new function is required.
1278 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1280 //Make a Python command
1281 TCollection_AsciiString anEntry, aDescr;
1282 TDF_Tool::Entry(aResult->GetEntry(), anEntry);
1283 aDescr += (anEntry+" = IBlocksOperations.GetFaceByNormale(");
1284 TDF_Tool::Entry(theShape->GetEntry(), anEntry);
1285 aDescr += (anEntry+", ");
1286 TDF_Tool::Entry(theVector->GetEntry(), anEntry);
1287 aDescr += (anEntry+")");
1289 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n";
1290 aNewDescr += aDescr;
1291 aFunction->SetDescription(aNewDescr);
1297 //=============================================================================
1299 * IsCompoundOfBlocks
1301 //=============================================================================
1302 Standard_Boolean GEOMImpl_IBlocksOperations::IsCompoundOfBlocks
1303 (Handle(GEOM_Object) theCompound,
1304 const Standard_Integer theMinNbFaces,
1305 const Standard_Integer theMaxNbFaces,
1306 Standard_Integer& theNbBlocks)
1309 Standard_Boolean isCompOfBlocks = Standard_False;
1312 if (theCompound.IsNull()) return isCompOfBlocks;
1313 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
1316 isCompOfBlocks = Standard_True;
1318 TopTools_MapOfShape mapShape;
1319 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
1320 for (; exp.More(); exp.Next()) {
1321 if (mapShape.Add(exp.Current())) {
1322 TopoDS_Shape aSolid = exp.Current();
1324 TopTools_MapOfShape mapFaces;
1325 TopExp_Explorer expF (aSolid, TopAbs_FACE);
1326 Standard_Integer nbFaces = 0;
1327 for (; expF.More(); expF.Next()) {
1328 if (mapFaces.Add(expF.Current())) {
1330 if (nbFaces > theMaxNbFaces) {
1331 isCompOfBlocks = Standard_False;
1336 if (nbFaces < theMinNbFaces || theMaxNbFaces < nbFaces) {
1337 isCompOfBlocks = Standard_False;
1344 catch (Standard_Failure) {
1345 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1346 SetErrorCode(aFail->GetMessageString());
1347 return isCompOfBlocks;
1351 return isCompOfBlocks;
1354 //=============================================================================
1356 * ExplodeCompoundOfBlocks
1358 //=============================================================================
1359 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::ExplodeCompoundOfBlocks
1360 (Handle(GEOM_Object) theCompound,
1361 const Standard_Integer theMinNbFaces,
1362 const Standard_Integer theMaxNbFaces)
1366 if (theCompound.IsNull()) return NULL;
1367 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
1368 if (aBlockOrComp.IsNull()) return NULL;
1370 Handle(TColStd_HSequenceOfTransient) aBlocks = new TColStd_HSequenceOfTransient;
1371 Handle(GEOM_Object) anObj;
1372 Handle(GEOM_Function) aFunction;
1374 TopTools_MapOfShape mapShape;
1375 TCollection_AsciiString anAsciiList = "[", anEntry;
1378 TopTools_IndexedMapOfShape anIndices;
1379 TopExp::MapShapes(aBlockOrComp, anIndices);
1380 Handle(TColStd_HArray1OfInteger) anArray;
1384 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
1385 for (; exp.More(); exp.Next()) {
1386 if (mapShape.Add(exp.Current())) {
1387 TopoDS_Shape aSolid = exp.Current();
1389 TopTools_MapOfShape mapFaces;
1390 TopExp_Explorer expF (aSolid, TopAbs_FACE);
1391 Standard_Integer nbFaces = 0;
1392 for (; expF.More(); expF.Next()) {
1393 if (mapFaces.Add(expF.Current())) {
1398 if (theMinNbFaces <= nbFaces && nbFaces <= theMaxNbFaces) {
1399 anArray = new TColStd_HArray1OfInteger(1,1);
1400 anArray->SetValue(1, anIndices.FindIndex(aSolid));
1401 anObj = GetEngine()->AddSubShape(theCompound, anArray);
1402 aBlocks->Append(anObj);
1404 //Make a Python command
1405 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1406 anAsciiList += anEntry;
1412 catch (Standard_Failure) {
1413 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1414 SetErrorCode(aFail->GetMessageString());
1418 if (aBlocks->IsEmpty()) {
1419 SetErrorCode("There are no specified blocks in the given shape");
1423 anAsciiList.Trunc(anAsciiList.Length() - 1);
1426 //The explode doesn't change object so no new function is required.
1427 aFunction = theCompound->GetLastFunction();
1429 //Make a Python command
1430 TCollection_AsciiString aDescr (anAsciiList);
1431 aDescr += " = IBlocksOperations.ExplodeCompoundOfBlocks(";
1432 TDF_Tool::Entry(theCompound->GetEntry(), anEntry);
1433 aDescr += anEntry + ", ";
1434 aDescr += TCollection_AsciiString(theMinNbFaces) + ", ";
1435 aDescr += TCollection_AsciiString(theMaxNbFaces) + ")";
1437 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n";
1438 aNewDescr += aDescr;
1439 aFunction->SetDescription(aNewDescr);
1445 //=============================================================================
1449 //=============================================================================
1450 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetBlockNearPoint
1451 (Handle(GEOM_Object) theCompound,
1452 Handle(GEOM_Object) thePoint)
1457 Handle(GEOM_Object) aResult;
1460 if (theCompound.IsNull() || thePoint.IsNull()) return NULL;
1462 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
1463 if (aBlockOrComp.IsNull()) {
1464 SetErrorCode("Compound is null");
1467 if (aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
1468 aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
1469 SetErrorCode("Shape is neither a block, nor a compound of blocks");
1473 TopoDS_Shape anArg = thePoint->GetValue();
1474 if (anArg.IsNull()) {
1475 SetErrorCode("Null shape is given as argument");
1478 if (anArg.ShapeType() != TopAbs_VERTEX) {
1479 SetErrorCode("Element for block identification is not a vertex");
1483 //Compute the Block value
1485 TopoDS_Shape aShape;
1486 TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
1487 gp_Pnt aPnt = BRep_Tool::Pnt(aVert);
1489 // 1. Explode compound on blocks
1490 TopTools_MapOfShape mapShape;
1491 Standard_Integer nbSolids = 0;
1492 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
1493 for (; exp.More(); exp.Next()) {
1494 if (mapShape.Add(exp.Current())) {
1500 Standard_Integer ind = 1;
1501 TopTools_Array1OfShape aSolids (1, nbSolids);
1502 TColStd_Array1OfInteger aDistances (1, nbSolids);
1503 for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next()) {
1504 if (mapShape.Add(exp.Current())) {
1505 TopoDS_Shape aSolid = exp.Current();
1506 aSolids(ind) = aSolid;
1508 // 2. Classify the point relatively each block
1509 BRepClass3d_SolidClassifier SC (aSolid, aPnt, Precision::Confusion());
1510 if (SC.State() == TopAbs_IN) {
1511 aDistances(ind) = -1;
1512 } else if (SC.State() == TopAbs_ON) {
1513 aDistances(ind) = 0;
1515 aDistances(ind) = 1;
1521 // 3. Define block, containing the point or having minimum distance to it
1522 Standard_Integer nearest = 2, nbFound = 0;
1523 for (ind = 1; ind <= nbSolids; ind++) {
1524 if (aDistances(ind) < nearest) {
1525 nearest = aDistances(ind);
1526 aShape = aSolids(ind);
1528 } else if (aDistances(ind) == nearest) {
1535 // The point is on boundary of some blocks and there are
1536 // no blocks, having the point inside their volume
1537 SetErrorCode("Multiple blocks near the given point are found");
1540 } else if (nearest == 1) {
1541 // The point is outside some blocks and there are
1542 // no blocks, having the point inside or on boundary.
1543 // We will get a nearest block
1544 Standard_Real minDist = RealLast();
1545 for (ind = 1; ind <= nbSolids; ind++) {
1546 if (aDistances(ind) == 1) {
1547 BRepExtrema_DistShapeShape aDistTool (aVert, aSolids(ind));
1548 if (!aDistTool.IsDone()) {
1549 SetErrorCode("Can not find a distance from the given point to one of blocks");
1552 Standard_Real aDist = aDistTool.Value();
1553 if (aDist < minDist) {
1555 aShape = aSolids(ind);
1559 } else { // nearest == -1
1560 // The point is inside some blocks.
1561 // We will get a block with nearest center
1562 Standard_Real minDist = RealLast();
1563 for (ind = 1; ind <= nbSolids; ind++) {
1564 if (aDistances(ind) == -1) {
1565 GProp_GProps aSystem;
1566 BRepGProp::VolumeProperties(aSolids(ind), aSystem);
1567 gp_Pnt aCenterMass = aSystem.CentreOfMass();
1569 Standard_Real aDist = aCenterMass.Distance(aPnt);
1570 if (aDist < minDist) {
1572 aShape = aSolids(ind);
1580 SetErrorCode("There are no blocks near the given point");
1583 TopTools_IndexedMapOfShape anIndices;
1584 TopExp::MapShapes(aBlockOrComp, anIndices);
1585 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1586 anArray->SetValue(1, anIndices.FindIndex(aShape));
1587 aResult = GetEngine()->AddSubShape(theCompound, anArray);
1590 catch (Standard_Failure) {
1591 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1592 SetErrorCode(aFail->GetMessageString());
1596 //The GetBlockNearPoint() doesn't change object so no new function is required.
1597 Handle(GEOM_Function) aFunction = theCompound->GetLastFunction();
1599 //Make a Python command
1600 TCollection_AsciiString anEntry, aDescr;
1601 TDF_Tool::Entry(aResult->GetEntry(), anEntry);
1602 aDescr += (anEntry+" = IBlocksOperations.GetBlockNearPoint(");
1603 TDF_Tool::Entry(theCompound->GetEntry(), anEntry);
1604 aDescr += (anEntry+", ");
1605 TDF_Tool::Entry(thePoint->GetEntry(), anEntry);
1606 aDescr += (anEntry+")");
1608 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n";
1609 aNewDescr += aDescr;
1610 aFunction->SetDescription(aNewDescr);
1616 //=============================================================================
1620 //=============================================================================
1621 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetBlockByParts
1622 (Handle(GEOM_Object) theCompound,
1623 const Handle(TColStd_HSequenceOfTransient)& theParts)
1627 Handle(GEOM_Object) aResult;
1629 if (theCompound.IsNull() || theParts.IsNull()) return NULL;
1630 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
1631 if (aBlockOrComp.IsNull()) return NULL;
1634 Standard_Integer argi, aLen = theParts->Length();
1635 TopTools_Array1OfShape anArgs (1, aLen);
1636 TCollection_AsciiString anEntry, aPartsDescr;
1637 for (argi = 1; argi <= aLen; argi++) {
1638 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theParts->Value(argi));
1639 Handle(GEOM_Function) aRef = anObj->GetLastFunction();
1640 if (aRef.IsNull()) return NULL;
1642 TopoDS_Shape anArg = aRef->GetValue();
1643 if (anArg.IsNull()) {
1644 SetErrorCode("Null shape is given as argument");
1647 anArgs(argi) = anArg;
1649 // For Python command
1650 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1651 if (argi > 1) aPartsDescr += ", ";
1652 aPartsDescr += anEntry;
1655 //Compute the Block value
1657 // 1. Explode compound on solids
1658 TopTools_MapOfShape mapShape;
1659 Standard_Integer nbSolids = 0;
1660 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
1661 for (; exp.More(); exp.Next()) {
1662 if (mapShape.Add(exp.Current())) {
1668 Standard_Integer ind = 1;
1669 TopTools_Array1OfShape aSolids (1, nbSolids);
1670 TColStd_Array1OfInteger aNbParts (1, nbSolids);
1671 for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next(), ind++) {
1672 if (mapShape.Add(exp.Current())) {
1673 TopoDS_Shape aSolid = exp.Current();
1674 aSolids(ind) = aSolid;
1677 // 2. Define quantity of parts, contained in each solid
1678 TopTools_IndexedMapOfShape aSubShapes;
1679 TopExp::MapShapes(aSolid, aSubShapes);
1680 for (argi = 1; argi <= aLen; argi++) {
1681 if (aSubShapes.Contains(anArgs(argi))) {
1688 // 3. Define solid, containing maximum quantity of parts
1689 Standard_Integer maxNb = 0, nbFound = 0;
1690 TopoDS_Shape aShape;
1691 for (ind = 1; ind <= nbSolids; ind++) {
1692 if (aNbParts(ind) > maxNb) {
1693 maxNb = aNbParts(ind);
1694 aShape = aSolids(ind);
1696 } else if (aNbParts(ind) == maxNb) {
1702 SetErrorCode("Multiple blocks, containing maximum quantity of the given parts, are found");
1704 } else if (nbFound == 0) {
1705 SetErrorCode("There are no blocks, containing the given parts");
1708 TopTools_IndexedMapOfShape anIndices;
1709 TopExp::MapShapes(aBlockOrComp, anIndices);
1710 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1711 anArray->SetValue(1, anIndices.FindIndex(aShape));
1712 aResult = GetEngine()->AddSubShape(theCompound, anArray);
1714 } catch (Standard_Failure) {
1715 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1716 SetErrorCode(aFail->GetMessageString());
1720 //The GetBlockByParts() doesn't change object so no new function is required.
1721 Handle(GEOM_Function) aFunction = theCompound->GetLastFunction();
1723 //Make a Python command
1724 TDF_Tool::Entry(aResult->GetEntry(), anEntry);
1725 TCollection_AsciiString aDescr (anEntry);
1726 aDescr += " = IBlocksOperations.GetBlockByParts(";
1727 TDF_Tool::Entry(theCompound->GetEntry(), anEntry);
1728 aDescr += anEntry + ", [";
1729 aDescr += aPartsDescr + "])";
1731 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n";
1732 aNewDescr += aDescr;
1733 aFunction->SetDescription(aNewDescr);
1739 //=============================================================================
1743 //=============================================================================
1744 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::GetBlocksByParts
1745 (Handle(GEOM_Object) theCompound,
1746 const Handle(TColStd_HSequenceOfTransient)& theParts)
1750 if (theCompound.IsNull() || theParts.IsNull()) return NULL;
1751 TopoDS_Shape aBlockOrComp = theCompound->GetValue();
1752 if (aBlockOrComp.IsNull()) return NULL;
1754 Handle(TColStd_HSequenceOfTransient) aBlocks = new TColStd_HSequenceOfTransient;
1755 Handle(GEOM_Object) anObj;
1756 Handle(GEOM_Function) aFunction;
1759 Standard_Integer argi, aLen = theParts->Length();
1760 TopTools_Array1OfShape anArgs (1, aLen);
1761 TCollection_AsciiString anEntry, aPartsDescr, anAsciiList = "[";
1762 for (argi = 1; argi <= aLen; argi++) {
1763 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theParts->Value(argi));
1764 Handle(GEOM_Function) aRef = anObj->GetLastFunction();
1765 if (aRef.IsNull()) return NULL;
1767 TopoDS_Shape anArg = aRef->GetValue();
1768 if (anArg.IsNull()) {
1769 SetErrorCode("Null shape is given as argument");
1772 anArgs(argi) = anArg;
1774 // For Python command
1775 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1776 if (argi > 1) aPartsDescr += ", ";
1777 aPartsDescr += anEntry;
1782 TopTools_MapOfShape mapShape;
1783 Standard_Integer nbSolids = 0;
1784 TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
1785 for (; exp.More(); exp.Next()) {
1786 if (mapShape.Add(exp.Current())) {
1792 Standard_Integer ind = 1;
1793 TopTools_Array1OfShape aSolids (1, nbSolids);
1794 TColStd_Array1OfInteger aNbParts (1, nbSolids);
1795 for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next(), ind++) {
1796 if (mapShape.Add(exp.Current())) {
1797 TopoDS_Shape aSolid = exp.Current();
1798 aSolids(ind) = aSolid;
1801 // 2. Define quantity of parts, contained in each solid
1802 TopTools_IndexedMapOfShape aSubShapes;
1803 TopExp::MapShapes(aSolid, aSubShapes);
1804 for (argi = 1; argi <= aLen; argi++) {
1805 if (aSubShapes.Contains(anArgs(argi))) {
1812 // 3. Define solid, containing maximum quantity of parts
1813 Standard_Integer maxNb = 0, nbFound = 0;
1814 for (ind = 1; ind <= nbSolids; ind++) {
1815 if (aNbParts(ind) > maxNb) {
1816 maxNb = aNbParts(ind);
1818 } else if (aNbParts(ind) == maxNb) {
1824 SetErrorCode("There are no blocks, containing the given parts");
1829 TopTools_IndexedMapOfShape anIndices;
1830 TopExp::MapShapes(aBlockOrComp, anIndices);
1831 Handle(TColStd_HArray1OfInteger) anArray;
1833 for (ind = 1; ind <= nbSolids; ind++) {
1834 if (aNbParts(ind) == maxNb) {
1835 anArray = new TColStd_HArray1OfInteger(1,1);
1836 anArray->SetValue(1, anIndices.FindIndex(aSolids(ind)));
1837 anObj = GetEngine()->AddSubShape(theCompound, anArray);
1838 aBlocks->Append(anObj);
1840 //Make a Python command
1841 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1842 anAsciiList += anEntry;
1847 catch (Standard_Failure) {
1848 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1849 SetErrorCode(aFail->GetMessageString());
1853 anAsciiList.Trunc(anAsciiList.Length() - 1);
1856 //The GetBlocksByParts() doesn't change object so no new function is required.
1857 aFunction = theCompound->GetLastFunction();
1859 //Make a Python command
1860 TCollection_AsciiString aDescr (anAsciiList);
1861 aDescr += " = IBlocksOperations.GetBlocksByParts(";
1862 TDF_Tool::Entry(theCompound->GetEntry(), anEntry);
1863 aDescr += anEntry + ", [";
1864 aDescr += aPartsDescr + "])";
1866 TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n";
1867 aNewDescr += aDescr;
1868 aFunction->SetDescription(aNewDescr);
1874 //=============================================================================
1876 * MakeMultiTransformation1D
1878 //=============================================================================
1879 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeMultiTransformation1D
1880 (Handle(GEOM_Object) theObject,
1881 const Standard_Integer theDirFace1,
1882 const Standard_Integer theDirFace2,
1883 const Standard_Integer theNbTimes)
1887 if (theObject.IsNull()) return NULL;
1889 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
1890 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be moved
1892 //Add a new Copy object
1893 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
1895 //Add a translate function
1896 Handle(GEOM_Function) aFunction =
1897 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_MULTI_TRANSFORM_1D);
1899 //Check if the function is set correctly
1900 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
1902 GEOMImpl_IBlockTrsf aTI (aFunction);
1903 aTI.SetOriginal(aLastFunction);
1904 aTI.SetFace1U(theDirFace1);
1905 aTI.SetFace2U(theDirFace2);
1906 aTI.SetNbIterU(theNbTimes);
1908 //Compute the transformation
1910 if (!GetSolver()->ComputeFunction(aFunction)) {
1911 SetErrorCode("Block driver failed to make multi-transformation");
1915 catch (Standard_Failure) {
1916 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1917 SetErrorCode(aFail->GetMessageString());
1921 //Make a Python command
1922 TCollection_AsciiString anEntry, aDescr;
1923 TDF_Tool::Entry(aCopy->GetEntry(), anEntry);
1924 aDescr += (anEntry+" = IBlocksOperations.MakeMultiTransformation1D(");
1925 TDF_Tool::Entry(theObject->GetEntry(), anEntry);
1926 aDescr += (anEntry+", ");
1927 aDescr += (TCollection_AsciiString(theDirFace1)+", ");
1928 aDescr += (TCollection_AsciiString(theDirFace2)+", ");
1929 aDescr += (TCollection_AsciiString(theNbTimes)+") ");
1931 aFunction->SetDescription(aDescr);
1937 //=============================================================================
1939 * MakeMultiTransformation2D
1941 //=============================================================================
1942 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeMultiTransformation2D
1943 (Handle(GEOM_Object) theObject,
1944 const Standard_Integer theDirFace1U,
1945 const Standard_Integer theDirFace2U,
1946 const Standard_Integer theNbTimesU,
1947 const Standard_Integer theDirFace1V,
1948 const Standard_Integer theDirFace2V,
1949 const Standard_Integer theNbTimesV)
1953 if (theObject.IsNull()) return NULL;
1955 Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
1956 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be moved
1958 //Add a new Copy object
1959 Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
1961 //Add a translate function
1962 Handle(GEOM_Function) aFunction =
1963 aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_MULTI_TRANSFORM_2D);
1965 //Check if the function is set correctly
1966 if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
1968 GEOMImpl_IBlockTrsf aTI (aFunction);
1969 aTI.SetOriginal(aLastFunction);
1970 aTI.SetFace1U(theDirFace1U);
1971 aTI.SetFace2U(theDirFace2U);
1972 aTI.SetNbIterU(theNbTimesU);
1973 aTI.SetFace1V(theDirFace1V);
1974 aTI.SetFace2V(theDirFace2V);
1975 aTI.SetNbIterV(theNbTimesV);
1977 //Compute the transformation
1979 if (!GetSolver()->ComputeFunction(aFunction)) {
1980 SetErrorCode("Block driver failed to make multi-transformation");
1984 catch (Standard_Failure) {
1985 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1986 SetErrorCode(aFail->GetMessageString());
1990 //Make a Python command
1991 TCollection_AsciiString anEntry, aDescr;
1992 TDF_Tool::Entry(aCopy->GetEntry(), anEntry);
1993 aDescr += (anEntry+" = IBlocksOperations.MakeMultiTransformation2D(");
1994 TDF_Tool::Entry(theObject->GetEntry(), anEntry);
1995 aDescr += (anEntry+", ");
1996 aDescr += (TCollection_AsciiString(theDirFace1U)+", ");
1997 aDescr += (TCollection_AsciiString(theDirFace2U)+", ");
1998 aDescr += (TCollection_AsciiString(theNbTimesU)+", ");
1999 aDescr += (TCollection_AsciiString(theDirFace1V)+", ");
2000 aDescr += (TCollection_AsciiString(theDirFace2V)+", ");
2001 aDescr += (TCollection_AsciiString(theNbTimesV)+") ");
2003 aFunction->SetDescription(aDescr);