4 #include <BRepOffsetAPI_MakeFilling.hxx>
6 #include "GEOMImpl_BlockDriver.hxx"
7 #include "GEOMImpl_IBlocks.hxx"
8 #include "GEOMImpl_IBlockTrsf.hxx"
9 #include "GEOMImpl_GlueDriver.hxx"
10 #include "GEOMImpl_Types.hxx"
11 #include "GEOMImpl_ILocalOperations.hxx"
12 #include "GEOMImpl_Block6Explorer.hxx"
13 #include "GEOMImpl_IBlocksOperations.hxx"
15 #include "GEOM_Function.hxx"
17 #include "ShHealOper_Sewing.hxx"
18 #include "NMTAlgo_Splitter1.hxx"
19 #include "BlockFix_BlockFixAPI.hxx"
21 #include "utilities.h"
23 #include <TNaming_CopyShape.hxx>
25 #include <BRepLib.hxx>
26 #include <BRep_Tool.hxx>
27 #include <BRepTools.hxx>
28 #include <BRepGProp.hxx>
29 #include <BRep_Builder.hxx>
30 #include <BRepTools_Quilt.hxx>
31 #include <BRepTools_WireExplorer.hxx>
32 #include <BRepBuilderAPI_MakeEdge.hxx>
33 #include <BRepBuilderAPI_MakeWire.hxx>
34 #include <BRepBuilderAPI_MakePolygon.hxx>
35 #include <BRepBuilderAPI_Transform.hxx>
36 #include <BRepClass_FaceClassifier.hxx>
37 #include <BRepClass3d_SolidClassifier.hxx>
38 #include <BRepExtrema_ExtPF.hxx>
39 #include <BRepExtrema_DistShapeShape.hxx>
43 #include <TopoDS_Shape.hxx>
44 #include <TopoDS_Edge.hxx>
45 #include <TopoDS_Wire.hxx>
46 #include <TopoDS_Shell.hxx>
47 #include <TopoDS_Solid.hxx>
48 #include <TopoDS_Compound.hxx>
49 #include <TopoDS_Iterator.hxx>
51 #include <TopExp_Explorer.hxx>
52 #include <TopTools_MapOfShape.hxx>
53 #include <TopTools_MapIteratorOfMapOfShape.hxx>
54 #include <TopTools_Array1OfShape.hxx>
55 #include <TopTools_SequenceOfShape.hxx>
56 #include <TopTools_ListOfShape.hxx>
57 #include <TopTools_ListIteratorOfListOfShape.hxx>
58 #include <TopTools_IndexedMapOfShape.hxx>
59 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
61 #include <GProp_GProps.hxx>
66 #include <Precision.hxx>
67 #include <TColgp_Array1OfPnt.hxx>
68 #include <TColStd_Array1OfInteger.hxx>
69 #include <TColStd_IndexedDataMapOfTransientTransient.hxx>
70 #include <StdFail_NotDone.hxx>
71 #include <Standard_NullObject.hxx>
72 #include <Standard_TypeMismatch.hxx>
73 #include <Standard_ConstructionError.hxx>
75 //=======================================================================
78 //=======================================================================
79 const Standard_GUID& GEOMImpl_BlockDriver::GetID()
81 static Standard_GUID aBlockDriver("FF1BBB67-5D14-4df2-980B-3A668264EA16");
86 //=======================================================================
87 //function : GEOMImpl_BlockDriver
89 //=======================================================================
90 GEOMImpl_BlockDriver::GEOMImpl_BlockDriver()
94 //=======================================================================
97 //=======================================================================
98 Standard_Integer GEOMImpl_BlockDriver::Execute(TFunction_Logbook& log) const
100 if (Label().IsNull()) return 0;
101 Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
103 Standard_Integer aType = aFunction->GetType();
108 Standard_Real prec = Precision::Confusion();
110 Standard_Integer aNbSub = 0;
111 if (aType == BLOCK_COMPOUND_GLUE) {
115 } else if (aType == BLOCK_FACE_TWO_EDGES ||
116 aType == BLOCK_TWO_FACES) {
120 } else if (aType == BLOCK_FACE_FOUR_PNT ||
121 aType == BLOCK_FACE_FOUR_EDGES) {
125 } else if (aType == BLOCK_SIX_FACES) {
133 GEOMImpl_IBlocks aCI (aFunction);
134 Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
135 Standard_Integer nbshapes = aShapes->Length();
137 if (nbshapes != aNbSub) {
138 Standard_TypeMismatch::Raise
139 ("Number of elements for object construction does not correspond to the used constructor");
142 TopTools_Array1OfShape anArgs (1, aNbSub);
143 Standard_Integer argi;
144 for (argi = 1; argi <= aNbSub; argi++) {
145 Handle(GEOM_Function) aRef = Handle(GEOM_Function)::DownCast(aShapes->Value(argi));
146 TopoDS_Shape anArg = aRef->GetValue();
147 if (anArg.IsNull()) {
148 Standard_NullObject::Raise("Null shape is given as argument");
150 anArgs(argi) = anArg;
153 if (aType == BLOCK_FACE_FOUR_EDGES) {
155 // Make face from four edges
156 if (anArgs(1).ShapeType() != TopAbs_EDGE || anArgs(2).ShapeType() != TopAbs_EDGE ||
157 anArgs(3).ShapeType() != TopAbs_EDGE || anArgs(4).ShapeType() != TopAbs_EDGE) {
158 Standard_TypeMismatch::Raise("Shape for face construction is not an edge");
161 // count corner vertices
162 TopTools_MapOfShape aVertMap;
163 for (Standard_Integer ii = 1; ii <= 4; ii++) {
164 TopoDS_Edge anEdge = TopoDS::Edge(anArgs(ii));
165 TopoDS_Vertex V1, V2;
166 TopExp::Vertices(anEdge, V1, V2, Standard_True);
167 if (V1.IsNull() || V2.IsNull()) {
168 Standard_NullObject::Raise("Bad edge for face construction: vertex is not defined");
170 if (BRepTools::Compare(V1,V2)) {
171 Standard_ConstructionError::Raise("Edge ends are too close");
173 Standard_Boolean isCoin1 = Standard_False, isCoin2 = Standard_False;
174 TopTools_MapIteratorOfMapOfShape anIter (aVertMap);
175 for (; anIter.More(); anIter.Next()) {
176 TopoDS_Vertex V = TopoDS::Vertex(anIter.Key());
177 if (BRepTools::Compare(V,V1)) isCoin1 = Standard_True;
178 if (BRepTools::Compare(V,V2)) isCoin2 = Standard_True;
180 if (!isCoin1) aVertMap.Add(V1);
181 if (!isCoin2) aVertMap.Add(V2);
183 if (aVertMap.Extent() != 4) {
184 Standard_ConstructionError::Raise("The edges must form a closed wire");
187 TopoDS_Edge anEdge1 = TopoDS::Edge(anArgs(1));
188 TopoDS_Edge anEdge2 = TopoDS::Edge(anArgs(2));
189 TopoDS_Edge anEdge3 = TopoDS::Edge(anArgs(3));
190 TopoDS_Edge anEdge4 = TopoDS::Edge(anArgs(4));
192 // check, if anEdge1 has common/coincident vertex with anEdge2,
193 Standard_Boolean isConnected12 = Standard_False;
194 TopoDS_Vertex V11, V12, V21, V22;
195 TopExp::Vertices(anEdge1, V11, V12, Standard_True);
196 TopExp::Vertices(anEdge2, V21, V22, Standard_True);
197 if (BRepTools::Compare(V11,V21) || BRepTools::Compare(V11,V22) ||
198 BRepTools::Compare(V12,V21) || BRepTools::Compare(V12,V22)) {
199 // the edges have common vertex
200 isConnected12 = Standard_True;
203 // build wire in right order, corresponding to edges connexity
204 BRepBuilderAPI_MakeWire* MW;
206 MW = new BRepBuilderAPI_MakeWire(anEdge1, anEdge2, anEdge3, anEdge4);
208 MW = new BRepBuilderAPI_MakeWire(anEdge1, anEdge3, anEdge2, anEdge4);
211 Standard_ConstructionError::Raise
212 ("Impossible to build a connected wire from the given edges");
214 TopoDS_Wire aWire = *MW;
216 if (!aWire.Closed()) {
217 Standard_ConstructionError::Raise
218 ("Impossible to build a closed wire from the given edges");
221 // try to build face on the wire
222 GEOMImpl_Block6Explorer::MakeFace(aWire, Standard_False, aShape);
223 if (aShape.IsNull()) {
224 Standard_ConstructionError::Raise("Face construction failed");
227 } else if (aType == BLOCK_FACE_TWO_EDGES) {
229 // Make face from two opposite edges
230 if (anArgs(1).ShapeType() != TopAbs_EDGE ||
231 anArgs(2).ShapeType() != TopAbs_EDGE) {
232 Standard_TypeMismatch::Raise("Shape for face construction is not an edge");
235 TopoDS_Edge anEdge1 = TopoDS::Edge(anArgs(1));
236 TopoDS_Edge anEdge2 = TopoDS::Edge(anArgs(2));
238 if (anEdge1.IsSame(anEdge2)) {
239 Standard_ConstructionError::Raise("The edges must be different");
242 // create two edges, linking ends of the given edges
243 TopoDS_Vertex V11, V12, V21, V22;
244 TopExp::Vertices(anEdge1, V11, V12, Standard_True);
245 TopExp::Vertices(anEdge2, V21, V22, Standard_True);
246 if (V11.IsNull() || V12.IsNull() ||
247 V21.IsNull() || V22.IsNull()) {
248 Standard_NullObject::Raise("Bad edge for face construction: vertex is not defined");
250 gp_Pnt P11 = BRep_Tool::Pnt(V11);
251 gp_Pnt P12 = BRep_Tool::Pnt(V12);
252 gp_Pnt P21 = BRep_Tool::Pnt(V21);
253 gp_Pnt P22 = BRep_Tool::Pnt(V22);
255 if (P11.Distance(P21) < prec || P12.Distance(P22) < prec ||
256 P11.Distance(P22) < prec || P12.Distance(P21) < prec) {
257 Standard_ConstructionError::Raise("Given edges have too close ends");
260 Standard_Real per11 = P11.Distance(P21) + P12.Distance(P22);
261 Standard_Real per12 = P11.Distance(P22) + P12.Distance(P21);
266 anEdge3 = BRepBuilderAPI_MakeEdge(V11, V21);
267 anEdge4 = BRepBuilderAPI_MakeEdge(V12, V22);
269 anEdge3 = BRepBuilderAPI_MakeEdge(V11, V22);
270 anEdge4 = BRepBuilderAPI_MakeEdge(V12, V21);
274 BRepBuilderAPI_MakeWire MW (anEdge1, anEdge3, anEdge2, anEdge4);
276 Standard_ConstructionError::Raise("Wire construction failed");
279 // try to build face on the wire
280 GEOMImpl_Block6Explorer::MakeFace(MW, Standard_False, aShape);
281 if (aShape.IsNull()) {
282 Standard_ConstructionError::Raise("Face construction failed");
285 } else if (aType == BLOCK_FACE_FOUR_PNT) {
287 // Make face from four corner vertices
288 if (anArgs(1).ShapeType() != TopAbs_VERTEX ||
289 anArgs(2).ShapeType() != TopAbs_VERTEX ||
290 anArgs(3).ShapeType() != TopAbs_VERTEX ||
291 anArgs(4).ShapeType() != TopAbs_VERTEX) {
292 Standard_TypeMismatch::Raise("Shape for face construction is not a vertex");
295 TopoDS_Vertex V1 = TopoDS::Vertex(anArgs(1));
296 TopoDS_Vertex V2 = TopoDS::Vertex(anArgs(2));
297 TopoDS_Vertex V3 = TopoDS::Vertex(anArgs(3));
298 TopoDS_Vertex V4 = TopoDS::Vertex(anArgs(4));
300 gp_Pnt P1 = BRep_Tool::Pnt(V1);
301 gp_Pnt P2 = BRep_Tool::Pnt(V2);
302 gp_Pnt P3 = BRep_Tool::Pnt(V3);
303 gp_Pnt P4 = BRep_Tool::Pnt(V4);
305 if (P1.Distance(P2) < prec || P1.Distance(P3) < prec ||
306 P1.Distance(P4) < prec || P2.Distance(P3) < prec ||
307 P2.Distance(P4) < prec || P3.Distance(P4) < prec) {
308 Standard_ConstructionError::Raise("Four not coincident points must be given");
311 // calculate perimeters
312 Standard_Real per1234 = P1.Distance(P2) + P2.Distance(P3) +
313 P3.Distance(P4) + P4.Distance(P1);
314 Standard_Real per1243 = P1.Distance(P2) + P2.Distance(P4) +
315 P4.Distance(P3) + P3.Distance(P1);
316 Standard_Real per1324 = P1.Distance(P3) + P3.Distance(P2) +
317 P2.Distance(P4) + P4.Distance(P1);
320 if (per1243 < per1234 && per1243 < per1324) {
321 TopoDS_Vertex Vtmp = V3;
324 } else if (per1324 < per1234 && per1324 < per1243) {
325 TopoDS_Vertex Vtmp = V3;
332 BRepBuilderAPI_MakePolygon aMkPoly (V1, V2, V3, V4, Standard_True);
333 if (!aMkPoly.IsDone()) {
334 Standard_ConstructionError::Raise("Polygon construction failed");
337 // try to build face on the wire
338 GEOMImpl_Block6Explorer::MakeFace(aMkPoly, Standard_False, aShape);
339 if (aShape.IsNull()) {
340 Standard_ConstructionError::Raise("Face construction failed");
343 } else if (aType == BLOCK_SIX_FACES || aType == BLOCK_TWO_FACES) {
345 BRepTools_Quilt Glue;
347 if (aType == BLOCK_SIX_FACES) {
349 // Make block (hexahedral solid) from six faces
350 for (Standard_Integer ind = 1; ind <= nbshapes; ind++) {
351 if (anArgs(ind).ShapeType() != TopAbs_FACE) {
352 Standard_TypeMismatch::Raise("Shape for block construction is not a face");
354 Glue.Add(anArgs(ind));
359 // Make block (hexahedral solid) from two opposite faces
360 if (anArgs(1).ShapeType() != TopAbs_FACE ||
361 anArgs(2).ShapeType() != TopAbs_FACE) {
362 Standard_TypeMismatch::Raise("Shape for block construction is not a face");
365 // Get wires of the given faces
366 TopExp_Explorer wires1 (anArgs(1), TopAbs_WIRE);
367 TopExp_Explorer wires2 (anArgs(2), TopAbs_WIRE);
368 if (!wires1.More() || !wires2.More()) {
369 Standard_ConstructionError::Raise("A face for the block has no wires");
371 TopoDS_Shape aWire1 = wires1.Current();
372 TopoDS_Shape aWire2 = wires2.Current();
375 if (wires1.More() || wires2.More()) {
376 Standard_ConstructionError::Raise("A face for the block has more than one wire");
379 GEOMImpl_Block6Explorer aBlockTool;
380 aBlockTool.InitByTwoFaces(anArgs(1), anArgs(2));
382 // Construct the linking faces and add them in the gluing tool
384 Glue.Add(aBlockTool.GetFace(3, Standard_True));
385 Glue.Add(aBlockTool.GetFace(4, Standard_True));
386 Glue.Add(aBlockTool.GetFace(5, Standard_True));
387 Glue.Add(aBlockTool.GetFace(6, Standard_True));
391 TopExp_Explorer exp (Glue.Shells(), TopAbs_SHELL);
392 Standard_Integer ish = 0;
393 TopTools_MapOfShape mapShape;
394 for (; exp.More(); exp.Next()) {
395 if (mapShape.Add(exp.Current())) {
396 aShape = exp.Current();
402 aShape = Glue.Shells();
403 Standard_Real aTol = prec; // Precision::Confusion()
404 TopExp_Explorer expF (aShape, TopAbs_FACE);
405 TopTools_MapOfShape mapF;
408 for (; expF.More(); expF.Next()) {
409 if (mapF.Add(expF.Current())) {
410 B.Add(Shell, expF.Current());
411 Standard_Real aToler = BRep_Tool::Tolerance(TopoDS::Face(expF.Current()));
416 ShHealOper_Sewing aHealer (Shell, aTol);
417 if (aHealer.Perform())
418 aShape = aHealer.GetResultShape();
420 Standard_ConstructionError::Raise
421 ("Impossible to build a connected shell on the given faces");
424 if (aType == BLOCK_SIX_FACES) {
425 if (!aShape.Closed()) {
426 Standard_ConstructionError::Raise
427 ("Impossible to build a closed shell on the given faces");
434 BRepClass3d_SolidClassifier SC (Sol);
435 SC.PerformInfinitePoint(prec);
436 if (SC.State() == TopAbs_IN) {
438 B.Add(Sol, aShape.Reversed());
441 BRepLib::SameParameter(aShape, 1.E-5, Standard_True);
443 } else if (aType == BLOCK_COMPOUND_GLUE) {
445 // Make blocks compound from a compound
446 if (anArgs(1).ShapeType() != TopAbs_COMPOUND &&
447 anArgs(2).ShapeType() != TopAbs_COMPSOLID) {
448 Standard_TypeMismatch::Raise("Not a compound given");
451 TopoDS_Shape aCompound = anArgs(1);
453 // Glue coincident faces and edges (with Partition algorithm).
454 NMTAlgo_Splitter1 PS;
455 PS.AddShape(aCompound);
457 PS.SetRemoveWebs(Standard_False);
458 // PS.Build(aCompound.ShapeType());
459 PS.Build(TopAbs_SOLID);
465 } else { // Multi-transformations and compound improving
467 if (aType == BLOCK_REMOVE_EXTRA ||
468 aType == BLOCK_COMPOUND_IMPROVE) {
470 GEOMImpl_IBlockTrsf aCI (aFunction);
471 Handle(GEOM_Function) aRefShape = aCI.GetOriginal();
472 TopoDS_Shape aBlockOrComp = aRefShape->GetValue();
473 if (aBlockOrComp.IsNull()) {
474 Standard_NullObject::Raise("Null Shape given");
477 // 1. Improve solids with seam and/or degenerated edges
478 BlockFix_BlockFixAPI aTool;
479 //aTool.Tolerance() = toler;
480 aTool.SetShape(aBlockOrComp);
483 if (aType == BLOCK_REMOVE_EXTRA) {
485 aShape = aTool.Shape();
486 if (aShape == aBlockOrComp) {
487 MESSAGE("No modifications have been done");
490 } else { // aType == BLOCK_COMPOUND_IMPROVE
492 TopoDS_Shape aFixedExtra = aTool.Shape();
494 // 2. Separate non-blocks
495 TopTools_ListOfShape BLO; // All blocks from the given compound
496 TopTools_ListOfShape NOT; // Not blocks
497 TopTools_ListOfShape EXT; // Hexahedral solids, having degenerated and/or seam edges
498 GEOMImpl_IBlocksOperations::AddBlocksFrom(aFixedExtra, BLO, NOT, EXT);
500 if (NOT.Extent() > 0) {
501 MESSAGE("Some non-blocks have been removed");
504 // 3. Warn about staying extra-edges
505 if (EXT.Extent() > 0) {
506 MESSAGE("Warning: Not all seam or degenerated edges was removed");
509 // ??? Throw away standalone blocks ???
511 // 4. Create compound of all blocks
512 TopoDS_Compound aComp;
514 BB.MakeCompound(aComp);
515 TopTools_ListIteratorOfListOfShape BLOit (BLO);
516 for (; BLOit.More(); BLOit.Next()) {
517 BB.Add(aComp, BLOit.Value());
521 aShape = GEOMImpl_GlueDriver::GlueFaces(aComp, Precision::Confusion());
524 } else if (aType == BLOCK_MULTI_TRANSFORM_1D ||
525 aType == BLOCK_MULTI_TRANSFORM_2D) {
528 GEOMImpl_IBlockTrsf aCI (aFunction);
529 Handle(GEOM_Function) aRefShape = aCI.GetOriginal();
530 TopoDS_Shape aBlockIni = aRefShape->GetValue();
531 if (aBlockIni.IsNull()) {
532 Standard_NullObject::Raise("Null Block");
535 // Copy block to avoid problems (PAL6706)
536 TColStd_IndexedDataMapOfTransientTransient aMap;
538 TNaming_CopyShape::CopyTool(aBlockIni, aMap, aBlock);
540 // Block tolerance in vertices
541 Standard_Real aTol = prec;
542 TopExp_Explorer expV (aBlock, TopAbs_VERTEX);
543 TopTools_MapOfShape mapShape;
544 for (; expV.More(); expV.Next()) {
545 if (mapShape.Add(expV.Current())) {
546 TopoDS_Vertex aV = TopoDS::Vertex(expV.Current());
547 aTol = Max(BRep_Tool::Tolerance(aV), aTol);
551 if (aType == BLOCK_MULTI_TRANSFORM_1D) {
552 // Retrieve a faces by Ids
553 Standard_Integer aFace1Id = aCI.GetFace1U();
554 Standard_Integer aFace2Id = aCI.GetFace2U();
555 TopoDS_Shape aFace1, aFace2;
556 if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace1Id, aFace1)) {
557 Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
559 if (aFace1.ShapeType() != TopAbs_FACE) {
560 Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
564 if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace2Id, aFace2)) {
565 Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
567 if (aFace2.ShapeType() != TopAbs_FACE) {
568 Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
572 Standard_Integer aNbIter = aCI.GetNbIterU();
574 MultiTransformate1D(aBlock, aFace1, aFace2, aNbIter, aMulti);
576 } else { // aType == BLOCK_MULTI_TRANSFORM_2D
577 // Retrieve a faces by Ids
578 Standard_Integer aFace1UId = aCI.GetFace1U();
579 Standard_Integer aFace2UId = aCI.GetFace2U();
580 Standard_Integer aFace1VId = aCI.GetFace1V();
581 Standard_Integer aFace2VId = aCI.GetFace2V();
583 TopoDS_Shape aFace1U, aFace2U, aFace1V, aFace2V;
584 if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace1UId, aFace1U) ||
585 !GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace1VId, aFace1V)) {
586 Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
589 if (aFace1U.ShapeType() != TopAbs_FACE ||
590 aFace1V.ShapeType() != TopAbs_FACE) {
591 Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
595 if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace2UId, aFace2U)) {
596 Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
599 if (aFace2U.ShapeType() != TopAbs_FACE) {
600 Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
605 if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace2VId, aFace2V)) {
606 Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
609 if (aFace2V.ShapeType() != TopAbs_FACE) {
610 Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
614 Standard_Integer aNbIterU = aCI.GetNbIterU();
615 Standard_Integer aNbIterV = aCI.GetNbIterV();
617 MultiTransformate2D(aBlock,
618 aFace1U, aFace2U, aNbIterU,
619 aFace1V, aFace2V, aNbIterV, aMulti);
622 if (aMulti.IsNull()) {
623 StdFail_NotDone::Raise("Multi-transformation failed");
626 // Glue faces of the multi-block
627 aShape = GEOMImpl_GlueDriver::GlueFaces(aMulti, aTol);
629 } else { // unknown function type
634 if (aShape.IsNull()) return 0;
636 aFunction->SetValue(aShape);
638 log.SetTouched(Label());
643 //=======================================================================
644 //function : MultiTransformate1D
646 //=======================================================================
647 void GEOMImpl_BlockDriver::MultiTransformate1D (const TopoDS_Shape& theBlock,
648 const TopoDS_Shape& theFace1,
649 const TopoDS_Shape& theFace2,
650 const Standard_Integer theNbIter,
651 TopoDS_Shape& theResult) const
653 // Construct Tool, where <theFace1> will be the first face,
654 // and a face, opposite to <theFace1>, will be the second face
655 GEOMImpl_Block6Explorer aBlockTool;
656 aBlockTool.InitByBlockAndFace(theBlock, theFace1);
658 // Find IDs of the faces
659 Standard_Integer dir_face1 = 1, dir_face2 = 2;
660 if (!theFace2.IsNull()) {
661 dir_face2 = aBlockTool.GetFaceID(theFace2);
664 // Find three pairs of points
665 Standard_Integer v11_id = 0, v12_id = 0, v13_id = 0; // vertices of the first face
666 Standard_Integer v21_id = 0, v22_id = 0, v23_id = 0; // vertices of the second face
668 if (dir_face2 == 2) { // <theFace2> is opposite to <theFace1>
670 // We will take vertices with equal local numbers on the faces,
671 // as the Block6Explorer gives equal local numbers
672 // to the linked vertices on the opposite faces,
673 // i.e. v1* is linked with the v2* by an edge:
677 // / | / | dir_face1 - bottom
679 // /________ / | dir_face2 - top
688 v11_id = aBlockTool.GetVertexID(dir_face1, 1);
689 v12_id = aBlockTool.GetVertexID(dir_face1, 2);
690 v13_id = aBlockTool.GetVertexID(dir_face1, 4);
692 v21_id = aBlockTool.GetVertexID(dir_face2, 1);
693 v22_id = aBlockTool.GetVertexID(dir_face2, 2);
694 v23_id = aBlockTool.GetVertexID(dir_face2, 4);
700 // / | / | dir_face1 - bottom
702 // /________ / | dir_face2 - right (for example)
705 // | / | /v12 = v22 (common_vertex2)
709 // v13 v11 = v21 (common_vertex1)
711 Standard_Integer common_edge_id = aBlockTool.FindCommonEdgeID(dir_face1, dir_face2);
712 Standard_Integer common_vertex1 = aBlockTool.GetVertexOnEdgeID(common_edge_id, 1);
713 Standard_Integer common_vertex2 = aBlockTool.GetVertexOnEdgeID(common_edge_id, 2);
715 Standard_Integer not_common_v1 = 0;
716 Standard_Integer vid = 1;
717 Standard_Boolean isFound = Standard_False;
718 while (!isFound && vid <= 4) {
719 not_common_v1 = aBlockTool.GetVertexID(dir_face1, vid);
720 isFound = (not_common_v1 != common_vertex2 &&
721 aBlockTool.FindEdgeID(not_common_v1, common_vertex1) != 0);
725 Standard_Integer not_common_v2 = 0;
727 isFound = Standard_False;
728 while (!isFound && vid <= 4) {
729 not_common_v2 = aBlockTool.GetVertexID(dir_face2, vid);
730 isFound = (not_common_v2 != common_vertex2 &&
731 aBlockTool.FindEdgeID(not_common_v2, common_vertex1) != 0);
735 v11_id = common_vertex1;
736 v12_id = common_vertex2;
737 v13_id = not_common_v1;
739 v21_id = common_vertex1;
740 v22_id = common_vertex2;
741 v23_id = not_common_v2;
744 // Construct a transformation operator
745 TopoDS_Vertex V11 = TopoDS::Vertex(aBlockTool.GetVertex(v11_id));
746 TopoDS_Vertex V12 = TopoDS::Vertex(aBlockTool.GetVertex(v12_id));
747 TopoDS_Vertex V13 = TopoDS::Vertex(aBlockTool.GetVertex(v13_id));
749 TopoDS_Vertex V21 = TopoDS::Vertex(aBlockTool.GetVertex(v21_id));
750 TopoDS_Vertex V22 = TopoDS::Vertex(aBlockTool.GetVertex(v22_id));
751 TopoDS_Vertex V23 = TopoDS::Vertex(aBlockTool.GetVertex(v23_id));
753 // Axes of the first direction face
754 gp_Pnt P1 = BRep_Tool::Pnt(V11);
755 gp_Vec VecN1 (P1, BRep_Tool::Pnt(V12));
756 gp_Vec VecX1 (P1, BRep_Tool::Pnt(V13));
757 gp_Ax3 Ax1 (P1, VecN1, VecX1);
759 // Axes of the second direction face
760 gp_Pnt P2 = BRep_Tool::Pnt(V21);
761 gp_Vec VecN2 (P2, BRep_Tool::Pnt(V22));
762 gp_Vec VecX2 (P2, BRep_Tool::Pnt(V23));
763 gp_Ax3 Ax2 (P2, VecN2, VecX2);
766 aTrsf.SetDisplacement(Ax1, Ax2);
768 // Check, that <theFace2> is similar to <theFace1>.
769 // Actually, we need only to check right position of one
770 // vertex, not involved into the transformation construction.
771 if (!aBlockTool.IsSimilarFaces(dir_face1, dir_face2, aTrsf)) {
772 Standard_ConstructionError::Raise("The direction faces are not similar");
775 // Perform multi-transformation
776 TopoDS_Compound aCompound;
778 B.MakeCompound(aCompound);
780 TopoDS_Shape aPrevShape = theBlock;
781 for (Standard_Integer i = 0; i < theNbIter; i++) {
782 B.Add(aCompound, aPrevShape);
783 BRepBuilderAPI_Transform aTransformation (aPrevShape, aTrsf, Standard_False);
784 aPrevShape = aTransformation.Shape();
786 theResult = aCompound;
789 //=======================================================================
790 //function : MultiTransformate2D
792 //=======================================================================
793 void GEOMImpl_BlockDriver::MultiTransformate2D (const TopoDS_Shape& theBlock,
794 const TopoDS_Shape& theFace1U,
795 const TopoDS_Shape& theFace2U,
796 const Standard_Integer theNbIterU,
797 const TopoDS_Shape& theFace1V,
798 const TopoDS_Shape& theFace2V,
799 const Standard_Integer theNbIterV,
800 TopoDS_Shape& theResult) const
802 // Construct Tool, where <theFace1U> will be the first face,
803 // and a face, opposite to <theFace1U>, will be the second face
804 GEOMImpl_Block6Explorer aBlockTool;
805 aBlockTool.InitByBlockAndFace(theBlock, theFace1U);
807 gp_Trsf aTrsfU, aTrsfV;
809 for (Standard_Integer uv = 1; uv <= 2; uv++) {
811 TopoDS_Shape theFace1 = theFace1U;
812 TopoDS_Shape theFace2 = theFace2U;
815 theFace1 = theFace1V;
816 theFace2 = theFace2V;
819 // Find IDs of the faces
820 Standard_Integer dir_face1 = aBlockTool.GetFaceID(theFace1);
821 Standard_Integer dir_face2 = 0;
822 Standard_Integer opp_face1 = aBlockTool.GetOppositeFaceID(dir_face1);
823 if (theFace2.IsNull()) {
824 dir_face2 = opp_face1;
826 dir_face2 = aBlockTool.GetFaceID(theFace2);
829 // Find three pairs of points
830 Standard_Integer v11_id = 0, v12_id = 0, v13_id = 0; // vertices of the first face
831 Standard_Integer v21_id = 0, v22_id = 0, v23_id = 0; // vertices of the second face
833 if (dir_face2 == opp_face1) { // <theFace2> is opposite to <theFace1>
835 // We will take vertices with equal local numbers on the faces,
836 // as the Block6Explorer gives equal local numbers
837 // to the linked vertices on the opposite faces,
838 // i.e. v1* is linked with the v2* by an edge:
840 v11_id = aBlockTool.GetVertexID(dir_face1, 1);
841 v12_id = aBlockTool.GetVertexID(dir_face1, 2);
842 v13_id = aBlockTool.GetVertexID(dir_face1, 4);
844 v21_id = aBlockTool.GetVertexID(dir_face2, 1);
845 v22_id = aBlockTool.GetVertexID(dir_face2, 2);
846 v23_id = aBlockTool.GetVertexID(dir_face2, 4);
850 Standard_Integer common_edge_id = aBlockTool.FindCommonEdgeID(dir_face1, dir_face2);
851 Standard_Integer common_vertex1 = aBlockTool.GetVertexOnEdgeID(common_edge_id, 1);
852 Standard_Integer common_vertex2 = aBlockTool.GetVertexOnEdgeID(common_edge_id, 2);
854 Standard_Integer not_common_v1 = 0;
855 Standard_Integer vid = 1;
856 Standard_Boolean isFound = Standard_False;
857 while (!isFound && vid <= 4) {
858 not_common_v1 = aBlockTool.GetVertexID(dir_face1, vid);
859 isFound = (not_common_v1 != common_vertex2 &&
860 aBlockTool.FindEdgeID(not_common_v1, common_vertex1) != 0);
864 Standard_Integer not_common_v2 = 0;
866 isFound = Standard_False;
867 while (!isFound && vid <= 4) {
868 not_common_v2 = aBlockTool.GetVertexID(dir_face2, vid);
869 isFound = (not_common_v2 != common_vertex2 &&
870 aBlockTool.FindEdgeID(not_common_v2, common_vertex1) != 0);
874 v11_id = common_vertex1;
875 v12_id = common_vertex2;
876 v13_id = not_common_v1;
878 v21_id = common_vertex1;
879 v22_id = common_vertex2;
880 v23_id = not_common_v2;
883 // Construct a transformation operator
884 TopoDS_Vertex V11 = TopoDS::Vertex(aBlockTool.GetVertex(v11_id));
885 TopoDS_Vertex V12 = TopoDS::Vertex(aBlockTool.GetVertex(v12_id));
886 TopoDS_Vertex V13 = TopoDS::Vertex(aBlockTool.GetVertex(v13_id));
888 TopoDS_Vertex V21 = TopoDS::Vertex(aBlockTool.GetVertex(v21_id));
889 TopoDS_Vertex V22 = TopoDS::Vertex(aBlockTool.GetVertex(v22_id));
890 TopoDS_Vertex V23 = TopoDS::Vertex(aBlockTool.GetVertex(v23_id));
892 // Axes of the first direction face
893 gp_Pnt P1 = BRep_Tool::Pnt(V11);
894 gp_Vec VecN1 (P1, BRep_Tool::Pnt(V12));
895 gp_Vec VecX1 (P1, BRep_Tool::Pnt(V13));
896 gp_Ax3 Ax1 (P1, VecN1, VecX1);
898 // Axes of the second direction face
899 gp_Pnt P2 = BRep_Tool::Pnt(V21);
900 gp_Vec VecN2 (P2, BRep_Tool::Pnt(V22));
901 gp_Vec VecX2 (P2, BRep_Tool::Pnt(V23));
902 gp_Ax3 Ax2 (P2, VecN2, VecX2);
905 aTrsf.SetDisplacement(Ax1, Ax2);
914 // Check, that <theFace2> is similar to <theFace1>.
915 // Actually, we need only to check right position of one
916 // vertex, not involved into the transformation construction.
917 if (!aBlockTool.IsSimilarFaces(dir_face1, dir_face2, aTrsf)) {
918 Standard_ConstructionError::Raise("The direction faces are not similar");
922 // Perform multi-transformation
923 TopoDS_Compound aCompound;
925 B.MakeCompound(aCompound);
927 TopoDS_Shape aPrevShapeU = theBlock;
928 for (int i = 0; i < theNbIterU; i++) {
929 TopoDS_Shape aPrevShapeV = aPrevShapeU;
930 for (int j = 0; j < theNbIterV; j++) {
931 B.Add(aCompound, aPrevShapeV);
932 BRepBuilderAPI_Transform aTransformationV (aPrevShapeV, aTrsfV, Standard_False);
933 aPrevShapeV = aTransformationV.Shape();
935 BRepBuilderAPI_Transform aTransformationU (aPrevShapeU, aTrsfU, Standard_False);
936 aPrevShapeU = aTransformationU.Shape();
937 // Correction of the second transformation according to the first transformation
938 Ax1V.Transform(aTrsfU);
939 Ax2V.Transform(aTrsfU);
940 aTrsfV.SetDisplacement(Ax1V, Ax2V);
943 theResult = aCompound;
946 //=======================================================================
947 //function : GEOMImpl_BlockDriver_Type_
949 //=======================================================================
950 Standard_EXPORT Handle_Standard_Type& GEOMImpl_BlockDriver_Type_()
953 static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver);
954 if ( aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver);
955 static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared);
956 if ( aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared);
957 static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient);
958 if ( aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient);
961 static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL};
962 static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_BlockDriver",
963 sizeof(GEOMImpl_BlockDriver),
965 (Standard_Address)_Ancestors,
966 (Standard_Address)NULL);
971 //=======================================================================
972 //function : DownCast
974 //=======================================================================
975 const Handle(GEOMImpl_BlockDriver) Handle(GEOMImpl_BlockDriver)::DownCast(const Handle(Standard_Transient)& AnObject)
977 Handle(GEOMImpl_BlockDriver) _anOtherObject;
979 if (!AnObject.IsNull()) {
980 if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_BlockDriver))) {
981 _anOtherObject = Handle(GEOMImpl_BlockDriver)((Handle(GEOMImpl_BlockDriver)&)AnObject);
985 return _anOtherObject ;