1 // Copyright (C) 2005 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License.
9 // This library is distributed in the hope that it will be useful
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 #include <Standard_Stream.hxx>
23 #include <BRepOffsetAPI_MakeFilling.hxx>
25 #include <GEOMImpl_BlockDriver.hxx>
26 #include <GEOMImpl_IBlocks.hxx>
27 #include <GEOMImpl_IBlockTrsf.hxx>
28 #include <GEOMImpl_GlueDriver.hxx>
29 #include <GEOMImpl_Types.hxx>
30 #include <GEOMImpl_ILocalOperations.hxx>
31 #include <GEOMImpl_Block6Explorer.hxx>
32 #include <GEOMImpl_IBlocksOperations.hxx>
34 #include <GEOM_Function.hxx>
36 #include <ShHealOper_Sewing.hxx>
37 //#include <NMTAlgo_Splitter1.hxx>
38 #include <GEOMAlgo_Gluer.hxx>
39 #include <BlockFix_BlockFixAPI.hxx>
41 #include "utilities.h"
43 #include <TNaming_CopyShape.hxx>
45 #include <BRepLib.hxx>
46 #include <BRep_Tool.hxx>
47 #include <BRepTools.hxx>
48 #include <BRepGProp.hxx>
49 #include <BRep_Builder.hxx>
50 #include <BRepTools_Quilt.hxx>
51 #include <BRepTools_WireExplorer.hxx>
52 #include <BRepBuilderAPI_MakeEdge.hxx>
53 #include <BRepBuilderAPI_MakeWire.hxx>
54 #include <BRepBuilderAPI_MakePolygon.hxx>
55 #include <BRepBuilderAPI_Transform.hxx>
56 #include <BRepClass_FaceClassifier.hxx>
57 #include <BRepClass3d_SolidClassifier.hxx>
58 #include <BRepExtrema_ExtPF.hxx>
59 #include <BRepExtrema_DistShapeShape.hxx>
63 #include <TopoDS_Shape.hxx>
64 #include <TopoDS_Edge.hxx>
65 #include <TopoDS_Wire.hxx>
66 #include <TopoDS_Shell.hxx>
67 #include <TopoDS_Solid.hxx>
68 #include <TopoDS_Compound.hxx>
69 #include <TopoDS_Iterator.hxx>
71 #include <TopExp_Explorer.hxx>
72 #include <TopTools_MapOfShape.hxx>
73 #include <TopTools_MapIteratorOfMapOfShape.hxx>
74 #include <TopTools_Array1OfShape.hxx>
75 #include <TopTools_SequenceOfShape.hxx>
76 #include <TopTools_ListOfShape.hxx>
77 #include <TopTools_ListIteratorOfListOfShape.hxx>
78 #include <TopTools_IndexedMapOfShape.hxx>
79 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
81 #include <GProp_GProps.hxx>
86 #include <Precision.hxx>
87 #include <TColgp_Array1OfPnt.hxx>
88 #include <TColStd_Array1OfInteger.hxx>
89 #include <TColStd_IndexedDataMapOfTransientTransient.hxx>
90 #include <StdFail_NotDone.hxx>
91 #include <Standard_NullObject.hxx>
92 #include <Standard_TypeMismatch.hxx>
93 #include <Standard_ConstructionError.hxx>
95 //=======================================================================
98 //=======================================================================
99 const Standard_GUID& GEOMImpl_BlockDriver::GetID()
101 static Standard_GUID aBlockDriver("FF1BBB67-5D14-4df2-980B-3A668264EA16");
106 //=======================================================================
107 //function : GEOMImpl_BlockDriver
109 //=======================================================================
110 GEOMImpl_BlockDriver::GEOMImpl_BlockDriver()
114 //=======================================================================
117 //=======================================================================
118 Standard_Integer GEOMImpl_BlockDriver::Execute(TFunction_Logbook& log) const
120 if (Label().IsNull()) return 0;
121 Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
123 Standard_Integer aType = aFunction->GetType();
128 Standard_Real prec = Precision::Confusion();
130 Standard_Integer aNbSub = 0;
131 if (aType == BLOCK_COMPOUND_GLUE) {
135 } else if (aType == BLOCK_FACE_TWO_EDGES ||
136 aType == BLOCK_TWO_FACES) {
140 } else if (aType == BLOCK_FACE_FOUR_PNT ||
141 aType == BLOCK_FACE_FOUR_EDGES) {
145 } else if (aType == BLOCK_SIX_FACES) {
153 GEOMImpl_IBlocks aCI (aFunction);
154 Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
155 Standard_Integer nbshapes = aShapes->Length();
157 if (nbshapes != aNbSub) {
158 Standard_TypeMismatch::Raise
159 ("Number of elements for object construction does not correspond to the used constructor");
162 TopTools_Array1OfShape anArgs (1, aNbSub);
163 Standard_Integer argi;
164 for (argi = 1; argi <= aNbSub; argi++) {
165 Handle(GEOM_Function) aRef = Handle(GEOM_Function)::DownCast(aShapes->Value(argi));
166 TopoDS_Shape anArg = aRef->GetValue();
167 if (anArg.IsNull()) {
168 Standard_NullObject::Raise("Null shape is given as argument");
170 anArgs(argi) = anArg;
173 if (aType == BLOCK_FACE_FOUR_EDGES) {
175 // Make face from four edges
176 if (anArgs(1).ShapeType() != TopAbs_EDGE || anArgs(2).ShapeType() != TopAbs_EDGE ||
177 anArgs(3).ShapeType() != TopAbs_EDGE || anArgs(4).ShapeType() != TopAbs_EDGE) {
178 Standard_TypeMismatch::Raise("Shape for face construction is not an edge");
181 // count corner vertices
182 TopTools_MapOfShape aVertMap;
183 for (Standard_Integer ii = 1; ii <= 4; ii++) {
184 TopoDS_Edge anEdge = TopoDS::Edge(anArgs(ii));
185 TopoDS_Vertex V1, V2;
186 TopExp::Vertices(anEdge, V1, V2, Standard_True);
187 if (V1.IsNull() || V2.IsNull()) {
188 Standard_NullObject::Raise("Bad edge for face construction: vertex is not defined");
190 if (BRepTools::Compare(V1,V2)) {
191 Standard_ConstructionError::Raise("Edge ends are too close");
193 Standard_Boolean isCoin1 = Standard_False, isCoin2 = Standard_False;
194 TopTools_MapIteratorOfMapOfShape anIter (aVertMap);
195 for (; anIter.More(); anIter.Next()) {
196 TopoDS_Vertex V = TopoDS::Vertex(anIter.Key());
197 if (BRepTools::Compare(V,V1)) isCoin1 = Standard_True;
198 if (BRepTools::Compare(V,V2)) isCoin2 = Standard_True;
200 if (!isCoin1) aVertMap.Add(V1);
201 if (!isCoin2) aVertMap.Add(V2);
203 if (aVertMap.Extent() != 4) {
204 Standard_ConstructionError::Raise("The edges must form a closed wire");
207 TopoDS_Edge anEdge1 = TopoDS::Edge(anArgs(1));
208 TopoDS_Edge anEdge2 = TopoDS::Edge(anArgs(2));
209 TopoDS_Edge anEdge3 = TopoDS::Edge(anArgs(3));
210 TopoDS_Edge anEdge4 = TopoDS::Edge(anArgs(4));
212 // check, if anEdge1 has common/coincident vertex with anEdge2,
213 Standard_Boolean isConnected12 = Standard_False;
214 TopoDS_Vertex V11, V12, V21, V22;
215 TopExp::Vertices(anEdge1, V11, V12, Standard_True);
216 TopExp::Vertices(anEdge2, V21, V22, Standard_True);
217 if (BRepTools::Compare(V11,V21) || BRepTools::Compare(V11,V22) ||
218 BRepTools::Compare(V12,V21) || BRepTools::Compare(V12,V22)) {
219 // the edges have common vertex
220 isConnected12 = Standard_True;
223 // build wire in right order, corresponding to edges connexity
224 BRepBuilderAPI_MakeWire* MW;
226 MW = new BRepBuilderAPI_MakeWire(anEdge1, anEdge2, anEdge3, anEdge4);
228 MW = new BRepBuilderAPI_MakeWire(anEdge1, anEdge3, anEdge2, anEdge4);
231 Standard_ConstructionError::Raise
232 ("Impossible to build a connected wire from the given edges");
234 TopoDS_Wire aWire = *MW;
236 if (!aWire.Closed()) {
237 Standard_ConstructionError::Raise
238 ("Impossible to build a closed wire from the given edges");
241 // try to build face on the wire
242 GEOMImpl_Block6Explorer::MakeFace(aWire, Standard_False, aShape);
243 if (aShape.IsNull()) {
244 Standard_ConstructionError::Raise("Face construction failed");
247 } else if (aType == BLOCK_FACE_TWO_EDGES) {
249 // Make face from two opposite edges
250 if (anArgs(1).ShapeType() != TopAbs_EDGE ||
251 anArgs(2).ShapeType() != TopAbs_EDGE) {
252 Standard_TypeMismatch::Raise("Shape for face construction is not an edge");
255 TopoDS_Edge anEdge1 = TopoDS::Edge(anArgs(1));
256 TopoDS_Edge anEdge2 = TopoDS::Edge(anArgs(2));
258 if (anEdge1.IsSame(anEdge2)) {
259 Standard_ConstructionError::Raise("The edges must be different");
262 // create two edges, linking ends of the given edges
263 TopoDS_Vertex V11, V12, V21, V22;
264 TopExp::Vertices(anEdge1, V11, V12, Standard_True);
265 TopExp::Vertices(anEdge2, V21, V22, Standard_True);
266 if (V11.IsNull() || V12.IsNull() ||
267 V21.IsNull() || V22.IsNull()) {
268 Standard_NullObject::Raise("Bad edge for face construction: vertex is not defined");
270 gp_Pnt P11 = BRep_Tool::Pnt(V11);
271 gp_Pnt P12 = BRep_Tool::Pnt(V12);
272 gp_Pnt P21 = BRep_Tool::Pnt(V21);
273 gp_Pnt P22 = BRep_Tool::Pnt(V22);
275 if (P11.Distance(P21) < prec || P12.Distance(P22) < prec ||
276 P11.Distance(P22) < prec || P12.Distance(P21) < prec) {
277 Standard_ConstructionError::Raise("Given edges have too close ends");
280 Standard_Real per11 = P11.Distance(P21) + P12.Distance(P22);
281 Standard_Real per12 = P11.Distance(P22) + P12.Distance(P21);
286 anEdge3 = BRepBuilderAPI_MakeEdge(V11, V21);
287 anEdge4 = BRepBuilderAPI_MakeEdge(V12, V22);
289 anEdge3 = BRepBuilderAPI_MakeEdge(V11, V22);
290 anEdge4 = BRepBuilderAPI_MakeEdge(V12, V21);
294 BRepBuilderAPI_MakeWire MW (anEdge1, anEdge3, anEdge2, anEdge4);
296 Standard_ConstructionError::Raise("Wire construction failed");
299 // try to build face on the wire
300 GEOMImpl_Block6Explorer::MakeFace(MW, Standard_False, aShape);
301 if (aShape.IsNull()) {
302 Standard_ConstructionError::Raise("Face construction failed");
305 } else if (aType == BLOCK_FACE_FOUR_PNT) {
307 // Make face from four corner vertices
308 if (anArgs(1).ShapeType() != TopAbs_VERTEX ||
309 anArgs(2).ShapeType() != TopAbs_VERTEX ||
310 anArgs(3).ShapeType() != TopAbs_VERTEX ||
311 anArgs(4).ShapeType() != TopAbs_VERTEX) {
312 Standard_TypeMismatch::Raise("Shape for face construction is not a vertex");
315 TopoDS_Vertex V1 = TopoDS::Vertex(anArgs(1));
316 TopoDS_Vertex V2 = TopoDS::Vertex(anArgs(2));
317 TopoDS_Vertex V3 = TopoDS::Vertex(anArgs(3));
318 TopoDS_Vertex V4 = TopoDS::Vertex(anArgs(4));
320 gp_Pnt P1 = BRep_Tool::Pnt(V1);
321 gp_Pnt P2 = BRep_Tool::Pnt(V2);
322 gp_Pnt P3 = BRep_Tool::Pnt(V3);
323 gp_Pnt P4 = BRep_Tool::Pnt(V4);
325 if (P1.Distance(P2) < prec || P1.Distance(P3) < prec ||
326 P1.Distance(P4) < prec || P2.Distance(P3) < prec ||
327 P2.Distance(P4) < prec || P3.Distance(P4) < prec) {
328 Standard_ConstructionError::Raise("Four not coincident points must be given");
331 // calculate perimeters
332 Standard_Real per1234 = P1.Distance(P2) + P2.Distance(P3) +
333 P3.Distance(P4) + P4.Distance(P1);
334 Standard_Real per1243 = P1.Distance(P2) + P2.Distance(P4) +
335 P4.Distance(P3) + P3.Distance(P1);
336 Standard_Real per1324 = P1.Distance(P3) + P3.Distance(P2) +
337 P2.Distance(P4) + P4.Distance(P1);
340 if (per1243 < per1234 && per1243 < per1324) {
341 TopoDS_Vertex Vtmp = V3;
344 } else if (per1324 < per1234 && per1324 < per1243) {
345 TopoDS_Vertex Vtmp = V3;
352 BRepBuilderAPI_MakePolygon aMkPoly (V1, V2, V3, V4, Standard_True);
353 if (!aMkPoly.IsDone()) {
354 Standard_ConstructionError::Raise("Polygon construction failed");
357 // try to build face on the wire
358 GEOMImpl_Block6Explorer::MakeFace(aMkPoly, Standard_False, aShape);
359 if (aShape.IsNull()) {
360 Standard_ConstructionError::Raise("Face construction failed");
363 } else if (aType == BLOCK_SIX_FACES || aType == BLOCK_TWO_FACES) {
365 BRepTools_Quilt Glue;
367 if (aType == BLOCK_SIX_FACES) {
369 // Make block (hexahedral solid) from six faces
370 for (Standard_Integer ind = 1; ind <= nbshapes; ind++) {
371 if (anArgs(ind).ShapeType() != TopAbs_FACE) {
372 Standard_TypeMismatch::Raise("Shape for block construction is not a face");
374 Glue.Add(anArgs(ind));
379 // Make block (hexahedral solid) from two opposite faces
380 if (anArgs(1).ShapeType() != TopAbs_FACE ||
381 anArgs(2).ShapeType() != TopAbs_FACE) {
382 Standard_TypeMismatch::Raise("Shape for block construction is not a face");
385 // Get wires of the given faces
386 TopExp_Explorer wires1 (anArgs(1), TopAbs_WIRE);
387 TopExp_Explorer wires2 (anArgs(2), TopAbs_WIRE);
388 if (!wires1.More() || !wires2.More()) {
389 Standard_ConstructionError::Raise("A face for the block has no wires");
391 TopoDS_Shape aWire1 = wires1.Current();
392 TopoDS_Shape aWire2 = wires2.Current();
395 if (wires1.More() || wires2.More()) {
396 Standard_ConstructionError::Raise("A face for the block has more than one wire");
399 GEOMImpl_Block6Explorer aBlockTool;
400 aBlockTool.InitByTwoFaces(anArgs(1), anArgs(2));
402 // Construct the linking faces and add them in the gluing tool
404 Glue.Add(aBlockTool.GetFace(3, Standard_True));
405 Glue.Add(aBlockTool.GetFace(4, Standard_True));
406 Glue.Add(aBlockTool.GetFace(5, Standard_True));
407 Glue.Add(aBlockTool.GetFace(6, Standard_True));
411 TopExp_Explorer exp (Glue.Shells(), TopAbs_SHELL);
412 Standard_Integer ish = 0;
413 TopTools_MapOfShape mapShape;
414 for (; exp.More(); exp.Next()) {
415 if (mapShape.Add(exp.Current())) {
416 aShape = exp.Current();
422 aShape = Glue.Shells();
423 Standard_Real aTol = prec; // Precision::Confusion()
424 TopExp_Explorer expF (aShape, TopAbs_FACE);
425 TopTools_MapOfShape mapF;
428 for (; expF.More(); expF.Next()) {
429 if (mapF.Add(expF.Current())) {
430 B.Add(Shell, expF.Current());
431 Standard_Real aToler = BRep_Tool::Tolerance(TopoDS::Face(expF.Current()));
436 ShHealOper_Sewing aHealer (Shell, aTol);
437 if (aHealer.Perform())
438 aShape = aHealer.GetResultShape();
440 Standard_ConstructionError::Raise
441 ("Impossible to build a connected shell on the given faces");
444 if (aType == BLOCK_SIX_FACES) {
445 if (!aShape.Closed()) {
446 Standard_ConstructionError::Raise
447 ("Impossible to build a closed shell on the given faces");
454 BRepClass3d_SolidClassifier SC (Sol);
455 SC.PerformInfinitePoint(prec);
456 if (SC.State() == TopAbs_IN) {
458 B.Add(Sol, aShape.Reversed());
461 BRepLib::SameParameter(aShape, 1.E-5, Standard_True);
463 } else if (aType == BLOCK_COMPOUND_GLUE) {
465 // Make blocks compound from a compound
466 if (anArgs(1).ShapeType() != TopAbs_COMPOUND &&
467 anArgs(2).ShapeType() != TopAbs_COMPSOLID) {
468 Standard_TypeMismatch::Raise("Not a compound given");
471 TopoDS_Shape aCompound = anArgs(1);
473 // Glue coincident faces and edges (with Partition algorithm).
474 //NMTAlgo_Splitter1 PS;
475 //PS.AddShape(aCompound);
477 //PS.SetRemoveWebs(Standard_False);
478 // PS.Build(aCompound.ShapeType());
479 //PS.Build(TopAbs_SOLID);
480 //aShape = PS.Shape();
482 GEOMAlgo_Gluer aGluer;
483 aGluer.SetShape(aCompound);
484 aGluer.SetCheckGeometry(Standard_True);
486 aShape = aGluer.Result();
492 } else { // Multi-transformations and compound improving
494 if (aType == BLOCK_REMOVE_EXTRA ||
495 aType == BLOCK_COMPOUND_IMPROVE) {
497 GEOMImpl_IBlockTrsf aCI (aFunction);
498 Handle(GEOM_Function) aRefShape = aCI.GetOriginal();
499 TopoDS_Shape aBlockOrComp = aRefShape->GetValue();
500 if (aBlockOrComp.IsNull()) {
501 Standard_NullObject::Raise("Null Shape given");
504 // 1. Improve solids with seam and/or degenerated edges
505 BlockFix_BlockFixAPI aTool;
506 //aTool.Tolerance() = toler;
507 aTool.SetShape(aBlockOrComp);
510 if (aType == BLOCK_REMOVE_EXTRA) {
512 aShape = aTool.Shape();
513 if (aShape == aBlockOrComp) {
514 MESSAGE("No modifications have been done");
517 } else { // aType == BLOCK_COMPOUND_IMPROVE
519 TopoDS_Shape aFixedExtra = aTool.Shape();
521 // 2. Separate non-blocks
522 TopTools_ListOfShape BLO; // All blocks from the given compound
523 TopTools_ListOfShape NOT; // Not blocks
524 TopTools_ListOfShape EXT; // Hexahedral solids, having degenerated and/or seam edges
525 GEOMImpl_IBlocksOperations::AddBlocksFrom(aFixedExtra, BLO, NOT, EXT);
527 if (NOT.Extent() > 0) {
528 MESSAGE("Some non-blocks have been removed");
531 // 3. Warn about staying extra-edges
532 if (EXT.Extent() > 0) {
533 MESSAGE("Warning: Not all seam or degenerated edges was removed");
536 // ??? Throw away standalone blocks ???
538 // 4. Create compound of all blocks
539 TopoDS_Compound aComp;
541 BB.MakeCompound(aComp);
542 TopTools_ListIteratorOfListOfShape BLOit (BLO);
543 for (; BLOit.More(); BLOit.Next()) {
544 BB.Add(aComp, BLOit.Value());
548 aShape = GEOMImpl_GlueDriver::GlueFaces(aComp, Precision::Confusion(), Standard_False);
551 } else if (aType == BLOCK_MULTI_TRANSFORM_1D ||
552 aType == BLOCK_MULTI_TRANSFORM_2D) {
555 GEOMImpl_IBlockTrsf aCI (aFunction);
556 Handle(GEOM_Function) aRefShape = aCI.GetOriginal();
557 TopoDS_Shape aBlockIni = aRefShape->GetValue();
558 if (aBlockIni.IsNull()) {
559 Standard_NullObject::Raise("Null Block");
562 // Copy block to avoid problems (PAL6706)
563 TColStd_IndexedDataMapOfTransientTransient aMap;
565 TNaming_CopyShape::CopyTool(aBlockIni, aMap, aBlock);
567 // Block tolerance in vertices
568 Standard_Real aTol = prec;
569 TopExp_Explorer expV (aBlock, TopAbs_VERTEX);
570 TopTools_MapOfShape mapShape;
571 for (; expV.More(); expV.Next()) {
572 if (mapShape.Add(expV.Current())) {
573 TopoDS_Vertex aV = TopoDS::Vertex(expV.Current());
574 aTol = Max(BRep_Tool::Tolerance(aV), aTol);
578 if (aType == BLOCK_MULTI_TRANSFORM_1D) {
579 // Retrieve a faces by Ids
580 Standard_Integer aFace1Id = aCI.GetFace1U();
581 Standard_Integer aFace2Id = aCI.GetFace2U();
582 TopoDS_Shape aFace1, aFace2;
583 if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace1Id, aFace1)) {
584 Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
586 if (aFace1.ShapeType() != TopAbs_FACE) {
587 Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
591 if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace2Id, aFace2)) {
592 Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
594 if (aFace2.ShapeType() != TopAbs_FACE) {
595 Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
599 Standard_Integer aNbIter = aCI.GetNbIterU();
601 MultiTransformate1D(aBlock, aFace1, aFace2, aNbIter, aMulti);
603 } else { // aType == BLOCK_MULTI_TRANSFORM_2D
604 // Retrieve a faces by Ids
605 Standard_Integer aFace1UId = aCI.GetFace1U();
606 Standard_Integer aFace2UId = aCI.GetFace2U();
607 Standard_Integer aFace1VId = aCI.GetFace1V();
608 Standard_Integer aFace2VId = aCI.GetFace2V();
610 TopoDS_Shape aFace1U, aFace2U, aFace1V, aFace2V;
611 if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace1UId, aFace1U) ||
612 !GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace1VId, aFace1V)) {
613 Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
616 if (aFace1U.ShapeType() != TopAbs_FACE ||
617 aFace1V.ShapeType() != TopAbs_FACE) {
618 Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
622 if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace2UId, aFace2U)) {
623 Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
626 if (aFace2U.ShapeType() != TopAbs_FACE) {
627 Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
632 if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace2VId, aFace2V)) {
633 Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
636 if (aFace2V.ShapeType() != TopAbs_FACE) {
637 Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
641 Standard_Integer aNbIterU = aCI.GetNbIterU();
642 Standard_Integer aNbIterV = aCI.GetNbIterV();
644 MultiTransformate2D(aBlock,
645 aFace1U, aFace2U, aNbIterU,
646 aFace1V, aFace2V, aNbIterV, aMulti);
649 if (aMulti.IsNull()) {
650 StdFail_NotDone::Raise("Multi-transformation failed");
653 // Glue faces of the multi-block
654 aShape = GEOMImpl_GlueDriver::GlueFaces(aMulti, aTol, Standard_False);
656 } else { // unknown function type
661 if (aShape.IsNull()) return 0;
663 aFunction->SetValue(aShape);
665 log.SetTouched(Label());
670 //=======================================================================
671 //function : MultiTransformate1D
673 //=======================================================================
674 void GEOMImpl_BlockDriver::MultiTransformate1D (const TopoDS_Shape& theBlock,
675 const TopoDS_Shape& theFace1,
676 const TopoDS_Shape& theFace2,
677 const Standard_Integer theNbIter,
678 TopoDS_Shape& theResult) const
680 // Construct Tool, where <theFace1> will be the first face,
681 // and a face, opposite to <theFace1>, will be the second face
682 GEOMImpl_Block6Explorer aBlockTool;
683 aBlockTool.InitByBlockAndFace(theBlock, theFace1);
685 // Find IDs of the faces
686 Standard_Integer dir_face1 = 1, dir_face2 = 2;
687 if (!theFace2.IsNull()) {
688 dir_face2 = aBlockTool.GetFaceID(theFace2);
691 // Find three pairs of points
692 Standard_Integer v11_id = 0, v12_id = 0, v13_id = 0; // vertices of the first face
693 Standard_Integer v21_id = 0, v22_id = 0, v23_id = 0; // vertices of the second face
695 if (dir_face2 == 2) { // <theFace2> is opposite to <theFace1>
697 // We will take vertices with equal local numbers on the faces,
698 // as the Block6Explorer gives equal local numbers
699 // to the linked vertices on the opposite faces,
700 // i.e. v1* is linked with the v2* by an edge:
704 // / | / | dir_face1 - bottom
706 // /________ / | dir_face2 - top
715 v11_id = aBlockTool.GetVertexID(dir_face1, 1);
716 v12_id = aBlockTool.GetVertexID(dir_face1, 2);
717 v13_id = aBlockTool.GetVertexID(dir_face1, 4);
719 v21_id = aBlockTool.GetVertexID(dir_face2, 1);
720 v22_id = aBlockTool.GetVertexID(dir_face2, 2);
721 v23_id = aBlockTool.GetVertexID(dir_face2, 4);
727 // / | / | dir_face1 - bottom
729 // /________ / | dir_face2 - right (for example)
732 // | / | /v12 = v22 (common_vertex2)
736 // v13 v11 = v21 (common_vertex1)
738 Standard_Integer common_edge_id = aBlockTool.FindCommonEdgeID(dir_face1, dir_face2);
739 Standard_Integer common_vertex1 = aBlockTool.GetVertexOnEdgeID(common_edge_id, 1);
740 Standard_Integer common_vertex2 = aBlockTool.GetVertexOnEdgeID(common_edge_id, 2);
742 Standard_Integer not_common_v1 = 0;
743 Standard_Integer vid = 1;
744 Standard_Boolean isFound = Standard_False;
745 while (!isFound && vid <= 4) {
746 not_common_v1 = aBlockTool.GetVertexID(dir_face1, vid);
747 isFound = (not_common_v1 != common_vertex2 &&
748 aBlockTool.FindEdgeID(not_common_v1, common_vertex1) != 0);
752 Standard_Integer not_common_v2 = 0;
754 isFound = Standard_False;
755 while (!isFound && vid <= 4) {
756 not_common_v2 = aBlockTool.GetVertexID(dir_face2, vid);
757 isFound = (not_common_v2 != common_vertex2 &&
758 aBlockTool.FindEdgeID(not_common_v2, common_vertex1) != 0);
762 v11_id = common_vertex1;
763 v12_id = common_vertex2;
764 v13_id = not_common_v1;
766 v21_id = common_vertex1;
767 v22_id = common_vertex2;
768 v23_id = not_common_v2;
771 // Construct a transformation operator
772 TopoDS_Vertex V11 = TopoDS::Vertex(aBlockTool.GetVertex(v11_id));
773 TopoDS_Vertex V12 = TopoDS::Vertex(aBlockTool.GetVertex(v12_id));
774 TopoDS_Vertex V13 = TopoDS::Vertex(aBlockTool.GetVertex(v13_id));
776 TopoDS_Vertex V21 = TopoDS::Vertex(aBlockTool.GetVertex(v21_id));
777 TopoDS_Vertex V22 = TopoDS::Vertex(aBlockTool.GetVertex(v22_id));
778 TopoDS_Vertex V23 = TopoDS::Vertex(aBlockTool.GetVertex(v23_id));
780 // Axes of the first direction face
781 gp_Pnt P1 = BRep_Tool::Pnt(V11);
782 gp_Vec VecN1 (P1, BRep_Tool::Pnt(V12));
783 gp_Vec VecX1 (P1, BRep_Tool::Pnt(V13));
784 gp_Ax3 Ax1 (P1, VecN1, VecX1);
786 // Axes of the second direction face
787 gp_Pnt P2 = BRep_Tool::Pnt(V21);
788 gp_Vec VecN2 (P2, BRep_Tool::Pnt(V22));
789 gp_Vec VecX2 (P2, BRep_Tool::Pnt(V23));
790 gp_Ax3 Ax2 (P2, VecN2, VecX2);
793 aTrsf.SetDisplacement(Ax1, Ax2);
795 // Check, that <theFace2> is similar to <theFace1>.
796 // Actually, we need only to check right position of one
797 // vertex, not involved into the transformation construction.
798 if (!aBlockTool.IsSimilarFaces(dir_face1, dir_face2, aTrsf)) {
799 Standard_ConstructionError::Raise("The direction faces are not similar");
802 // Perform multi-transformation
803 TopoDS_Compound aCompound;
805 B.MakeCompound(aCompound);
807 TopoDS_Shape aPrevShape = theBlock;
808 for (Standard_Integer i = 0; i < theNbIter; i++) {
809 B.Add(aCompound, aPrevShape);
810 BRepBuilderAPI_Transform aTransformation (aPrevShape, aTrsf, Standard_False);
811 aPrevShape = aTransformation.Shape();
813 theResult = aCompound;
816 //=======================================================================
817 //function : MultiTransformate2D
819 //=======================================================================
820 void GEOMImpl_BlockDriver::MultiTransformate2D (const TopoDS_Shape& theBlock,
821 const TopoDS_Shape& theFace1U,
822 const TopoDS_Shape& theFace2U,
823 const Standard_Integer theNbIterU,
824 const TopoDS_Shape& theFace1V,
825 const TopoDS_Shape& theFace2V,
826 const Standard_Integer theNbIterV,
827 TopoDS_Shape& theResult) const
829 // Construct Tool, where <theFace1U> will be the first face,
830 // and a face, opposite to <theFace1U>, will be the second face
831 GEOMImpl_Block6Explorer aBlockTool;
832 aBlockTool.InitByBlockAndFace(theBlock, theFace1U);
834 gp_Trsf aTrsfU, aTrsfV;
836 for (Standard_Integer uv = 1; uv <= 2; uv++) {
838 TopoDS_Shape theFace1 = theFace1U;
839 TopoDS_Shape theFace2 = theFace2U;
842 theFace1 = theFace1V;
843 theFace2 = theFace2V;
846 // Find IDs of the faces
847 Standard_Integer dir_face1 = aBlockTool.GetFaceID(theFace1);
848 Standard_Integer dir_face2 = 0;
849 Standard_Integer opp_face1 = aBlockTool.GetOppositeFaceID(dir_face1);
850 if (theFace2.IsNull()) {
851 dir_face2 = opp_face1;
853 dir_face2 = aBlockTool.GetFaceID(theFace2);
856 // Find three pairs of points
857 Standard_Integer v11_id = 0, v12_id = 0, v13_id = 0; // vertices of the first face
858 Standard_Integer v21_id = 0, v22_id = 0, v23_id = 0; // vertices of the second face
860 if (dir_face2 == opp_face1) { // <theFace2> is opposite to <theFace1>
862 // We will take vertices with equal local numbers on the faces,
863 // as the Block6Explorer gives equal local numbers
864 // to the linked vertices on the opposite faces,
865 // i.e. v1* is linked with the v2* by an edge:
867 v11_id = aBlockTool.GetVertexID(dir_face1, 1);
868 v12_id = aBlockTool.GetVertexID(dir_face1, 2);
869 v13_id = aBlockTool.GetVertexID(dir_face1, 4);
871 v21_id = aBlockTool.GetVertexID(dir_face2, 1);
872 v22_id = aBlockTool.GetVertexID(dir_face2, 2);
873 v23_id = aBlockTool.GetVertexID(dir_face2, 4);
877 Standard_Integer common_edge_id = aBlockTool.FindCommonEdgeID(dir_face1, dir_face2);
878 Standard_Integer common_vertex1 = aBlockTool.GetVertexOnEdgeID(common_edge_id, 1);
879 Standard_Integer common_vertex2 = aBlockTool.GetVertexOnEdgeID(common_edge_id, 2);
881 Standard_Integer not_common_v1 = 0;
882 Standard_Integer vid = 1;
883 Standard_Boolean isFound = Standard_False;
884 while (!isFound && vid <= 4) {
885 not_common_v1 = aBlockTool.GetVertexID(dir_face1, vid);
886 isFound = (not_common_v1 != common_vertex2 &&
887 aBlockTool.FindEdgeID(not_common_v1, common_vertex1) != 0);
891 Standard_Integer not_common_v2 = 0;
893 isFound = Standard_False;
894 while (!isFound && vid <= 4) {
895 not_common_v2 = aBlockTool.GetVertexID(dir_face2, vid);
896 isFound = (not_common_v2 != common_vertex2 &&
897 aBlockTool.FindEdgeID(not_common_v2, common_vertex1) != 0);
901 v11_id = common_vertex1;
902 v12_id = common_vertex2;
903 v13_id = not_common_v1;
905 v21_id = common_vertex1;
906 v22_id = common_vertex2;
907 v23_id = not_common_v2;
910 // Construct a transformation operator
911 TopoDS_Vertex V11 = TopoDS::Vertex(aBlockTool.GetVertex(v11_id));
912 TopoDS_Vertex V12 = TopoDS::Vertex(aBlockTool.GetVertex(v12_id));
913 TopoDS_Vertex V13 = TopoDS::Vertex(aBlockTool.GetVertex(v13_id));
915 TopoDS_Vertex V21 = TopoDS::Vertex(aBlockTool.GetVertex(v21_id));
916 TopoDS_Vertex V22 = TopoDS::Vertex(aBlockTool.GetVertex(v22_id));
917 TopoDS_Vertex V23 = TopoDS::Vertex(aBlockTool.GetVertex(v23_id));
919 // Axes of the first direction face
920 gp_Pnt P1 = BRep_Tool::Pnt(V11);
921 gp_Vec VecN1 (P1, BRep_Tool::Pnt(V12));
922 gp_Vec VecX1 (P1, BRep_Tool::Pnt(V13));
923 gp_Ax3 Ax1 (P1, VecN1, VecX1);
925 // Axes of the second direction face
926 gp_Pnt P2 = BRep_Tool::Pnt(V21);
927 gp_Vec VecN2 (P2, BRep_Tool::Pnt(V22));
928 gp_Vec VecX2 (P2, BRep_Tool::Pnt(V23));
929 gp_Ax3 Ax2 (P2, VecN2, VecX2);
932 aTrsf.SetDisplacement(Ax1, Ax2);
941 // Check, that <theFace2> is similar to <theFace1>.
942 // Actually, we need only to check right position of one
943 // vertex, not involved into the transformation construction.
944 if (!aBlockTool.IsSimilarFaces(dir_face1, dir_face2, aTrsf)) {
945 Standard_ConstructionError::Raise("The direction faces are not similar");
949 // Perform multi-transformation
950 TopoDS_Compound aCompound;
952 B.MakeCompound(aCompound);
954 TopoDS_Shape aPrevShapeU = theBlock;
955 for (int i = 0; i < theNbIterU; i++) {
956 TopoDS_Shape aPrevShapeV = aPrevShapeU;
957 for (int j = 0; j < theNbIterV; j++) {
958 B.Add(aCompound, aPrevShapeV);
959 BRepBuilderAPI_Transform aTransformationV (aPrevShapeV, aTrsfV, Standard_False);
960 aPrevShapeV = aTransformationV.Shape();
962 BRepBuilderAPI_Transform aTransformationU (aPrevShapeU, aTrsfU, Standard_False);
963 aPrevShapeU = aTransformationU.Shape();
964 // Correction of the second transformation according to the first transformation
965 Ax1V.Transform(aTrsfU);
966 Ax2V.Transform(aTrsfU);
967 aTrsfV.SetDisplacement(Ax1V, Ax2V);
970 theResult = aCompound;
973 //=======================================================================
974 //function : GEOMImpl_BlockDriver_Type_
976 //=======================================================================
977 Standard_EXPORT Handle_Standard_Type& GEOMImpl_BlockDriver_Type_()
980 static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver);
981 if ( aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver);
982 static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared);
983 if ( aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared);
984 static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient);
985 if ( aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient);
988 static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL};
989 static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_BlockDriver",
990 sizeof(GEOMImpl_BlockDriver),
992 (Standard_Address)_Ancestors,
993 (Standard_Address)NULL);
998 //=======================================================================
999 //function : DownCast
1001 //=======================================================================
1002 const Handle(GEOMImpl_BlockDriver) Handle(GEOMImpl_BlockDriver)::DownCast(const Handle(Standard_Transient)& AnObject)
1004 Handle(GEOMImpl_BlockDriver) _anOtherObject;
1006 if (!AnObject.IsNull()) {
1007 if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_BlockDriver))) {
1008 _anOtherObject = Handle(GEOMImpl_BlockDriver)((Handle(GEOMImpl_BlockDriver)&)AnObject);
1012 return _anOtherObject ;