Salome HOME
38065f47f8e75a9509d3ba2ed55450dd426e2183
[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     //Calculate Lines Intersection Point
194     BRepExtrema_DistShapeShape dst (aRefShape1, aRefShape2);
195     if (dst.IsDone()) {
196       gp_Pnt P1, P2;
197       BRep_Builder B;
198       B.MakeCompound( aCompound );
199       for (int i = 1; i <= dst.NbSolution(); i++) {
200         P1 = dst.PointOnShape1(i);
201         P2 = dst.PointOnShape2(i);
202         Standard_Real Dist = P1.Distance(P2);
203         if ( Dist <= Precision::Confusion() && dst.NbSolution() > 1) {
204           BRepBuilderAPI_MakeVertex mkVertex (P1);
205           B.Add(aCompound, mkVertex.Shape());
206           retCompound = true;
207         } else if ( Dist <= Precision::Confusion() ) {
208           aPnt = P1;
209         } else {
210           Standard_TypeMismatch::Raise ("Shapes have not an Intersection Point");
211         }
212       }
213     }
214   }
215   else {
216     return 0;
217   }
218
219   TopoDS_Shape aShape;
220   if ( retCompound ) {
221     aShape = aCompound;
222   } else {
223     BRepBuilderAPI_MakeVertex mkVertex (aPnt);
224     aShape = mkVertex.Shape();
225   }
226
227   //aShape.Infinite(Standard_True); // VSR: 05/04/2010: Fix 20668 (Fit All for points & lines)
228   aFunction->SetValue(aShape);
229
230   log.SetTouched(Label());
231
232   return 1;
233 }
234
235
236 //=======================================================================
237 //function :  GEOMImpl_PointDriver_Type_
238 //purpose  :
239 //=======================================================================
240 Standard_EXPORT Handle_Standard_Type& GEOMImpl_PointDriver_Type_()
241 {
242
243   static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver);
244   if ( aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver);
245   static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared);
246   if ( aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared);
247   static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient);
248   if ( aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient);
249
250
251   static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL};
252   static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_PointDriver",
253                                                          sizeof(GEOMImpl_PointDriver),
254                                                          1,
255                                                          (Standard_Address)_Ancestors,
256                                                          (Standard_Address)NULL);
257
258   return _aType;
259 }
260
261 //=======================================================================
262 //function : DownCast
263 //purpose  :
264 //=======================================================================
265
266 const Handle(GEOMImpl_PointDriver) Handle(GEOMImpl_PointDriver)::DownCast(const Handle(Standard_Transient)& AnObject)
267 {
268   Handle(GEOMImpl_PointDriver) _anOtherObject;
269
270   if (!AnObject.IsNull()) {
271      if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_PointDriver))) {
272        _anOtherObject = Handle(GEOMImpl_PointDriver)((Handle(GEOMImpl_PointDriver)&)AnObject);
273      }
274   }
275
276   return _anOtherObject ;
277 }