Salome HOME
Update copyright information
[modules/geom.git] / src / GEOMImpl / GEOMImpl_MeasureDriver.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_MeasureDriver.hxx>
25 #include <GEOMImpl_IMeasure.hxx>
26 #include <GEOMImpl_IMeasureOperations.hxx>
27 #include <GEOMImpl_Types.hxx>
28 #include <GEOM_Function.hxx>
29
30 #include <BRep_Tool.hxx>
31 #include <BRepGProp.hxx>
32 #include <BRepBuilderAPI_MakeVertex.hxx>
33 #include <BRepBuilderAPI_MakeEdge.hxx>
34
35 #include <TopAbs.hxx>
36 #include <TopoDS.hxx>
37 #include <TopoDS_Shape.hxx>
38
39 #include <GProp_GProps.hxx>
40 #include <GeomLProp_SLProps.hxx>
41 #include <Geom_Surface.hxx>
42
43 #include <Bnd_Box.hxx>
44 #include <BRepBndLib.hxx>
45 #include <BRepAdaptor_Surface.hxx>
46 #include <ShapeAnalysis_Surface.hxx>
47
48 #include <gp_Pnt.hxx>
49 #include <Precision.hxx>
50 #include <Standard_NullObject.hxx>
51
52 //=======================================================================
53 //function : GetID
54 //purpose  :
55 //======================================================================= 
56 const Standard_GUID& GEOMImpl_MeasureDriver::GetID()
57 {
58   static Standard_GUID aMeasureDriver("FF1BBB65-5D14-4df2-980B-3A668264EA16");
59   return aMeasureDriver; 
60 }
61
62
63 //=======================================================================
64 //function : GEOMImpl_MeasureDriver
65 //purpose  : 
66 //=======================================================================
67 GEOMImpl_MeasureDriver::GEOMImpl_MeasureDriver() 
68 {
69 }
70
71 //=======================================================================
72 //function : Execute
73 //purpose  :
74 //======================================================================= 
75 Standard_Integer GEOMImpl_MeasureDriver::Execute(TFunction_Logbook& log) const
76 {
77   if (Label().IsNull()) return 0;    
78   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
79
80   GEOMImpl_IMeasure aCI (aFunction);
81   Standard_Integer aType = aFunction->GetType();
82
83   TopoDS_Shape aShape;
84
85   if (aType == CDG_MEASURE)
86   {
87     Handle(GEOM_Function) aRefBase = aCI.GetBase();
88     TopoDS_Shape aShapeBase = aRefBase->GetValue();
89     if (aShapeBase.IsNull()) {
90       Standard_NullObject::Raise("Shape for centre of mass calculation is null");
91     }
92
93     GProp_GProps aSystem;
94     gp_Pnt aCenterMass;
95
96     if (aShapeBase.ShapeType() == TopAbs_VERTEX) {
97       aCenterMass = BRep_Tool::Pnt(TopoDS::Vertex(aShapeBase));
98     } else if (aShapeBase.ShapeType() == TopAbs_EDGE || aShapeBase.ShapeType() == TopAbs_WIRE) {
99       BRepGProp::LinearProperties(aShapeBase, aSystem);
100       aCenterMass = aSystem.CentreOfMass();
101     } else if (aShapeBase.ShapeType() == TopAbs_FACE || aShapeBase.ShapeType() == TopAbs_SHELL) {
102       BRepGProp::SurfaceProperties(aShapeBase, aSystem);
103       aCenterMass = aSystem.CentreOfMass();
104     } else {
105       BRepGProp::VolumeProperties(aShapeBase, aSystem);
106       aCenterMass = aSystem.CentreOfMass();
107     }
108
109     aShape = BRepBuilderAPI_MakeVertex(aCenterMass).Shape();
110   }
111   else if (aType == VECTOR_FACE_NORMALE)
112   {
113     // Face
114     Handle(GEOM_Function) aRefBase = aCI.GetBase();
115     TopoDS_Shape aShapeBase = aRefBase->GetValue();
116     if (aShapeBase.IsNull()) {
117       Standard_NullObject::Raise("Face for normale calculation is null");
118     }
119     if (aShapeBase.ShapeType() != TopAbs_FACE) {
120       Standard_NullObject::Raise("Shape for normale calculation is not a face");
121     }
122     TopoDS_Face aFace = TopoDS::Face(aShapeBase);
123
124     // Point
125     gp_Pnt p1 (0,0,0);
126
127     Handle(GEOM_Function) aPntFunc = aCI.GetPoint();
128     if (!aPntFunc.IsNull())
129     {
130       TopoDS_Shape anOptPnt = aPntFunc->GetValue();
131       if (anOptPnt.IsNull())
132         Standard_NullObject::Raise("Invalid shape given for point argument");
133       p1 = BRep_Tool::Pnt(TopoDS::Vertex(anOptPnt));
134     }
135     else
136     {
137       gp_Ax3 aPos = GEOMImpl_IMeasureOperations::GetPosition(aFace);
138       p1 = aPos.Location();
139     }
140
141     // Point parameters on surface
142     Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
143     Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf);
144     gp_Pnt2d pUV = aSurfAna->ValueOfUV(p1, Precision::Confusion());
145
146     // Normal direction
147     gp_Vec Vec1,Vec2;
148     BRepAdaptor_Surface SF (aFace);
149     SF.D1(pUV.X(), pUV.Y(), p1, Vec1, Vec2);
150     gp_Vec V = Vec1.Crossed(Vec2);
151     Standard_Real mod = V.Magnitude();
152     if (mod < Precision::Confusion())
153       Standard_NullObject::Raise("Normal vector of a face has null magnitude");
154
155     // Set length of normal vector to average radius of curvature
156     Standard_Real radius = 0.0;
157     GeomLProp_SLProps aProperties (aSurf, pUV.X(), pUV.Y(), 2, Precision::Confusion());
158     if (aProperties.IsCurvatureDefined()) {
159       Standard_Real radius1 = Abs(aProperties.MinCurvature());
160       Standard_Real radius2 = Abs(aProperties.MaxCurvature());
161       if (Abs(radius1) > Precision::Confusion()) {
162         radius = 1.0 / radius1;
163         if (Abs(radius2) > Precision::Confusion()) {
164           radius = (radius + 1.0 / radius2) / 2.0;
165         }
166       }
167       else {
168         if (Abs(radius2) > Precision::Confusion()) {
169           radius = 1.0 / radius2;
170         }
171       }
172     }
173
174     // Set length of normal vector to average dimension of the face
175     // (only if average radius of curvature is not appropriate)
176     if (radius < Precision::Confusion()) {
177         Bnd_Box B;
178         Standard_Real Xmin, Xmax, Ymin, Ymax, Zmin, Zmax;
179         BRepBndLib::Add(aFace, B);
180         B.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
181         radius = ((Xmax - Xmin) + (Ymax - Ymin) + (Zmax - Zmin)) / 3.0;
182     }
183
184     if (radius < Precision::Confusion())
185       radius = 1.0;
186
187     V *= radius / mod;
188
189     // consider the face orientation
190     if (aFace.Orientation() == TopAbs_REVERSED ||
191         aFace.Orientation() == TopAbs_INTERNAL) {
192       V = - V;
193     }
194
195     // Edge
196     gp_Pnt p2 = p1.Translated(V);
197     BRepBuilderAPI_MakeEdge aBuilder (p1, p2);
198     if (!aBuilder.IsDone())
199       Standard_NullObject::Raise("Vector construction failed");
200     aShape = aBuilder.Shape();
201   }
202   else {
203   }
204
205   if (aShape.IsNull()) return 0;
206
207   aFunction->SetValue(aShape);
208
209   log.SetTouched(Label()); 
210
211   return 1;
212 }
213
214
215 //=======================================================================
216 //function :  GEOMImpl_MeasureDriver_Type_
217 //purpose  :
218 //======================================================================= 
219 Standard_EXPORT Handle_Standard_Type& GEOMImpl_MeasureDriver_Type_()
220 {
221
222   static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver);
223   if ( aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver);
224   static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared);
225   if ( aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared); 
226   static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient);
227   if ( aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient);
228  
229
230   static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL};
231   static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_MeasureDriver",
232                                                          sizeof(GEOMImpl_MeasureDriver),
233                                                          1,
234                                                          (Standard_Address)_Ancestors,
235                                                          (Standard_Address)NULL);
236
237   return _aType;
238 }
239
240 //=======================================================================
241 //function : DownCast
242 //purpose  :
243 //======================================================================= 
244 const Handle(GEOMImpl_MeasureDriver) Handle(GEOMImpl_MeasureDriver)::DownCast(const Handle(Standard_Transient)& AnObject)
245 {
246   Handle(GEOMImpl_MeasureDriver) _anOtherObject;
247
248   if (!AnObject.IsNull()) {
249      if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_MeasureDriver))) {
250        _anOtherObject = Handle(GEOMImpl_MeasureDriver)((Handle(GEOMImpl_MeasureDriver)&)AnObject);
251      }
252   }
253
254   return _anOtherObject ;
255 }