]> SALOME platform Git repositories - modules/geom.git/blob - src/GEOMImpl/GEOMImpl_PositionDriver.cxx
Salome HOME
Update from BR_V5_DEV 13Feb2009
[modules/geom.git] / src / GEOMImpl / GEOMImpl_PositionDriver.cxx
1 //  Copyright (C) 2007-2008  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 <Standard_Stream.hxx>
23 //
24 #include <GEOMImpl_PositionDriver.hxx>
25 #include <GEOMImpl_IPosition.hxx>
26 #include <GEOMImpl_Types.hxx>
27 #include <GEOM_Function.hxx>
28
29 #include <GEOMImpl_IMeasureOperations.hxx>
30
31 // OCCT Includes
32 #include <BRepBuilderAPI_Transform.hxx>
33 #include <GCPnts_AbscissaPoint.hxx>
34 #include <ShHealOper_EdgeDivide.hxx>
35 #include <BRep_Tool.hxx>
36 #include <BRepTools.hxx>
37 #include <BRepTools_WireExplorer.hxx>
38 #include <TopoDS.hxx>
39 #include <TopoDS_Shape.hxx>
40 #include <TopoDS_Vertex.hxx>
41 #include <TopoDS_Edge.hxx>
42 #include <TopoDS_Wire.hxx>
43 #include <TopAbs.hxx>
44 #include <TopExp.hxx>
45 #include <TopExp_Explorer.hxx>
46 #include <gp_Pln.hxx>
47 #include <Geom_Plane.hxx>
48 #include <Geom_Curve.hxx>
49 #include <GProp_GProps.hxx>
50 #include <BRepGProp.hxx>
51 #include <ShapeAnalysis_Edge.hxx>
52 #include <GeomAdaptor_Curve.hxx>
53 #include <BRepGProp.hxx>
54 #include <ShapeFix_Wire.hxx>
55
56 #include <Precision.hxx>
57 #include <gp_Pnt.hxx>
58 #include <gp_Vec.hxx>
59 #include <TopExp.hxx>
60
61 //=======================================================================
62 //function : GetID
63 //purpose  :
64 //=======================================================================
65 const Standard_GUID& GEOMImpl_PositionDriver::GetID()
66 {
67   static Standard_GUID aPositionDriver("FF1BBB69-5D14-4df2-980B-3A668264EA16");
68   return aPositionDriver;
69 }
70
71
72 //=======================================================================
73 //function : GEOMImpl_PositionDriver
74 //purpose  :
75 //=======================================================================
76 GEOMImpl_PositionDriver::GEOMImpl_PositionDriver()
77 {
78 }
79
80 //=======================================================================
81 //function : Execute
82 //purpose  :
83 //=======================================================================
84 Standard_Integer GEOMImpl_PositionDriver::Execute(TFunction_Logbook& log) const
85 {
86   if (Label().IsNull()) return 0;
87   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
88
89   GEOMImpl_IPosition aCI (aFunction);
90   Standard_Integer aType = aFunction->GetType();
91
92   TopoDS_Shape aShape;
93
94   if (aType == POSITION_SHAPE || aType == POSITION_SHAPE_COPY) {
95     Handle(GEOM_Function) aRefShape = aCI.GetShape();
96     Handle(GEOM_Function) aRefStartLCS = aCI.GetStartLCS();
97     Handle(GEOM_Function) aRefEndLCS = aCI.GetEndLCS();
98
99     TopoDS_Shape aShapeBase = aRefShape->GetValue();
100     TopoDS_Shape aShapeStartLCS = aRefStartLCS->GetValue();
101     TopoDS_Shape aShapeEndLCS = aRefEndLCS->GetValue();
102
103     if (aShapeBase.IsNull() || aShapeStartLCS.IsNull() ||
104         aShapeEndLCS.IsNull() || aShapeEndLCS.ShapeType() != TopAbs_FACE)
105       return 0;
106
107     gp_Trsf aTrsf;
108     gp_Ax3 aStartAx3, aDestAx3;
109
110     // End LCS
111     aDestAx3 = GEOMImpl_IMeasureOperations::GetPosition(aShapeEndLCS);
112
113     // Start LCS
114     aStartAx3 = GEOMImpl_IMeasureOperations::GetPosition(aShapeStartLCS);
115
116     // Set transformation
117     aTrsf.SetDisplacement(aStartAx3, aDestAx3);
118
119     // Perform transformation
120     BRepBuilderAPI_Transform aBRepTrsf (aShapeBase, aTrsf, Standard_False);
121     aShape = aBRepTrsf.Shape();
122   }
123   else if (aType == POSITION_SHAPE_FROM_GLOBAL ||
124            aType == POSITION_SHAPE_FROM_GLOBAL_COPY) {
125     Handle(GEOM_Function) aRefShape = aCI.GetShape();
126     Handle(GEOM_Function) aRefEndLCS = aCI.GetEndLCS();
127
128     TopoDS_Shape aShapeBase = aRefShape->GetValue();
129     TopoDS_Shape aShapeEndLCS = aRefEndLCS->GetValue();
130
131     if (aShapeBase.IsNull() || aShapeEndLCS.IsNull() ||
132         aShapeEndLCS.ShapeType() != TopAbs_FACE)
133       return 0;
134
135     gp_Trsf aTrsf;
136     gp_Ax3 aStartAx3, aDestAx3;
137
138     // End LCS
139     aDestAx3 = GEOMImpl_IMeasureOperations::GetPosition(aShapeEndLCS);
140
141     // Set transformation
142     aTrsf.SetDisplacement(aStartAx3, aDestAx3);
143
144     // Perform transformation
145     BRepBuilderAPI_Transform aBRepTrsf (aShapeBase, aTrsf, Standard_False);
146     aShape = aBRepTrsf.Shape();
147   }
148   else if (aType == POSITION_ALONG_PATH) {
149     Handle(GEOM_Function) aRefShape = aCI.GetShape();
150     Handle(GEOM_Function) aPathShape = aCI.GetPath();
151     double aValue = aCI.GetDistance();
152     bool aReversed = aCI.GetReverse();
153
154     TopoDS_Shape aShapeBase = aRefShape->GetValue();
155     TopoDS_Shape aPath = aPathShape->GetValue();
156
157     if (aShapeBase.IsNull() || aPath.IsNull())
158       return 0;
159
160     //Get a Center Of Mass Of Base Object
161     GProp_GProps aSystem;
162     gp_Pnt aCenterMass;
163     if (aShapeBase.ShapeType() == TopAbs_VERTEX) {
164       aCenterMass = BRep_Tool::Pnt(TopoDS::Vertex(aShapeBase));
165     } else if (aShapeBase.ShapeType() == TopAbs_EDGE || aShapeBase.ShapeType() == TopAbs_WIRE) {
166       BRepGProp::LinearProperties(aShapeBase, aSystem);
167       aCenterMass = aSystem.CentreOfMass();
168     } else if (aShapeBase.ShapeType() == TopAbs_FACE || aShapeBase.ShapeType() == TopAbs_SHELL) {
169       BRepGProp::SurfaceProperties(aShapeBase, aSystem);
170       aCenterMass = aSystem.CentreOfMass();
171     } else {
172       BRepGProp::VolumeProperties(aShapeBase, aSystem);
173       aCenterMass = aSystem.CentreOfMass();
174     }
175
176     TopoDS_Shape aTrimmedPath;
177     gp_Trsf aTrsf;
178     Handle(Geom_Curve) aCurve;    
179     Standard_Real aFirst =0.,aLast=0.;
180     Standard_Real aParam = 0.;
181     Standard_Real aLength = 0.;
182
183     gp_Pnt aPFirst, aPLast;
184    
185     if ( aPath.ShapeType() == TopAbs_EDGE ) { // The Path is Edge
186       TopoDS_Edge anEdge = TopoDS::Edge(aPath);
187
188       BRep_Tool::Range(anEdge,aFirst,aLast);
189       aCurve = BRep_Tool::Curve(anEdge,aFirst,aLast);
190       if (aReversed)
191         aCurve = aCurve->Reversed();
192
193       aCurve->D0(aFirst, aPFirst);
194       aCurve->D0(aLast, aPLast);
195
196       // Translate a CenterMass of Base Shape to the start of the path
197       if ( !aPFirst.IsEqual(aCenterMass, gp::Resolution()) ) {
198         gp_Trsf aCurTrsf;
199         aCurTrsf.SetTranslation(aCenterMass, aPFirst);
200         aTrsf.PreMultiply(aCurTrsf);
201       }
202       aParam = aFirst + aValue*(aLast - aFirst); // Calculate parameter
203     } else if ( aPath.ShapeType() == TopAbs_WIRE ) { // The  path Shape is Wire
204       TopoDS_Wire aWire = TopoDS::Wire(aPath);
205
206      // fix edges order
207       Handle(ShapeFix_Wire) aFixWire = new ShapeFix_Wire;
208       aFixWire->Load(aWire);
209       aFixWire->FixReorder();
210       aWire = aFixWire->Wire();
211       
212       TopExp_Explorer ex;
213       TopTools_SequenceOfShape Edges;
214       Standard_Real nbEdges = 0.;
215       BRepTools_WireExplorer aWE (aWire);
216       for (; aWE.More(); aWE.Next(), nbEdges++) // Explore a Wire on Edges
217         Edges.Append(aWE.Current());
218
219       Standard_Real aSummOfLen =0.;
220       Standard_Real aCurLen =0.;
221       GeomAdaptor_Curve aAdC;
222
223       for(int i=1; i<=Edges.Length(); i++) { // Calculate summary Lenght of edges
224         TopoDS_Edge anEdge = TopoDS::Edge(Edges.Value(i));
225         BRep_Tool::Range(anEdge,aFirst,aLast);
226         aCurve = BRep_Tool::Curve(anEdge,aFirst,aLast);
227         aAdC.Load(aCurve,aFirst,aLast);
228         aCurLen = GCPnts_AbscissaPoint::Length(aAdC,aFirst,aLast); 
229         aSummOfLen += aCurLen;
230       }
231
232       // Move BaseShape to the Start Of the Curve
233       TopoDS_Edge anEdge;
234       if (!aReversed)
235         anEdge = TopoDS::Edge(Edges.Value(1));
236       else
237         anEdge = TopoDS::Edge(Edges.Value(Edges.Length()));
238
239       BRep_Tool::Range(anEdge,aFirst,aLast);
240       aCurve = BRep_Tool::Curve(anEdge,aFirst,aLast);
241       aCurve->D0(aFirst, aPFirst);
242       aCurve->D0(aLast, aPLast);
243       if ( !aPFirst.IsEqual(aCenterMass, gp::Resolution()) ) {
244         gp_Trsf aCurTrsf;
245         if (aReversed && anEdge.Orientation() == TopAbs_FORWARD)
246           aPFirst = aPLast;
247
248         aCurTrsf.SetTranslation(aCenterMass, aPFirst);
249         aTrsf.PreMultiply(aCurTrsf);
250       }
251
252       Standard_Real aWireLen = aSummOfLen*aValue;
253       aSummOfLen = 0;
254       for(int i=1; i<=Edges.Length(); i++) {
255         TopoDS_Edge anEdge;
256         if (!aReversed)
257           anEdge = TopoDS::Edge(Edges.Value(i));
258         else
259           anEdge = TopoDS::Edge(Edges.Value(Edges.Length() - i + 1));
260
261         aCurve = BRep_Tool::Curve(anEdge,aFirst,aLast);
262         BRep_Tool::Range(anEdge,aFirst,aLast);
263
264         if (!aReversed && anEdge.Orientation() == TopAbs_REVERSED)
265           aCurve = aCurve->Reversed();
266
267         if (aReversed && anEdge.Orientation() == TopAbs_FORWARD)
268           aCurve = aCurve->Reversed();
269
270         aAdC.Load(aCurve,aFirst,aLast);
271         aCurLen = GCPnts_AbscissaPoint::Length(aAdC,aFirst,aLast);
272
273         if ( aWireLen > (aSummOfLen + aCurLen) ) { // Transform a Base object along this Edge
274           aSummOfLen += aCurLen;
275           gp_Pnt aP1, aP2;
276           gp_Vec aStartVec1, aStartVec2, aDestVec1, aDestVec2;
277           aCurve->D2(aFirst, aP1, aStartVec1, aStartVec2 );
278           aCurve->D2(aLast, aP2, aDestVec1, aDestVec2 );
279           gp_Trsf aCurTrsf;
280           if (aStartVec2.Magnitude() > gp::Resolution() && aDestVec2.Magnitude() > gp::Resolution()) {
281             gp_Ax3 aStartAx3(aP1, aStartVec1, aStartVec2);
282             gp_Ax3 aDestAx3(aP2, aDestVec1, aDestVec2);
283             aCurTrsf.SetDisplacement(aStartAx3, aDestAx3);
284           } else
285             aCurTrsf.SetTranslation(aP1, aP2);
286
287           aTrsf.PreMultiply(aCurTrsf);
288         }
289         else {
290           aLength = aWireLen - aSummOfLen;
291           GCPnts_AbscissaPoint anAbsc(aAdC,aLength,aFirst);
292           if(anAbsc.IsDone()) 
293             aParam = anAbsc.Parameter();
294           break;
295         }
296       }
297     } else
298       return 0; // Unknown Type
299
300     gp_Trsf aCurTrsf;
301     gp_Pnt aP1, aP2;
302     gp_Vec aStartVec1, aStartVec2, aDestVec1, aDestVec2;
303     aCurve->D2(aFirst, aP1, aStartVec1, aStartVec2 );
304     aCurve->D2(aParam, aP2, aDestVec1, aDestVec2 );
305
306     if (aStartVec2.Magnitude() > gp::Resolution() && aDestVec2.Magnitude() > gp::Resolution()) {
307       gp_Ax3 aStartAx3(aP1, aStartVec1, aStartVec2);
308       gp_Ax3 aDestAx3(aP2, aDestVec1, aDestVec2);
309       aCurTrsf.SetDisplacement(aStartAx3, aDestAx3);
310     } else
311       aCurTrsf.SetTranslation(aP1, aP2);
312
313     aTrsf.PreMultiply(aCurTrsf);
314     
315     if ( !aPFirst.IsEqual(aCenterMass, gp::Resolution()) ) {
316       gp_Trsf aCurTrsf;
317       aCurTrsf.SetTranslation(aPFirst, aCenterMass);
318       aTrsf.PreMultiply(aCurTrsf);
319     }
320
321     // Perform transformation
322     BRepBuilderAPI_Transform aBRepTrsf (aShapeBase, aTrsf, Standard_False);
323     aShape = aBRepTrsf.Shape();
324   }
325   else
326     return 0;
327
328   if (aShape.IsNull()) return 0;
329
330   aFunction->SetValue(aShape);
331
332   log.SetTouched(Label());
333
334   return 1;
335 }
336
337
338 //=======================================================================
339 //function :  GEOMImpl_PositionDriver_Type_
340 //purpose  :
341 //=======================================================================
342 Standard_EXPORT Handle_Standard_Type& GEOMImpl_PositionDriver_Type_()
343 {
344
345   static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver);
346   if ( aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver);
347   static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared);
348   if ( aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared);
349   static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient);
350   if ( aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient);
351
352
353   static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL};
354   static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_PositionDriver",
355                                                          sizeof(GEOMImpl_PositionDriver),
356                                                          1,
357                                                          (Standard_Address)_Ancestors,
358                                                          (Standard_Address)NULL);
359
360   return _aType;
361 }
362
363 //=======================================================================
364 //function : DownCast
365 //purpose  :
366 //=======================================================================
367 const Handle(GEOMImpl_PositionDriver) Handle(GEOMImpl_PositionDriver)::DownCast(const Handle(Standard_Transient)& AnObject)
368 {
369   Handle(GEOMImpl_PositionDriver) _anOtherObject;
370
371   if (!AnObject.IsNull()) {
372      if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_PositionDriver))) {
373        _anOtherObject = Handle(GEOMImpl_PositionDriver)((Handle(GEOMImpl_PositionDriver)&)AnObject);
374      }
375   }
376
377   return _anOtherObject ;
378 }