1 // Copyright (C) 2007-2012 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 <BRepAdaptor_Curve.hxx>
47 #include <BRepLib.hxx>
48 #include <BRep_Tool.hxx>
49 #include <BRepTools.hxx>
50 #include <BRepGProp.hxx>
51 #include <BRep_Builder.hxx>
52 #include <BRepTools_Quilt.hxx>
53 #include <BRepTools_WireExplorer.hxx>
54 #include <BRepBuilderAPI_MakeEdge.hxx>
55 #include <BRepBuilderAPI_MakeWire.hxx>
56 #include <BRepBuilderAPI_MakePolygon.hxx>
57 #include <BRepBuilderAPI_Transform.hxx>
58 #include <BRepCheck_Analyzer.hxx>
59 #include <BRepClass_FaceClassifier.hxx>
60 #include <BRepClass3d_SolidClassifier.hxx>
61 #include <BRepExtrema_ExtPF.hxx>
62 #include <BRepExtrema_DistShapeShape.hxx>
66 #include <TopoDS_Shape.hxx>
67 #include <TopoDS_Edge.hxx>
68 #include <TopoDS_Wire.hxx>
69 #include <TopoDS_Shell.hxx>
70 #include <TopoDS_Solid.hxx>
71 #include <TopoDS_Compound.hxx>
72 #include <TopoDS_Iterator.hxx>
74 #include <TopExp_Explorer.hxx>
75 #include <TopTools_MapOfShape.hxx>
76 #include <TopTools_MapIteratorOfMapOfShape.hxx>
77 #include <TopTools_Array1OfShape.hxx>
78 #include <TopTools_SequenceOfShape.hxx>
79 #include <TopTools_ListOfShape.hxx>
80 #include <TopTools_ListIteratorOfListOfShape.hxx>
81 #include <TopTools_IndexedMapOfShape.hxx>
82 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
84 #include <GProp_GProps.hxx>
86 #include <Geom_Line.hxx>
87 #include <GC_MakeLine.hxx>
92 #include <Precision.hxx>
93 #include <TColgp_Array1OfPnt.hxx>
94 #include <TColStd_Array1OfInteger.hxx>
95 #include <TColStd_IndexedDataMapOfTransientTransient.hxx>
96 #include <StdFail_NotDone.hxx>
97 #include <Standard_NullObject.hxx>
98 #include <Standard_TypeMismatch.hxx>
99 #include <Standard_ConstructionError.hxx>
101 //=======================================================================
104 //=======================================================================
105 const Standard_GUID& GEOMImpl_BlockDriver::GetID()
107 static Standard_GUID aBlockDriver("FF1BBB67-5D14-4df2-980B-3A668264EA16");
112 //=======================================================================
113 //function : GEOMImpl_BlockDriver
115 //=======================================================================
116 GEOMImpl_BlockDriver::GEOMImpl_BlockDriver()
120 //=======================================================================
123 //=======================================================================
124 Standard_Integer GEOMImpl_BlockDriver::Execute(TFunction_Logbook& log) const
126 if (Label().IsNull()) return 0;
127 Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
129 Standard_Integer aType = aFunction->GetType();
134 Standard_Real prec = Precision::Confusion();
136 Standard_Integer aNbSub = 0;
137 if (aType == BLOCK_COMPOUND_GLUE) {
141 } else if (aType == BLOCK_FACE_TWO_EDGES ||
142 aType == BLOCK_TWO_FACES) {
146 } else if (aType == BLOCK_FACE_FOUR_PNT ||
147 aType == BLOCK_FACE_FOUR_EDGES) {
151 } else if (aType == BLOCK_SIX_FACES) {
159 GEOMImpl_IBlocks aCI (aFunction);
160 Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
161 Standard_Integer nbshapes = aShapes->Length();
163 if (nbshapes != aNbSub) {
164 Standard_TypeMismatch::Raise
165 ("Number of elements for object construction does not correspond to the used constructor");
168 TopTools_Array1OfShape anArgs (1, aNbSub);
169 Standard_Integer argi;
170 for (argi = 1; argi <= aNbSub; argi++) {
171 Handle(GEOM_Function) aRef = Handle(GEOM_Function)::DownCast(aShapes->Value(argi));
172 TopoDS_Shape anArg = aRef->GetValue();
173 if (anArg.IsNull()) {
174 Standard_NullObject::Raise("Null shape is given as argument");
176 anArgs(argi) = anArg;
179 if (aType == BLOCK_FACE_FOUR_EDGES) {
181 // Make face from four edges
182 if (anArgs(1).ShapeType() != TopAbs_EDGE || anArgs(2).ShapeType() != TopAbs_EDGE ||
183 anArgs(3).ShapeType() != TopAbs_EDGE || anArgs(4).ShapeType() != TopAbs_EDGE) {
184 Standard_TypeMismatch::Raise("Shape for face construction is not an edge");
187 // count corner vertices
188 TopTools_MapOfShape aVertMap;
189 for (Standard_Integer ii = 1; ii <= 4; ii++) {
190 TopoDS_Edge anEdge = TopoDS::Edge(anArgs(ii));
191 TopoDS_Vertex V1, V2;
192 TopExp::Vertices(anEdge, V1, V2, Standard_True);
193 if (V1.IsNull() || V2.IsNull()) {
194 Standard_NullObject::Raise("Bad edge for face construction: vertex is not defined");
196 if (BRepTools::Compare(V1,V2)) {
197 Standard_ConstructionError::Raise("Edge ends are too close");
199 Standard_Boolean isCoin1 = Standard_False, isCoin2 = Standard_False;
200 TopTools_MapIteratorOfMapOfShape anIter (aVertMap);
201 for (; anIter.More(); anIter.Next()) {
202 TopoDS_Vertex V = TopoDS::Vertex(anIter.Key());
203 if (BRepTools::Compare(V,V1)) isCoin1 = Standard_True;
204 if (BRepTools::Compare(V,V2)) isCoin2 = Standard_True;
206 if (!isCoin1) aVertMap.Add(V1);
207 if (!isCoin2) aVertMap.Add(V2);
209 if (aVertMap.Extent() != 4) {
210 Standard_ConstructionError::Raise("The edges must form a closed wire");
213 TopoDS_Edge anEdge1 = TopoDS::Edge(anArgs(1));
214 TopoDS_Edge anEdge2 = TopoDS::Edge(anArgs(2));
215 TopoDS_Edge anEdge3 = TopoDS::Edge(anArgs(3));
216 TopoDS_Edge anEdge4 = TopoDS::Edge(anArgs(4));
218 // check, if anEdge1 has common/coincident vertex with anEdge2,
219 Standard_Boolean isConnected12 = Standard_False;
220 TopoDS_Vertex V11, V12, V21, V22;
221 TopExp::Vertices(anEdge1, V11, V12, Standard_True);
222 TopExp::Vertices(anEdge2, V21, V22, Standard_True);
223 if (BRepTools::Compare(V11,V21) || BRepTools::Compare(V11,V22) ||
224 BRepTools::Compare(V12,V21) || BRepTools::Compare(V12,V22)) {
225 // the edges have common vertex
226 isConnected12 = Standard_True;
229 // build wire in right order, corresponding to edges connexity
230 BRepBuilderAPI_MakeWire* MW;
232 MW = new BRepBuilderAPI_MakeWire(anEdge1, anEdge2, anEdge3, anEdge4);
234 MW = new BRepBuilderAPI_MakeWire(anEdge1, anEdge3, anEdge2, anEdge4);
237 Standard_ConstructionError::Raise
238 ("Impossible to build a connected wire from the given edges");
240 TopoDS_Wire aWire = *MW;
243 // check the wire closure
244 TopoDS_Vertex aV1, aV2;
245 TopExp::Vertices(aWire, aV1, aV2);
246 if ( !aV1.IsNull() && !aV2.IsNull() && aV1.IsSame(aV2) )
247 aWire.Closed( true );
249 if (!aWire.Closed()) {
250 Standard_ConstructionError::Raise
251 ("Impossible to build a closed wire from the given edges");
254 // try to build face on the wire
255 GEOMImpl_Block6Explorer::MakeFace(aWire, Standard_False, aShape);
256 if (aShape.IsNull()) {
257 Standard_ConstructionError::Raise("Face construction failed");
260 } else if (aType == BLOCK_FACE_TWO_EDGES) {
262 // Make face from two opposite edges
263 if (anArgs(1).ShapeType() != TopAbs_EDGE ||
264 anArgs(2).ShapeType() != TopAbs_EDGE) {
265 Standard_TypeMismatch::Raise("Shape for face construction is not an edge");
268 TopoDS_Edge anEdge1 = TopoDS::Edge(anArgs(1));
269 TopoDS_Edge anEdge2 = TopoDS::Edge(anArgs(2));
271 if (anEdge1.IsSame(anEdge2)) {
272 Standard_ConstructionError::Raise("The edges must be different");
275 // create two edges, linking ends of the given edges
276 TopoDS_Vertex V11, V12, V21, V22;
277 TopExp::Vertices(anEdge1, V11, V12, Standard_False);
278 TopExp::Vertices(anEdge2, V21, V22, Standard_False);
279 if (V11.IsNull() || V12.IsNull() ||
280 V21.IsNull() || V22.IsNull()) {
281 Standard_NullObject::Raise("Bad edge for face construction: vertex is not defined");
284 BRepAdaptor_Curve C1 (anEdge1);
285 BRepAdaptor_Curve C2 (anEdge2);
286 gp_Pnt P11, P12, P21, P22;
288 // Mantis issue 0020599: Creation of a quadrangle face from 2 edges: SIGSEGV
289 P11 = C1.Value(C1.FirstParameter());
290 P12 = C1.Value(C1.LastParameter());
291 P21 = C2.Value(C2.FirstParameter());
292 P22 = C2.Value(C2.LastParameter());
293 //gp_Pnt P11 = BRep_Tool::Pnt(V11);
294 //gp_Pnt P12 = BRep_Tool::Pnt(V12);
295 //gp_Pnt P21 = BRep_Tool::Pnt(V21);
296 //gp_Pnt P22 = BRep_Tool::Pnt(V22);
298 if (P11.Distance(P21) < prec || P12.Distance(P22) < prec ||
299 P11.Distance(P22) < prec || P12.Distance(P21) < prec) {
300 Standard_ConstructionError::Raise("Given edges have too close ends");
303 Standard_Real per11 = P11.Distance(P21) + P12.Distance(P22);
304 Standard_Real per12 = P11.Distance(P22) + P12.Distance(P21);
311 // Mantis issue 0020599: Creation of a quadrangle face from 2 edges: SIGSEGV
313 Handle(Geom_Line) Line1 = GC_MakeLine(P11, P21).Value();
314 Handle(Geom_Line) Line2 = GC_MakeLine(P12, P22).Value();
316 BB.MakeEdge(anEdge3, Line1, Precision::Confusion());
317 BB.Range(anEdge3, 0., P11.Distance(P21));
318 BB.Add(anEdge3, V11.Oriented(TopAbs_FORWARD));
319 BB.Add(anEdge3, V21.Oriented(TopAbs_REVERSED));
321 BB.MakeEdge(anEdge4, Line2, Precision::Confusion());
322 BB.Range(anEdge4, 0., P12.Distance(P22));
323 BB.Add(anEdge4, V12.Oriented(TopAbs_FORWARD));
324 BB.Add(anEdge4, V22.Oriented(TopAbs_REVERSED));
327 Handle(Geom_Line) Line1 = GC_MakeLine(P11, P22).Value();
328 Handle(Geom_Line) Line2 = GC_MakeLine(P12, P21).Value();
330 BB.MakeEdge(anEdge3, Line1, Precision::Confusion());
331 BB.Range(anEdge3, 0., P11.Distance(P22));
332 BB.Add(anEdge3, V11.Oriented(TopAbs_FORWARD));
333 BB.Add(anEdge3, V22.Oriented(TopAbs_REVERSED));
335 BB.MakeEdge(anEdge4, Line2, Precision::Confusion());
336 BB.Range(anEdge4, 0., P12.Distance(P21));
337 BB.Add(anEdge4, V12.Oriented(TopAbs_FORWARD));
338 BB.Add(anEdge4, V21.Oriented(TopAbs_REVERSED));
340 //if (per11 < per12) {
341 // anEdge3 = BRepBuilderAPI_MakeEdge(V11, V21);
342 // anEdge4 = BRepBuilderAPI_MakeEdge(V12, V22);
344 // anEdge3 = BRepBuilderAPI_MakeEdge(V11, V22);
345 // anEdge4 = BRepBuilderAPI_MakeEdge(V12, V21);
349 BRepBuilderAPI_MakeWire* MW;
350 MW = new BRepBuilderAPI_MakeWire(anEdge1, anEdge3, anEdge2, anEdge4);
352 Standard_ConstructionError::Raise("Wire construction failed");
355 TopoDS_Wire aWire = *MW;
358 TopoDS_Vertex aV1, aV2;
359 TopExp::Vertices(aWire, aV1, aV2);
360 if ( !aV1.IsNull() && !aV2.IsNull() && aV1.IsSame(aV2) )
361 aWire.Closed( true );
363 if (!aWire.Closed()) {
364 Standard_ConstructionError::Raise
365 ("Impossible to build a closed wire from the given edges");
368 // try to build face on the wire
369 GEOMImpl_Block6Explorer::MakeFace(aWire, Standard_False, aShape);
370 if (aShape.IsNull()) {
371 Standard_ConstructionError::Raise("Face construction failed");
374 } else if (aType == BLOCK_FACE_FOUR_PNT) {
376 // Make face from four corner vertices
377 if (anArgs(1).ShapeType() != TopAbs_VERTEX ||
378 anArgs(2).ShapeType() != TopAbs_VERTEX ||
379 anArgs(3).ShapeType() != TopAbs_VERTEX ||
380 anArgs(4).ShapeType() != TopAbs_VERTEX) {
381 Standard_TypeMismatch::Raise("Shape for face construction is not a vertex");
384 TopoDS_Vertex V1 = TopoDS::Vertex(anArgs(1));
385 TopoDS_Vertex V2 = TopoDS::Vertex(anArgs(2));
386 TopoDS_Vertex V3 = TopoDS::Vertex(anArgs(3));
387 TopoDS_Vertex V4 = TopoDS::Vertex(anArgs(4));
389 gp_Pnt P1 = BRep_Tool::Pnt(V1);
390 gp_Pnt P2 = BRep_Tool::Pnt(V2);
391 gp_Pnt P3 = BRep_Tool::Pnt(V3);
392 gp_Pnt P4 = BRep_Tool::Pnt(V4);
394 if (P1.Distance(P2) < prec || P1.Distance(P3) < prec ||
395 P1.Distance(P4) < prec || P2.Distance(P3) < prec ||
396 P2.Distance(P4) < prec || P3.Distance(P4) < prec) {
397 Standard_ConstructionError::Raise("Four not coincident points must be given");
400 // calculate perimeters
401 Standard_Real per1234 = P1.Distance(P2) + P2.Distance(P3) +
402 P3.Distance(P4) + P4.Distance(P1);
403 Standard_Real per1243 = P1.Distance(P2) + P2.Distance(P4) +
404 P4.Distance(P3) + P3.Distance(P1);
405 Standard_Real per1324 = P1.Distance(P3) + P3.Distance(P2) +
406 P2.Distance(P4) + P4.Distance(P1);
409 if (per1243 < per1234 && per1243 < per1324) {
410 TopoDS_Vertex Vtmp = V3;
413 } else if (per1324 < per1234 && per1324 < per1243) {
414 TopoDS_Vertex Vtmp = V3;
421 BRepBuilderAPI_MakePolygon aMkPoly (V1, V2, V3, V4, Standard_True);
422 if (!aMkPoly.IsDone()) {
423 Standard_ConstructionError::Raise("Polygon construction failed");
426 // try to build face on the wire
428 GEOMImpl_Block6Explorer::MakeFace(aMkPoly, Standard_False, aShape);
429 if (aShape.IsNull()) {
430 Standard_ConstructionError::Raise("Face construction failed");
433 } else if (aType == BLOCK_SIX_FACES || aType == BLOCK_TWO_FACES) {
435 BRepTools_Quilt Glue;
437 if (aType == BLOCK_SIX_FACES) {
438 // Make block (hexahedral solid) from six faces
439 for (Standard_Integer ind = 1; ind <= nbshapes; ind++) {
440 if (anArgs(ind).ShapeType() != TopAbs_FACE) {
441 Standard_TypeMismatch::Raise("Shape for block construction is not a face");
443 Glue.Add(anArgs(ind));
448 // Make block (hexahedral solid) from two opposite faces
449 if (anArgs(1).ShapeType() != TopAbs_FACE ||
450 anArgs(2).ShapeType() != TopAbs_FACE) {
451 Standard_TypeMismatch::Raise("Shape for block construction is not a face");
454 // Get wires of the given faces
455 TopExp_Explorer wires1 (anArgs(1), TopAbs_WIRE);
456 TopExp_Explorer wires2 (anArgs(2), TopAbs_WIRE);
457 if (!wires1.More() || !wires2.More()) {
458 Standard_ConstructionError::Raise("A face for the block has no wires");
460 TopoDS_Shape aWire1 = wires1.Current();
461 TopoDS_Shape aWire2 = wires2.Current();
464 if (wires1.More() || wires2.More()) {
465 Standard_ConstructionError::Raise("A face for the block has more than one wire");
468 GEOMImpl_Block6Explorer aBlockTool;
469 aBlockTool.InitByTwoFaces(anArgs(1), anArgs(2));
471 // Construct the linking faces and add them in the gluing tool
473 Glue.Add(aBlockTool.GetFace(3, Standard_True));
474 Glue.Add(aBlockTool.GetFace(4, Standard_True));
475 Glue.Add(aBlockTool.GetFace(5, Standard_True));
476 Glue.Add(aBlockTool.GetFace(6, Standard_True));
480 TopExp_Explorer exp (Glue.Shells(), TopAbs_SHELL);
481 Standard_Integer ish = 0;
482 TopTools_MapOfShape mapShape;
483 for (; exp.More(); exp.Next()) {
484 if (mapShape.Add(exp.Current())) {
485 aShape = exp.Current();
491 aShape = Glue.Shells();
492 Standard_Real aTol = prec; // Precision::Confusion()
493 TopExp_Explorer expF (aShape, TopAbs_FACE);
494 TopTools_MapOfShape mapF;
497 for (; expF.More(); expF.Next()) {
498 if (mapF.Add(expF.Current())) {
499 B.Add(Shell, expF.Current());
500 Standard_Real aToler = BRep_Tool::Tolerance(TopoDS::Face(expF.Current()));
505 ShHealOper_Sewing aHealer (Shell, aTol);
506 if (aHealer.Perform())
507 aShape = aHealer.GetResultShape();
509 Standard_ConstructionError::Raise
510 ("Impossible to build a connected shell on the given faces");
513 if (aType == BLOCK_SIX_FACES) {
514 if (!aShape.Closed()) {
515 Standard_ConstructionError::Raise
516 ("Impossible to build a closed shell on the given faces");
523 BRepClass3d_SolidClassifier SC (Sol);
524 SC.PerformInfinitePoint(prec);
525 if (SC.State() == TopAbs_IN) {
527 B.Add(Sol, aShape.Reversed());
530 BRepLib::SameParameter(aShape, 1.E-5, Standard_True);
532 else if (aType == BLOCK_COMPOUND_GLUE) {
533 // Make blocks compound from a compound
534 if (anArgs(1).ShapeType() != TopAbs_COMPOUND &&
535 anArgs(2).ShapeType() != TopAbs_COMPSOLID) {
536 Standard_TypeMismatch::Raise("Not a compound given");
539 TopoDS_Shape aCompound = anArgs(1);
541 // Glue coincident faces and edges
542 aShape = GEOMImpl_GlueDriver::GlueFaces(aCompound, Precision::Confusion(), Standard_True);
543 //GEOMAlgo_Gluer aGluer;
544 //aGluer.SetShape(aCompound);
545 //aGluer.SetCheckGeometry(Standard_True);
547 //aShape = aGluer.Result();
552 } else { // Multi-transformations and compound improving
554 if (aType == BLOCK_REMOVE_EXTRA ||
555 aType == BLOCK_COMPOUND_IMPROVE) {
557 GEOMImpl_IBlockTrsf aCI (aFunction);
558 Handle(GEOM_Function) aRefShape = aCI.GetOriginal();
559 TopoDS_Shape aBlockOrComp = aRefShape->GetValue();
560 if (aBlockOrComp.IsNull()) {
561 Standard_NullObject::Raise("Null Shape given");
564 // Copy shape to avoid problems (Mantis issue 0021683)
565 TopoDS_Shape aShapeCopy;
566 TColStd_IndexedDataMapOfTransientTransient aMapTShapes;
567 TNaming_CopyShape::CopyTool(aBlockOrComp, aMapTShapes, aShapeCopy);
568 aBlockOrComp = aShapeCopy;
570 // 1. Improve solids with seam and/or degenerated edges
571 BlockFix_BlockFixAPI aTool;
572 //aTool.Tolerance() = toler;
573 aTool.OptimumNbFaces() = aCI.GetOptimumNbFaces();
574 aTool.SetShape(aBlockOrComp);
577 TopoDS_Shape aFixedExtra = aTool.Shape();
580 BRepCheck_Analyzer ana (aFixedExtra, false);
581 if (!ana.IsValid()) {
583 ShHealOper_ShapeProcess aHealer;
584 aHealer.Perform(aFixedExtra, aFixed);
585 if (aHealer.isDone())
586 aFixedExtra = aFixed;
589 if (aType == BLOCK_REMOVE_EXTRA)
591 aShape = aFixedExtra;
593 if (aShape == aBlockOrComp) {
594 MESSAGE("No modifications have been done");
597 else // aType == BLOCK_COMPOUND_IMPROVE
599 // 2. Separate non-blocks
600 TopTools_ListOfShape BLO; // All blocks from the given compound
601 TopTools_ListOfShape NOT; // Not blocks
602 TopTools_ListOfShape EXT; // Hexahedral solids, having degenerated and/or seam edges
603 TopTools_ListOfShape NOQ; // All non-quadrangular faces
604 GEOMImpl_IBlocksOperations::AddBlocksFrom(aFixedExtra, BLO, NOT, EXT, NOQ);
606 if (NOT.Extent() > 0) {
607 MESSAGE("Some non-blocks have been removed");
610 // 3. Warn about staying extra-edges
611 if (EXT.Extent() > 0) {
612 MESSAGE("Warning: Not all seam or degenerated edges was removed");
615 // ??? Throw away standalone blocks ???
617 // 4. Create compound of all blocks
618 TopoDS_Compound aComp;
620 BB.MakeCompound(aComp);
621 TopTools_ListIteratorOfListOfShape BLOit (BLO);
622 for (; BLOit.More(); BLOit.Next()) {
623 BB.Add(aComp, BLOit.Value());
627 aShape = GEOMImpl_GlueDriver::GlueFaces(aComp, Precision::Confusion(), Standard_False);
630 } else if (aType == BLOCK_MULTI_TRANSFORM_1D ||
631 aType == BLOCK_MULTI_TRANSFORM_2D) {
634 GEOMImpl_IBlockTrsf aCI (aFunction);
635 Handle(GEOM_Function) aRefShape = aCI.GetOriginal();
636 TopoDS_Shape aBlockIni = aRefShape->GetValue();
637 if (aBlockIni.IsNull()) {
638 Standard_NullObject::Raise("Null Block");
641 // Copy block to avoid problems (PAL6706)
642 TColStd_IndexedDataMapOfTransientTransient aMap;
644 TNaming_CopyShape::CopyTool(aBlockIni, aMap, aBlock);
646 // Block tolerance in vertices
647 Standard_Real aTol = prec;
648 TopExp_Explorer expV (aBlock, TopAbs_VERTEX);
649 TopTools_MapOfShape mapShape;
650 for (; expV.More(); expV.Next()) {
651 if (mapShape.Add(expV.Current())) {
652 TopoDS_Vertex aV = TopoDS::Vertex(expV.Current());
653 aTol = Max(BRep_Tool::Tolerance(aV), aTol);
657 if (aType == BLOCK_MULTI_TRANSFORM_1D) {
658 // Retrieve a faces by Ids
659 Standard_Integer aFace1Id = aCI.GetFace1U();
660 Standard_Integer aFace2Id = aCI.GetFace2U();
661 TopoDS_Shape aFace1, aFace2;
662 if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace1Id, aFace1)) {
663 Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
665 if (aFace1.ShapeType() != TopAbs_FACE) {
666 Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
670 if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace2Id, aFace2)) {
671 Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
673 if (aFace2.ShapeType() != TopAbs_FACE) {
674 Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
678 Standard_Integer aNbIter = aCI.GetNbIterU();
680 MultiTransformate1D(aBlock, aFace1, aFace2, aNbIter, aMulti);
682 } else { // aType == BLOCK_MULTI_TRANSFORM_2D
683 // Retrieve a faces by Ids
684 Standard_Integer aFace1UId = aCI.GetFace1U();
685 Standard_Integer aFace2UId = aCI.GetFace2U();
686 Standard_Integer aFace1VId = aCI.GetFace1V();
687 Standard_Integer aFace2VId = aCI.GetFace2V();
689 TopoDS_Shape aFace1U, aFace2U, aFace1V, aFace2V;
690 if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace1UId, aFace1U) ||
691 !GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace1VId, aFace1V)) {
692 Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
695 if (aFace1U.ShapeType() != TopAbs_FACE ||
696 aFace1V.ShapeType() != TopAbs_FACE) {
697 Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
701 if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace2UId, aFace2U)) {
702 Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
705 if (aFace2U.ShapeType() != TopAbs_FACE) {
706 Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
711 if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace2VId, aFace2V)) {
712 Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
715 if (aFace2V.ShapeType() != TopAbs_FACE) {
716 Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
720 Standard_Integer aNbIterU = aCI.GetNbIterU();
721 Standard_Integer aNbIterV = aCI.GetNbIterV();
723 MultiTransformate2D(aBlock,
724 aFace1U, aFace2U, aNbIterU,
725 aFace1V, aFace2V, aNbIterV, aMulti);
728 if (aMulti.IsNull()) {
729 StdFail_NotDone::Raise("Multi-transformation failed");
732 // Glue faces of the multi-block
733 aShape = GEOMImpl_GlueDriver::GlueFaces(aMulti, aTol, Standard_False);
735 } else { // unknown function type
740 if (aShape.IsNull()) return 0;
742 aFunction->SetValue(aShape);
744 log.SetTouched(Label());
749 //=======================================================================
750 //function : MultiTransformate1D
752 //=======================================================================
753 void GEOMImpl_BlockDriver::MultiTransformate1D (const TopoDS_Shape& theBlock,
754 const TopoDS_Shape& theFace1,
755 const TopoDS_Shape& theFace2,
756 const Standard_Integer theNbIter,
757 TopoDS_Shape& theResult) const
759 // Construct Tool, where <theFace1> will be the first face,
760 // and a face, opposite to <theFace1>, will be the second face
761 GEOMImpl_Block6Explorer aBlockTool;
762 aBlockTool.InitByBlockAndFace(theBlock, theFace1);
764 // Find IDs of the faces
765 Standard_Integer dir_face1 = 1, dir_face2 = 2;
766 if (!theFace2.IsNull()) {
767 dir_face2 = aBlockTool.GetFaceID(theFace2);
770 // Find three pairs of points
771 Standard_Integer v11_id = 0, v12_id = 0, v13_id = 0; // vertices of the first face
772 Standard_Integer v21_id = 0, v22_id = 0, v23_id = 0; // vertices of the second face
774 if (dir_face2 == 2) { // <theFace2> is opposite to <theFace1>
776 // We will take vertices with equal local numbers on the faces,
777 // as the Block6Explorer gives equal local numbers
778 // to the linked vertices on the opposite faces,
779 // i.e. v1* is linked with the v2* by an edge:
783 // / | / | dir_face1 - bottom
785 // /________ / | dir_face2 - top
794 v11_id = aBlockTool.GetVertexID(dir_face1, 1);
795 v12_id = aBlockTool.GetVertexID(dir_face1, 2);
796 v13_id = aBlockTool.GetVertexID(dir_face1, 4);
798 v21_id = aBlockTool.GetVertexID(dir_face2, 1);
799 v22_id = aBlockTool.GetVertexID(dir_face2, 2);
800 v23_id = aBlockTool.GetVertexID(dir_face2, 4);
806 // / | / | dir_face1 - bottom
808 // /________ / | dir_face2 - right (for example)
811 // | / | /v12 = v22 (common_vertex2)
815 // v13 v11 = v21 (common_vertex1)
817 Standard_Integer common_edge_id = aBlockTool.FindCommonEdgeID(dir_face1, dir_face2);
818 Standard_Integer common_vertex1 = aBlockTool.GetVertexOnEdgeID(common_edge_id, 1);
819 Standard_Integer common_vertex2 = aBlockTool.GetVertexOnEdgeID(common_edge_id, 2);
821 Standard_Integer not_common_v1 = 0;
822 Standard_Integer vid = 1;
823 Standard_Boolean isFound = Standard_False;
824 while (!isFound && vid <= 4) {
825 not_common_v1 = aBlockTool.GetVertexID(dir_face1, vid);
826 isFound = (not_common_v1 != common_vertex2 &&
827 aBlockTool.FindEdgeID(not_common_v1, common_vertex1) != 0);
831 Standard_Integer not_common_v2 = 0;
833 isFound = Standard_False;
834 while (!isFound && vid <= 4) {
835 not_common_v2 = aBlockTool.GetVertexID(dir_face2, vid);
836 isFound = (not_common_v2 != common_vertex2 &&
837 aBlockTool.FindEdgeID(not_common_v2, common_vertex1) != 0);
841 v11_id = common_vertex1;
842 v12_id = common_vertex2;
843 v13_id = not_common_v1;
845 v21_id = common_vertex1;
846 v22_id = common_vertex2;
847 v23_id = not_common_v2;
850 // Construct a transformation operator
851 TopoDS_Vertex V11 = TopoDS::Vertex(aBlockTool.GetVertex(v11_id));
852 TopoDS_Vertex V12 = TopoDS::Vertex(aBlockTool.GetVertex(v12_id));
853 TopoDS_Vertex V13 = TopoDS::Vertex(aBlockTool.GetVertex(v13_id));
855 TopoDS_Vertex V21 = TopoDS::Vertex(aBlockTool.GetVertex(v21_id));
856 TopoDS_Vertex V22 = TopoDS::Vertex(aBlockTool.GetVertex(v22_id));
857 TopoDS_Vertex V23 = TopoDS::Vertex(aBlockTool.GetVertex(v23_id));
859 // Axes of the first direction face
860 gp_Pnt P1 = BRep_Tool::Pnt(V11);
861 gp_Vec VecN1 (P1, BRep_Tool::Pnt(V12));
862 gp_Vec VecX1 (P1, BRep_Tool::Pnt(V13));
863 gp_Ax3 Ax1 (P1, VecN1, VecX1);
865 // Axes of the second direction face
866 gp_Pnt P2 = BRep_Tool::Pnt(V21);
867 gp_Vec VecN2 (P2, BRep_Tool::Pnt(V22));
868 gp_Vec VecX2 (P2, BRep_Tool::Pnt(V23));
869 gp_Ax3 Ax2 (P2, VecN2, VecX2);
872 aTrsf.SetDisplacement(Ax1, Ax2);
874 // Check, that <theFace2> is similar to <theFace1>.
875 // Actually, we need only to check right position of one
876 // vertex, not involved into the transformation construction.
877 if (!aBlockTool.IsSimilarFaces(dir_face1, dir_face2, aTrsf)) {
878 Standard_ConstructionError::Raise("The direction faces are not similar");
881 // Perform multi-transformation
882 TopoDS_Compound aCompound;
884 B.MakeCompound(aCompound);
886 TopoDS_Shape aPrevShape = theBlock;
887 for (Standard_Integer i = 0; i < theNbIter; i++) {
888 B.Add(aCompound, aPrevShape);
889 BRepBuilderAPI_Transform aTransformation (aPrevShape, aTrsf, Standard_False);
890 aPrevShape = aTransformation.Shape();
892 theResult = aCompound;
895 //=======================================================================
896 //function : MultiTransformate2D
898 //=======================================================================
899 void GEOMImpl_BlockDriver::MultiTransformate2D (const TopoDS_Shape& theBlock,
900 const TopoDS_Shape& theFace1U,
901 const TopoDS_Shape& theFace2U,
902 const Standard_Integer theNbIterU,
903 const TopoDS_Shape& theFace1V,
904 const TopoDS_Shape& theFace2V,
905 const Standard_Integer theNbIterV,
906 TopoDS_Shape& theResult) const
908 // Construct Tool, where <theFace1U> will be the first face,
909 // and a face, opposite to <theFace1U>, will be the second face
910 GEOMImpl_Block6Explorer aBlockTool;
911 aBlockTool.InitByBlockAndFace(theBlock, theFace1U);
913 gp_Trsf aTrsfU, aTrsfV;
915 for (Standard_Integer uv = 1; uv <= 2; uv++) {
917 TopoDS_Shape theFace1 = theFace1U;
918 TopoDS_Shape theFace2 = theFace2U;
921 theFace1 = theFace1V;
922 theFace2 = theFace2V;
925 // Find IDs of the faces
926 Standard_Integer dir_face1 = aBlockTool.GetFaceID(theFace1);
927 Standard_Integer dir_face2 = 0;
928 Standard_Integer opp_face1 = aBlockTool.GetOppositeFaceID(dir_face1);
929 if (theFace2.IsNull()) {
930 dir_face2 = opp_face1;
932 dir_face2 = aBlockTool.GetFaceID(theFace2);
935 // Find three pairs of points
936 Standard_Integer v11_id = 0, v12_id = 0, v13_id = 0; // vertices of the first face
937 Standard_Integer v21_id = 0, v22_id = 0, v23_id = 0; // vertices of the second face
939 if (dir_face2 == opp_face1) { // <theFace2> is opposite to <theFace1>
941 // We will take vertices with equal local numbers on the faces,
942 // as the Block6Explorer gives equal local numbers
943 // to the linked vertices on the opposite faces,
944 // i.e. v1* is linked with the v2* by an edge:
946 v11_id = aBlockTool.GetVertexID(dir_face1, 1);
947 v12_id = aBlockTool.GetVertexID(dir_face1, 2);
948 v13_id = aBlockTool.GetVertexID(dir_face1, 4);
950 v21_id = aBlockTool.GetVertexID(dir_face2, 1);
951 v22_id = aBlockTool.GetVertexID(dir_face2, 2);
952 v23_id = aBlockTool.GetVertexID(dir_face2, 4);
956 Standard_Integer common_edge_id = aBlockTool.FindCommonEdgeID(dir_face1, dir_face2);
957 Standard_Integer common_vertex1 = aBlockTool.GetVertexOnEdgeID(common_edge_id, 1);
958 Standard_Integer common_vertex2 = aBlockTool.GetVertexOnEdgeID(common_edge_id, 2);
960 Standard_Integer not_common_v1 = 0;
961 Standard_Integer vid = 1;
962 Standard_Boolean isFound = Standard_False;
963 while (!isFound && vid <= 4) {
964 not_common_v1 = aBlockTool.GetVertexID(dir_face1, vid);
965 isFound = (not_common_v1 != common_vertex2 &&
966 aBlockTool.FindEdgeID(not_common_v1, common_vertex1) != 0);
970 Standard_Integer not_common_v2 = 0;
972 isFound = Standard_False;
973 while (!isFound && vid <= 4) {
974 not_common_v2 = aBlockTool.GetVertexID(dir_face2, vid);
975 isFound = (not_common_v2 != common_vertex2 &&
976 aBlockTool.FindEdgeID(not_common_v2, common_vertex1) != 0);
980 v11_id = common_vertex1;
981 v12_id = common_vertex2;
982 v13_id = not_common_v1;
984 v21_id = common_vertex1;
985 v22_id = common_vertex2;
986 v23_id = not_common_v2;
989 // Construct a transformation operator
990 TopoDS_Vertex V11 = TopoDS::Vertex(aBlockTool.GetVertex(v11_id));
991 TopoDS_Vertex V12 = TopoDS::Vertex(aBlockTool.GetVertex(v12_id));
992 TopoDS_Vertex V13 = TopoDS::Vertex(aBlockTool.GetVertex(v13_id));
994 TopoDS_Vertex V21 = TopoDS::Vertex(aBlockTool.GetVertex(v21_id));
995 TopoDS_Vertex V22 = TopoDS::Vertex(aBlockTool.GetVertex(v22_id));
996 TopoDS_Vertex V23 = TopoDS::Vertex(aBlockTool.GetVertex(v23_id));
998 // Axes of the first direction face
999 gp_Pnt P1 = BRep_Tool::Pnt(V11);
1000 gp_Vec VecN1 (P1, BRep_Tool::Pnt(V12));
1001 gp_Vec VecX1 (P1, BRep_Tool::Pnt(V13));
1002 gp_Ax3 Ax1 (P1, VecN1, VecX1);
1004 // Axes of the second direction face
1005 gp_Pnt P2 = BRep_Tool::Pnt(V21);
1006 gp_Vec VecN2 (P2, BRep_Tool::Pnt(V22));
1007 gp_Vec VecX2 (P2, BRep_Tool::Pnt(V23));
1008 gp_Ax3 Ax2 (P2, VecN2, VecX2);
1011 aTrsf.SetDisplacement(Ax1, Ax2);
1020 // Check, that <theFace2> is similar to <theFace1>.
1021 // Actually, we need only to check right position of one
1022 // vertex, not involved into the transformation construction.
1023 if (!aBlockTool.IsSimilarFaces(dir_face1, dir_face2, aTrsf)) {
1024 Standard_ConstructionError::Raise("The direction faces are not similar");
1028 // Perform multi-transformation
1029 TopoDS_Compound aCompound;
1031 B.MakeCompound(aCompound);
1033 TopoDS_Shape aPrevShapeU = theBlock;
1034 for (int i = 0; i < theNbIterU; i++) {
1035 TopoDS_Shape aPrevShapeV = aPrevShapeU;
1036 for (int j = 0; j < theNbIterV; j++) {
1037 B.Add(aCompound, aPrevShapeV);
1038 BRepBuilderAPI_Transform aTransformationV (aPrevShapeV, aTrsfV, Standard_False);
1039 aPrevShapeV = aTransformationV.Shape();
1041 BRepBuilderAPI_Transform aTransformationU (aPrevShapeU, aTrsfU, Standard_False);
1042 aPrevShapeU = aTransformationU.Shape();
1043 // Correction of the second transformation according to the first transformation
1044 Ax1V.Transform(aTrsfU);
1045 Ax2V.Transform(aTrsfU);
1046 aTrsfV.SetDisplacement(Ax1V, Ax2V);
1049 theResult = aCompound;
1052 //=======================================================================
1053 //function : GEOMImpl_BlockDriver_Type_
1055 //=======================================================================
1056 Standard_EXPORT Handle_Standard_Type& GEOMImpl_BlockDriver_Type_()
1059 static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver);
1060 if ( aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver);
1061 static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared);
1062 if ( aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared);
1063 static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient);
1064 if ( aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient);
1067 static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL};
1068 static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_BlockDriver",
1069 sizeof(GEOMImpl_BlockDriver),
1071 (Standard_Address)_Ancestors,
1072 (Standard_Address)NULL);
1077 //=======================================================================
1078 //function : DownCast
1080 //=======================================================================
1081 const Handle(GEOMImpl_BlockDriver) Handle(GEOMImpl_BlockDriver)::DownCast
1082 (const Handle(Standard_Transient)& AnObject)
1084 Handle(GEOMImpl_BlockDriver) _anOtherObject;
1086 if (!AnObject.IsNull()) {
1087 if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_BlockDriver))) {
1088 _anOtherObject = Handle(GEOMImpl_BlockDriver)((Handle(GEOMImpl_BlockDriver)&)AnObject);
1092 return _anOtherObject;