Salome HOME
Win32 compilation.
[modules/geom.git] / src / GEOMImpl / GEOMImpl_ProjectionDriver.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 <Standard_Stream.hxx>
24
25 #include <GEOMImpl_ProjectionDriver.hxx>
26
27 #include <GEOMImpl_IMirror.hxx>
28 #include <GEOMImpl_Types.hxx>
29 #include <GEOM_Function.hxx>
30
31 #include <BRep_Tool.hxx>
32 #include <BRepBuilderAPI_Transform.hxx>
33 #include <BRepBuilderAPI_MakeVertex.hxx>
34 #include <BRepClass_FaceClassifier.hxx>
35 #include <BRepOffsetAPI_NormalProjection.hxx>
36 #include <BRepTools.hxx>
37
38 #include <TopAbs.hxx>
39 #include <TopExp.hxx>
40 #include <TopoDS.hxx>
41 #include <TopoDS_Shape.hxx>
42 #include <TopoDS_Edge.hxx>
43 #include <TopoDS_Face.hxx>
44 #include <TopoDS_Vertex.hxx>
45 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
46
47 #include <GeomAPI_ProjectPointOnSurf.hxx>
48 #include <Geom_Plane.hxx>
49
50 #include <gp_Trsf.hxx>
51 #include <gp_Pnt.hxx>
52 #include <gp_Vec.hxx>
53
54 //=======================================================================
55 //function : GetID
56 //purpose  :
57 //======================================================================= 
58 const Standard_GUID& GEOMImpl_ProjectionDriver::GetID()
59 {
60   static Standard_GUID aProjectionDriver ("FF1BBB70-5D14-4df2-980B-3A668264EA16");
61   return aProjectionDriver; 
62 }
63
64
65 //=======================================================================
66 //function : GEOMImpl_ProjectionDriver
67 //purpose  : 
68 //=======================================================================
69
70 GEOMImpl_ProjectionDriver::GEOMImpl_ProjectionDriver() 
71 {
72 }
73
74 //=======================================================================
75 //function : Execute
76 //purpose  :
77 //======================================================================= 
78 Standard_Integer GEOMImpl_ProjectionDriver::Execute(TFunction_Logbook& log) const
79 {
80   if (Label().IsNull())  return 0;    
81   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
82
83   if (aFunction.IsNull()) return 0;
84
85   TopoDS_Shape aShape;
86   gp_Trsf aTrsf;
87
88   GEOMImpl_IMirror TI (aFunction);
89   Standard_Integer aType = aFunction->GetType();
90
91   Handle(GEOM_Function) anOriginalFunction = TI.GetOriginal();
92   if (anOriginalFunction.IsNull()) return 0;
93
94   TopoDS_Shape anOriginal = anOriginalFunction->GetValue();
95   if (anOriginal.IsNull()) return 0;
96
97   // Projection
98   if (aType == PROJECTION_COPY) {
99     // Source shape (point, edge or wire)
100     if (anOriginal.ShapeType() != TopAbs_VERTEX &&
101         anOriginal.ShapeType() != TopAbs_EDGE &&
102         anOriginal.ShapeType() != TopAbs_WIRE) {
103       Standard_ConstructionError::Raise
104         ("Projection aborted : the source shape is neither a vertex, nor an edge or a wire");
105     }
106
107     // Target face
108     Handle(GEOM_Function) aTargetFunction = TI.GetPlane();
109     if (aTargetFunction.IsNull()) return 0;
110     TopoDS_Shape aFaceShape = aTargetFunction->GetValue();
111     //if (aFaceShape.IsNull() || aFaceShape.ShapeType() != TopAbs_FACE) {
112     //  Standard_ConstructionError::Raise
113     //    ("Projection aborted : the target shape is not a face");
114     //}
115
116     Standard_Real tol = 1.e-4;        
117
118     if (anOriginal.ShapeType() == TopAbs_VERTEX) {
119       if (aFaceShape.IsNull() || aFaceShape.ShapeType() != TopAbs_FACE) {
120         Standard_ConstructionError::Raise
121           ("Projection aborted : the target shape is not a face");
122       }
123       TopoDS_Face aFace = TopoDS::Face(aFaceShape);
124       Handle(Geom_Surface) surface = BRep_Tool::Surface(aFace);
125       double U1, U2, V1, V2;
126       //surface->Bounds(U1, U2, V1, V2);
127       BRepTools::UVBounds(aFace, U1, U2, V1, V2);
128
129       // projector
130       GeomAPI_ProjectPointOnSurf proj;
131       proj.Init(surface, U1, U2, V1, V2, tol);
132
133       gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(anOriginal));
134       proj.Perform(aPnt);
135       if (!proj.IsDone()) {
136         Standard_ConstructionError::Raise
137           ("Projection aborted : GeomAPI_ProjectPointOnSurf failed");
138       }
139       int nbPoints = proj.NbPoints();
140       if (nbPoints < 1) {
141         Standard_ConstructionError::Raise("No solution found");
142       }
143
144       Quantity_Parameter U, V;
145       proj.LowerDistanceParameters(U, V);
146       gp_Pnt2d aProjPnt (U, V);
147
148       // classifier
149       BRepClass_FaceClassifier aClsf (aFace, aProjPnt, tol);
150       if (aClsf.State() != TopAbs_IN && aClsf.State() != TopAbs_ON) {
151         bool isSol = false;
152         double minDist = RealLast();
153         for (int i = 1; i <= nbPoints; i++) {
154           Quantity_Parameter Ui, Vi;
155           proj.Parameters(i, Ui, Vi);
156           aProjPnt = gp_Pnt2d(Ui, Vi);
157           aClsf.Perform(aFace, aProjPnt, tol);
158           if (aClsf.State() == TopAbs_IN || aClsf.State() == TopAbs_ON) {
159             isSol = true;
160             double dist = proj.Distance(i);
161             if (dist < minDist) {
162               minDist = dist;
163               U = Ui;
164               V = Vi;
165             }
166           }
167         }
168         if (!isSol) {
169           Standard_ConstructionError::Raise("No solution found");
170         }
171       }
172
173       gp_Pnt surfPnt = surface->Value(U, V);
174
175       aShape = BRepBuilderAPI_MakeVertex(surfPnt).Shape();
176     }
177     else {
178       //see BRepTest_BasicCommands.cxx for example of BRepOffsetAPI_NormalProjection
179       BRepOffsetAPI_NormalProjection OrtProj (aFaceShape);
180       OrtProj.Add(anOriginal);
181
182       //Standard_Real tol = 1.e-4;        
183       //Standard_Real tol2d = Pow(tol, 2./3);
184       //GeomAbs_Shape Continuity = GeomAbs_C2;  
185       //Standard_Integer MaxDeg = 14;           
186       //Standard_Integer MaxSeg = 16;           
187       //OrtProj.SetParams(tol, tol2d, Continuity, MaxDeg, MaxSeg);
188       try {
189         OrtProj.Build();
190       } catch (Standard_Failure) {
191         Handle(Standard_Failure) aFail = Standard_Failure::Caught();
192         TCollection_AsciiString aMsg (aFail->GetMessageString());
193         if (!aMsg.Length())
194           aMsg = "Projection aborted : possibly the source shape intersects the cylinder's axis";
195         Standard_ConstructionError::Raise(aMsg.ToCString());
196       }
197       if (!OrtProj.IsDone()) {
198         Standard_ConstructionError::Raise
199           ("Projection aborted : BRepOffsetAPI_NormalProjection failed");
200       }
201
202       aShape = OrtProj.Shape();
203     }
204
205     if (aShape.IsNull()) return 0;
206
207     aFunction->SetValue(aShape);
208     log.SetTouched(Label()); 
209   }
210
211   return 1;
212 }
213
214
215 //=======================================================================
216 //function :  GEOMImpl_ProjectionDriver_Type_
217 //purpose  :
218 //======================================================================= 
219 Standard_EXPORT Handle_Standard_Type& GEOMImpl_ProjectionDriver_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_ProjectionDriver",
232                                                          sizeof(GEOMImpl_ProjectionDriver),
233                                                          1,
234                                                          (Standard_Address)_Ancestors,
235                                                          (Standard_Address)NULL);
236
237   return _aType;
238 }
239
240 //=======================================================================
241 //function : DownCast
242 //purpose  :
243 //======================================================================= 
244
245 const Handle(GEOMImpl_ProjectionDriver) Handle(GEOMImpl_ProjectionDriver)::DownCast(const Handle(Standard_Transient)& AnObject)
246 {
247   Handle(GEOMImpl_ProjectionDriver) _anOtherObject;
248
249   if (!AnObject.IsNull()) {
250      if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_ProjectionDriver))) {
251        _anOtherObject = Handle(GEOMImpl_ProjectionDriver)((Handle(GEOMImpl_ProjectionDriver)&)AnObject);
252      }
253   }
254
255   return _anOtherObject;
256 }