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