Salome HOME
Merge from V6_main 11/02/2013
[modules/geom.git] / src / GEOMImpl / GEOMImpl_PointDriver.cxx
1 // Copyright (C) 2007-2012  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_PointDriver.hxx>
25 #include <GEOMImpl_IPoint.hxx>
26 #include <GEOMImpl_Types.hxx>
27 #include <GEOM_Function.hxx>
28 #include <GEOMAlgo_Tools3D.hxx>
29
30 #include <ShapeAnalysis.hxx>
31
32 #include <BRep_Builder.hxx>
33 #include <BRep_Tool.hxx>
34 #include <BRepAdaptor_Curve.hxx>
35 #include <BRepBuilderAPI_MakeVertex.hxx>
36 #include <BRepExtrema_DistShapeShape.hxx>
37
38 #include <TopAbs.hxx>
39 #include <TopExp.hxx>
40 #include <TopoDS.hxx>
41 #include <TopoDS_Edge.hxx>
42 #include <TopoDS_Face.hxx>
43 #include <TopoDS_Shape.hxx>
44 #include <TopoDS_Vertex.hxx>
45 #include <TopoDS_Compound.hxx>
46 #include <TopoDS_Iterator.hxx>
47
48 #include <GCPnts_AbscissaPoint.hxx>
49 #include <IntTools.hxx>
50
51 #include <Geom_Curve.hxx>
52 #include <Geom_Surface.hxx>
53
54 #include <gp_Pnt.hxx>
55
56 #include <Precision.hxx>
57
58 #include <Standard_NullObject.hxx>
59
60 //=======================================================================
61 //function : GetID
62 //purpose  :
63 //=======================================================================
64 const Standard_GUID& GEOMImpl_PointDriver::GetID()
65 {
66   static Standard_GUID aPointDriver("FF1BBB02-5D14-4df2-980B-3A668264EA16");
67   return aPointDriver;
68 }
69
70
71 //=======================================================================
72 //function : GEOMImpl_PointDriver
73 //purpose  :
74 //=======================================================================
75 GEOMImpl_PointDriver::GEOMImpl_PointDriver()
76 {
77 }
78
79 //=======================================================================
80 //function : getExtremaSolution
81 //purpose  : local function
82 //=======================================================================
83 static Standard_Boolean getExtremaSolution
84 (const gp_Pnt&       theInitPnt,
85  const TopoDS_Shape& theRefShape,
86  gp_Pnt& thePnt)
87 {
88   BRepBuilderAPI_MakeVertex mkVertex (theInitPnt);
89   TopoDS_Vertex anInitV = TopoDS::Vertex(mkVertex.Shape());
90   
91   BRepExtrema_DistShapeShape anExt (anInitV, theRefShape);
92   if ( !anExt.IsDone() || anExt.NbSolution() < 1 )
93     return Standard_False;
94   thePnt = anExt.PointOnShape2(1);
95   Standard_Real aMinDist2 = theInitPnt.SquareDistance( thePnt );
96   for ( Standard_Integer j = 2, jn = anExt.NbSolution(); j <= jn; j++ )
97   {
98     gp_Pnt aPnt = anExt.PointOnShape2(j);
99     Standard_Real aDist2 = theInitPnt.SquareDistance( aPnt );
100     if ( aDist2 > aMinDist2)
101       continue;
102     aMinDist2 = aDist2;
103     thePnt = aPnt;
104   }
105   return Standard_True;
106 }
107
108 //=======================================================================
109 //function : Execute
110 //purpose  :
111 //=======================================================================
112 Standard_Integer GEOMImpl_PointDriver::Execute(TFunction_Logbook& log) const
113 {
114   if (Label().IsNull())  return 0;
115   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
116
117   GEOMImpl_IPoint aPI (aFunction);
118   Standard_Integer aType = aFunction->GetType();
119
120   gp_Pnt aPnt;
121   TopoDS_Compound aCompound;
122   bool retCompound = false;
123
124   if (aType == POINT_XYZ) {
125     aPnt = gp_Pnt(aPI.GetX(), aPI.GetY(), aPI.GetZ());
126   }
127   else if (aType == POINT_XYZ_REF) {
128     Handle(GEOM_Function) aRefFunc = aPI.GetRef();
129     TopoDS_Shape aRefShape = aRefFunc->GetValue();
130     if (aRefShape.ShapeType() != TopAbs_VERTEX) {
131       Standard_TypeMismatch::Raise
132         ("Point creation aborted : referenced shape is not a vertex");
133     }
134     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aRefShape));
135     aPnt = gp_Pnt(P.X() + aPI.GetX(), P.Y() + aPI.GetY(), P.Z() + aPI.GetZ());
136   }
137   else if (aType == POINT_CURVE_PAR) {
138     Handle(GEOM_Function) aRefFunc = aPI.GetCurve();
139     TopoDS_Shape aRefShape = aRefFunc->GetValue();
140     if (aRefShape.ShapeType() != TopAbs_EDGE) {
141       Standard_TypeMismatch::Raise
142         ("Point On Curve creation aborted : curve shape is not an edge");
143     }
144     Standard_Real aFP, aLP, aP;
145     Handle(Geom_Curve) aCurve = BRep_Tool::Curve(TopoDS::Edge(aRefShape), aFP, aLP);
146     if ( !aCurve.IsNull() ) {
147       aP = aFP + (aLP - aFP) * aPI.GetParameter();
148       aPnt = aCurve->Value(aP);
149     }
150     else {
151       // null curve, e.g. degenerated edge
152       TopoDS_Iterator It(aRefShape, Standard_False, Standard_False);
153       TopoDS_Vertex aVertex;
154       if ( It.More() ) {
155         TopoDS_Shape aShape = It.Value();
156         if ( !aShape.IsNull() )
157           aVertex = TopoDS::Vertex( aShape );
158       }
159       if ( !aVertex.IsNull() ) {
160         aPnt = BRep_Tool::Pnt( aVertex );
161       }
162       else {
163         Standard_TypeMismatch::Raise
164           ("Point On Curve creation aborted : null curve");
165       }
166     }
167   }
168   else if (aType == POINT_CURVE_COORD) {
169     Handle(GEOM_Function) aRefFunc = aPI.GetCurve();
170     TopoDS_Shape aRefShape = aRefFunc->GetValue();
171     if (aRefShape.ShapeType() != TopAbs_EDGE) {
172       Standard_TypeMismatch::Raise
173         ("Point On Curve creation aborted : curve shape is not an edge");
174     }
175     gp_Pnt anInitPnt (aPI.GetX(), aPI.GetY(), aPI.GetZ());
176     if (!getExtremaSolution(anInitPnt, aRefShape, aPnt)) {
177       Standard_ConstructionError::Raise
178         ("Point On Curve creation aborted : cannot project point");
179     }
180   }
181   else if (aType == POINT_CURVE_LENGTH) {
182     // RefCurve
183     Handle(GEOM_Function) aRefFunc = aPI.GetCurve();
184     if (aRefFunc.IsNull()) {
185       Standard_NullObject::Raise
186         ("Point On Curve creation aborted : curve object is null");
187     }
188     TopoDS_Shape aRefShape1 = aRefFunc->GetValue();
189     if (aRefShape1.ShapeType() != TopAbs_EDGE) {
190       Standard_TypeMismatch::Raise
191         ("Point On Curve creation aborted : curve shape is not an edge");
192     }
193     TopoDS_Edge aRefEdge = TopoDS::Edge(aRefShape1);
194     TopoDS_Vertex V1, V2;
195     TopExp::Vertices(aRefEdge, V1, V2, Standard_True);
196
197     // RefPoint
198     TopoDS_Vertex aRefVertex;
199     Handle(GEOM_Function) aRefPoint = aPI.GetRef();
200     if (aRefPoint.IsNull()) {
201       aRefVertex = V1;
202     }
203     else {
204       TopoDS_Shape aRefShape2 = aRefPoint->GetValue();
205       if (aRefShape2.ShapeType() != TopAbs_VERTEX) {
206         Standard_TypeMismatch::Raise
207           ("Point On Curve creation aborted : start point shape is not a vertex");
208       }
209       aRefVertex = TopoDS::Vertex(aRefShape2);
210     }
211     gp_Pnt aRefPnt = BRep_Tool::Pnt(aRefVertex);
212
213     // Length
214     Standard_Real aLength = aPI.GetLength();
215     //Standard_Real theCurveLength = IntTools::Length(aRefEdge);
216     //if (aLength > theCurveLength) {
217     //  Standard_ConstructionError::Raise
218     //    ("Point On Curve creation aborted : given length is greater than edges length");
219     //}
220
221     // Check orientation
222     Standard_Real UFirst, ULast;
223     Handle(Geom_Curve) EdgeCurve = BRep_Tool::Curve(aRefEdge, UFirst, ULast);
224
225     if ( !EdgeCurve.IsNull() ) {
226       Handle(Geom_Curve) ReOrientedCurve = EdgeCurve;
227
228       Standard_Real dU = ULast - UFirst;
229       Standard_Real par1 = UFirst + 0.1 * dU;
230       Standard_Real par2 = ULast  - 0.1 * dU;
231       
232       gp_Pnt P1 = EdgeCurve->Value(par1);
233       gp_Pnt P2 = EdgeCurve->Value(par2);
234       
235       if (aRefPnt.SquareDistance(P2) < aRefPnt.SquareDistance(P1)) {
236         ReOrientedCurve = EdgeCurve->Reversed();
237         UFirst = EdgeCurve->ReversedParameter(ULast);
238       }
239       
240       // Get the point by length
241       GeomAdaptor_Curve AdapCurve = GeomAdaptor_Curve(ReOrientedCurve);
242       GCPnts_AbscissaPoint anAbsPnt (AdapCurve, aLength, UFirst); 
243       Standard_Real aParam = anAbsPnt.Parameter();
244       aPnt = AdapCurve.Value(aParam);
245     }
246     else {
247       // null curve, e.g. degenerated edge
248       TopoDS_Iterator It(aRefEdge, Standard_False, Standard_False);
249       TopoDS_Vertex aVertex;
250       if ( It.More() ) {
251         TopoDS_Shape aShape = It.Value();
252         if ( !aShape.IsNull() )
253           aVertex = TopoDS::Vertex( aShape );
254       }
255       if ( !aVertex.IsNull() ) {
256         aPnt = BRep_Tool::Pnt( aVertex );
257       }
258       else {
259         Standard_TypeMismatch::Raise
260           ("Point On Curve creation aborted : null curve");
261       }
262     }
263   }
264   else if (aType == POINT_SURFACE_PAR) {
265     Handle(GEOM_Function) aRefFunc = aPI.GetSurface();
266     TopoDS_Shape aRefShape = aRefFunc->GetValue();
267     if (aRefShape.ShapeType() != TopAbs_FACE) {
268       Standard_TypeMismatch::Raise
269         ("Point On Surface creation aborted : surface shape is not a face");
270     }
271     TopoDS_Face F = TopoDS::Face(aRefShape);
272     Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
273     Standard_Real U1,U2,V1,V2;
274     //aSurf->Bounds(U1,U2,V1,V2);
275     ShapeAnalysis::GetFaceUVBounds(F,U1,U2,V1,V2);
276     Standard_Real U = U1 + (U2-U1) * aPI.GetParameter();
277     Standard_Real V = V1 + (V2-V1) * aPI.GetParameter2();
278     aPnt = aSurf->Value(U,V);
279   }
280   else if (aType == POINT_SURFACE_COORD) {
281     Handle(GEOM_Function) aRefFunc = aPI.GetSurface();
282     TopoDS_Shape aRefShape = aRefFunc->GetValue();
283     if (aRefShape.ShapeType() != TopAbs_FACE) {
284       Standard_TypeMismatch::Raise
285         ("Point On Surface creation aborted : surface shape is not a face");
286     }
287     gp_Pnt anInitPnt (aPI.GetX(), aPI.GetY(), aPI.GetZ());
288     if (!getExtremaSolution(anInitPnt, aRefShape, aPnt)) {
289       Standard_ConstructionError::Raise
290         ("Point On Surface creation aborted : cannot project point");
291     }
292   }
293   else if (aType == POINT_FACE_ANY) {
294     Handle(GEOM_Function) aRefFunc = aPI.GetSurface();
295     TopoDS_Shape aRefShape = aRefFunc->GetValue();
296     if (aRefShape.ShapeType() != TopAbs_FACE) {
297       Standard_TypeMismatch::Raise
298         ("Point On Surface creation aborted : surface shape is not a face");
299     }
300     TopoDS_Face F = TopoDS::Face(aRefShape);
301     gp_Pnt2d aP2d;
302     GEOMAlgo_Tools3D::PntInFace(F, aPnt, aP2d);
303   }
304   else if (aType == POINT_LINES_INTERSECTION) {
305     Handle(GEOM_Function) aRef1 = aPI.GetLine1();
306     Handle(GEOM_Function) aRef2 = aPI.GetLine2();
307
308     TopoDS_Shape aRefShape1 = aRef1->GetValue();
309     TopoDS_Shape aRefShape2 = aRef2->GetValue();
310
311     if ( (aRefShape1.ShapeType() != TopAbs_EDGE && aRefShape1.ShapeType() != TopAbs_WIRE)
312       || (aRefShape2.ShapeType() != TopAbs_EDGE && aRefShape2.ShapeType() != TopAbs_WIRE) ) {
313       Standard_TypeMismatch::Raise
314         ("Creation Point On Lines Intersection Aborted : Line shape is not an edge or wire");
315     }
316
317     if (aRefShape1.IsSame(aRefShape2))
318       Standard_ConstructionError::Raise("The lines to make intersection must be different");
319
320     //Calculate Lines Intersection Point
321     BRepExtrema_DistShapeShape dst (aRefShape1, aRefShape2);
322     if (dst.IsDone()) {
323       gp_Pnt P1, P2;
324       BRep_Builder B;
325       B.MakeCompound( aCompound );
326       for (int i = 1; i <= dst.NbSolution(); i++) {
327         P1 = dst.PointOnShape1(i);
328         P2 = dst.PointOnShape2(i);
329         Standard_Real Dist = P1.Distance(P2);
330         if ( Dist <= Precision::Confusion() && dst.NbSolution() > 1) {
331           BRepBuilderAPI_MakeVertex mkVertex (P1);
332           B.Add(aCompound, mkVertex.Shape());
333           retCompound = true;
334         } else if ( Dist <= Precision::Confusion() ) {
335           aPnt = P1;
336         } else {
337           Standard_TypeMismatch::Raise ("Shapes have not an Intersection Point");
338         }
339       }
340     }
341   }
342   else {
343     return 0;
344   }
345
346   TopoDS_Shape aShape;
347   if ( retCompound ) {
348     aShape = aCompound;
349   } else {
350     BRepBuilderAPI_MakeVertex mkVertex (aPnt);
351     aShape = mkVertex.Shape();
352   }
353
354   //aShape.Infinite(Standard_True); // VSR: 05/04/2010: Fix 20668 (Fit All for points & lines)
355   aFunction->SetValue(aShape);
356
357   log.SetTouched(Label());
358
359   return 1;
360 }
361
362
363 //=======================================================================
364 //function :  GEOMImpl_PointDriver_Type_
365 //purpose  :
366 //=======================================================================
367 Standard_EXPORT Handle_Standard_Type& GEOMImpl_PointDriver_Type_()
368 {
369
370   static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver);
371   if ( aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver);
372   static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared);
373   if ( aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared);
374   static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient);
375   if ( aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient);
376
377
378   static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL};
379   static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_PointDriver",
380                                                          sizeof(GEOMImpl_PointDriver),
381                                                          1,
382                                                          (Standard_Address)_Ancestors,
383                                                          (Standard_Address)NULL);
384
385   return _aType;
386 }
387
388 //=======================================================================
389 //function : DownCast
390 //purpose  :
391 //=======================================================================
392
393 const Handle(GEOMImpl_PointDriver) Handle(GEOMImpl_PointDriver)::DownCast(const Handle(Standard_Transient)& AnObject)
394 {
395   Handle(GEOMImpl_PointDriver) _anOtherObject;
396
397   if (!AnObject.IsNull()) {
398      if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_PointDriver))) {
399        _anOtherObject = Handle(GEOMImpl_PointDriver)((Handle(GEOMImpl_PointDriver)&)AnObject);
400      }
401   }
402
403   return _anOtherObject ;
404 }