1 // Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 #include <Standard_Stream.hxx>
24 #include <BRepOffsetAPI_MakeFilling.hxx>
26 #include <GEOMImpl_BlockDriver.hxx>
27 #include <GEOMImpl_IBlocks.hxx>
28 #include <GEOMImpl_IBlockTrsf.hxx>
29 #include <GEOMImpl_GlueDriver.hxx>
30 #include <GEOMImpl_Types.hxx>
31 #include <GEOMImpl_ILocalOperations.hxx>
32 #include <GEOMImpl_Block6Explorer.hxx>
33 #include <GEOMImpl_IBlocksOperations.hxx>
35 #include <GEOM_Function.hxx>
37 #include <ShHealOper_Sewing.hxx>
38 #include <ShHealOper_ShapeProcess.hxx>
39 #include <GEOMAlgo_Gluer.hxx>
40 #include <BlockFix_BlockFixAPI.hxx>
42 #include "utilities.h"
44 #include <TNaming_CopyShape.hxx>
46 #include <BRepLib.hxx>
47 #include <BRep_Tool.hxx>
48 #include <BRepTools.hxx>
49 #include <BRepGProp.hxx>
50 #include <BRep_Builder.hxx>
51 #include <BRepTools_Quilt.hxx>
52 #include <BRepTools_WireExplorer.hxx>
53 #include <BRepBuilderAPI_MakeEdge.hxx>
54 #include <BRepBuilderAPI_MakeWire.hxx>
55 #include <BRepBuilderAPI_MakePolygon.hxx>
56 #include <BRepBuilderAPI_Transform.hxx>
57 #include <BRepCheck_Analyzer.hxx>
58 #include <BRepClass_FaceClassifier.hxx>
59 #include <BRepClass3d_SolidClassifier.hxx>
60 #include <BRepExtrema_ExtPF.hxx>
61 #include <BRepExtrema_DistShapeShape.hxx>
65 #include <TopoDS_Shape.hxx>
66 #include <TopoDS_Edge.hxx>
67 #include <TopoDS_Wire.hxx>
68 #include <TopoDS_Shell.hxx>
69 #include <TopoDS_Solid.hxx>
70 #include <TopoDS_Compound.hxx>
71 #include <TopoDS_Iterator.hxx>
73 #include <TopExp_Explorer.hxx>
74 #include <TopTools_MapOfShape.hxx>
75 #include <TopTools_MapIteratorOfMapOfShape.hxx>
76 #include <TopTools_Array1OfShape.hxx>
77 #include <TopTools_SequenceOfShape.hxx>
78 #include <TopTools_ListOfShape.hxx>
79 #include <TopTools_ListIteratorOfListOfShape.hxx>
80 #include <TopTools_IndexedMapOfShape.hxx>
81 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
83 #include <GProp_GProps.hxx>
88 #include <Precision.hxx>
89 #include <TColgp_Array1OfPnt.hxx>
90 #include <TColStd_Array1OfInteger.hxx>
91 #include <TColStd_IndexedDataMapOfTransientTransient.hxx>
92 #include <StdFail_NotDone.hxx>
93 #include <Standard_NullObject.hxx>
94 #include <Standard_TypeMismatch.hxx>
95 #include <Standard_ConstructionError.hxx>
97 //=======================================================================
100 //=======================================================================
101 const Standard_GUID& GEOMImpl_BlockDriver::GetID()
103 static Standard_GUID aBlockDriver("FF1BBB67-5D14-4df2-980B-3A668264EA16");
108 //=======================================================================
109 //function : GEOMImpl_BlockDriver
111 //=======================================================================
112 GEOMImpl_BlockDriver::GEOMImpl_BlockDriver()
116 //=======================================================================
119 //=======================================================================
120 Standard_Integer GEOMImpl_BlockDriver::Execute(TFunction_Logbook& log) const
122 if (Label().IsNull()) return 0;
123 Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
125 Standard_Integer aType = aFunction->GetType();
130 Standard_Real prec = Precision::Confusion();
132 Standard_Integer aNbSub = 0;
133 if (aType == BLOCK_COMPOUND_GLUE) {
137 } else if (aType == BLOCK_FACE_TWO_EDGES ||
138 aType == BLOCK_TWO_FACES) {
142 } else if (aType == BLOCK_FACE_FOUR_PNT ||
143 aType == BLOCK_FACE_FOUR_EDGES) {
147 } else if (aType == BLOCK_SIX_FACES) {
155 GEOMImpl_IBlocks aCI (aFunction);
156 Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
157 Standard_Integer nbshapes = aShapes->Length();
159 if (nbshapes != aNbSub) {
160 Standard_TypeMismatch::Raise
161 ("Number of elements for object construction does not correspond to the used constructor");
164 TopTools_Array1OfShape anArgs (1, aNbSub);
165 Standard_Integer argi;
166 for (argi = 1; argi <= aNbSub; argi++) {
167 Handle(GEOM_Function) aRef = Handle(GEOM_Function)::DownCast(aShapes->Value(argi));
168 TopoDS_Shape anArg = aRef->GetValue();
169 if (anArg.IsNull()) {
170 Standard_NullObject::Raise("Null shape is given as argument");
172 anArgs(argi) = anArg;
175 if (aType == BLOCK_FACE_FOUR_EDGES) {
177 // Make face from four edges
178 if (anArgs(1).ShapeType() != TopAbs_EDGE || anArgs(2).ShapeType() != TopAbs_EDGE ||
179 anArgs(3).ShapeType() != TopAbs_EDGE || anArgs(4).ShapeType() != TopAbs_EDGE) {
180 Standard_TypeMismatch::Raise("Shape for face construction is not an edge");
183 // count corner vertices
184 TopTools_MapOfShape aVertMap;
185 for (Standard_Integer ii = 1; ii <= 4; ii++) {
186 TopoDS_Edge anEdge = TopoDS::Edge(anArgs(ii));
187 TopoDS_Vertex V1, V2;
188 TopExp::Vertices(anEdge, V1, V2, Standard_True);
189 if (V1.IsNull() || V2.IsNull()) {
190 Standard_NullObject::Raise("Bad edge for face construction: vertex is not defined");
192 if (BRepTools::Compare(V1,V2)) {
193 Standard_ConstructionError::Raise("Edge ends are too close");
195 Standard_Boolean isCoin1 = Standard_False, isCoin2 = Standard_False;
196 TopTools_MapIteratorOfMapOfShape anIter (aVertMap);
197 for (; anIter.More(); anIter.Next()) {
198 TopoDS_Vertex V = TopoDS::Vertex(anIter.Key());
199 if (BRepTools::Compare(V,V1)) isCoin1 = Standard_True;
200 if (BRepTools::Compare(V,V2)) isCoin2 = Standard_True;
202 if (!isCoin1) aVertMap.Add(V1);
203 if (!isCoin2) aVertMap.Add(V2);
205 if (aVertMap.Extent() != 4) {
206 Standard_ConstructionError::Raise("The edges must form a closed wire");
209 TopoDS_Edge anEdge1 = TopoDS::Edge(anArgs(1));
210 TopoDS_Edge anEdge2 = TopoDS::Edge(anArgs(2));
211 TopoDS_Edge anEdge3 = TopoDS::Edge(anArgs(3));
212 TopoDS_Edge anEdge4 = TopoDS::Edge(anArgs(4));
214 // check, if anEdge1 has common/coincident vertex with anEdge2,
215 Standard_Boolean isConnected12 = Standard_False;
216 TopoDS_Vertex V11, V12, V21, V22;
217 TopExp::Vertices(anEdge1, V11, V12, Standard_True);
218 TopExp::Vertices(anEdge2, V21, V22, Standard_True);
219 if (BRepTools::Compare(V11,V21) || BRepTools::Compare(V11,V22) ||
220 BRepTools::Compare(V12,V21) || BRepTools::Compare(V12,V22)) {
221 // the edges have common vertex
222 isConnected12 = Standard_True;
225 // build wire in right order, corresponding to edges connexity
226 BRepBuilderAPI_MakeWire* MW;
228 MW = new BRepBuilderAPI_MakeWire(anEdge1, anEdge2, anEdge3, anEdge4);
230 MW = new BRepBuilderAPI_MakeWire(anEdge1, anEdge3, anEdge2, anEdge4);
233 Standard_ConstructionError::Raise
234 ("Impossible to build a connected wire from the given edges");
236 TopoDS_Wire aWire = *MW;
239 // check the wire closure
240 TopoDS_Vertex aV1, aV2;
241 TopExp::Vertices(aWire, aV1, aV2);
242 if ( !aV1.IsNull() && !aV2.IsNull() && aV1.IsSame(aV2) )
243 aWire.Closed( true );
245 if (!aWire.Closed()) {
246 Standard_ConstructionError::Raise
247 ("Impossible to build a closed wire from the given edges");
250 // try to build face on the wire
251 GEOMImpl_Block6Explorer::MakeFace(aWire, Standard_False, aShape);
252 if (aShape.IsNull()) {
253 Standard_ConstructionError::Raise("Face construction failed");
256 } else if (aType == BLOCK_FACE_TWO_EDGES) {
258 // Make face from two opposite edges
259 if (anArgs(1).ShapeType() != TopAbs_EDGE ||
260 anArgs(2).ShapeType() != TopAbs_EDGE) {
261 Standard_TypeMismatch::Raise("Shape for face construction is not an edge");
264 TopoDS_Edge anEdge1 = TopoDS::Edge(anArgs(1));
265 TopoDS_Edge anEdge2 = TopoDS::Edge(anArgs(2));
267 if (anEdge1.IsSame(anEdge2)) {
268 Standard_ConstructionError::Raise("The edges must be different");
271 // create two edges, linking ends of the given edges
272 TopoDS_Vertex V11, V12, V21, V22;
273 TopExp::Vertices(anEdge1, V11, V12, Standard_True);
274 TopExp::Vertices(anEdge2, V21, V22, Standard_True);
275 if (V11.IsNull() || V12.IsNull() ||
276 V21.IsNull() || V22.IsNull()) {
277 Standard_NullObject::Raise("Bad edge for face construction: vertex is not defined");
279 gp_Pnt P11 = BRep_Tool::Pnt(V11);
280 gp_Pnt P12 = BRep_Tool::Pnt(V12);
281 gp_Pnt P21 = BRep_Tool::Pnt(V21);
282 gp_Pnt P22 = BRep_Tool::Pnt(V22);
284 if (P11.Distance(P21) < prec || P12.Distance(P22) < prec ||
285 P11.Distance(P22) < prec || P12.Distance(P21) < prec) {
286 Standard_ConstructionError::Raise("Given edges have too close ends");
289 Standard_Real per11 = P11.Distance(P21) + P12.Distance(P22);
290 Standard_Real per12 = P11.Distance(P22) + P12.Distance(P21);
295 anEdge3 = BRepBuilderAPI_MakeEdge(V11, V21);
296 anEdge4 = BRepBuilderAPI_MakeEdge(V12, V22);
298 anEdge3 = BRepBuilderAPI_MakeEdge(V11, V22);
299 anEdge4 = BRepBuilderAPI_MakeEdge(V12, V21);
303 BRepBuilderAPI_MakeWire* MW;
304 MW = new BRepBuilderAPI_MakeWire(anEdge1, anEdge3, anEdge2, anEdge4);
306 Standard_ConstructionError::Raise("Wire construction failed");
309 TopoDS_Wire aWire = *MW;
312 TopoDS_Vertex aV1, aV2;
313 TopExp::Vertices(aWire, aV1, aV2);
314 if ( !aV1.IsNull() && !aV2.IsNull() && aV1.IsSame(aV2) )
315 aWire.Closed( true );
317 if (!aWire.Closed()) {
318 Standard_ConstructionError::Raise
319 ("Impossible to build a closed wire from the given edges");
322 // try to build face on the wire
323 GEOMImpl_Block6Explorer::MakeFace(aWire, Standard_False, aShape);
324 if (aShape.IsNull()) {
325 Standard_ConstructionError::Raise("Face construction failed");
328 } else if (aType == BLOCK_FACE_FOUR_PNT) {
330 // Make face from four corner vertices
331 if (anArgs(1).ShapeType() != TopAbs_VERTEX ||
332 anArgs(2).ShapeType() != TopAbs_VERTEX ||
333 anArgs(3).ShapeType() != TopAbs_VERTEX ||
334 anArgs(4).ShapeType() != TopAbs_VERTEX) {
335 Standard_TypeMismatch::Raise("Shape for face construction is not a vertex");
338 TopoDS_Vertex V1 = TopoDS::Vertex(anArgs(1));
339 TopoDS_Vertex V2 = TopoDS::Vertex(anArgs(2));
340 TopoDS_Vertex V3 = TopoDS::Vertex(anArgs(3));
341 TopoDS_Vertex V4 = TopoDS::Vertex(anArgs(4));
343 gp_Pnt P1 = BRep_Tool::Pnt(V1);
344 gp_Pnt P2 = BRep_Tool::Pnt(V2);
345 gp_Pnt P3 = BRep_Tool::Pnt(V3);
346 gp_Pnt P4 = BRep_Tool::Pnt(V4);
348 if (P1.Distance(P2) < prec || P1.Distance(P3) < prec ||
349 P1.Distance(P4) < prec || P2.Distance(P3) < prec ||
350 P2.Distance(P4) < prec || P3.Distance(P4) < prec) {
351 Standard_ConstructionError::Raise("Four not coincident points must be given");
354 // calculate perimeters
355 Standard_Real per1234 = P1.Distance(P2) + P2.Distance(P3) +
356 P3.Distance(P4) + P4.Distance(P1);
357 Standard_Real per1243 = P1.Distance(P2) + P2.Distance(P4) +
358 P4.Distance(P3) + P3.Distance(P1);
359 Standard_Real per1324 = P1.Distance(P3) + P3.Distance(P2) +
360 P2.Distance(P4) + P4.Distance(P1);
363 if (per1243 < per1234 && per1243 < per1324) {
364 TopoDS_Vertex Vtmp = V3;
367 } else if (per1324 < per1234 && per1324 < per1243) {
368 TopoDS_Vertex Vtmp = V3;
375 BRepBuilderAPI_MakePolygon aMkPoly (V1, V2, V3, V4, Standard_True);
376 if (!aMkPoly.IsDone()) {
377 Standard_ConstructionError::Raise("Polygon construction failed");
380 // try to build face on the wire
382 GEOMImpl_Block6Explorer::MakeFace(aMkPoly, Standard_False, aShape);
383 if (aShape.IsNull()) {
384 Standard_ConstructionError::Raise("Face construction failed");
387 } else if (aType == BLOCK_SIX_FACES || aType == BLOCK_TWO_FACES) {
389 BRepTools_Quilt Glue;
391 if (aType == BLOCK_SIX_FACES) {
393 // Make block (hexahedral solid) from six faces
394 for (Standard_Integer ind = 1; ind <= nbshapes; ind++) {
395 if (anArgs(ind).ShapeType() != TopAbs_FACE) {
396 Standard_TypeMismatch::Raise("Shape for block construction is not a face");
398 Glue.Add(anArgs(ind));
403 // Make block (hexahedral solid) from two opposite faces
404 if (anArgs(1).ShapeType() != TopAbs_FACE ||
405 anArgs(2).ShapeType() != TopAbs_FACE) {
406 Standard_TypeMismatch::Raise("Shape for block construction is not a face");
409 // Get wires of the given faces
410 TopExp_Explorer wires1 (anArgs(1), TopAbs_WIRE);
411 TopExp_Explorer wires2 (anArgs(2), TopAbs_WIRE);
412 if (!wires1.More() || !wires2.More()) {
413 Standard_ConstructionError::Raise("A face for the block has no wires");
415 TopoDS_Shape aWire1 = wires1.Current();
416 TopoDS_Shape aWire2 = wires2.Current();
419 if (wires1.More() || wires2.More()) {
420 Standard_ConstructionError::Raise("A face for the block has more than one wire");
423 GEOMImpl_Block6Explorer aBlockTool;
424 aBlockTool.InitByTwoFaces(anArgs(1), anArgs(2));
426 // Construct the linking faces and add them in the gluing tool
428 Glue.Add(aBlockTool.GetFace(3, Standard_True));
429 Glue.Add(aBlockTool.GetFace(4, Standard_True));
430 Glue.Add(aBlockTool.GetFace(5, Standard_True));
431 Glue.Add(aBlockTool.GetFace(6, Standard_True));
435 TopExp_Explorer exp (Glue.Shells(), TopAbs_SHELL);
436 Standard_Integer ish = 0;
437 TopTools_MapOfShape mapShape;
438 for (; exp.More(); exp.Next()) {
439 if (mapShape.Add(exp.Current())) {
440 aShape = exp.Current();
446 aShape = Glue.Shells();
447 Standard_Real aTol = prec; // Precision::Confusion()
448 TopExp_Explorer expF (aShape, TopAbs_FACE);
449 TopTools_MapOfShape mapF;
452 for (; expF.More(); expF.Next()) {
453 if (mapF.Add(expF.Current())) {
454 B.Add(Shell, expF.Current());
455 Standard_Real aToler = BRep_Tool::Tolerance(TopoDS::Face(expF.Current()));
460 ShHealOper_Sewing aHealer (Shell, aTol);
461 if (aHealer.Perform())
462 aShape = aHealer.GetResultShape();
464 Standard_ConstructionError::Raise
465 ("Impossible to build a connected shell on the given faces");
468 if (aType == BLOCK_SIX_FACES) {
469 if (!aShape.Closed()) {
470 Standard_ConstructionError::Raise
471 ("Impossible to build a closed shell on the given faces");
478 BRepClass3d_SolidClassifier SC (Sol);
479 SC.PerformInfinitePoint(prec);
480 if (SC.State() == TopAbs_IN) {
482 B.Add(Sol, aShape.Reversed());
485 BRepLib::SameParameter(aShape, 1.E-5, Standard_True);
487 } else if (aType == BLOCK_COMPOUND_GLUE) {
489 // Make blocks compound from a compound
490 if (anArgs(1).ShapeType() != TopAbs_COMPOUND &&
491 anArgs(2).ShapeType() != TopAbs_COMPSOLID) {
492 Standard_TypeMismatch::Raise("Not a compound given");
495 TopoDS_Shape aCompound = anArgs(1);
497 // Glue coincident faces and edges (with Partition algorithm).
498 //NMTAlgo_Splitter1 PS;
499 //PS.AddShape(aCompound);
501 //PS.SetRemoveWebs(Standard_False);
502 // PS.Build(aCompound.ShapeType());
503 //PS.Build(TopAbs_SOLID);
504 //aShape = PS.Shape();
506 GEOMAlgo_Gluer aGluer;
507 aGluer.SetShape(aCompound);
508 aGluer.SetCheckGeometry(Standard_True);
510 aShape = aGluer.Result();
516 } else { // Multi-transformations and compound improving
518 if (aType == BLOCK_REMOVE_EXTRA ||
519 aType == BLOCK_COMPOUND_IMPROVE) {
521 GEOMImpl_IBlockTrsf aCI (aFunction);
522 Handle(GEOM_Function) aRefShape = aCI.GetOriginal();
523 TopoDS_Shape aBlockOrComp = aRefShape->GetValue();
524 if (aBlockOrComp.IsNull()) {
525 Standard_NullObject::Raise("Null Shape given");
528 // 1. Improve solids with seam and/or degenerated edges
529 BlockFix_BlockFixAPI aTool;
530 //aTool.Tolerance() = toler;
531 aTool.OptimumNbFaces() = aCI.GetOptimumNbFaces();
532 aTool.SetShape(aBlockOrComp);
535 TopoDS_Shape aFixedExtra = aTool.Shape();
538 BRepCheck_Analyzer ana (aFixedExtra, false);
539 if (!ana.IsValid()) {
541 ShHealOper_ShapeProcess aHealer;
542 aHealer.Perform(aFixedExtra, aFixed);
543 if (aHealer.isDone())
544 aFixedExtra = aFixed;
547 if (aType == BLOCK_REMOVE_EXTRA)
549 aShape = aFixedExtra;
551 if (aShape == aBlockOrComp) {
552 MESSAGE("No modifications have been done");
555 else // aType == BLOCK_COMPOUND_IMPROVE
557 // 2. Separate non-blocks
558 TopTools_ListOfShape BLO; // All blocks from the given compound
559 TopTools_ListOfShape NOT; // Not blocks
560 TopTools_ListOfShape EXT; // Hexahedral solids, having degenerated and/or seam edges
561 GEOMImpl_IBlocksOperations::AddBlocksFrom(aFixedExtra, BLO, NOT, EXT);
563 if (NOT.Extent() > 0) {
564 MESSAGE("Some non-blocks have been removed");
567 // 3. Warn about staying extra-edges
568 if (EXT.Extent() > 0) {
569 MESSAGE("Warning: Not all seam or degenerated edges was removed");
572 // ??? Throw away standalone blocks ???
574 // 4. Create compound of all blocks
575 TopoDS_Compound aComp;
577 BB.MakeCompound(aComp);
578 TopTools_ListIteratorOfListOfShape BLOit (BLO);
579 for (; BLOit.More(); BLOit.Next()) {
580 BB.Add(aComp, BLOit.Value());
584 aShape = GEOMImpl_GlueDriver::GlueFaces(aComp, Precision::Confusion(), Standard_False);
587 } else if (aType == BLOCK_MULTI_TRANSFORM_1D ||
588 aType == BLOCK_MULTI_TRANSFORM_2D) {
591 GEOMImpl_IBlockTrsf aCI (aFunction);
592 Handle(GEOM_Function) aRefShape = aCI.GetOriginal();
593 TopoDS_Shape aBlockIni = aRefShape->GetValue();
594 if (aBlockIni.IsNull()) {
595 Standard_NullObject::Raise("Null Block");
598 // Copy block to avoid problems (PAL6706)
599 TColStd_IndexedDataMapOfTransientTransient aMap;
601 TNaming_CopyShape::CopyTool(aBlockIni, aMap, aBlock);
603 // Block tolerance in vertices
604 Standard_Real aTol = prec;
605 TopExp_Explorer expV (aBlock, TopAbs_VERTEX);
606 TopTools_MapOfShape mapShape;
607 for (; expV.More(); expV.Next()) {
608 if (mapShape.Add(expV.Current())) {
609 TopoDS_Vertex aV = TopoDS::Vertex(expV.Current());
610 aTol = Max(BRep_Tool::Tolerance(aV), aTol);
614 if (aType == BLOCK_MULTI_TRANSFORM_1D) {
615 // Retrieve a faces by Ids
616 Standard_Integer aFace1Id = aCI.GetFace1U();
617 Standard_Integer aFace2Id = aCI.GetFace2U();
618 TopoDS_Shape aFace1, aFace2;
619 if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace1Id, aFace1)) {
620 Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
622 if (aFace1.ShapeType() != TopAbs_FACE) {
623 Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
627 if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace2Id, aFace2)) {
628 Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
630 if (aFace2.ShapeType() != TopAbs_FACE) {
631 Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
635 Standard_Integer aNbIter = aCI.GetNbIterU();
637 MultiTransformate1D(aBlock, aFace1, aFace2, aNbIter, aMulti);
639 } else { // aType == BLOCK_MULTI_TRANSFORM_2D
640 // Retrieve a faces by Ids
641 Standard_Integer aFace1UId = aCI.GetFace1U();
642 Standard_Integer aFace2UId = aCI.GetFace2U();
643 Standard_Integer aFace1VId = aCI.GetFace1V();
644 Standard_Integer aFace2VId = aCI.GetFace2V();
646 TopoDS_Shape aFace1U, aFace2U, aFace1V, aFace2V;
647 if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace1UId, aFace1U) ||
648 !GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace1VId, aFace1V)) {
649 Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
652 if (aFace1U.ShapeType() != TopAbs_FACE ||
653 aFace1V.ShapeType() != TopAbs_FACE) {
654 Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
658 if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace2UId, aFace2U)) {
659 Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
662 if (aFace2U.ShapeType() != TopAbs_FACE) {
663 Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
668 if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace2VId, aFace2V)) {
669 Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
672 if (aFace2V.ShapeType() != TopAbs_FACE) {
673 Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
677 Standard_Integer aNbIterU = aCI.GetNbIterU();
678 Standard_Integer aNbIterV = aCI.GetNbIterV();
680 MultiTransformate2D(aBlock,
681 aFace1U, aFace2U, aNbIterU,
682 aFace1V, aFace2V, aNbIterV, aMulti);
685 if (aMulti.IsNull()) {
686 StdFail_NotDone::Raise("Multi-transformation failed");
689 // Glue faces of the multi-block
690 aShape = GEOMImpl_GlueDriver::GlueFaces(aMulti, aTol, Standard_False);
692 } else { // unknown function type
697 if (aShape.IsNull()) return 0;
699 aFunction->SetValue(aShape);
701 log.SetTouched(Label());
706 //=======================================================================
707 //function : MultiTransformate1D
709 //=======================================================================
710 void GEOMImpl_BlockDriver::MultiTransformate1D (const TopoDS_Shape& theBlock,
711 const TopoDS_Shape& theFace1,
712 const TopoDS_Shape& theFace2,
713 const Standard_Integer theNbIter,
714 TopoDS_Shape& theResult) const
716 // Construct Tool, where <theFace1> will be the first face,
717 // and a face, opposite to <theFace1>, will be the second face
718 GEOMImpl_Block6Explorer aBlockTool;
719 aBlockTool.InitByBlockAndFace(theBlock, theFace1);
721 // Find IDs of the faces
722 Standard_Integer dir_face1 = 1, dir_face2 = 2;
723 if (!theFace2.IsNull()) {
724 dir_face2 = aBlockTool.GetFaceID(theFace2);
727 // Find three pairs of points
728 Standard_Integer v11_id = 0, v12_id = 0, v13_id = 0; // vertices of the first face
729 Standard_Integer v21_id = 0, v22_id = 0, v23_id = 0; // vertices of the second face
731 if (dir_face2 == 2) { // <theFace2> is opposite to <theFace1>
733 // We will take vertices with equal local numbers on the faces,
734 // as the Block6Explorer gives equal local numbers
735 // to the linked vertices on the opposite faces,
736 // i.e. v1* is linked with the v2* by an edge:
740 // / | / | dir_face1 - bottom
742 // /________ / | dir_face2 - top
751 v11_id = aBlockTool.GetVertexID(dir_face1, 1);
752 v12_id = aBlockTool.GetVertexID(dir_face1, 2);
753 v13_id = aBlockTool.GetVertexID(dir_face1, 4);
755 v21_id = aBlockTool.GetVertexID(dir_face2, 1);
756 v22_id = aBlockTool.GetVertexID(dir_face2, 2);
757 v23_id = aBlockTool.GetVertexID(dir_face2, 4);
763 // / | / | dir_face1 - bottom
765 // /________ / | dir_face2 - right (for example)
768 // | / | /v12 = v22 (common_vertex2)
772 // v13 v11 = v21 (common_vertex1)
774 Standard_Integer common_edge_id = aBlockTool.FindCommonEdgeID(dir_face1, dir_face2);
775 Standard_Integer common_vertex1 = aBlockTool.GetVertexOnEdgeID(common_edge_id, 1);
776 Standard_Integer common_vertex2 = aBlockTool.GetVertexOnEdgeID(common_edge_id, 2);
778 Standard_Integer not_common_v1 = 0;
779 Standard_Integer vid = 1;
780 Standard_Boolean isFound = Standard_False;
781 while (!isFound && vid <= 4) {
782 not_common_v1 = aBlockTool.GetVertexID(dir_face1, vid);
783 isFound = (not_common_v1 != common_vertex2 &&
784 aBlockTool.FindEdgeID(not_common_v1, common_vertex1) != 0);
788 Standard_Integer not_common_v2 = 0;
790 isFound = Standard_False;
791 while (!isFound && vid <= 4) {
792 not_common_v2 = aBlockTool.GetVertexID(dir_face2, vid);
793 isFound = (not_common_v2 != common_vertex2 &&
794 aBlockTool.FindEdgeID(not_common_v2, common_vertex1) != 0);
798 v11_id = common_vertex1;
799 v12_id = common_vertex2;
800 v13_id = not_common_v1;
802 v21_id = common_vertex1;
803 v22_id = common_vertex2;
804 v23_id = not_common_v2;
807 // Construct a transformation operator
808 TopoDS_Vertex V11 = TopoDS::Vertex(aBlockTool.GetVertex(v11_id));
809 TopoDS_Vertex V12 = TopoDS::Vertex(aBlockTool.GetVertex(v12_id));
810 TopoDS_Vertex V13 = TopoDS::Vertex(aBlockTool.GetVertex(v13_id));
812 TopoDS_Vertex V21 = TopoDS::Vertex(aBlockTool.GetVertex(v21_id));
813 TopoDS_Vertex V22 = TopoDS::Vertex(aBlockTool.GetVertex(v22_id));
814 TopoDS_Vertex V23 = TopoDS::Vertex(aBlockTool.GetVertex(v23_id));
816 // Axes of the first direction face
817 gp_Pnt P1 = BRep_Tool::Pnt(V11);
818 gp_Vec VecN1 (P1, BRep_Tool::Pnt(V12));
819 gp_Vec VecX1 (P1, BRep_Tool::Pnt(V13));
820 gp_Ax3 Ax1 (P1, VecN1, VecX1);
822 // Axes of the second direction face
823 gp_Pnt P2 = BRep_Tool::Pnt(V21);
824 gp_Vec VecN2 (P2, BRep_Tool::Pnt(V22));
825 gp_Vec VecX2 (P2, BRep_Tool::Pnt(V23));
826 gp_Ax3 Ax2 (P2, VecN2, VecX2);
829 aTrsf.SetDisplacement(Ax1, Ax2);
831 // Check, that <theFace2> is similar to <theFace1>.
832 // Actually, we need only to check right position of one
833 // vertex, not involved into the transformation construction.
834 if (!aBlockTool.IsSimilarFaces(dir_face1, dir_face2, aTrsf)) {
835 Standard_ConstructionError::Raise("The direction faces are not similar");
838 // Perform multi-transformation
839 TopoDS_Compound aCompound;
841 B.MakeCompound(aCompound);
843 TopoDS_Shape aPrevShape = theBlock;
844 for (Standard_Integer i = 0; i < theNbIter; i++) {
845 B.Add(aCompound, aPrevShape);
846 BRepBuilderAPI_Transform aTransformation (aPrevShape, aTrsf, Standard_False);
847 aPrevShape = aTransformation.Shape();
849 theResult = aCompound;
852 //=======================================================================
853 //function : MultiTransformate2D
855 //=======================================================================
856 void GEOMImpl_BlockDriver::MultiTransformate2D (const TopoDS_Shape& theBlock,
857 const TopoDS_Shape& theFace1U,
858 const TopoDS_Shape& theFace2U,
859 const Standard_Integer theNbIterU,
860 const TopoDS_Shape& theFace1V,
861 const TopoDS_Shape& theFace2V,
862 const Standard_Integer theNbIterV,
863 TopoDS_Shape& theResult) const
865 // Construct Tool, where <theFace1U> will be the first face,
866 // and a face, opposite to <theFace1U>, will be the second face
867 GEOMImpl_Block6Explorer aBlockTool;
868 aBlockTool.InitByBlockAndFace(theBlock, theFace1U);
870 gp_Trsf aTrsfU, aTrsfV;
872 for (Standard_Integer uv = 1; uv <= 2; uv++) {
874 TopoDS_Shape theFace1 = theFace1U;
875 TopoDS_Shape theFace2 = theFace2U;
878 theFace1 = theFace1V;
879 theFace2 = theFace2V;
882 // Find IDs of the faces
883 Standard_Integer dir_face1 = aBlockTool.GetFaceID(theFace1);
884 Standard_Integer dir_face2 = 0;
885 Standard_Integer opp_face1 = aBlockTool.GetOppositeFaceID(dir_face1);
886 if (theFace2.IsNull()) {
887 dir_face2 = opp_face1;
889 dir_face2 = aBlockTool.GetFaceID(theFace2);
892 // Find three pairs of points
893 Standard_Integer v11_id = 0, v12_id = 0, v13_id = 0; // vertices of the first face
894 Standard_Integer v21_id = 0, v22_id = 0, v23_id = 0; // vertices of the second face
896 if (dir_face2 == opp_face1) { // <theFace2> is opposite to <theFace1>
898 // We will take vertices with equal local numbers on the faces,
899 // as the Block6Explorer gives equal local numbers
900 // to the linked vertices on the opposite faces,
901 // i.e. v1* is linked with the v2* by an edge:
903 v11_id = aBlockTool.GetVertexID(dir_face1, 1);
904 v12_id = aBlockTool.GetVertexID(dir_face1, 2);
905 v13_id = aBlockTool.GetVertexID(dir_face1, 4);
907 v21_id = aBlockTool.GetVertexID(dir_face2, 1);
908 v22_id = aBlockTool.GetVertexID(dir_face2, 2);
909 v23_id = aBlockTool.GetVertexID(dir_face2, 4);
913 Standard_Integer common_edge_id = aBlockTool.FindCommonEdgeID(dir_face1, dir_face2);
914 Standard_Integer common_vertex1 = aBlockTool.GetVertexOnEdgeID(common_edge_id, 1);
915 Standard_Integer common_vertex2 = aBlockTool.GetVertexOnEdgeID(common_edge_id, 2);
917 Standard_Integer not_common_v1 = 0;
918 Standard_Integer vid = 1;
919 Standard_Boolean isFound = Standard_False;
920 while (!isFound && vid <= 4) {
921 not_common_v1 = aBlockTool.GetVertexID(dir_face1, vid);
922 isFound = (not_common_v1 != common_vertex2 &&
923 aBlockTool.FindEdgeID(not_common_v1, common_vertex1) != 0);
927 Standard_Integer not_common_v2 = 0;
929 isFound = Standard_False;
930 while (!isFound && vid <= 4) {
931 not_common_v2 = aBlockTool.GetVertexID(dir_face2, vid);
932 isFound = (not_common_v2 != common_vertex2 &&
933 aBlockTool.FindEdgeID(not_common_v2, common_vertex1) != 0);
937 v11_id = common_vertex1;
938 v12_id = common_vertex2;
939 v13_id = not_common_v1;
941 v21_id = common_vertex1;
942 v22_id = common_vertex2;
943 v23_id = not_common_v2;
946 // Construct a transformation operator
947 TopoDS_Vertex V11 = TopoDS::Vertex(aBlockTool.GetVertex(v11_id));
948 TopoDS_Vertex V12 = TopoDS::Vertex(aBlockTool.GetVertex(v12_id));
949 TopoDS_Vertex V13 = TopoDS::Vertex(aBlockTool.GetVertex(v13_id));
951 TopoDS_Vertex V21 = TopoDS::Vertex(aBlockTool.GetVertex(v21_id));
952 TopoDS_Vertex V22 = TopoDS::Vertex(aBlockTool.GetVertex(v22_id));
953 TopoDS_Vertex V23 = TopoDS::Vertex(aBlockTool.GetVertex(v23_id));
955 // Axes of the first direction face
956 gp_Pnt P1 = BRep_Tool::Pnt(V11);
957 gp_Vec VecN1 (P1, BRep_Tool::Pnt(V12));
958 gp_Vec VecX1 (P1, BRep_Tool::Pnt(V13));
959 gp_Ax3 Ax1 (P1, VecN1, VecX1);
961 // Axes of the second direction face
962 gp_Pnt P2 = BRep_Tool::Pnt(V21);
963 gp_Vec VecN2 (P2, BRep_Tool::Pnt(V22));
964 gp_Vec VecX2 (P2, BRep_Tool::Pnt(V23));
965 gp_Ax3 Ax2 (P2, VecN2, VecX2);
968 aTrsf.SetDisplacement(Ax1, Ax2);
977 // Check, that <theFace2> is similar to <theFace1>.
978 // Actually, we need only to check right position of one
979 // vertex, not involved into the transformation construction.
980 if (!aBlockTool.IsSimilarFaces(dir_face1, dir_face2, aTrsf)) {
981 Standard_ConstructionError::Raise("The direction faces are not similar");
985 // Perform multi-transformation
986 TopoDS_Compound aCompound;
988 B.MakeCompound(aCompound);
990 TopoDS_Shape aPrevShapeU = theBlock;
991 for (int i = 0; i < theNbIterU; i++) {
992 TopoDS_Shape aPrevShapeV = aPrevShapeU;
993 for (int j = 0; j < theNbIterV; j++) {
994 B.Add(aCompound, aPrevShapeV);
995 BRepBuilderAPI_Transform aTransformationV (aPrevShapeV, aTrsfV, Standard_False);
996 aPrevShapeV = aTransformationV.Shape();
998 BRepBuilderAPI_Transform aTransformationU (aPrevShapeU, aTrsfU, Standard_False);
999 aPrevShapeU = aTransformationU.Shape();
1000 // Correction of the second transformation according to the first transformation
1001 Ax1V.Transform(aTrsfU);
1002 Ax2V.Transform(aTrsfU);
1003 aTrsfV.SetDisplacement(Ax1V, Ax2V);
1006 theResult = aCompound;
1009 //=======================================================================
1010 //function : GEOMImpl_BlockDriver_Type_
1012 //=======================================================================
1013 Standard_EXPORT Handle_Standard_Type& GEOMImpl_BlockDriver_Type_()
1016 static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver);
1017 if ( aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver);
1018 static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared);
1019 if ( aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared);
1020 static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient);
1021 if ( aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient);
1024 static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL};
1025 static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_BlockDriver",
1026 sizeof(GEOMImpl_BlockDriver),
1028 (Standard_Address)_Ancestors,
1029 (Standard_Address)NULL);
1034 //=======================================================================
1035 //function : DownCast
1037 //=======================================================================
1038 const Handle(GEOMImpl_BlockDriver) Handle(GEOMImpl_BlockDriver)::DownCast(const Handle(Standard_Transient)& AnObject)
1040 Handle(GEOMImpl_BlockDriver) _anOtherObject;
1042 if (!AnObject.IsNull()) {
1043 if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_BlockDriver))) {
1044 _anOtherObject = Handle(GEOMImpl_BlockDriver)((Handle(GEOMImpl_BlockDriver)&)AnObject);
1048 return _anOtherObject ;