]> SALOME platform Git repositories - modules/geom.git/blob - src/GEOMImpl/GEOMImpl_PointDriver.cxx
Salome HOME
[bos #42424] [CEA][FORUM] bug with MinDistance in Geom Module. Old workarounds causin...
[modules/geom.git] / src / GEOMImpl / GEOMImpl_PointDriver.cxx
1 // Copyright (C) 2007-2024  CEA, EDF, 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, or (at your option) any later version.
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 <Basics_OCCTVersion.hxx>
26
27 #include <GEOMImpl_PointDriver.hxx>
28 #include <GEOMImpl_IPoint.hxx>
29 #include <GEOMImpl_Types.hxx>
30 #include <GEOM_Function.hxx>
31 #include <GEOMAlgo_AlgoTools.hxx>
32
33 #include <BRep_Builder.hxx>
34 #include <BRep_Tool.hxx>
35 #include <BRepAdaptor_Curve.hxx>
36 #include <BRepBuilderAPI_MakeVertex.hxx>
37 #include <BRepExtrema_DistShapeShape.hxx>
38 #include <BRepTools.hxx>
39
40 #include <TopAbs.hxx>
41 #include <TopExp.hxx>
42 #include <TopoDS.hxx>
43 #include <TopoDS_Edge.hxx>
44 #include <TopoDS_Face.hxx>
45 #include <TopoDS_Shape.hxx>
46 #include <TopoDS_Vertex.hxx>
47 #include <TopoDS_Compound.hxx>
48 #include <TopoDS_Iterator.hxx>
49
50 #include <GCPnts_AbscissaPoint.hxx>
51 #include <IntTools.hxx>
52
53 #include <Geom_Curve.hxx>
54 #include <Geom_Surface.hxx>
55
56 #include <gp_Pnt.hxx>
57
58 #include <Precision.hxx>
59
60 #include <Standard_NullObject.hxx>
61 #include <Standard_NotImplemented.hxx>
62
63 //=======================================================================
64 //function : GetID
65 //purpose  :
66 //=======================================================================
67 const Standard_GUID& GEOMImpl_PointDriver::GetID()
68 {
69   static Standard_GUID aPointDriver("FF1BBB02-5D14-4df2-980B-3A668264EA16");
70   return aPointDriver;
71 }
72
73
74 //=======================================================================
75 //function : GEOMImpl_PointDriver
76 //purpose  :
77 //=======================================================================
78 GEOMImpl_PointDriver::GEOMImpl_PointDriver()
79 {
80 }
81
82 //=======================================================================
83 //function : getExtremaSolution
84 //purpose  : local function
85 //=======================================================================
86 static Standard_Boolean getExtremaSolution
87 (const gp_Pnt&       theInitPnt,
88  const TopoDS_Shape& theRefShape,
89  gp_Pnt& thePnt)
90 {
91   BRepBuilderAPI_MakeVertex mkVertex (theInitPnt);
92   TopoDS_Vertex anInitV = TopoDS::Vertex(mkVertex.Shape());
93   
94   BRepExtrema_DistShapeShape anExt (anInitV, theRefShape);
95   if ( !anExt.IsDone() || anExt.NbSolution() < 1 )
96     return Standard_False;
97   thePnt = anExt.PointOnShape2(1);
98   Standard_Real aMinDist2 = theInitPnt.SquareDistance( thePnt );
99   for ( Standard_Integer j = 2, jn = anExt.NbSolution(); j <= jn; j++ )
100   {
101     gp_Pnt aPnt = anExt.PointOnShape2(j);
102     Standard_Real aDist2 = theInitPnt.SquareDistance( aPnt );
103     if ( aDist2 > aMinDist2)
104       continue;
105     aMinDist2 = aDist2;
106     thePnt = aPnt;
107   }
108   return Standard_True;
109 }
110
111 //=======================================================================
112 //function : Execute
113 //purpose  :
114 //=======================================================================
115 Standard_Integer GEOMImpl_PointDriver::Execute(Handle(TFunction_Logbook)& log) const
116 {
117   if (Label().IsNull())  return 0;
118   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
119
120   GEOMImpl_IPoint aPI (aFunction);
121   Standard_Integer aType = aFunction->GetType();
122
123   gp_Pnt aPnt;
124   TopoDS_Compound aCompound;
125   bool retCompound = false;
126
127   if (aType == POINT_XYZ) {
128     aPnt = gp_Pnt(aPI.GetX(), aPI.GetY(), aPI.GetZ());
129   }
130   else if (aType == POINT_XYZ_REF) {
131     Handle(GEOM_Function) aRefFunc = aPI.GetRef();
132     TopoDS_Shape aRefShape = aRefFunc->GetValue();
133     if (aRefShape.ShapeType() != TopAbs_VERTEX) {
134       Standard_TypeMismatch::Raise
135         ("Point creation aborted : referenced shape is not a vertex");
136     }
137     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aRefShape));
138     aPnt = gp_Pnt(P.X() + aPI.GetX(), P.Y() + aPI.GetY(), P.Z() + aPI.GetZ());
139   }
140   else if (aType == POINT_CURVE_PAR) {
141     Handle(GEOM_Function) aRefFunc = aPI.GetCurve();
142     TopoDS_Shape aRefShape = aRefFunc->GetValue();
143     if (aRefShape.ShapeType() != TopAbs_EDGE) {
144       Standard_TypeMismatch::Raise
145         ("Point On Curve creation aborted : curve shape is not an edge");
146     }
147     Standard_Real aFP, aLP, aP;
148     Handle(Geom_Curve) aCurve = BRep_Tool::Curve(TopoDS::Edge(aRefShape), aFP, aLP);
149     if ( !aCurve.IsNull() ) {
150       if (aPI.GetTakeOrientationIntoAccount() &&
151           aRefShape.Orientation() == TopAbs_REVERSED) {
152         aP = 1. - aPI.GetParameter();
153       } else {
154         aP = aPI.GetParameter();
155       }
156
157       aP = aFP + (aLP - aFP) * aP;
158       aPnt = aCurve->Value(aP);
159     }
160     else {
161       // null curve, e.g. degenerated edge
162       TopoDS_Iterator It(aRefShape, Standard_False, Standard_False);
163       TopoDS_Vertex aVertex;
164       if ( It.More() ) {
165         TopoDS_Shape aShape = It.Value();
166         if ( !aShape.IsNull() )
167           aVertex = TopoDS::Vertex( aShape );
168       }
169       if ( !aVertex.IsNull() ) {
170         aPnt = BRep_Tool::Pnt( aVertex );
171       }
172       else {
173         Standard_TypeMismatch::Raise
174           ("Point On Curve creation aborted : null curve");
175       }
176     }
177   }
178   else if (aType == POINT_CURVE_COORD) {
179     Handle(GEOM_Function) aRefFunc = aPI.GetCurve();
180     TopoDS_Shape aRefShape = aRefFunc->GetValue();
181     if (aRefShape.ShapeType() != TopAbs_EDGE) {
182       Standard_TypeMismatch::Raise
183         ("Point On Curve creation aborted : curve shape is not an edge");
184     }
185     gp_Pnt anInitPnt (aPI.GetX(), aPI.GetY(), aPI.GetZ());
186     if (!getExtremaSolution(anInitPnt, aRefShape, aPnt)) {
187       Standard_ConstructionError::Raise
188         ("Point On Curve creation aborted : cannot project point");
189     }
190   }
191   else if (aType == POINT_CURVE_LENGTH) {
192     // RefCurve
193     Handle(GEOM_Function) aRefFunc = aPI.GetCurve();
194     if (aRefFunc.IsNull()) {
195       Standard_NullObject::Raise
196         ("Point On Curve creation aborted : curve object is null");
197     }
198     TopoDS_Shape aRefShape1 = aRefFunc->GetValue();
199     if (aRefShape1.ShapeType() != TopAbs_EDGE) {
200       Standard_TypeMismatch::Raise
201         ("Point On Curve creation aborted : curve shape is not an edge");
202     }
203     TopoDS_Edge aRefEdge = TopoDS::Edge(aRefShape1);
204     TopoDS_Vertex V1, V2;
205     TopExp::Vertices(aRefEdge, V1, V2, Standard_True);
206
207     // RefPoint
208     TopoDS_Vertex aRefVertex;
209     Handle(GEOM_Function) aRefPoint = aPI.GetRef();
210     if (aRefPoint.IsNull()) {
211       aRefVertex = V1;
212     }
213     else {
214       TopoDS_Shape aRefShape2 = aRefPoint->GetValue();
215       if (aRefShape2.ShapeType() != TopAbs_VERTEX) {
216         Standard_TypeMismatch::Raise
217           ("Point On Curve creation aborted : start point shape is not a vertex");
218       }
219       aRefVertex = TopoDS::Vertex(aRefShape2);
220     }
221     gp_Pnt aRefPnt = BRep_Tool::Pnt(aRefVertex);
222
223     // Length
224     Standard_Real aLength = aPI.GetLength();
225     //Standard_Real theCurveLength = IntTools::Length(aRefEdge);
226     //if (aLength > theCurveLength) {
227     //  Standard_ConstructionError::Raise
228     //    ("Point On Curve creation aborted : given length is greater than edges length");
229     //}
230
231     // Check orientation
232     Standard_Real UFirst, ULast;
233     Handle(Geom_Curve) EdgeCurve = BRep_Tool::Curve(aRefEdge, UFirst, ULast);
234
235     if ( !EdgeCurve.IsNull() ) {
236       Handle(Geom_Curve) ReOrientedCurve = EdgeCurve;
237
238       Standard_Real dU = ULast - UFirst;
239       Standard_Real par1 = UFirst + 0.1 * dU;
240       Standard_Real par2 = ULast  - 0.1 * dU;
241       
242       gp_Pnt P1 = EdgeCurve->Value(par1);
243       gp_Pnt P2 = EdgeCurve->Value(par2);
244       
245       if (aRefPnt.SquareDistance(P2) < aRefPnt.SquareDistance(P1)) {
246         ReOrientedCurve = EdgeCurve->Reversed();
247         UFirst = EdgeCurve->ReversedParameter(ULast);
248       }
249       
250       // Get the point by length
251       GeomAdaptor_Curve AdapCurve = GeomAdaptor_Curve(ReOrientedCurve);
252       GCPnts_AbscissaPoint anAbsPnt (AdapCurve, aLength, UFirst); 
253       Standard_Real aParam = anAbsPnt.Parameter();
254       aPnt = AdapCurve.Value(aParam);
255     }
256     else {
257       // null curve, e.g. degenerated edge
258       TopoDS_Iterator It(aRefEdge, Standard_False, Standard_False);
259       TopoDS_Vertex aVertex;
260       if ( It.More() ) {
261         TopoDS_Shape aShape = It.Value();
262         if ( !aShape.IsNull() )
263           aVertex = TopoDS::Vertex( aShape );
264       }
265       if ( !aVertex.IsNull() ) {
266         aPnt = BRep_Tool::Pnt( aVertex );
267       }
268       else {
269         Standard_TypeMismatch::Raise
270           ("Point On Curve creation aborted : null curve");
271       }
272     }
273   }
274   else if (aType == POINT_SURFACE_PAR) {
275     Handle(GEOM_Function) aRefFunc = aPI.GetSurface();
276     TopoDS_Shape aRefShape = aRefFunc->GetValue();
277     if (aRefShape.ShapeType() != TopAbs_FACE) {
278       Standard_TypeMismatch::Raise
279         ("Point On Surface creation aborted : surface shape is not a face");
280     }
281     TopoDS_Face F = TopoDS::Face(aRefShape);
282     Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
283     Standard_Real U1,U2,V1,V2;
284     BRepTools::UVBounds(F,U1,U2,V1,V2);
285     Standard_Real U = U1 + (U2-U1) * aPI.GetParameter();
286     Standard_Real V = V1 + (V2-V1) * aPI.GetParameter2();
287     aPnt = aSurf->Value(U,V);
288   }
289   else if (aType == POINT_SURFACE_COORD) {
290     Handle(GEOM_Function) aRefFunc = aPI.GetSurface();
291     TopoDS_Shape aRefShape = aRefFunc->GetValue();
292     if (aRefShape.ShapeType() != TopAbs_FACE) {
293       Standard_TypeMismatch::Raise
294         ("Point On Surface creation aborted : surface shape is not a face");
295     }
296     gp_Pnt anInitPnt (aPI.GetX(), aPI.GetY(), aPI.GetZ());
297     if (!getExtremaSolution(anInitPnt, aRefShape, aPnt)) {
298       Standard_ConstructionError::Raise
299         ("Point On Surface creation aborted : cannot project point");
300     }
301   }
302   else if (aType == POINT_FACE_ANY) {
303     Handle(GEOM_Function) aRefFunc = aPI.GetSurface();
304     TopoDS_Shape aRefShape = aRefFunc->GetValue();
305     int aNbPnts = aPI.GetNumberOfPoints();
306     if (aNbPnts < 1) {
307       Standard_TypeMismatch::Raise
308         ("Point On Surface creation aborted : number of points is zero or negative");
309     }
310     if (aRefShape.ShapeType() != TopAbs_FACE) {
311       Standard_TypeMismatch::Raise
312         ("Point On Surface creation aborted : surface shape is not a face");
313     }
314     TopoDS_Face F = TopoDS::Face(aRefShape);
315     if (aNbPnts == 1)
316     {
317       gp_Pnt2d aP2d;
318       GEOMAlgo_AlgoTools::PntInFace(F, aPnt, aP2d);
319     }
320     else
321     {
322 #if OCC_VERSION_LARGE < 0x07050304
323       Standard_NotImplemented::Raise("Point cloud creation aborted. Improper OCCT version: please, use OCCT 7.5.3p4 or newer.");
324 #else
325       if (GEOMAlgo_AlgoTools::PointCloudInFace(F, aNbPnts, aCompound) < 0)
326         Standard_ConstructionError::Raise("Point cloud creation aborted : algorithm failed");
327       retCompound = true;
328 #endif
329     }
330   }
331   else if (aType == POINT_LINES_INTERSECTION) {
332     Handle(GEOM_Function) aRef1 = aPI.GetLine1();
333     Handle(GEOM_Function) aRef2 = aPI.GetLine2();
334
335     TopoDS_Shape aRefShape1 = aRef1->GetValue();
336     TopoDS_Shape aRefShape2 = aRef2->GetValue();
337
338     if ( (aRefShape1.ShapeType() != TopAbs_EDGE && aRefShape1.ShapeType() != TopAbs_WIRE)
339       || (aRefShape2.ShapeType() != TopAbs_EDGE && aRefShape2.ShapeType() != TopAbs_WIRE) ) {
340       Standard_TypeMismatch::Raise
341         ("Creation Point On Lines Intersection Aborted : Line shape is not an edge or wire");
342     }
343
344     if (aRefShape1.IsSame(aRefShape2))
345       Standard_ConstructionError::Raise("The lines to make intersection must be different");
346
347     //Calculate Lines Intersection Point
348     BRepExtrema_DistShapeShape dst (aRefShape1, aRefShape2);
349     if (dst.IsDone()) {
350       gp_Pnt P1, P2;
351       BRep_Builder B;
352       B.MakeCompound( aCompound );
353       for (int i = 1; i <= dst.NbSolution(); i++) {
354         P1 = dst.PointOnShape1(i);
355         P2 = dst.PointOnShape2(i);
356         Standard_Real Dist = P1.Distance(P2);
357         if ( Dist <= Precision::Confusion() && dst.NbSolution() > 1) {
358           BRepBuilderAPI_MakeVertex mkVertex (P1);
359           B.Add(aCompound, mkVertex.Shape());
360           retCompound = true;
361         } else if ( Dist <= Precision::Confusion() ) {
362           aPnt = P1;
363         } else {
364           Standard_TypeMismatch::Raise ("Shapes have not an Intersection Point");
365         }
366       }
367     }
368   }
369   else {
370     return 0;
371   }
372
373   TopoDS_Shape aShape;
374   if ( retCompound ) {
375     aShape = aCompound;
376   } else {
377     BRepBuilderAPI_MakeVertex mkVertex (aPnt);
378     aShape = mkVertex.Shape();
379   }
380
381   //aShape.Infinite(Standard_True); // VSR: 05/04/2010: Fix 20668 (Fit All for points & lines)
382   aFunction->SetValue(aShape);
383
384   log->SetTouched(Label());
385
386   return 1;
387 }
388
389 //================================================================================
390 /*!
391  * \brief Returns a name of creation operation and names and values of creation parameters
392  */
393 //================================================================================
394
395 bool GEOMImpl_PointDriver::
396 GetCreationInformation(std::string&             theOperationName,
397                        std::vector<GEOM_Param>& theParams)
398 {
399   if (Label().IsNull()) return 0;
400   Handle(GEOM_Function) function = GEOM_Function::GetFunction(Label());
401
402   GEOMImpl_IPoint aCI( function );
403   Standard_Integer aType = function->GetType();
404
405   theOperationName = "POINT";
406
407   switch ( aType ) {
408   case POINT_XYZ:
409     AddParam( theParams, "X", aCI.GetX() );
410     AddParam( theParams, "Y", aCI.GetY() );
411     AddParam( theParams, "Z", aCI.GetZ() );
412     break;
413   case POINT_XYZ_REF:
414     AddParam( theParams, "Point", aCI.GetRef() );
415     AddParam( theParams, "Dx", aCI.GetX() );
416     AddParam( theParams, "Dy", aCI.GetY() );
417     AddParam( theParams, "Dz", aCI.GetZ() );
418     break;
419   case POINT_CURVE_PAR:
420     AddParam( theParams, "Edge", aCI.GetCurve() );
421     AddParam( theParams, "Parameter", aCI.GetParameter() );
422     AddParam( theParams, "Use Orientation", aCI.GetTakeOrientationIntoAccount() );
423     break;
424   case POINT_CURVE_COORD:
425     AddParam( theParams, "X", aCI.GetX() );
426     AddParam( theParams, "Y", aCI.GetY() );
427     AddParam( theParams, "Z", aCI.GetZ() );
428     AddParam( theParams, "Edge", aCI.GetCurve() );
429     break;
430   case POINT_CURVE_LENGTH:
431     AddParam( theParams, "Edge", aCI.GetCurve() );
432     AddParam( theParams, "Start Point", aCI.GetRef(), "First Vertex" );
433     AddParam( theParams, "Length", aCI.GetLength() );
434     break;
435   case POINT_SURFACE_PAR:
436     AddParam( theParams, "Face", aCI.GetSurface() );
437     AddParam( theParams, "U-Parameter", aCI.GetParameter() );
438     AddParam( theParams, "V-Parameter", aCI.GetParameter2() );
439     break;
440   case POINT_SURFACE_COORD:
441     AddParam( theParams, "X", aCI.GetX() );
442     AddParam( theParams, "Y", aCI.GetY() );
443     AddParam( theParams, "Z", aCI.GetZ() );
444     AddParam( theParams, "Face", aCI.GetSurface() );
445     break;
446   case POINT_FACE_ANY:
447     AddParam( theParams, "Face", aCI.GetSurface() );
448     break;
449   case POINT_LINES_INTERSECTION:
450     AddParam( theParams, "Line 1", aCI.GetLine1() );
451     AddParam( theParams, "Line 2", aCI.GetLine2() );
452     break;
453   default:
454     return false;
455   }
456
457   return true;
458 }
459
460 IMPLEMENT_STANDARD_RTTIEXT (GEOMImpl_PointDriver,GEOM_BaseDriver)