Salome HOME
0020956: [CEA 421] Problem with ChangeOrientation.
[modules/geom.git] / src / GEOMImpl / GEOMImpl_PointDriver.cxx
1 //  Copyright (C) 2007-2010  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_PointDriver.hxx>
26 #include <GEOMImpl_IPoint.hxx>
27 #include <GEOMImpl_Types.hxx>
28 #include <GEOM_Function.hxx>
29
30 #include <BRep_Tool.hxx>
31 #include <BRepBuilderAPI_MakeVertex.hxx>
32 #include <BRepExtrema_DistShapeShape.hxx>
33 #include <BRep_Builder.hxx>
34 #include <Precision.hxx>
35 #include <TopAbs.hxx>
36 #include <TopoDS.hxx>
37 #include <TopoDS_Edge.hxx>
38 #include <TopoDS_Shape.hxx>
39 #include <TopoDS_Vertex.hxx>
40 #include <TopoDS_Compound.hxx>
41
42 #include <Geom_Curve.hxx>
43 #include <Geom_Surface.hxx>
44 #include <gp_Pnt.hxx>
45 #include <TopoDS_Face.hxx>
46 #include <ShapeAnalysis.hxx>
47
48
49 //=======================================================================
50 //function : GetID
51 //purpose  :
52 //=======================================================================
53 const Standard_GUID& GEOMImpl_PointDriver::GetID()
54 {
55   static Standard_GUID aPointDriver("FF1BBB02-5D14-4df2-980B-3A668264EA16");
56   return aPointDriver;
57 }
58
59
60 //=======================================================================
61 //function : GEOMImpl_PointDriver
62 //purpose  :
63 //=======================================================================
64 GEOMImpl_PointDriver::GEOMImpl_PointDriver()
65 {
66 }
67
68 //=======================================================================
69 //function : getExtremaSolution
70 //purpose  : local function
71 //=======================================================================
72 static Standard_Boolean getExtremaSolution
73 (GEOMImpl_IPoint& thePI,
74  TopoDS_Shape&    theRefShape,
75  gp_Pnt& thePnt)
76 {
77   gp_Pnt anInitPnt( thePI.GetX(), thePI.GetY(), thePI.GetZ() );
78   BRepBuilderAPI_MakeVertex mkVertex (anInitPnt);
79   TopoDS_Vertex anInitV = TopoDS::Vertex(mkVertex.Shape());
80   
81   BRepExtrema_DistShapeShape anExt( anInitV, theRefShape );
82   if ( !anExt.IsDone() || anExt.NbSolution() < 1 )
83     return Standard_False;
84   thePnt = anExt.PointOnShape2(1);
85   Standard_Real aMinDist2 = anInitPnt.SquareDistance( thePnt );
86   for ( Standard_Integer j = 2, jn = anExt.NbSolution(); j <= jn; j++ )
87   {
88     gp_Pnt aPnt = anExt.PointOnShape2(j);
89     Standard_Real aDist2 = anInitPnt.SquareDistance( aPnt );
90     if ( aDist2 > aMinDist2)
91       continue;
92     aMinDist2 = aDist2;
93     thePnt = aPnt;
94   }
95   return Standard_True;
96 }
97
98 //=======================================================================
99 //function : Execute
100 //purpose  :
101 //=======================================================================
102 Standard_Integer GEOMImpl_PointDriver::Execute(TFunction_Logbook& log) const
103 {
104   if (Label().IsNull())  return 0;
105   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
106
107   GEOMImpl_IPoint aPI (aFunction);
108   Standard_Integer aType = aFunction->GetType();
109
110   gp_Pnt aPnt;
111   TopoDS_Compound aCompound;
112   bool retCompound = false;
113
114   if (aType == POINT_XYZ) {
115     aPnt = gp_Pnt(aPI.GetX(), aPI.GetY(), aPI.GetZ());
116
117   }
118   else if (aType == POINT_XYZ_REF) {
119
120     Handle(GEOM_Function) aRefPoint = aPI.GetRef();
121     TopoDS_Shape aRefShape = aRefPoint->GetValue();
122     if (aRefShape.ShapeType() != TopAbs_VERTEX) {
123       Standard_TypeMismatch::Raise
124         ("Point creation aborted : referenced shape is not a vertex");
125     }
126     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aRefShape));
127     aPnt = gp_Pnt(P.X() + aPI.GetX(), P.Y() + aPI.GetY(), P.Z() + aPI.GetZ());
128   }
129   else if (aType == POINT_CURVE_PAR) {
130     Handle(GEOM_Function) aRefCurve = aPI.GetCurve();
131     TopoDS_Shape aRefShape = aRefCurve->GetValue();
132     if (aRefShape.ShapeType() != TopAbs_EDGE) {
133       Standard_TypeMismatch::Raise
134         ("Point On Curve creation aborted : curve shape is not an edge");
135     }
136     Standard_Real aFP, aLP, aP;
137     Handle(Geom_Curve) aCurve = BRep_Tool::Curve(TopoDS::Edge(aRefShape), aFP, aLP);
138     aP = aFP + (aLP - aFP) * aPI.GetParameter();
139     aPnt = aCurve->Value(aP);
140   }
141   else if (aType == POINT_CURVE_COORD) {
142     Handle(GEOM_Function) aRefCurve = aPI.GetCurve();
143     TopoDS_Shape aRefShape = aRefCurve->GetValue();
144     if (aRefShape.ShapeType() != TopAbs_EDGE) {
145       Standard_TypeMismatch::Raise
146         ("Point On Curve creation aborted : curve shape is not an edge");
147     }
148     if (!getExtremaSolution( aPI, aRefShape, aPnt ) ) {
149       Standard_ConstructionError::Raise
150         ("Point On Curve creation aborted : cannot project point");
151     }
152   }
153   else if (aType == POINT_SURFACE_PAR) {
154     Handle(GEOM_Function) aRefCurve = aPI.GetSurface();
155     TopoDS_Shape aRefShape = aRefCurve->GetValue();
156     if (aRefShape.ShapeType() != TopAbs_FACE) {
157       Standard_TypeMismatch::Raise
158         ("Point On Surface creation aborted : surface shape is not a face");
159     }
160     TopoDS_Face F = TopoDS::Face(aRefShape);
161     Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
162     Standard_Real U1,U2,V1,V2;
163     //aSurf->Bounds(U1,U2,V1,V2);
164     ShapeAnalysis::GetFaceUVBounds(F,U1,U2,V1,V2);
165     Standard_Real U = U1 + (U2-U1) * aPI.GetParameter();
166     Standard_Real V = V1 + (V2-V1) * aPI.GetParameter2();
167     aPnt = aSurf->Value(U,V);
168   }
169   else if (aType == POINT_SURFACE_COORD) {
170     Handle(GEOM_Function) aRefCurve = aPI.GetSurface();
171     TopoDS_Shape aRefShape = aRefCurve->GetValue();
172     if (aRefShape.ShapeType() != TopAbs_FACE) {
173       Standard_TypeMismatch::Raise
174         ("Point On Surface creation aborted : surface shape is not a face");
175     }
176     if (!getExtremaSolution( aPI, aRefShape, aPnt ) ) {
177       Standard_ConstructionError::Raise
178         ("Point On Surface creation aborted : cannot project point");
179     }
180   }
181   else if (aType == POINT_LINES_INTERSECTION) {
182     Handle(GEOM_Function) aRef1 = aPI.GetLine1();
183     Handle(GEOM_Function) aRef2 = aPI.GetLine2();
184
185     TopoDS_Shape aRefShape1 = aRef1->GetValue();
186     TopoDS_Shape aRefShape2 = aRef2->GetValue();
187
188     if ( (aRefShape1.ShapeType() != TopAbs_EDGE && aRefShape1.ShapeType() != TopAbs_WIRE)
189       || (aRefShape2.ShapeType() != TopAbs_EDGE && aRefShape2.ShapeType() != TopAbs_WIRE) ) {
190       Standard_TypeMismatch::Raise
191         ("Creation Point On Lines Intersection Aborted : Line shape is not an edge or wire");
192     }
193
194     if (aRefShape1.IsSame(aRefShape2))
195       Standard_ConstructionError::Raise("The lines to make intersection must be different");
196
197     //Calculate Lines Intersection Point
198     BRepExtrema_DistShapeShape dst (aRefShape1, aRefShape2);
199     if (dst.IsDone()) {
200       gp_Pnt P1, P2;
201       BRep_Builder B;
202       B.MakeCompound( aCompound );
203       for (int i = 1; i <= dst.NbSolution(); i++) {
204         P1 = dst.PointOnShape1(i);
205         P2 = dst.PointOnShape2(i);
206         Standard_Real Dist = P1.Distance(P2);
207         if ( Dist <= Precision::Confusion() && dst.NbSolution() > 1) {
208           BRepBuilderAPI_MakeVertex mkVertex (P1);
209           B.Add(aCompound, mkVertex.Shape());
210           retCompound = true;
211         } else if ( Dist <= Precision::Confusion() ) {
212           aPnt = P1;
213         } else {
214           Standard_TypeMismatch::Raise ("Shapes have not an Intersection Point");
215         }
216       }
217     }
218   }
219   else {
220     return 0;
221   }
222
223   TopoDS_Shape aShape;
224   if ( retCompound ) {
225     aShape = aCompound;
226   } else {
227     BRepBuilderAPI_MakeVertex mkVertex (aPnt);
228     aShape = mkVertex.Shape();
229   }
230
231   //aShape.Infinite(Standard_True); // VSR: 05/04/2010: Fix 20668 (Fit All for points & lines)
232   aFunction->SetValue(aShape);
233
234   log.SetTouched(Label());
235
236   return 1;
237 }
238
239
240 //=======================================================================
241 //function :  GEOMImpl_PointDriver_Type_
242 //purpose  :
243 //=======================================================================
244 Standard_EXPORT Handle_Standard_Type& GEOMImpl_PointDriver_Type_()
245 {
246
247   static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver);
248   if ( aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver);
249   static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared);
250   if ( aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared);
251   static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient);
252   if ( aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient);
253
254
255   static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL};
256   static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_PointDriver",
257                                                          sizeof(GEOMImpl_PointDriver),
258                                                          1,
259                                                          (Standard_Address)_Ancestors,
260                                                          (Standard_Address)NULL);
261
262   return _aType;
263 }
264
265 //=======================================================================
266 //function : DownCast
267 //purpose  :
268 //=======================================================================
269
270 const Handle(GEOMImpl_PointDriver) Handle(GEOMImpl_PointDriver)::DownCast(const Handle(Standard_Transient)& AnObject)
271 {
272   Handle(GEOMImpl_PointDriver) _anOtherObject;
273
274   if (!AnObject.IsNull()) {
275      if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_PointDriver))) {
276        _anOtherObject = Handle(GEOMImpl_PointDriver)((Handle(GEOMImpl_PointDriver)&)AnObject);
277      }
278   }
279
280   return _anOtherObject ;
281 }