Salome HOME
Small fix in French resource file
[modules/geom.git] / src / GEOMImpl / GEOMImpl_PrismDriver.cxx
1 // Copyright (C) 2007-2011  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
23 #include <GEOMImpl_PrismDriver.hxx>
24
25 #include <GEOMImpl_IPrism.hxx>
26 #include <GEOMImpl_IShapesOperations.hxx>
27 #include <GEOMImpl_IMeasureOperations.hxx>
28 #include <GEOMImpl_GlueDriver.hxx>
29 #include <GEOMImpl_PipeDriver.hxx>
30 #include <GEOMImpl_Types.hxx>
31 #include <GEOM_Function.hxx>
32
33 #include <BRepPrimAPI_MakePrism.hxx>
34
35 #include <BRep_Builder.hxx>
36 #include <BRepBuilderAPI_MakeEdge.hxx>
37 #include <BRepBuilderAPI_MakeWire.hxx>
38 #include <BRepBuilderAPI_MakeVertex.hxx>
39 #include <BRepBuilderAPI_Sewing.hxx>
40 #include <BRepBuilderAPI_Transform.hxx>
41 #include <BRepCheck_Shell.hxx>
42 #include <BRepClass3d_SolidClassifier.hxx>
43 #include <BRep_Tool.hxx>
44
45 #include <TopAbs.hxx>
46 #include <TopExp.hxx>
47 #include <TopExp_Explorer.hxx>
48 #include <TopoDS.hxx>
49 #include <TopoDS_Compound.hxx>
50 #include <TopoDS_Edge.hxx>
51 #include <TopoDS_Shape.hxx>
52 #include <TopoDS_Shell.hxx>
53 #include <TopoDS_Solid.hxx>
54 #include <TopoDS_Vertex.hxx>
55 #include <TopTools_HSequenceOfShape.hxx>
56 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
57
58 #include <Precision.hxx>
59 #include <gp_Ax3.hxx>
60 #include <gp_Pnt.hxx>
61 #include <gp_Vec.hxx>
62 #include <gp_Trsf.hxx>
63
64 #include <Standard_Stream.hxx>
65
66 #include <Standard_ConstructionError.hxx>
67
68 //=======================================================================
69 //function : GetID
70 //purpose  :
71 //=======================================================================
72 const Standard_GUID& GEOMImpl_PrismDriver::GetID()
73 {
74   static Standard_GUID aPrismDriver("FF1BBB17-5D14-4df2-980B-3A668264EA16");
75   return aPrismDriver;
76 }
77
78
79 //=======================================================================
80 //function : GEOMImpl_PrismDriver
81 //purpose  :
82 //=======================================================================
83 GEOMImpl_PrismDriver::GEOMImpl_PrismDriver()
84 {
85 }
86
87 //=======================================================================
88 //function : Execute
89 //purpose  :
90 //=======================================================================
91 Standard_Integer GEOMImpl_PrismDriver::Execute(TFunction_Logbook& log) const
92 {
93   if (Label().IsNull()) return 0;
94   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
95
96   GEOMImpl_IPrism aCI (aFunction);
97   Standard_Integer aType = aFunction->GetType();
98
99   TopoDS_Shape aShape;
100
101   if (aType == PRISM_BASE_VEC_H || aType == PRISM_BASE_VEC_H_2WAYS) {
102     Handle(GEOM_Function) aRefBase = aCI.GetBase();
103     Handle(GEOM_Function) aRefVector = aCI.GetVector();
104     TopoDS_Shape aShapeBase = aRefBase->GetValue();
105     TopoDS_Shape aShapeVec = aRefVector->GetValue();
106     if (aShapeVec.ShapeType() == TopAbs_EDGE) {
107       TopoDS_Edge anE = TopoDS::Edge(aShapeVec);
108       TopoDS_Vertex V1, V2;
109       TopExp::Vertices(anE, V1, V2, Standard_True);
110       if (!V1.IsNull() && !V2.IsNull()) {
111         gp_Vec aV (BRep_Tool::Pnt(V1), BRep_Tool::Pnt(V2));
112         if (Abs(aCI.GetH()) < Precision::Confusion()) {
113           Standard_ConstructionError::Raise("Absolute value of prism height is too small");
114         }
115         if (aV.Magnitude() > Precision::Confusion()) {
116           aV.Normalize();
117           if (aType != PRISM_BASE_DXDYDZ_2WAYS && aCI.GetScale() > Precision::Confusion()) {
118             aShape = MakeScaledPrism(aShapeBase, aV * aCI.GetH(), aCI.GetScale());
119           }
120           else {
121             if (aType == PRISM_BASE_VEC_H_2WAYS) {
122               gp_Trsf aTrsf;
123               aTrsf.SetTranslation((-aV) * aCI.GetH());
124               BRepBuilderAPI_Transform aTransformation(aShapeBase, aTrsf, Standard_False);
125               aShapeBase = aTransformation.Shape();
126               aCI.SetH(aCI.GetH()*2);
127             }
128             aShape = BRepPrimAPI_MakePrism(aShapeBase, aV * aCI.GetH(), Standard_False).Shape();
129           }
130         }
131       }
132     }
133   } else if (aType == PRISM_BASE_TWO_PNT || aType == PRISM_BASE_TWO_PNT_2WAYS) {
134     Handle(GEOM_Function) aRefBase = aCI.GetBase();
135     Handle(GEOM_Function) aRefPnt1 = aCI.GetFirstPoint();
136     Handle(GEOM_Function) aRefPnt2 = aCI.GetLastPoint();
137     TopoDS_Shape aShapeBase = aRefBase->GetValue();
138     TopoDS_Shape aShapePnt1 = aRefPnt1->GetValue();
139     TopoDS_Shape aShapePnt2 = aRefPnt2->GetValue();
140     if (aShapePnt1.ShapeType() == TopAbs_VERTEX &&
141         aShapePnt2.ShapeType() == TopAbs_VERTEX) {
142       TopoDS_Vertex V1 = TopoDS::Vertex(aShapePnt1);
143       TopoDS_Vertex V2 = TopoDS::Vertex(aShapePnt2);
144       if (!V1.IsNull() && !V2.IsNull()) {
145         gp_Vec aV (BRep_Tool::Pnt(V1), BRep_Tool::Pnt(V2));
146         if (aV.Magnitude() > gp::Resolution()) {
147           if (aType != PRISM_BASE_DXDYDZ_2WAYS && aCI.GetScale() > Precision::Confusion()) {
148             aShape = MakeScaledPrism(aShapeBase, aV, aCI.GetScale());
149           }
150           else {
151             if (aType == PRISM_BASE_TWO_PNT_2WAYS) {
152               gp_Trsf aTrsf;
153               aTrsf.SetTranslation(-aV);
154               BRepBuilderAPI_Transform aTransformation(aShapeBase, aTrsf, Standard_False);
155               aShapeBase = aTransformation.Shape();
156               aV = aV * 2;
157             }
158             aShape = BRepPrimAPI_MakePrism(aShapeBase, aV, Standard_False).Shape();
159           }
160         }
161       }
162     }
163   } else if (aType == PRISM_BASE_DXDYDZ || aType == PRISM_BASE_DXDYDZ_2WAYS) {
164     Handle(GEOM_Function) aRefBase = aCI.GetBase();
165     TopoDS_Shape aShapeBase = aRefBase->GetValue();
166     gp_Vec aV (aCI.GetDX(), aCI.GetDY(), aCI.GetDZ());
167     if (aV.Magnitude() > gp::Resolution()) {
168       if (aType != PRISM_BASE_DXDYDZ_2WAYS && aCI.GetScale() > Precision::Confusion()) {
169         aShape = MakeScaledPrism(aShapeBase, aV, aCI.GetScale());
170       }
171       else {
172         if (aType == PRISM_BASE_DXDYDZ_2WAYS) {
173           gp_Trsf aTrsf;
174           aTrsf.SetTranslation(-aV);
175           BRepBuilderAPI_Transform aTransformation(aShapeBase, aTrsf, Standard_False);
176           aShapeBase = aTransformation.Shape();
177           aV = aV * 2;
178         }
179         aShape = BRepPrimAPI_MakePrism(aShapeBase, aV, Standard_False).Shape();
180       }
181     }
182   }
183
184   if (aShape.IsNull()) return 0;
185
186   TopoDS_Shape aRes = GEOMImpl_IShapesOperations::CompsolidToCompound(aShape);
187   aFunction->SetValue(aRes);
188
189   log.SetTouched(Label());
190
191   return 1;
192 }
193
194 //=======================================================================
195 //function : MakeScaledPrism
196 //purpose  :
197 //=======================================================================
198 TopoDS_Shape GEOMImpl_PrismDriver::MakeScaledPrism (const TopoDS_Shape& theShapeBase,
199                                                     const gp_Vec&       theVector,
200                                                     const Standard_Real theScaleFactor,
201                                                     const gp_Pnt&       theCDG,
202                                                     bool                isCDG)
203 {
204   TopoDS_Shape aShape;
205   BRep_Builder B;
206
207   // 1. aCDG = geompy.MakeCDG(theBase)
208   gp_Pnt aCDG = theCDG;
209   if (!isCDG) {
210     gp_Ax3 aPos = GEOMImpl_IMeasureOperations::GetPosition(theShapeBase);
211     aCDG = aPos.Location();
212   }
213   TopoDS_Shape aShapeCDG_1 = BRepBuilderAPI_MakeVertex(aCDG).Shape();
214
215   // Process case of several given shapes
216   if (theShapeBase.ShapeType() == TopAbs_COMPOUND ||
217       theShapeBase.ShapeType() == TopAbs_SHELL) {
218     int nbSub = 0;
219     TopoDS_Shape aShapeI;
220     TopoDS_Compound aCompound;
221     B.MakeCompound(aCompound);
222     TopoDS_Iterator It (theShapeBase, Standard_True, Standard_True);
223     for (; It.More(); It.Next()) {
224       nbSub++;
225       aShapeI = MakeScaledPrism(It.Value(), theVector, theScaleFactor, aCDG, true);
226       B.Add(aCompound, aShapeI);
227     }
228     if (nbSub == 1)
229       aShape = aShapeI;
230     else if (nbSub > 1)
231       aShape = GEOMImpl_GlueDriver::GlueFaces(aCompound, Precision::Confusion(), Standard_True);
232     return aShape;
233   }
234
235   // 2. Scale = geompy.MakeScaleTransform(theBase, aCDG, theScaleFactor)
236
237   // Bug 6839: Check for standalone (not included in faces) degenerated edges
238   TopTools_IndexedDataMapOfShapeListOfShape aEFMap;
239   TopExp::MapShapesAndAncestors(theShapeBase, TopAbs_EDGE, TopAbs_FACE, aEFMap);
240   Standard_Integer i, nbE = aEFMap.Extent();
241   for (i = 1; i <= nbE; i++) {
242     TopoDS_Shape anEdgeSh = aEFMap.FindKey(i);
243     if (BRep_Tool::Degenerated(TopoDS::Edge(anEdgeSh))) {
244       const TopTools_ListOfShape& aFaces = aEFMap.FindFromIndex(i);
245       if (aFaces.IsEmpty())
246         Standard_ConstructionError::Raise
247           ("Scaling aborted : cannot scale standalone degenerated edge");
248     }
249   }
250
251   // Perform Scaling
252   gp_Trsf aTrsf;
253   aTrsf.SetScale(aCDG, theScaleFactor);
254   BRepBuilderAPI_Transform aBRepTrsf (theShapeBase, aTrsf, Standard_False);
255   TopoDS_Shape aScale = aBRepTrsf.Shape();
256
257   // 3. aBase2 = geompy.MakeTranslationVectorDistance(Scale, theVec, theH)
258   gp_Trsf aTrsf3;
259   aTrsf3.SetTranslation(theVector);
260   TopLoc_Location aLocOrig = aScale.Location();
261   gp_Trsf aTrsfOrig = aLocOrig.Transformation();
262   TopLoc_Location aLocRes (aTrsf3 * aTrsfOrig);
263   TopoDS_Shape aBase2 = aScale.Located(aLocRes);
264
265   // 4. aCDG_2 = geompy.MakeTranslationVectorDistance(aCDG, theVec, theH)
266   gp_Pnt aCDG_2 = aCDG.Translated(theVector);
267   TopoDS_Shape aShapeCDG_2 = BRepBuilderAPI_MakeVertex(aCDG_2).Shape();
268
269   // 5. Vector = geompy.MakeVector(aCDG, aCDG_2)
270   TopoDS_Shape aShapeVec = BRepBuilderAPI_MakeEdge(aCDG, aCDG_2).Shape();
271   TopoDS_Edge anEdge = TopoDS::Edge(aShapeVec);
272   TopoDS_Wire aWirePath = BRepBuilderAPI_MakeWire(anEdge);
273
274   // 6. aPrism = geompy.MakePipeWithDifferentSections([theBase, aBase2], [aCDG, aCDG_2], Vector, False, False)
275   Handle(TopTools_HSequenceOfShape) aBases = new TopTools_HSequenceOfShape;
276   aBases->Append(theShapeBase);
277   aBases->Append(aBase2);
278
279   Handle(TopTools_HSequenceOfShape) aLocs = new TopTools_HSequenceOfShape;
280   aLocs->Append(aShapeCDG_1);
281   aLocs->Append(aShapeCDG_2);
282
283   aShape = GEOMImpl_PipeDriver::CreatePipeWithDifferentSections(aWirePath, aBases, aLocs, false, false);
284
285   // 7. Make a solid, if possible
286   if (theShapeBase.ShapeType() == TopAbs_FACE) {
287     BRepBuilderAPI_Sewing aSewing (Precision::Confusion()*10.0);
288     TopExp_Explorer expF (aShape, TopAbs_FACE);
289     Standard_Integer ifa = 0;
290     for (; expF.More(); expF.Next()) {
291       aSewing.Add(expF.Current());
292       ifa++;
293     }
294     if (ifa > 0) {
295       aSewing.Perform();
296       TopoDS_Shape aShell;
297
298       TopoDS_Shape sh = aSewing.SewedShape();
299       if (sh.ShapeType() == TopAbs_FACE && ifa == 1) {
300         // case for creation of shell from one face
301         TopoDS_Shell ss;
302         B.MakeShell(ss);
303         B.Add(ss,sh);
304         aShell = ss;
305       }
306       else {
307         TopExp_Explorer exp (sh, TopAbs_SHELL);
308         Standard_Integer ish = 0;
309         for (; exp.More(); exp.Next()) {
310           aShell = exp.Current();
311           ish++;
312         }
313         if (ish != 1)
314           aShell = sh;
315       }
316       BRepCheck_Shell chkShell (TopoDS::Shell(aShell));
317       if (chkShell.Closed() == BRepCheck_NoError) {
318         TopoDS_Solid Sol;
319         B.MakeSolid(Sol);
320         B.Add(Sol, aShell);
321         BRepClass3d_SolidClassifier SC (Sol);
322         SC.PerformInfinitePoint(Precision::Confusion());
323         if (SC.State() == TopAbs_IN) {
324           B.MakeSolid(Sol);
325           B.Add(Sol, aShell.Reversed());
326         }
327         aShape = Sol;
328       }
329     }
330   }
331
332   return aShape;
333 }
334
335 //=======================================================================
336 //function : GEOMImpl_PrismDriver_Type_
337 //purpose  :
338 //=======================================================================
339 Standard_EXPORT Handle_Standard_Type& GEOMImpl_PrismDriver_Type_()
340 {
341
342   static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver);
343   if (aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver);
344   static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared);
345   if (aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared);
346   static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient);
347   if (aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient);
348
349   static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL};
350   static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_PrismDriver",
351                                                          sizeof(GEOMImpl_PrismDriver),
352                                                          1,
353                                                          (Standard_Address)_Ancestors,
354                                                          (Standard_Address)NULL);
355
356   return _aType;
357 }
358
359 //=======================================================================
360 //function : DownCast
361 //purpose  :
362 //=======================================================================
363 const Handle(GEOMImpl_PrismDriver) Handle(GEOMImpl_PrismDriver)::DownCast(const Handle(Standard_Transient)& AnObject)
364 {
365   Handle(GEOMImpl_PrismDriver) _anOtherObject;
366
367   if (!AnObject.IsNull()) {
368      if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_PrismDriver))) {
369        _anOtherObject = Handle(GEOMImpl_PrismDriver)((Handle(GEOMImpl_PrismDriver)&)AnObject);
370      }
371   }
372
373   return _anOtherObject;
374 }