]> SALOME platform Git repositories - modules/geom.git/blob - src/GEOMImpl/GEOMImpl_PrismDriver.cxx
Salome HOME
Merge from V6_main 11/02/2013
[modules/geom.git] / src / GEOMImpl / GEOMImpl_PrismDriver.cxx
1 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
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.
10 //
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.
15 //
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
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21
22 #include <GEOMImpl_PrismDriver.hxx>
23
24 #include <GEOMImpl_IPrism.hxx>
25 #include <GEOMImpl_GlueDriver.hxx>
26 #include <GEOMImpl_PipeDriver.hxx>
27 #include <GEOMImpl_Types.hxx>
28
29 #include <GEOM_Function.hxx>
30 #include <GEOM_Object.hxx>
31
32 #include <GEOMUtils.hxx>
33
34 #include <BRepPrimAPI_MakePrism.hxx>
35 #include <BRepFeat_MakeDPrism.hxx>
36
37 #include <BRep_Builder.hxx>
38 #include <BRepBuilderAPI_MakeEdge.hxx>
39 #include <BRepBuilderAPI_MakeWire.hxx>
40 #include <BRepBuilderAPI_MakeFace.hxx>
41 #include <BRepBuilderAPI_MakeVertex.hxx>
42 #include <BRepBuilderAPI_Sewing.hxx>
43 #include <BRepBuilderAPI_Transform.hxx>
44 #include <BRepCheck_Shell.hxx>
45 #include <BRepClass3d_SolidClassifier.hxx>
46 #include <BRep_Tool.hxx>
47 #include <BRepTools.hxx>
48
49 #include <TopAbs.hxx>
50 #include <TopExp.hxx>
51 #include <TopExp_Explorer.hxx>
52 #include <TopoDS.hxx>
53 #include <TopoDS_Compound.hxx>
54 #include <TopoDS_Edge.hxx>
55 #include <TopoDS_Shape.hxx>
56 #include <TopoDS_Shell.hxx>
57 #include <TopoDS_Solid.hxx>
58 #include <TopoDS_Vertex.hxx>
59 #include <TopTools_HSequenceOfShape.hxx>
60 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
61
62 #include <Precision.hxx>
63 #include <gp_Ax3.hxx>
64 #include <gp_Pnt.hxx>
65 #include <gp_Vec.hxx>
66 #include <gp_Trsf.hxx>
67
68 #include <Standard_Stream.hxx>
69
70 #include <Standard_ConstructionError.hxx>
71
72 #include "utilities.h"
73
74 //=======================================================================
75 //function : GetID
76 //purpose  :
77 //=======================================================================
78 const Standard_GUID& GEOMImpl_PrismDriver::GetID()
79 {
80   static Standard_GUID aPrismDriver("FF1BBB17-5D14-4df2-980B-3A668264EA16");
81   return aPrismDriver;
82 }
83
84
85 //=======================================================================
86 //function : GEOMImpl_PrismDriver
87 //purpose  :
88 //=======================================================================
89 GEOMImpl_PrismDriver::GEOMImpl_PrismDriver()
90 {
91 }
92
93 //=======================================================================
94 //function : Execute
95 //purpose  :
96 //=======================================================================
97 Standard_Integer GEOMImpl_PrismDriver::Execute(TFunction_Logbook& log) const
98 {
99   if (Label().IsNull()) return 0;
100   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
101
102   GEOMImpl_IPrism aCI (aFunction);
103   Standard_Integer aType = aFunction->GetType();
104
105   TopoDS_Shape aShape;
106
107   if (aType == PRISM_BASE_VEC_H || aType == PRISM_BASE_VEC_H_2WAYS) {
108     Handle(GEOM_Function) aRefBase = aCI.GetBase();
109     Handle(GEOM_Function) aRefVector = aCI.GetVector();
110     TopoDS_Shape aShapeBase = aRefBase->GetValue();
111     TopoDS_Shape aShapeVec = aRefVector->GetValue();
112     if (aShapeVec.ShapeType() == TopAbs_EDGE) {
113       TopoDS_Edge anE = TopoDS::Edge(aShapeVec);
114       TopoDS_Vertex V1, V2;
115       TopExp::Vertices(anE, V1, V2, Standard_True);
116       if (!V1.IsNull() && !V2.IsNull()) {
117         gp_Vec aV (BRep_Tool::Pnt(V1), BRep_Tool::Pnt(V2));
118         if (Abs(aCI.GetH()) < Precision::Confusion()) {
119           Standard_ConstructionError::Raise("Absolute value of prism height is too small");
120         }
121         if (aV.Magnitude() > Precision::Confusion()) {
122           aV.Normalize();
123           if (aType != PRISM_BASE_DXDYDZ_2WAYS && aCI.GetScale() > Precision::Confusion()) {
124             aShape = MakeScaledPrism(aShapeBase, aV * aCI.GetH(), aCI.GetScale());
125           }
126           else {
127             if (aType == PRISM_BASE_VEC_H_2WAYS) {
128               gp_Trsf aTrsf;
129               aTrsf.SetTranslation((-aV) * aCI.GetH());
130               BRepBuilderAPI_Transform aTransformation(aShapeBase, aTrsf, Standard_False);
131               aShapeBase = aTransformation.Shape();
132               aCI.SetH(aCI.GetH()*2);
133             }
134             aShape = BRepPrimAPI_MakePrism(aShapeBase, aV * aCI.GetH(), Standard_False).Shape();
135           }
136         }
137       }
138     }
139   } else if (aType == PRISM_BASE_TWO_PNT || aType == PRISM_BASE_TWO_PNT_2WAYS) {
140     Handle(GEOM_Function) aRefBase = aCI.GetBase();
141     Handle(GEOM_Function) aRefPnt1 = aCI.GetFirstPoint();
142     Handle(GEOM_Function) aRefPnt2 = aCI.GetLastPoint();
143     TopoDS_Shape aShapeBase = aRefBase->GetValue();
144     TopoDS_Shape aShapePnt1 = aRefPnt1->GetValue();
145     TopoDS_Shape aShapePnt2 = aRefPnt2->GetValue();
146     if (aShapePnt1.ShapeType() == TopAbs_VERTEX &&
147         aShapePnt2.ShapeType() == TopAbs_VERTEX) {
148       TopoDS_Vertex V1 = TopoDS::Vertex(aShapePnt1);
149       TopoDS_Vertex V2 = TopoDS::Vertex(aShapePnt2);
150       if (!V1.IsNull() && !V2.IsNull()) {
151         gp_Vec aV (BRep_Tool::Pnt(V1), BRep_Tool::Pnt(V2));
152         if (aV.Magnitude() > gp::Resolution()) {
153           if (aType != PRISM_BASE_DXDYDZ_2WAYS && aCI.GetScale() > Precision::Confusion()) {
154             aShape = MakeScaledPrism(aShapeBase, aV, aCI.GetScale());
155           }
156           else {
157             if (aType == PRISM_BASE_TWO_PNT_2WAYS) {
158               gp_Trsf aTrsf;
159               aTrsf.SetTranslation(-aV);
160               BRepBuilderAPI_Transform aTransformation(aShapeBase, aTrsf, Standard_False);
161               aShapeBase = aTransformation.Shape();
162               aV = aV * 2;
163             }
164             aShape = BRepPrimAPI_MakePrism(aShapeBase, aV, Standard_False).Shape();
165           }
166         }
167       }
168     }
169   } else if (aType == PRISM_BASE_DXDYDZ || aType == PRISM_BASE_DXDYDZ_2WAYS) {
170     Handle(GEOM_Function) aRefBase = aCI.GetBase();
171     TopoDS_Shape aShapeBase = aRefBase->GetValue();
172     gp_Vec aV (aCI.GetDX(), aCI.GetDY(), aCI.GetDZ());
173     if (aV.Magnitude() > gp::Resolution()) {
174       if (aType != PRISM_BASE_DXDYDZ_2WAYS && aCI.GetScale() > Precision::Confusion()) {
175         aShape = MakeScaledPrism(aShapeBase, aV, aCI.GetScale());
176       }
177       else {
178         if (aType == PRISM_BASE_DXDYDZ_2WAYS) {
179           gp_Trsf aTrsf;
180           aTrsf.SetTranslation(-aV);
181           BRepBuilderAPI_Transform aTransformation(aShapeBase, aTrsf, Standard_False);
182           aShapeBase = aTransformation.Shape();
183           aV = aV * 2;
184         }
185         aShape = BRepPrimAPI_MakePrism(aShapeBase, aV, Standard_False).Shape();
186       }
187     }
188   }
189   
190   else if (aType == DRAFT_PRISM_FEATURE) {
191     Handle(GEOM_Function) aRefInit = aCI.GetInitShape();
192     Handle(GEOM_Function) aRefBase = aCI.GetBase();   
193     TopoDS_Shape anInitShape = aRefInit->GetValue();        // Initial shape
194     TopoDS_Shape aSketch     = aRefBase->GetValue();  
195     Standard_Real aHeight    = aCI.GetH();                  // Height of the extrusion
196     Standard_Real anAngle    = aCI.GetDraftAngle();         // Draft angle
197     Standard_Boolean isProtrusion = (aCI.GetFuseFlag()==1); 
198     // Flag to know wether the feature is a protrusion (fuse) or a depression (cut)
199     
200     // history of the Base wire (RefBase)
201     Handle(GEOM_Object) aSuppObj;
202     TDF_LabelSequence aLabelSeq;
203     aRefBase->GetDependency(aLabelSeq);
204     
205     // If the base wire has only one dependency we use it
206     // to determine the right normal of the face which
207     // must be oriented towards outside of the solid (like the support face)
208     if (aLabelSeq.Length()==1)  
209     {
210       TDF_Label anArgumentRefLabel = aLabelSeq.Value(1);
211       aSuppObj = GEOM_Object::GetReferencedObject(anArgumentRefLabel);   
212     }
213     
214     TopoDS_Shape aSupport;
215     
216     if(!aSuppObj.IsNull())      // If the wire has a support
217       aSupport = aSuppObj->GetValue();
218     
219     aShape = MakeDraftPrism(anInitShape, aSketch, aHeight, anAngle, isProtrusion, aSupport); 
220   }
221
222   if (aShape.IsNull()) return 0;
223   
224   
225   if (aType == DRAFT_PRISM_FEATURE)
226   {
227     TopoDS_Shape aRes = aShape;
228     
229     // If the result is a compound with only one solid,
230     // return the solid
231     if (aShape.ShapeType() == TopAbs_COMPOUND)  
232     {
233       TopExp_Explorer anExp(aShape, TopAbs_SOLID);
234       
235       int solidNb = 0;
236       TopoDS_Solid aSolid;
237       
238       for(;anExp.More();anExp.Next())
239       {
240         aSolid = TopoDS::Solid(anExp.Current());
241         solidNb++;
242         if (solidNb > 1)
243           break;
244       }
245       if (solidNb == 1)
246         aRes = aSolid;
247     } 
248     
249     aFunction->SetValue(aRes);
250   }
251   else
252   {
253     TopoDS_Shape aRes = GEOMUtils::CompsolidToCompound(aShape);
254     aFunction->SetValue(aRes);
255   }
256   
257
258   log.SetTouched(Label());
259
260   return 1;
261 }
262
263 //=======================================================================
264 //function : MakeScaledPrism
265 //purpose  :
266 //=======================================================================
267 TopoDS_Shape GEOMImpl_PrismDriver::MakeScaledPrism (const TopoDS_Shape& theShapeBase,
268                                                     const gp_Vec&       theVector,
269                                                     const Standard_Real theScaleFactor,
270                                                     const gp_Pnt&       theCDG,
271                                                     bool                isCDG)
272 {
273   TopoDS_Shape aShape;
274   BRep_Builder B;
275
276   // 1. aCDG = geompy.MakeCDG(theBase)
277   gp_Pnt aCDG = theCDG;
278   if (!isCDG) {
279     gp_Ax3 aPos = GEOMUtils::GetPosition(theShapeBase);
280     aCDG = aPos.Location();
281   }
282   TopoDS_Shape aShapeCDG_1 = BRepBuilderAPI_MakeVertex(aCDG).Shape();
283
284   // Process case of several given shapes
285   if (theShapeBase.ShapeType() == TopAbs_COMPOUND ||
286       theShapeBase.ShapeType() == TopAbs_SHELL) {
287     int nbSub = 0;
288     TopoDS_Shape aShapeI;
289     TopoDS_Compound aCompound;
290     B.MakeCompound(aCompound);
291     TopoDS_Iterator It (theShapeBase, Standard_True, Standard_True);
292     for (; It.More(); It.Next()) {
293       nbSub++;
294       aShapeI = MakeScaledPrism(It.Value(), theVector, theScaleFactor, aCDG, true);
295       B.Add(aCompound, aShapeI);
296     }
297     if (nbSub == 1)
298       aShape = aShapeI;
299     else if (nbSub > 1)
300       aShape = GEOMImpl_GlueDriver::GlueFaces(aCompound, Precision::Confusion(), Standard_True);
301     return aShape;
302   }
303
304   // 2. Scale = geompy.MakeScaleTransform(theBase, aCDG, theScaleFactor)
305
306   // Bug 6839: Check for standalone (not included in faces) degenerated edges
307   TopTools_IndexedDataMapOfShapeListOfShape aEFMap;
308   TopExp::MapShapesAndAncestors(theShapeBase, TopAbs_EDGE, TopAbs_FACE, aEFMap);
309   Standard_Integer i, nbE = aEFMap.Extent();
310   for (i = 1; i <= nbE; i++) {
311     TopoDS_Shape anEdgeSh = aEFMap.FindKey(i);
312     if (BRep_Tool::Degenerated(TopoDS::Edge(anEdgeSh))) {
313       const TopTools_ListOfShape& aFaces = aEFMap.FindFromIndex(i);
314       if (aFaces.IsEmpty())
315         Standard_ConstructionError::Raise
316           ("Scaling aborted : cannot scale standalone degenerated edge");
317     }
318   }
319
320   // Perform Scaling
321   gp_Trsf aTrsf;
322   aTrsf.SetScale(aCDG, theScaleFactor);
323   BRepBuilderAPI_Transform aBRepTrsf (theShapeBase, aTrsf, Standard_False);
324   TopoDS_Shape aScale = aBRepTrsf.Shape();
325
326   // 3. aBase2 = geompy.MakeTranslationVectorDistance(Scale, theVec, theH)
327   gp_Trsf aTrsf3;
328   aTrsf3.SetTranslation(theVector);
329   TopLoc_Location aLocOrig = aScale.Location();
330   gp_Trsf aTrsfOrig = aLocOrig.Transformation();
331   TopLoc_Location aLocRes (aTrsf3 * aTrsfOrig);
332   TopoDS_Shape aBase2 = aScale.Located(aLocRes);
333
334   // 4. aCDG_2 = geompy.MakeTranslationVectorDistance(aCDG, theVec, theH)
335   gp_Pnt aCDG_2 = aCDG.Translated(theVector);
336   TopoDS_Shape aShapeCDG_2 = BRepBuilderAPI_MakeVertex(aCDG_2).Shape();
337
338   // 5. Vector = geompy.MakeVector(aCDG, aCDG_2)
339   TopoDS_Shape aShapeVec = BRepBuilderAPI_MakeEdge(aCDG, aCDG_2).Shape();
340   TopoDS_Edge anEdge = TopoDS::Edge(aShapeVec);
341   TopoDS_Wire aWirePath = BRepBuilderAPI_MakeWire(anEdge);
342
343   // 6. aPrism = geompy.MakePipeWithDifferentSections([theBase, aBase2], [aCDG, aCDG_2], Vector, False, False)
344   Handle(TopTools_HSequenceOfShape) aBases = new TopTools_HSequenceOfShape;
345   aBases->Append(theShapeBase);
346   aBases->Append(aBase2);
347
348   Handle(TopTools_HSequenceOfShape) aLocs = new TopTools_HSequenceOfShape;
349   aLocs->Append(aShapeCDG_1);
350   aLocs->Append(aShapeCDG_2);
351
352   aShape = GEOMImpl_PipeDriver::CreatePipeWithDifferentSections(aWirePath, aBases, aLocs, false, false);
353
354   // 7. Make a solid, if possible
355   if (theShapeBase.ShapeType() == TopAbs_FACE) {
356     BRepBuilderAPI_Sewing aSewing (Precision::Confusion()*10.0);
357     TopExp_Explorer expF (aShape, TopAbs_FACE);
358     Standard_Integer ifa = 0;
359     for (; expF.More(); expF.Next()) {
360       aSewing.Add(expF.Current());
361       ifa++;
362     }
363     if (ifa > 0) {
364       aSewing.Perform();
365       TopoDS_Shape aShell;
366
367       TopoDS_Shape sh = aSewing.SewedShape();
368       if (sh.ShapeType() == TopAbs_FACE && ifa == 1) {
369         // case for creation of shell from one face
370         TopoDS_Shell ss;
371         B.MakeShell(ss);
372         B.Add(ss,sh);
373         aShell = ss;
374       }
375       else {
376         TopExp_Explorer exp (sh, TopAbs_SHELL);
377         Standard_Integer ish = 0;
378         for (; exp.More(); exp.Next()) {
379           aShell = exp.Current();
380           ish++;
381         }
382         if (ish != 1)
383           aShell = sh;
384       }
385       BRepCheck_Shell chkShell (TopoDS::Shell(aShell));
386       if (chkShell.Closed() == BRepCheck_NoError) {
387         TopoDS_Solid Sol;
388         B.MakeSolid(Sol);
389         B.Add(Sol, aShell);
390         BRepClass3d_SolidClassifier SC (Sol);
391         SC.PerformInfinitePoint(Precision::Confusion());
392         if (SC.State() == TopAbs_IN) {
393           B.MakeSolid(Sol);
394           B.Add(Sol, aShell.Reversed());
395         }
396         aShape = Sol;
397       }
398     }
399   }
400
401   return aShape;
402 }
403
404 //=======================================================================
405 //function : MakeDraftPrism
406 //purpose  :
407 //=======================================================================
408 TopoDS_Shape GEOMImpl_PrismDriver::MakeDraftPrism ( const TopoDS_Shape& theInitShape,
409                                                     const TopoDS_Shape& theBaseShape,
410                                                     const Standard_Real theHeight,
411                                                     const Standard_Real theAngle,
412                                                     bool                isProtrusion,
413                                                     const TopoDS_Shape& theSupport)
414 {
415   TopoDS_Shape aShape;
416   
417   if (theInitShape.ShapeType() == TopAbs_COMPOUND)
418     {
419       TopExp_Explorer anExp(theInitShape, TopAbs_SOLID);
420       int solidCount = 0;
421       for(;anExp.More();anExp.Next())
422       {
423         solidCount++;
424         if (solidCount > 1)
425           Standard_ConstructionError::Raise("The input shape is a compound with more than one solid");
426       }
427       if (solidCount == 0)
428         Standard_ConstructionError::Raise("The input shape is a compound without any solid");
429     }
430     
431     TopoDS_Wire aWire = TopoDS_Wire();
432     
433     if (theBaseShape.ShapeType() == TopAbs_EDGE)
434     {
435       aWire = BRepBuilderAPI_MakeWire(TopoDS::Edge(theBaseShape));
436     }
437     else if (theBaseShape.ShapeType() == TopAbs_WIRE)
438     {
439       aWire = TopoDS::Wire(theBaseShape);
440     }
441     else
442     {
443       Standard_ConstructionError::Raise("The input profile is neither a wire, nor edge");
444     }
445     
446     TopoDS_Vertex aV1, aV2;
447     TopExp::Vertices(aWire, aV1, aV2);
448     if ( !aV1.IsNull() && !aV2.IsNull() && aV1.IsSame(aV2) )
449       aWire.Closed( true );
450     
451     if (!aWire.Closed())
452       Standard_ConstructionError::Raise("The input profile is not closed");
453     
454     // Construction of the face if the wire hasn't any support face;
455     // the face must be planar for BRepFeat_MakeDPrism
456     TopoDS_Face aFaceBase = BRepBuilderAPI_MakeFace(aWire, /*OnlyPlane=*/true);
457
458     if(!theSupport.IsNull() && theSupport.ShapeType() == TopAbs_FACE) // If the wire has a support
459     {
460       Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(theSupport));
461       TopoDS_Face aTempFace = BRepBuilderAPI_MakeFace(aSurf, aWire);
462       
463       if(aTempFace.Orientation() != TopoDS::Face(theSupport).Orientation())
464       {
465         aFaceBase=TopoDS::Face(aTempFace.Reversed());
466       }
467       else
468         aFaceBase=aTempFace;
469     } 
470     
471     // Invert height and angle if the operation is an extruded cut
472     bool invert = !isProtrusion; 
473     
474     // If the face has a reversed orientation invert for extruded boss operations
475     if(aFaceBase.Orientation() == TopAbs_REVERSED)
476       invert = isProtrusion;
477
478     Standard_Real anAngle = theAngle;
479     Standard_Real aHeight = theHeight;
480     if(invert)
481     {
482       anAngle  = -theAngle;  // Invert angle and height
483       aHeight  = -theHeight;
484     }
485     
486     BRepFeat_MakeDPrism aPrism(theInitShape, aFaceBase, aFaceBase,
487                                anAngle*M_PI/180., isProtrusion, Standard_True); 
488     
489     aPrism.Perform(aHeight);
490     aPrism.Check();          // Raises NotDone if done is false
491     
492     aShape = aPrism.Shape();
493     
494     return aShape;
495 }
496                                                    
497
498 //=======================================================================
499 //function : GEOMImpl_PrismDriver_Type_
500 //purpose  :
501 //=======================================================================
502 Standard_EXPORT Handle_Standard_Type& GEOMImpl_PrismDriver_Type_()
503 {
504
505   static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver);
506   if (aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver);
507   static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared);
508   if (aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared);
509   static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient);
510   if (aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient);
511
512   static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL};
513   static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_PrismDriver",
514                                                          sizeof(GEOMImpl_PrismDriver),
515                                                          1,
516                                                          (Standard_Address)_Ancestors,
517                                                          (Standard_Address)NULL);
518
519   return _aType;
520 }
521
522 //=======================================================================
523 //function : DownCast
524 //purpose  :
525 //=======================================================================
526 const Handle(GEOMImpl_PrismDriver) Handle(GEOMImpl_PrismDriver)::DownCast(const Handle(Standard_Transient)& AnObject)
527 {
528   Handle(GEOMImpl_PrismDriver) _anOtherObject;
529
530   if (!AnObject.IsNull()) {
531      if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_PrismDriver))) {
532        _anOtherObject = Handle(GEOMImpl_PrismDriver)((Handle(GEOMImpl_PrismDriver)&)AnObject);
533      }
534   }
535
536   return _anOtherObject;
537 }