1 // Created on: 1995-01-11
2 // Created by: Remi LEQUETTE
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 // modified : pmn 11/04/97 : mis dans GeomliteTest
20 #include <GeomliteTest.hxx>
21 #include <Geom2d_BSplineCurve.hxx>
22 #include <Draw_Interpretor.hxx>
23 #include <DrawTrSurf.hxx>
24 #include <Draw_Appli.hxx>
25 #include <DrawTrSurf_Curve2d.hxx>
26 #include <Geom2dAPI_ProjectPointOnCurve.hxx>
27 #include <Geom2dAPI_ExtremaCurveCurve.hxx>
28 #include <Geom2dAPI_Interpolate.hxx>
29 #include <Geom2dAPI_PointsToBSpline.hxx>
30 #include <Geom2dAPI_InterCurveCurve.hxx>
31 #include <Geom2d_Line.hxx>
32 #include <Geom2d_TrimmedCurve.hxx>
33 #include <GeomLib_Tool.hxx>
34 #include <TColgp_Array1OfPnt2d.hxx>
35 #include <Draw_Marker2D.hxx>
36 #include <Draw_Color.hxx>
37 #include <Draw_MarkerShape.hxx>
38 #include <TColStd_Array1OfReal.hxx>
39 #include <GeomAbs_Shape.hxx>
40 #include <Precision.hxx>
41 #include <Geom2d_Circle.hxx>
42 #include <IntAna2d_AnaIntersection.hxx>
43 #include <IntAna2d_IntPoint.hxx>
44 #include <IntAna2d_Conic.hxx>
45 #include <IntRes2d_IntersectionPoint.hxx>
46 #include <Geom2dAdaptor_Curve.hxx>
47 #include <Message.hxx>
48 #include <NCollection_Shared.hxx>
53 Standard_IMPORT Draw_Viewer dout;
56 //=======================================================================
59 //=======================================================================
61 static Standard_Integer proj (Draw_Interpretor& di, Standard_Integer n, const char** a)
65 di << "Syntax error: wrong number of arguments";
69 Handle(Geom2d_Curve) GC = DrawTrSurf::GetCurve2d(a[1]);
72 di << "Syntax error: '" << a[1] << "' is NULL";
76 const gp_Pnt2d P (Draw::Atof (a[2]), Draw::Atof (a[3]));
77 Geom2dAPI_ProjectPointOnCurve proj(P,GC,GC->FirstParameter(), GC->LastParameter());
78 for (Standard_Integer i = 1; i <= proj.NbPoints(); i++)
80 gp_Pnt2d aP1 = proj.Point(i);
81 const Standard_Real aDist = P.Distance(aP1);
82 const TCollection_AsciiString aName = TCollection_AsciiString ("ext_") + i;
83 if (aDist > Precision::PConfusion())
85 Handle(Geom2d_Line) L = new Geom2d_Line(P, gp_Dir2d(aP1.XY() - P.XY()));
86 Handle(Geom2d_TrimmedCurve) CT = new Geom2d_TrimmedCurve(L, 0., aDist);
87 DrawTrSurf::Set (aName.ToCString(), CT);
91 DrawTrSurf::Set (aName.ToCString(), aP1);
100 //=======================================================================
103 //=======================================================================
105 static Standard_Integer appro(Draw_Interpretor& di, Standard_Integer n, const char** a)
107 // Approximation et interpolation 2d
110 // - affiche la tolerance
112 // - change la tolerance
113 // 2dappro result nbpoint
114 // - saisie interactive
115 // 2dappro result nbpoint curve
116 // - calcule des points sur la courbe
117 // 2dappro result nbpoint x1 y1 x2 y2 ..
118 // - tableau de points
119 // 2dappro result nbpoint x1 dx y1 y2 ..
120 // - tableau de points (x1,y1) (x1+dx,y2) ... avec x = t
122 static Standard_Real Tol2d = 1.e-6;
127 Tol2d = Draw::Atof(a[1]);
130 di << "Tolerance for 2d approx : "<< Tol2d << "\n";
134 Standard_Integer i, Nb = Draw::Atoi(a[2]);
136 Standard_Boolean hasPoints = Standard_True;
137 TColgp_Array1OfPnt2d Points(1, Nb);
138 TColStd_Array1OfReal YValues(1,Nb);
139 Standard_Real X0=0,DX=0;
141 Handle(Draw_Marker2D) mark;
144 // saisie interactive
145 Standard_Integer id,XX,YY,b;
146 dout.Select(id,XX,YY,b);
147 Standard_Real zoom = dout.Zoom(id);
149 Points(1) = gp_Pnt2d( ((Standard_Real)XX)/zoom,
150 ((Standard_Real)YY)/zoom );
152 mark = new Draw_Marker2D( Points(1), Draw_X, Draw_vert);
156 for (i = 2; i<=Nb; i++) {
157 dout.Select(id,XX,YY,b);
158 Points(i) = gp_Pnt2d( ((Standard_Real)XX)/zoom,
159 ((Standard_Real)YY)/zoom );
160 mark = new Draw_Marker2D( Points(i), Draw_X, Draw_vert);
167 Handle(Geom2d_Curve) GC = DrawTrSurf::GetCurve2d(a[3]);
171 Standard_Real U, U1, U2;
172 U1 = GC->FirstParameter();
173 U2 = GC->LastParameter();
174 Standard_Real Delta = ( U2 - U1) / (Nb-1);
175 for ( i = 1 ; i <= Nb; i++) {
176 U = U1 + (i-1) * Delta;
177 Points(i) = GC->Value(U);
182 // test points ou ordonnees
183 Standard_Integer nc = n - 3;
187 for (i = 1; i <= Nb; i++) {
188 Points(i).SetCoord(Draw::Atof(a[nc]),Draw::Atof(a[nc+1]));
192 else if (nc - 2 == Nb) {
194 hasPoints = Standard_False;
196 X0 = Draw::Atof(a[3]);
197 DX = Draw::Atof(a[4]);
198 for (i = 1; i <= Nb; i++) {
199 YValues(i) = Draw::Atof(a[nc]);
200 Points(i).SetCoord(X0+(i-1)*DX,YValues(i));
207 // display the points
208 for ( i = 1 ; i <= Nb; i++) {
209 mark = new Draw_Marker2D( Points(i), Draw_X, Draw_vert);
214 Standard_Integer Dmin = 3;
215 Standard_Integer Dmax = 8;
217 Handle(Geom2d_BSplineCurve) TheCurve;
220 if (!strcmp (a[0], "2dinterpole"))
222 Geom2dAPI_Interpolate anInterpol (new TColgp_HArray1OfPnt2d(Points), Standard_False, Tol2d);
223 anInterpol.Perform();
224 if (!anInterpol.IsDone())
229 TheCurve = anInterpol.Curve();
233 Geom2dAPI_PointsToBSpline anApprox (Points, Dmin, Dmax, GeomAbs_C2, Tol2d);
234 if (!anApprox.IsDone())
239 TheCurve = anApprox.Curve();
244 if (!strcmp (a[0], "2dinterpole"))
246 di << "incorrect usage";
249 Geom2dAPI_PointsToBSpline anApprox (YValues, X0, DX, Dmin, Dmax, GeomAbs_C2, Tol2d);
250 if (!anApprox.IsDone())
255 TheCurve = anApprox.Curve();
258 DrawTrSurf::Set(a[1], TheCurve);
263 //=======================================================================
266 //=======================================================================
268 static Standard_Integer extrema(Draw_Interpretor& di, Standard_Integer n, const char** a)
272 di << "Syntax error: wrong number of arguments";
276 Handle(Geom2d_Curve) GC1 = DrawTrSurf::GetCurve2d (a[1]);
277 Handle(Geom2d_Curve) GC2 = DrawTrSurf::GetCurve2d (a[2]);
280 di << "Syntax error: '" << a[1] << "' is NULL";
285 di << "Syntax error: '" << a[2] << "' is NULL";
289 const Standard_Real U1f = GC1->FirstParameter();
290 const Standard_Real U1l = GC1->LastParameter();
291 const Standard_Real U2f = GC2->FirstParameter();
292 const Standard_Real U2l = GC2->LastParameter();
294 Geom2dAPI_ExtremaCurveCurve Ex(GC1,GC2,U1f,U1l,U2f,U2l);
295 Standard_Boolean isInfinitySolutions = Ex.Extrema().IsParallel();
296 const Standard_Integer aNExtr = Ex.NbExtrema();
298 if (aNExtr == 0 || isInfinitySolutions)
300 // Infinity solutions flag may be set with 0 number of
301 // solutions in analytic extrema Curve/Curve.
302 if (isInfinitySolutions)
303 di << "Infinite number of extremas, distance = " << Ex.LowerDistance() << "\n";
305 di << "No solutions!\n";
308 for (Standard_Integer i = 1; i <= aNExtr; i++)
312 di << "dist " << i << ": " << Ex.Distance(i) << " ";
313 const TCollection_AsciiString aName = TCollection_AsciiString("ext_") + i;
314 if (Ex.Distance(i) <= Precision::PConfusion())
316 Handle(Draw_Marker2D) mark = new Draw_Marker2D( P1, Draw_X, Draw_vert);
319 const char* temp = aName.ToCString();
320 DrawTrSurf::Set(temp, P1);
324 Handle(Geom2d_Line) L = new Geom2d_Line(P1,gp_Vec2d(P1,P2));
325 Handle(Geom2d_TrimmedCurve) CT = new Geom2d_TrimmedCurve(L, 0., P1.Distance(P2));
326 const char* temp = aName.ToCString();
327 DrawTrSurf::Set(temp, CT);
335 //=======================================================================
336 //function : intersect
338 //=======================================================================
339 static Standard_Integer intersect(Draw_Interpretor& di, Standard_Integer n, const char** a)
341 Handle(Geom2d_Curve) C1, C2;
342 Standard_Real Tol = 0.001;
343 Standard_Boolean bPrintState = Standard_False;
345 // Retrieve other parameters if any
346 for (Standard_Integer i = 1; i < n; ++i)
348 if (!strcmp(a[i], "-tol"))
350 Tol = Draw::Atof(a[++i]);
352 else if (!strcmp(a[i], "-state"))
354 bPrintState = Standard_True;
356 else if (C1.IsNull())
358 C1 = DrawTrSurf::GetCurve2d (a[i]);
361 di << "Syntax error: curve '" << a[i] << "' is null";
365 else if (C2.IsNull())
367 C2 = DrawTrSurf::GetCurve2d(a[i]);
370 di << "Syntax error: curve '" << a[i] << "' is null";
376 di << "Syntax error at '" << a[i] << "'";
382 di << "Syntax error: wrong number of arguments";
386 Geom2dAPI_InterCurveCurve Intersector;
389 // Curves intersection
390 Intersector.Init(C1, C2, Tol);
394 // Self-intersection of the curve
395 Intersector.Init(C1, Tol);
398 const Geom2dInt_GInter& anIntTool = Intersector.Intersector();
399 if (!anIntTool.IsDone())
401 di << "Intersection failed\n";
405 if (anIntTool.IsEmpty())
410 Standard_Integer aNbPoints = Intersector.NbPoints();
411 for (Standard_Integer i = 1; i <= aNbPoints; i++)
413 // API simplified result
414 gp_Pnt2d P = Intersector.Point(i);
415 di << "Intersection point " << i << " : " << P.X() << " " << P.Y() << "\n";
416 // Intersection extended results from intersection tool
417 const IntRes2d_IntersectionPoint& aPInt = anIntTool.Point(i);
418 di << "parameter on the fist: " << aPInt.ParamOnFirst();
419 di << " parameter on the second: " << aPInt.ParamOnSecond() << "\n";
422 di << "Intersection type: " <<
423 (aPInt.TransitionOfFirst().IsTangent() ? "TOUCH" : "INTERSECTION") << "\n";
425 Handle(Draw_Marker2D) mark = new Draw_Marker2D(P, Draw_X, Draw_vert);
430 Handle(Geom2d_Curve) S1, S2;
431 Handle(DrawTrSurf_Curve2d) CD;
432 Standard_Integer aNbSegments = Intersector.NbSegments();
433 for (Standard_Integer i = 1; i <= aNbSegments; i++)
435 di << "Segment #" << i << " found.\n";
436 Intersector.Segment(i,S1,S2);
437 CD = new DrawTrSurf_Curve2d(S1, Draw_bleu, 30);
439 CD = new DrawTrSurf_Curve2d(S2, Draw_violet, 30);
447 //=======================================================================
448 //function : intersect_ana
450 //=======================================================================
452 static Standard_Integer intersect_ana(Draw_Interpretor& di, Standard_Integer n, const char** a)
456 di << "Syntax error: wrong number of arguments";
460 Handle(Geom2d_Curve) C1 = DrawTrSurf::GetCurve2d(a[1]);
461 Handle(Geom2d_Curve) C2 = DrawTrSurf::GetCurve2d(a[2]);
462 Handle(Geom2d_Circle) aCir1 = Handle(Geom2d_Circle)::DownCast(C1);
463 Handle(Geom2d_Circle) aCir2 = Handle(Geom2d_Circle)::DownCast(C2);
464 if (aCir1.IsNull() || aCir2.IsNull())
466 di << "Syntax error: '" << a[aCir1.IsNull() ? 1 : 2] << "' is not a circle";
470 IntAna2d_AnaIntersection Intersector(aCir1->Circ2d(), aCir2->Circ2d());
471 for (Standard_Integer i = 1; i <= Intersector.NbPoints(); i++)
473 gp_Pnt2d P = Intersector.Point(i).Value();
474 di << "Intersection point " << i << " : " << P.X() << " " << P.Y() << "\n";
475 di << "parameter on the fist: " << Intersector.Point(i).ParamOnFirst();
476 di << " parameter on the second: " << Intersector.Point(i).ParamOnSecond() << "\n";
477 Handle(Draw_Marker2D) mark = new Draw_Marker2D(P, Draw_X, Draw_vert);
484 //=======================================================================
485 //function : intconcon
487 //=======================================================================
489 static Standard_Integer intconcon(Draw_Interpretor& di, Standard_Integer n, const char** a)
493 di << "Syntax error: wrong number of arguments";
497 Handle(Geom2d_Curve) C1 = DrawTrSurf::GetCurve2d(a[1]);
500 di << "Syntax error: '" << a[1] << "' is Null";
504 Handle(Geom2d_Curve) C2 = DrawTrSurf::GetCurve2d(a[2]);
507 di << "Syntax error: '" << a[2] << "' is Null";
511 Geom2dAdaptor_Curve AC1(C1), AC2(C2);
512 GeomAbs_CurveType T1 = AC1.GetType(), T2 = AC2.GetType();
513 Handle(NCollection_Shared<IntAna2d_Conic>) pCon;
518 pCon.reset (new NCollection_Shared<IntAna2d_Conic>(AC2.Line()));
523 pCon.reset (new NCollection_Shared<IntAna2d_Conic>(AC2.Circle()));
526 case GeomAbs_Ellipse:
528 pCon.reset (new NCollection_Shared<IntAna2d_Conic>(AC2.Ellipse()));
531 case GeomAbs_Hyperbola:
533 pCon.reset (new NCollection_Shared<IntAna2d_Conic>(AC2.Hyperbola()));
536 case GeomAbs_Parabola:
538 pCon.reset (new NCollection_Shared<IntAna2d_Conic>(AC2.Parabola()));
543 di << "Syntax error: '" << a[2] << "' is not conic";
548 IntAna2d_AnaIntersection Intersector;
552 Intersector.Perform(AC1.Line(), *pCon);
555 Intersector.Perform(AC1.Circle(), *pCon);
557 case GeomAbs_Ellipse:
558 Intersector.Perform(AC1.Ellipse(), *pCon);
560 case GeomAbs_Hyperbola:
561 Intersector.Perform(AC1.Hyperbola(), *pCon);
563 case GeomAbs_Parabola:
564 Intersector.Perform(AC1.Parabola(), *pCon);
567 di << "Syntax error: '" << a[1] << "' is not conic";
571 for (Standard_Integer i = 1; i <= Intersector.NbPoints(); i++)
573 gp_Pnt2d P = Intersector.Point(i).Value();
574 di<<"Intersection point "<<i<<" : "<<P.X()<<" "<<P.Y()<<"\n";
575 di << "parameter on the fist: " << Intersector.Point(i).ParamOnFirst();
576 if (!Intersector.Point(i).SecondIsImplicit())
578 di << " parameter on the second: " << Intersector.Point(i).ParamOnSecond() << "\n";
584 Handle(Draw_Marker2D) mark = new Draw_Marker2D( P, Draw_X, Draw_vert);
591 //=======================================================================
592 //function : deviation
594 //=======================================================================
595 static Standard_Integer deviation(Draw_Interpretor& theDI, Standard_Integer theNArg, const char** theArgv)
599 theDI << "Syntax error: wrong number of arguments";
603 const Handle(Geom2d_Curve) aC = DrawTrSurf::GetCurve2d(theArgv[2]);
607 theDI << "Error: " << theArgv[2] << " is not a 2D-curve.\n";
611 Geom2dAdaptor_Curve anAC(aC);
613 Standard_Integer aNbInterv = 2;
614 Standard_Real aU0 = RealLast();
615 Standard_Integer aNbApprox = 10;
616 Standard_Integer aNbExact = 100;
617 Standard_Boolean anIsApproxOnly = Standard_False;
620 for (Standard_Integer aCurrArg = 3; aCurrArg < theNArg; aCurrArg++)
622 TCollection_AsciiString anArg(theArgv[aCurrArg]);
626 aU0 = Draw::Atof(theArgv[++aCurrArg]);
628 else if (anArg == "-d")
630 aNbInterv = Draw::Atoi(theArgv[++aCurrArg]);
632 else if (anArg == "-napprox")
634 aNbApprox = Draw::Atoi(theArgv[++aCurrArg]);
636 else if (anArg == "-nexact")
638 aNbExact = Draw::Atoi(theArgv[++aCurrArg]);
640 else if (anArg == "-approxonly")
642 anIsApproxOnly = Standard_True;
647 theDI << "Error: Wrong option " << theArgv[aCurrArg] << "\n";
652 const Standard_Real aU1 = anAC.FirstParameter();
653 const Standard_Real aU2 = anAC.LastParameter();
655 Standard_Real aRetCurvParam = aU0;
660 Standard_Real aDefl = RealLast();
662 if (aU0 == RealLast() || anIsApproxOnly)
664 aDefl = GeomLib_Tool::ComputeDeviation(anAC, aU1, aU2,
665 aNbInterv, aNbApprox, &aU0);
669 theDI << "Error: Cannot compute deviation on interval.\n";
675 aDefl = GeomLib_Tool::ComputeDeviation(anAC, aU1, aU2, aU0, aNbExact,
676 &aRetCurvParam, &aPtOnCurv,
677 &aRetVec, &aLinSegm);
681 theDI << "Error: Cannot compute a deviation!\n";
684 theDI << "Computed value is: " << aDefl << "\n";
685 TCollection_AsciiString anArgString = theArgv[1];
686 TCollection_AsciiString aPntString = anArgString + "_pnt";
687 DrawTrSurf::Set(aPntString.ToCString(), aPtOnCurv);
688 theDI << "From point " << aPntString << " (with parameter " << aRetCurvParam << ") to ";
690 Handle(Geom2d_Curve) aLine = new Geom2d_Line(aLinSegm);
691 TCollection_AsciiString aLinString = anArgString + "_lin";
692 DrawTrSurf::Set(aLinString.ToCString(), aLine);
693 theDI << "the line " << aLinString << ".\n";
695 aLine = new Geom2d_Line(aPtOnCurv, aRetVec);
696 aLine = new Geom2d_TrimmedCurve(aLine, 0.0, aDefl);
697 TCollection_AsciiString aNormString = anArgString + "_norm";
698 DrawTrSurf::Set(aNormString.ToCString(), aLine);
699 theDI << "The deflection is measured along the line " << aNormString << ".\n";
704 void GeomliteTest::API2dCommands(Draw_Interpretor& theCommands)
706 static Standard_Boolean done = Standard_False;
711 done = Standard_True;
712 g = "GEOMETRY curves and surfaces analysis";
714 theCommands.Add("2dproj", "proj curve x y",__FILE__, proj,g);
716 g = "GEOMETRY approximations";
718 theCommands.Add("2dapprox", "2dapprox result nbpoint [curve] [[x] y [x] y...]",__FILE__,
720 theCommands.Add("2dinterpole", "2dinterpole result nbpoint [curve] [[x] y [x] y ...]",__FILE__,
723 g = "GEOMETRY curves and surfaces analysis";
725 theCommands.Add("2dextrema", "extrema curve curve",__FILE__,
728 g = "GEOMETRY intersections";
730 theCommands.Add("2dintersect", "2dintersect curve1 [curve2] [-tol tol] [-state]\n"
731 "Intersects the given 2d curve(s)."
732 "If only one curve is given, it will be checked on self-intersection.\n"
734 " -tol - allows changing the intersection tolerance (default value is 1.e-3);\n"
735 " -state - allows printing the intersection state for each point.",
736 __FILE__, intersect, g);
738 theCommands.Add("2dintanalytical", "2dintanalytical circle1 circle2"
739 "Intersect circle1 and circle2 using IntAna2d_AnaIntersection.",
740 __FILE__, intersect_ana, g);
741 theCommands.Add("intconcon", "intconcon curve1 curve2"
742 "Intersect conic curve1 and conic curve2 using IntAna2d_AnaIntersection",
743 __FILE__, intconcon, g);
745 theCommands.Add("2ddeviation", "2ddeviation result curve [-i U0] [-d N] [-Napprox N] [-Nexact N] [-approxOnly]\n"
746 "-i - sets an initial parameter for computation by iterative method;\n"
747 "-d - sets number of sub-intervals for searching. Default value is 2.\n"
748 "-Napprox - sets number of iteration for approx deviation computing,\n"
749 " defauilt value is 10"
750 "-Nexact - sets number of iteration for exact deviation computing,\n"
751 " defauilt value is 100"
752 "-approxOnly - to find deviation with approx method only,\n"
753 " the exact method is used if this parameter is not specified",
754 __FILE__, deviation, g);