0028631: Modeling Algorithms - Crash while building a 2D circle tangent to another...
authornds <nds@opencascade.com>
Fri, 26 May 2017 14:19:51 +0000 (17:19 +0300)
committerabv <abv@opencascade.com>
Thu, 17 Aug 2017 19:21:32 +0000 (22:21 +0300)
Code correction includes also:
- extending GccEnt to have GccEnt_Position conversion to string value and backward;
- new GeometryTest_DrawableQualifiedCurve2d DRAW object to wrap GccEnt_QualifiedCirc/GccEnt_QualifiedLin.
  It is a DrawTrSurf_Curve2d with GccEnt_Position visualized in orange color.
- qcircle/qline DRAW command to create instance of GeometryTest_DrawableQualifiedCurve2d
- circ2d3Tan DRAW command to wrap GccAna_Circ2d3Tan taking qcircle/qline/point arguments.

33 files changed:
src/GccAna/GccAna_Circ2d3Tan_4.cxx
src/GccAna/GccAna_Circ2d3Tan_7.cxx
src/GccEnt/GccEnt.cxx
src/GccEnt/GccEnt.hxx
src/GeometryTest/FILES
src/GeometryTest/GeometryTest.cxx
src/GeometryTest/GeometryTest.hxx
src/GeometryTest/GeometryTest_CurveTanCommands.cxx [new file with mode: 0644]
src/GeometryTest/GeometryTest_DrawableQualifiedCurve2d.cxx [new file with mode: 0644]
src/GeometryTest/GeometryTest_DrawableQualifiedCurve2d.hxx [new file with mode: 0644]
tests/geometry/circ2d3Tan/CircleCircleCircle_11 [new file with mode: 0644]
tests/geometry/circ2d3Tan/CircleCircleLin_11 [new file with mode: 0644]
tests/geometry/circ2d3Tan/CircleCirclePoint_11 [new file with mode: 0644]
tests/geometry/circ2d3Tan/CircleCirclePoint_12 [new file with mode: 0644]
tests/geometry/circ2d3Tan/CircleCirclePoint_13 [new file with mode: 0644]
tests/geometry/circ2d3Tan/CircleCirclePoint_14 [new file with mode: 0644]
tests/geometry/circ2d3Tan/CircleLinLin_11 [new file with mode: 0644]
tests/geometry/circ2d3Tan/CircleLinPoint_11 [new file with mode: 0644]
tests/geometry/circ2d3Tan/CirclePointPoint_11 [new file with mode: 0644]
tests/geometry/circ2d3Tan/CirclePointPoint_12 [new file with mode: 0644]
tests/geometry/circ2d3Tan/CirclePointPoint_13 [new file with mode: 0644]
tests/geometry/circ2d3Tan/CirclePointPoint_14 [new file with mode: 0644]
tests/geometry/circ2d3Tan/CirclePointPoint_15 [new file with mode: 0644]
tests/geometry/circ2d3Tan/CirclePointPoint_21 [new file with mode: 0644]
tests/geometry/circ2d3Tan/CirclePointPoint_22 [new file with mode: 0644]
tests/geometry/circ2d3Tan/CirclePointPoint_23 [new file with mode: 0644]
tests/geometry/circ2d3Tan/CirclePointPoint_24 [new file with mode: 0644]
tests/geometry/circ2d3Tan/CirclePointPoint_31 [new file with mode: 0644]
tests/geometry/circ2d3Tan/LinLinLin_11 [new file with mode: 0644]
tests/geometry/circ2d3Tan/LinLinPoint_11 [new file with mode: 0644]
tests/geometry/circ2d3Tan/LinPointPoint_11 [new file with mode: 0644]
tests/geometry/circ2d3Tan/PointPointPoint_11 [new file with mode: 0644]
tests/geometry/grids.list

index e1d936c..fa14517 100644 (file)
@@ -294,6 +294,8 @@ GccAna_Circ2d3Tan::
                   else {
                     TheSame1(NbrSol) = 0;
                     gp_Dir2d dc(center1.XY()-Center.XY());
+                    if (qualifier1(NbrSol) == GccEnt_enclosed)
+                      dc.Reverse(); // if tangent circle is inside the source circle, moving to edge of source circle
                     pnttg1sol(NbrSol)=gp_Pnt2d(Center.XY()+Radius(k1)*dc.XY());
                     par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
                                                      pnttg1sol(NbrSol));
index 21c87b5..5e521f3 100644 (file)
@@ -185,9 +185,10 @@ GccAna_Circ2d3Tan::
                 else {
                   TheSame1(NbrSol) = 0;
                   gp_Dir2d dc(center1.XY()-Center.XY());
+                  if (qualifier1(NbrSol) == GccEnt_enclosed)
+                    dc.Reverse(); // if tangent circle is inside the source circle, moving to edge of source circle
                   pnttg1sol(NbrSol)=gp_Pnt2d(Center.XY()+Radius(nbsol3)*dc.XY());
-                  par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
-                                                   pnttg1sol(NbrSol));
+                  par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol), pnttg1sol(NbrSol));
                   pararg1(NbrSol)=ElCLib::Parameter(C1,pnttg1sol(NbrSol));
                 }
 
index c5165c6..607fd56 100644 (file)
 #include <GccEnt_QualifiedLin.hxx>
 #include <gp_Circ2d.hxx>
 #include <gp_Lin2d.hxx>
+#include <TCollection_AsciiString.hxx>
+
+namespace
+{
+  static Standard_CString GccEnt_Table_PrintPosition[5] =
+  {
+    "UNQUALIFIED", "ENCLOSING", "ENCLOSED", "OUTSIDE", "NOQUALIFIER"
+  };
+}
+
+//=======================================================================
+//function : PositionToString
+//purpose  :
+//=======================================================================
+Standard_CString GccEnt::PositionToString (GccEnt_Position thePosition)
+{
+  return GccEnt_Table_PrintPosition[thePosition];
+}
+
+//=======================================================================
+//function : PositionFromString
+//purpose  :
+//=======================================================================
+Standard_Boolean GccEnt::PositionFromString (Standard_CString thePositionString,
+                                             GccEnt_Position& thePosition)
+{
+  TCollection_AsciiString aName (thePositionString);
+  aName.UpperCase();
+  for (Standard_Integer aTypeIter = 0; aTypeIter <= GccEnt_noqualifier; ++aTypeIter)
+  {
+    Standard_CString aTypeName = GccEnt_Table_PrintPosition[aTypeIter];
+    if (aName == aTypeName)
+    {
+      thePosition = GccEnt_Position(aTypeIter);
+      return Standard_True;
+    }
+  }
+  return Standard_False;
+}
 
 GccEnt_QualifiedLin
   GccEnt::Unqualified(const gp_Lin2d& Line) {
index b405d4d..dbaf7b5 100644 (file)
@@ -17,6 +17,7 @@
 #ifndef _GccEnt_HeaderFile
 #define _GccEnt_HeaderFile
 
+#include <GccEnt_Position.hxx>
 #include <Standard.hxx>
 #include <Standard_DefineAlloc.hxx>
 #include <Standard_Handle.hxx>
@@ -53,6 +54,34 @@ public:
 
   DEFINE_STANDARD_ALLOC
 
+
+  //! Prints the name of Position type as a String on the Stream.
+  static Standard_OStream& Print (const GccEnt_Position thePosition, Standard_OStream& theStream)
+  {
+    return (theStream << PositionToString (thePosition));
+  }
+
+  //! Returns the string name for a given position.
+  //! @param thePosition position type
+  //! @return string identifier from the list UNQUALIFIED ENCLOSING ENCLOSED OUTSIDE NOQUALIFIER
+  Standard_EXPORT static Standard_CString PositionToString (GccEnt_Position thePosition);
+
+  //! Returns the position from the given string identifier (using case-insensitive comparison).
+  //! @param thePositionString string identifier
+  //! @return position or GccEnt_unqualified if string identifier is invalid
+  static GccEnt_Position PositionFromString (Standard_CString thePositionString)
+  {
+    GccEnt_Position aPosition = GccEnt_unqualified;
+    PositionFromString (thePositionString, aPosition);
+    return aPosition;
+  }
+
+  //! Determines the position from the given string identifier (using case-insensitive comparison).
+  //! @param thePositionString string identifier
+  //! @param thePosition detected shape type
+  //! @return TRUE if string identifier is known
+  Standard_EXPORT static Standard_Boolean PositionFromString (Standard_CString thePositionString,
+                                                              GccEnt_Position& thePosition);
   
   //! Constructs a qualified line,
   //! so that the relative position to the circle or line of the
index 3041483..9af1016 100755 (executable)
@@ -5,6 +5,9 @@ GeometryTest_APICommands.cxx
 GeometryTest_ConstraintCommands.cxx
 GeometryTest_ContinuityCommands.cxx
 GeometryTest_CurveCommands.cxx
+GeometryTest_CurveTanCommands.cxx
+GeometryTest_DrawableQualifiedCurve2d.cxx
+GeometryTest_DrawableQualifiedCurve2d.hxx
 GeometryTest_FairCurveCommands.cxx
 GeometryTest_PolyCommands.cxx
 GeometryTest_SurfaceCommands.cxx
index 86e60fe..1e0e2e5 100644 (file)
@@ -30,6 +30,7 @@ void GeometryTest::AllCommands(Draw_Interpretor& theCommands)
 
   GeomliteTest::AllCommands(theCommands);
   GeometryTest::CurveCommands(theCommands);
+  GeometryTest::CurveTanCommands(theCommands);
   GeometryTest::FairCurveCommands(theCommands);
   GeometryTest::SurfaceCommands(theCommands);
   GeometryTest::ConstraintCommands(theCommands);
index 46e6cb4..6f0fa28 100644 (file)
@@ -39,6 +39,9 @@ public:
   //! defines curve commands.
   Standard_EXPORT static void CurveCommands (Draw_Interpretor& I);
   
+  //! defines tangent curve commands.
+  Standard_EXPORT static void CurveTanCommands (Draw_Interpretor& I);
+
   //! defines fair curve commands.
   Standard_EXPORT static void FairCurveCommands (Draw_Interpretor& I);
   
diff --git a/src/GeometryTest/GeometryTest_CurveTanCommands.cxx b/src/GeometryTest/GeometryTest_CurveTanCommands.cxx
new file mode 100644 (file)
index 0000000..d472a81
--- /dev/null
@@ -0,0 +1,340 @@
+// Created on: 2017-06-16
+// Created by: Natalia ERMOLAEVA
+// Copyright (c) 2017 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <Draw.hxx>
+#include <DrawTrSurf.hxx>
+#include <Draw_Interpretor.hxx>
+#include <GccAna_Circ2d3Tan.hxx>
+#include <GccEnt.hxx>
+#include <GccEnt_QualifiedLin.hxx>
+#include <GccEnt_QualifiedCirc.hxx>
+#include <Geom2d_Line.hxx>
+#include <Geom2d_Circle.hxx>
+#include <Geom2dAdaptor_Curve.hxx>
+#include <GeometryTest.hxx>
+#include <GeometryTest_DrawableQualifiedCurve2d.hxx>
+#include <Precision.hxx>
+#include <TCollection_AsciiString.hxx>
+#include <stdio.h>
+
+//=======================================================================
+//function : qcircle
+//purpose  : Parses command: "qcircle name x y radius [-unqualified|-enclosing|-enclosed|-outside|-noqualifier]"
+//=======================================================================
+static Standard_Integer qcurve (Draw_Interpretor&, Standard_Integer theArgsNb, const char** theArgVec)
+{
+  if (theArgsNb < 5)
+  {
+    cout << "Error: wrong number of arguments.\n";
+    return 1;
+  }
+
+  Handle(Geom2d_Curve)  aResult2d;
+  TCollection_AsciiString aPositionType;
+  if (!strcmp (theArgVec[0], "qcircle"))
+  {
+    if (theArgsNb == 5 || theArgsNb == 6)
+      aResult2d = new Geom2d_Circle (gp_Ax22d (gp_Pnt2d (Draw::Atof (theArgVec[2]), Draw::Atof (theArgVec[3])),
+                                     gp_Dir2d (1,0)), Draw::Atof (theArgVec[4]));
+    else if (theArgsNb == 7 || theArgsNb == 8)
+      aResult2d = new Geom2d_Circle (gp_Ax22d (gp_Pnt2d (Draw::Atof (theArgVec[2]), Draw::Atof (theArgVec[3])),
+                  gp_Dir2d (Draw::Atof (theArgVec[4]), Draw::Atof (theArgVec[5]))), Draw::Atof (theArgVec[6]));
+
+    if (theArgsNb == 6)
+      aPositionType = theArgVec[5];
+    else if (theArgsNb == 8)
+      aPositionType = theArgVec[7];
+  }
+  else if(!strcmp (theArgVec[0], "qline"))
+  {
+    if (theArgsNb < 6)
+    {
+      cout << "Error: wrong number of arguments.\n";
+      return 1;
+    }
+    aResult2d = new Geom2d_Line (gp_Pnt2d (Draw::Atof (theArgVec[2]), Draw::Atof (theArgVec[3])),
+                                 gp_Dir2d (Draw::Atof (theArgVec[4]), Draw::Atof (theArgVec[5])));
+    if (theArgsNb == 7)
+      aPositionType = theArgVec[6];
+  }
+  else
+  {
+    cout << "Error: wrong command name.\n";
+    return 1;
+  }
+
+  GccEnt_Position aKindOfPosition = GccEnt_unqualified;
+  if (!aPositionType.IsEmpty())
+  {
+    GccEnt_Position aParameterPosition;
+    if (GccEnt::PositionFromString (aPositionType.ToCString(), aParameterPosition))
+      aKindOfPosition = aParameterPosition;
+  }
+
+  Draw::Set (theArgVec[1], new GeometryTest_DrawableQualifiedCurve2d (aResult2d, aKindOfPosition));
+  return 0;
+}
+
+//=======================================================================
+//function : solutions
+//purpose  : 
+//=======================================================================
+static Standard_Integer solutions (Draw_Interpretor& theDI, GccAna_Circ2d3Tan& theCirTan3, const char* theName)
+{
+  if (!theCirTan3.IsDone())
+  {
+    cout << "GccAna_Circ2d3Tan is not done";
+    return 1;
+  }
+
+  TCollection_AsciiString aName = TCollection_AsciiString (theName) + "_";
+  GccEnt_Position aQualifier1, aQualifier2, aQualifier3;
+  Standard_Real aParSol, aParArg;
+  gp_Pnt2d aPntSol;
+  for (Standard_Integer aSolId = 1; aSolId <= theCirTan3.NbSolutions(); aSolId++)
+  {
+    Handle(Geom2d_Circle) aCircle = new Geom2d_Circle (theCirTan3.ThisSolution (aSolId));
+    TCollection_AsciiString aSolIdName = aName;
+    aSolIdName += TCollection_AsciiString (aSolId);
+    DrawTrSurf::Set (aSolIdName.ToCString(), aCircle);
+    theCirTan3.WhichQualifier (aSolId, aQualifier1, aQualifier2, aQualifier3);
+    theDI << "circle: " << aSolIdName.ToCString() << ", " << "qualifiers: " << GccEnt::PositionToString (aQualifier1)
+          << ", " << GccEnt::PositionToString (aQualifier2) << ", " << GccEnt::PositionToString (aQualifier3) << "\n";
+
+    theDI << "  tangent points: point (parameter on solution, parameter on argument)\n";
+    // the first tangent point
+    if (theCirTan3.IsTheSame1 (aSolId))
+      theDI << "    " << "= the solution number " << aSolId << " is equal to the first argument\n";
+    else
+    {
+      theCirTan3.Tangency1 (aSolId, aParSol, aParArg, aPntSol);
+      TCollection_AsciiString aTanPntIdName = aSolIdName + "_tp_1";
+      DrawTrSurf::Set (aTanPntIdName.ToCString(), aPntSol);
+      theDI << "    " << aTanPntIdName.ToCString() << " (" << aParSol << ", " << aParArg << ")\n";
+    }
+    // the second tangent point
+    if (theCirTan3.IsTheSame2 (aSolId))
+      theDI << "    " << "= the solution number " << aSolId << " is equal to the second argument\n";
+    else
+    {
+      theCirTan3.Tangency2 (aSolId, aParSol, aParArg, aPntSol);
+      TCollection_AsciiString aTanPntIdName = aSolIdName + "_tp_2";
+      DrawTrSurf::Set (aTanPntIdName.ToCString(), aPntSol);
+      theDI << "    " << aTanPntIdName.ToCString() << " (" << aParSol << ", " << aParArg << ")\n";
+    }
+    // the third tangent point
+    if (theCirTan3.IsTheSame3 (aSolId))
+      theDI << "    " << "= the solution number " << aSolId << " is equal to the third argument\n";
+    else
+    {
+      theCirTan3.Tangency3 (aSolId, aParSol, aParArg, aPntSol);
+      TCollection_AsciiString aTanPntIdName = aSolIdName + "_tp_3";
+      DrawTrSurf::Set (aTanPntIdName.ToCString(), aPntSol);
+      theDI << "    " << aTanPntIdName.ToCString() << " (" << aParSol << ", " << aParArg << ")";
+    }
+    if (aSolId != theCirTan3.NbSolutions())
+      theDI << "\n";
+  }
+  return 0;
+}
+
+//=======================================================================
+//function : circ2d3Tan
+//purpose  : Parses command: [circ2d3Tan cname qcicrle1/qlin1/point1 qcicrle2/qlin2/point2 qcicrle3/qlin3/point3
+//                            tolerance]
+//=======================================================================
+static Standard_Integer circ2d3Tan (Draw_Interpretor& theDI, Standard_Integer theArgsNb, const char** theArgVec)
+{
+  if (theArgsNb < 5)
+  {
+    cout << "Error: wrong number of arguments.\n";
+    return 1;
+  }
+
+  Handle(GeometryTest_DrawableQualifiedCurve2d) aQCurve1 =
+    Handle(GeometryTest_DrawableQualifiedCurve2d)::DownCast (Draw::Get (theArgVec[2]));
+  Handle(GeometryTest_DrawableQualifiedCurve2d) aQCurve2 =
+    Handle(GeometryTest_DrawableQualifiedCurve2d)::DownCast (Draw::Get (theArgVec[3]));
+  Handle(GeometryTest_DrawableQualifiedCurve2d) aQCurve3 =
+    Handle(GeometryTest_DrawableQualifiedCurve2d)::DownCast (Draw::Get (theArgVec[4]));
+
+  gp_Pnt2d aPoint1, aPoint2, aPoint3;
+  Standard_Boolean anIsPoint1 = DrawTrSurf::GetPoint2d (theArgVec[2], aPoint1);
+  Standard_Boolean anIsPoint2 = DrawTrSurf::GetPoint2d (theArgVec[3], aPoint2);
+  Standard_Boolean anIsPoint3 = DrawTrSurf::GetPoint2d (theArgVec[4], aPoint3);
+
+  Standard_Real aTolerance = Precision::Confusion();
+  if (theArgsNb > 5)
+    aTolerance = Draw::Atof (theArgVec[5]);
+
+  if (aQCurve1.IsNull()) // <point, point, point>
+  {
+    if (!anIsPoint1 || !anIsPoint2 || !anIsPoint3)
+    {
+      cout << "Error: wrong points definition.\n";
+      return 1;
+    }
+    GccAna_Circ2d3Tan aCircBuilder (aPoint1, aPoint2, aPoint3, aTolerance);
+    return solutions (theDI, aCircBuilder, theArgVec[1]);
+  }
+
+  // the first curve is not NULL
+  if (aQCurve2.IsNull()) // <qcircle, point, point> or <qlin, point, point>
+  {
+    if (!anIsPoint2 || !anIsPoint3)
+    {
+      cout << "Error: wrong points definition.\n";
+      return 1;
+    }
+    Geom2dAdaptor_Curve anAdaptorCurve1 (aQCurve1->GetCurve());
+    if (anAdaptorCurve1.GetType() == GeomAbs_Circle)
+    {
+      GccEnt_QualifiedCirc aQualifiedCircle1 (anAdaptorCurve1.Circle(), aQCurve1->GetPosition());
+      GccAna_Circ2d3Tan aCircBuilder (aQualifiedCircle1, aPoint2, aPoint3, aTolerance);
+      return solutions (theDI, aCircBuilder, theArgVec[1]);
+    }
+    else if (anAdaptorCurve1.GetType() == GeomAbs_Line)
+    {
+      GccEnt_QualifiedLin aQualifiedLin1 (anAdaptorCurve1.Line(), aQCurve1->GetPosition());
+      GccAna_Circ2d3Tan aCircBuilder (aQualifiedLin1, aPoint2, aPoint3, aTolerance);
+      return solutions (theDI, aCircBuilder, theArgVec[1]);
+    }
+    cout << "Error: wrong curve type.\n";
+    return 1;
+  }
+
+  // the first and the second curves are not NULL
+  if (aQCurve3.IsNull()) // <qcircle, qcircle, point> or <qcircle, qlin, point> or <qlin, qlin, point>
+  {
+    if (!anIsPoint3)
+    {
+      cout << "Error: wrong point definition.\n";
+      return 1;
+    }
+    Geom2dAdaptor_Curve anAdaptorCurve1 (aQCurve1->GetCurve());
+    Geom2dAdaptor_Curve anAdaptorCurve2 (aQCurve2->GetCurve());
+    if (anAdaptorCurve1.GetType() == GeomAbs_Circle && anAdaptorCurve2.GetType() == GeomAbs_Circle)
+    {
+      GccEnt_QualifiedCirc aQualifiedCircle1 (anAdaptorCurve1.Circle(), aQCurve1->GetPosition());
+      GccEnt_QualifiedCirc aQualifiedCircle2 (anAdaptorCurve2.Circle(), aQCurve2->GetPosition());
+      GccAna_Circ2d3Tan aCircBuilder (aQualifiedCircle1, aQualifiedCircle2, aPoint3, aTolerance);
+      return solutions (theDI, aCircBuilder, theArgVec[1]);
+    }
+    else if (anAdaptorCurve1.GetType() == GeomAbs_Circle && anAdaptorCurve2.GetType() == GeomAbs_Line)
+    {
+      GccEnt_QualifiedCirc aQualifiedCircle1 (anAdaptorCurve1.Circle(), aQCurve1->GetPosition());
+      GccEnt_QualifiedLin aQualifiedLin2 (anAdaptorCurve2.Line(), aQCurve2->GetPosition());
+      GccAna_Circ2d3Tan aCircBuilder (aQualifiedCircle1, aQualifiedLin2, aPoint3, aTolerance);
+      return solutions (theDI, aCircBuilder, theArgVec[1]);
+    }
+    else if (anAdaptorCurve1.GetType() == GeomAbs_Line && anAdaptorCurve2.GetType() == GeomAbs_Line)
+    {
+      GccEnt_QualifiedLin aQualifiedLin1 (anAdaptorCurve1.Line(), aQCurve1->GetPosition());
+      GccEnt_QualifiedLin aQualifiedLin2 (anAdaptorCurve2.Line(), aQCurve2->GetPosition());
+      GccAna_Circ2d3Tan aCircBuilder (aQualifiedLin1, aQualifiedLin2, aPoint3, aTolerance);
+      return solutions (theDI, aCircBuilder, theArgVec[1]);
+    }
+    cout << "Error: wrong curve type.\n";
+    return 1;
+  }
+
+  // the first, the second and the third curves are not NULL
+  // <qcircle, qcircle, qcircle> or <qcircle, qcircle, qlin>, <qcircle, qlin, qlin>, <qlin, qlin, qlin>
+  Geom2dAdaptor_Curve anAdaptorCurve1 (aQCurve1->GetCurve());
+  Geom2dAdaptor_Curve anAdaptorCurve2 (aQCurve2->GetCurve());
+  Geom2dAdaptor_Curve anAdaptorCurve3 (aQCurve3->GetCurve());
+  if (anAdaptorCurve1.GetType() == GeomAbs_Circle && anAdaptorCurve2.GetType() == GeomAbs_Circle &&
+      anAdaptorCurve3.GetType() == GeomAbs_Circle)
+  {
+    GccEnt_QualifiedCirc aQualifiedCircle1 (anAdaptorCurve1.Circle(), aQCurve1->GetPosition());
+    GccEnt_QualifiedCirc aQualifiedCircle2 (anAdaptorCurve2.Circle(), aQCurve2->GetPosition());
+    GccEnt_QualifiedCirc aQualifiedCircle3 (anAdaptorCurve3.Circle(), aQCurve3->GetPosition());
+    GccAna_Circ2d3Tan aCircBuilder (aQualifiedCircle1, aQualifiedCircle2, aQualifiedCircle3, aTolerance);
+    return solutions (theDI, aCircBuilder, theArgVec[1]);
+  }
+  if (anAdaptorCurve1.GetType() == GeomAbs_Circle && anAdaptorCurve2.GetType() == GeomAbs_Circle &&
+      anAdaptorCurve3.GetType() == GeomAbs_Line)
+  {
+    GccEnt_QualifiedCirc aQualifiedCircle1 (anAdaptorCurve1.Circle(), aQCurve1->GetPosition());
+    GccEnt_QualifiedCirc aQualifiedCircle2 (anAdaptorCurve2.Circle(), aQCurve2->GetPosition());
+    GccEnt_QualifiedLin aQualifiedLin3 (anAdaptorCurve3.Line(), aQCurve3->GetPosition());
+    GccAna_Circ2d3Tan aCircBuilder (aQualifiedCircle1, aQualifiedCircle2, aQualifiedLin3, aTolerance);
+    return solutions (theDI, aCircBuilder, theArgVec[1]);
+  }
+  if (anAdaptorCurve1.GetType() == GeomAbs_Circle && anAdaptorCurve2.GetType() == GeomAbs_Line &&
+      anAdaptorCurve3.GetType() == GeomAbs_Line)
+  {
+    GccEnt_QualifiedCirc aQualifiedCircle1 (anAdaptorCurve1.Circle(), aQCurve1->GetPosition());
+    GccEnt_QualifiedLin aQualifiedLin2 (anAdaptorCurve2.Line(), aQCurve2->GetPosition());
+    GccEnt_QualifiedLin aQualifiedLin3 (anAdaptorCurve3.Line(), aQCurve3->GetPosition());
+    GccAna_Circ2d3Tan aCircBuilder (aQualifiedCircle1, aQualifiedLin2, aQualifiedLin3, aTolerance);
+    return solutions (theDI, aCircBuilder, theArgVec[1]);
+  }
+  if (anAdaptorCurve1.GetType() == GeomAbs_Line && anAdaptorCurve2.GetType() == GeomAbs_Line &&
+      anAdaptorCurve3.GetType() == GeomAbs_Line)
+  {
+    GccEnt_QualifiedLin aQualifiedLin1 (anAdaptorCurve1.Line(), aQCurve1->GetPosition());
+    GccEnt_QualifiedLin aQualifiedLin2 (anAdaptorCurve2.Line(), aQCurve2->GetPosition());
+    GccEnt_QualifiedLin aQualifiedLin3 (anAdaptorCurve3.Line(), aQCurve3->GetPosition());
+    GccAna_Circ2d3Tan aCircBuilder (aQualifiedLin1, aQualifiedLin2, aQualifiedLin3, aTolerance);
+    return solutions (theDI, aCircBuilder, theArgVec[1]);
+  }
+
+  cout << "Error: wrong curve type.\n";
+  return 1;
+}
+
+//=======================================================================
+//function : CurveTanCommands
+//purpose  : 
+//=======================================================================
+void  GeometryTest::CurveTanCommands (Draw_Interpretor& theCommands)
+{
+  static Standard_Boolean aLoaded = Standard_False;
+  if (aLoaded) return;
+  aLoaded = Standard_True;
+  
+  DrawTrSurf::BasicCommands (theCommands);
+  
+  const char* aGroup;
+  aGroup = "GEOMETRY tangent curves creation";
+
+  theCommands.Add ("qcircle",
+            "qcircle name {x y [ux uy] radius} [-unqualified|-enclosing|-enclosed|-outside|-noqualifier]"
+    "\n\t\t: Creates qualified circle.",
+   __FILE__, qcurve, aGroup);
+
+  theCommands.Add ("qline",
+            "qline name x y dx dy [-unqualified|-enclosing|-enclosed|-outside|-noqualifier]"
+    "\n\t\t: Creates qualified line.",
+    __FILE__, qcurve, aGroup);
+
+  theCommands.Add ("circ2d3Tan",
+            "circ2d3Tan cname {qcicrle1|qlin1|point1} {qcicrle2|qlin2|point2} {qcicrle3|qlin3|point3} [tolerance]"
+    "\n\t\t: Creates 2d circles tangent to 3 arguments. The arguments are points, lines or circles."
+    "\n\t\t: Possible arguments combinations:"
+    "\n\t\t:            <qcircle, qcircle, qcircle>,"
+    "\n\t\t:            <qcircle, qcircle, qlin>,"
+    "\n\t\t:            <qcircle, qcircle, point>,"
+    "\n\t\t:            <qcircle, qlin, qlin>,"
+    "\n\t\t:            <qcircle, qlin, point>,"
+    "\n\t\t:            <qcircle, qlin, qlin>,"
+    "\n\t\t:            <qcircle, point, point>,"
+    "\n\t\t:            <qlin, qlin, qlin>,"
+    "\n\t\t:            <qlin, qlin, point>,"
+    "\n\t\t:            <qlin, point, point>,"
+    "\n\t\t:            <point, point, point>.",
+    __FILE__, circ2d3Tan, aGroup);
+}
diff --git a/src/GeometryTest/GeometryTest_DrawableQualifiedCurve2d.cxx b/src/GeometryTest/GeometryTest_DrawableQualifiedCurve2d.cxx
new file mode 100644 (file)
index 0000000..60f2ef4
--- /dev/null
@@ -0,0 +1,96 @@
+// Created on: 2017-06-16
+// Created by: Natalia ERMOLAEVA
+// Copyright (c) 2017 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <GeometryTest_DrawableQualifiedCurve2d.hxx>
+
+#include <GccEnt.hxx>
+#include <Geom2d_Circle.hxx>
+#include <Geom2d_Curve.hxx>
+#include <Geom2d_Line.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(GeometryTest_DrawableQualifiedCurve2d, DrawTrSurf_Curve2d)
+
+//=======================================================================
+//function : GeometryTest_DrawableQualifiedCurve2d
+//purpose  : 
+//=======================================================================
+
+GeometryTest_DrawableQualifiedCurve2d::GeometryTest_DrawableQualifiedCurve2d (const Handle(Geom2d_Curve)& theCurve,
+                                                                              const GccEnt_Position thePosition,
+                                                                              const Standard_Boolean theDispOrigin)
+: DrawTrSurf_Curve2d (theCurve, theDispOrigin), myPosition (thePosition)
+{
+  look = Draw_orange;
+}
+
+//=======================================================================
+//function : GeometryTest_DrawableQualifiedCurve2d
+//purpose  : 
+//=======================================================================
+
+GeometryTest_DrawableQualifiedCurve2d::GeometryTest_DrawableQualifiedCurve2d (const Handle(Geom2d_Curve)& theCurve,
+                                                                              const Draw_Color& theColor,
+                                                                              const Standard_Integer theDiscret,
+                                                                              const GccEnt_Position thePosition,
+                                                                              const Standard_Boolean theDispOrigin,
+                                                                              const Standard_Boolean theDispCurvRadius,
+                                                                              const Standard_Real theRadiusMax,
+                                                                              const Standard_Real theRatioOfRadius)
+: DrawTrSurf_Curve2d (theCurve, theColor, theDiscret, theDispOrigin, theDispCurvRadius, theRadiusMax, theRatioOfRadius),
+  myPosition (thePosition)
+{
+  look = Draw_orange;
+}
+
+//=======================================================================
+//function : DrawOn
+//purpose  : 
+//=======================================================================
+
+void GeometryTest_DrawableQualifiedCurve2d::DrawOn (Draw_Display& theDisplay) const
+{
+  DrawTrSurf_Curve2d::DrawOn (theDisplay);
+}
+
+//=======================================================================
+//function : Dump
+//purpose  : 
+//=======================================================================
+
+void  GeometryTest_DrawableQualifiedCurve2d::Dump (Standard_OStream& theStream) const 
+{
+  theStream << "Qualified curve 2D: \n";
+  theStream << "Position :" << GccEnt::PositionToString (myPosition) << "\n";
+  DrawTrSurf_Curve2d::Dump (theStream);
+}
+
+//=======================================================================
+//function : Whatis
+//purpose  : 
+//=======================================================================
+
+void  GeometryTest_DrawableQualifiedCurve2d::Whatis (Draw_Interpretor& theDI)const 
+{
+  Handle(Standard_Type) aType = GetCurve()->DynamicType();
+
+  if (aType == STANDARD_TYPE (Geom2d_Circle))
+  {
+    theDI << "qualified 2d Circle";
+  }
+  else if (aType == STANDARD_TYPE (Geom2d_Line))
+  {
+    theDI << "qualified 2d Line";
+  }
+}
diff --git a/src/GeometryTest/GeometryTest_DrawableQualifiedCurve2d.hxx b/src/GeometryTest/GeometryTest_DrawableQualifiedCurve2d.hxx
new file mode 100644 (file)
index 0000000..29b56b1
--- /dev/null
@@ -0,0 +1,88 @@
+// Created on: 2017-06-16
+// Created by: Natalia ERMOLAEVA
+// Copyright (c) 2017 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _GeometryTest_DrawableQualifiedCirc_HeaderFile
+#define _GeometryTest_DrawableQualifiedCirc_HeaderFile
+
+#include <Standard.hxx>
+#include <DrawTrSurf_Curve2d.hxx>
+#include <GccEnt_Position.hxx>
+
+class Geom2d_Curve;
+
+class GeometryTest_DrawableQualifiedCurve2d;
+DEFINE_STANDARD_HANDLE(GeometryTest_DrawableQualifiedCurve2d, DrawTrSurf_Curve)
+
+//! Create geom curve drawable presentation with the position of a solution of a construction algorithm.
+class GeometryTest_DrawableQualifiedCurve2d : public DrawTrSurf_Curve2d
+{
+
+public:
+
+
+  //! Creates a drawable curve from a curve of package Geom.
+  Standard_EXPORT GeometryTest_DrawableQualifiedCurve2d (const Handle(Geom2d_Curve)& theCurve,
+                                                         const GccEnt_Position thePosition,
+                                                         const Standard_Boolean theDispOrigin = Standard_True);
+  
+  //! Creates a drawable curve from a curve of package Geom.
+  Standard_EXPORT GeometryTest_DrawableQualifiedCurve2d (const Handle(Geom2d_Curve)& theCurve,
+                                                         const Draw_Color& theColor,
+                                                         const Standard_Integer theDiscret,
+                                                         const GccEnt_Position thePosition,
+                                                         const Standard_Boolean theDispOrigin = Standard_True,
+                                                         const Standard_Boolean theDispCurvRadius = Standard_False,
+                                                         const Standard_Real theRadiusMax = 1.0e3,
+                                                         const Standard_Real theRatioOfRadius = 0.1);
+
+  //! \returns position of a solution
+  Standard_EXPORT GccEnt_Position GetPosition() const { return myPosition; }
+  
+  //! Sets position of a solution
+  //! \param thePosition the value
+  void SetPosition (const GccEnt_Position thePosition) { myPosition = thePosition; }
+
+  //! Paints the drawable presentation in given display
+  //! \param theDisplay
+  Standard_EXPORT void DrawOn (Draw_Display& theDisplay) const Standard_OVERRIDE;
+
+  //! For variable dump.
+  Standard_EXPORT virtual void Dump (Standard_OStream& S) const Standard_OVERRIDE;
+
+  //! For variable whatis command. Set  as a result  the
+  //! type of the variable.
+  Standard_EXPORT virtual void Whatis (Draw_Interpretor& I) const Standard_OVERRIDE;
+
+  DEFINE_STANDARD_RTTIEXT(GeometryTest_DrawableQualifiedCurve2d, DrawTrSurf_Curve2d)
+
+protected:
+
+
+
+
+private:
+
+
+  GccEnt_Position myPosition;
+
+};
+
+
+
+
+
+
+
+#endif // _GeometryTest_DrawableQualifiedCirc_HeaderFile
diff --git a/tests/geometry/circ2d3Tan/CircleCircleCircle_11 b/tests/geometry/circ2d3Tan/CircleCircleCircle_11
new file mode 100644 (file)
index 0000000..e5996c0
--- /dev/null
@@ -0,0 +1,13 @@
+qcircle c1 0 0 50
+qcircle c2 20 0 10
+qcircle c3 0 20 10
+circ2d3Tan tan1 c1 c2 c3
+
+checklength tan1_1 -l 168.36566348025758
+checklength tan1_2 -l 244.52937099154383
+checklength tan1_3 -l 131.42863607625242
+checklength tan1_4 -l 182.73062928272694
+checklength tan1_5 -l 182.7306292827268
+checklength tan1_6 -l 131.42863607625236
+checklength tan1_7 -l 94.936311385359318
+checklength tan1_8 -l 178.56704904481091
diff --git a/tests/geometry/circ2d3Tan/CircleCircleLin_11 b/tests/geometry/circ2d3Tan/CircleCircleLin_11
new file mode 100644 (file)
index 0000000..8589f82
--- /dev/null
@@ -0,0 +1,9 @@
+qcircle c1 0 0 50
+qcircle c2 20 0 10
+qline l1 -20 0 10 20
+circ2d3Tan tan1 c1 c2 l1
+
+checklength tan1_1 -l 115.99869565347736
+checklength tan1_2 -l 156.18117752496227
+checklength tan1_3 -l 165.15717356376749
+checklength tan1_4 -l 198.5849242626559
diff --git a/tests/geometry/circ2d3Tan/CircleCirclePoint_11 b/tests/geometry/circ2d3Tan/CircleCirclePoint_11
new file mode 100644 (file)
index 0000000..994fb70
--- /dev/null
@@ -0,0 +1,7 @@
+qcircle c1 0 0 10
+qcircle c2 30 0 20
+point p1 10 10
+circ2d3Tan tan1 c1 c2 p1
+
+checklength tan1_1 -l 13.802267767659149
+checklength tan1_2 -l 80.445511840034683
diff --git a/tests/geometry/circ2d3Tan/CircleCirclePoint_12 b/tests/geometry/circ2d3Tan/CircleCirclePoint_12
new file mode 100644 (file)
index 0000000..841e26d
--- /dev/null
@@ -0,0 +1,8 @@
+qcircle c1 0 0 10
+qcircle c2 30 0 20
+point p1 7 30
+circ2d3Tan tan1 c1 c2 p1
+
+checklength tan1_1 -l 951.90257403770727
+checklength tan1_2 -l 66.177052461460107
+checklength tan1_3 -l 190.20396243259333
diff --git a/tests/geometry/circ2d3Tan/CircleCirclePoint_13 b/tests/geometry/circ2d3Tan/CircleCirclePoint_13
new file mode 100644 (file)
index 0000000..aa5215b
--- /dev/null
@@ -0,0 +1,7 @@
+qcircle c1 0 0 10
+qcircle c2 30 0 20
+point p1 20 -10
+circ2d3Tan tan1 c1 c2 p1
+
+checklength tan1_1 -l 62.831853071795884
+checklength tan1_2 -l 62.831853071795841
diff --git a/tests/geometry/circ2d3Tan/CircleCirclePoint_14 b/tests/geometry/circ2d3Tan/CircleCirclePoint_14
new file mode 100644 (file)
index 0000000..508cd0c
--- /dev/null
@@ -0,0 +1,8 @@
+qcircle c1 0 0 10
+qcircle c2 30 0 20
+point p1 30 -20
+circ2d3Tan tan1 c1 c2 p1
+
+checklength tan1_1 -l 125.6637061435916
+checklength tan1_2 -l 376.99111854338514
+checklength tan1_3 -l 376.99111854338514
diff --git a/tests/geometry/circ2d3Tan/CircleLinLin_11 b/tests/geometry/circ2d3Tan/CircleLinLin_11
new file mode 100644 (file)
index 0000000..b731ad3
--- /dev/null
@@ -0,0 +1,9 @@
+qcircle c1 0 120 20
+qline l1 0 0 10 20
+qline l2 0 0 10 -40
+circ2d3Tan tan1 c1 l1 l2
+
+checklength tan1_1 -l 461.86006847878718
+checklength tan1_2 -l 163.75801021417183
+checklength tan1_3 -l 321.80336707682847
+checklength tan1_4 -l 235.02950419226329
diff --git a/tests/geometry/circ2d3Tan/CircleLinPoint_11 b/tests/geometry/circ2d3Tan/CircleLinPoint_11
new file mode 100644 (file)
index 0000000..8e12b22
--- /dev/null
@@ -0,0 +1,7 @@
+qcircle c1 0 0 10
+qline l1 0 0 10 20
+point p1 50 10
+circ2d3Tan tan1 c1 l1 p1
+
+checklength tan1_1 -l 563.33998470950314
+checklength tan1_2 -l 132.07599572229086
diff --git a/tests/geometry/circ2d3Tan/CirclePointPoint_11 b/tests/geometry/circ2d3Tan/CirclePointPoint_11
new file mode 100644 (file)
index 0000000..047a2c6
--- /dev/null
@@ -0,0 +1,7 @@
+qcircle c1 0 0 10
+point p1 20 0
+point p2 15 5
+circ2d3Tan tan1 c1 p1 p2
+
+checklength tan1_1 -l 157.07963267948966
+checklength tan1_2 -l 31.415926535897931
diff --git a/tests/geometry/circ2d3Tan/CirclePointPoint_12 b/tests/geometry/circ2d3Tan/CirclePointPoint_12
new file mode 100644 (file)
index 0000000..e4e9dec
--- /dev/null
@@ -0,0 +1,6 @@
+qcircle c1 0 0 10
+point p1 20 0
+point p2 10 0
+
+set log [circ2d3Tan tan1 c1 p1 p2]
+if {[llength $log]} {puts "Error:Incorrect circle is created"}
diff --git a/tests/geometry/circ2d3Tan/CirclePointPoint_13 b/tests/geometry/circ2d3Tan/CirclePointPoint_13
new file mode 100644 (file)
index 0000000..91e630d
--- /dev/null
@@ -0,0 +1,7 @@
+qcircle c1 0 0 10
+point p1 20 0
+point p2 0 10
+circ2d3Tan tan1 c1 p1 p2
+
+checklength tan1_1 -l 157.07963267948978
+checklength tan1_2 -l 157.07963267948978
diff --git a/tests/geometry/circ2d3Tan/CirclePointPoint_14 b/tests/geometry/circ2d3Tan/CirclePointPoint_14
new file mode 100644 (file)
index 0000000..cb9edda
--- /dev/null
@@ -0,0 +1,6 @@
+qcircle c1 0 0 10
+point p1 20 0
+point p2 5 5
+
+set log [circ2d3Tan tan1 c1 p1 p2]
+if {[llength $log]} {puts "Error:Incorrect circle is created"}
diff --git a/tests/geometry/circ2d3Tan/CirclePointPoint_15 b/tests/geometry/circ2d3Tan/CirclePointPoint_15
new file mode 100644 (file)
index 0000000..02eea2d
--- /dev/null
@@ -0,0 +1,7 @@
+qcircle c1 0 0 10
+point p1 20 0
+point p2 -20 0
+circ2d3Tan tan1 c1 p1 p2
+
+checklength tan1_1 -l 157.07963267948966
+checklength tan1_2 -l 157.07963267948966
diff --git a/tests/geometry/circ2d3Tan/CirclePointPoint_21 b/tests/geometry/circ2d3Tan/CirclePointPoint_21
new file mode 100644 (file)
index 0000000..705b119
--- /dev/null
@@ -0,0 +1,7 @@
+qcircle c1 0 0 10
+point p1 5 0
+point p2 0 5
+circ2d3Tan tan1 c1 p1 p2
+
+checklength tan1_1 -l 45.424379479936995
+checklength tan1_2 -l 26.383452602115419
diff --git a/tests/geometry/circ2d3Tan/CirclePointPoint_22 b/tests/geometry/circ2d3Tan/CirclePointPoint_22
new file mode 100644 (file)
index 0000000..b65b8de
--- /dev/null
@@ -0,0 +1,7 @@
+qcircle c1 0 0 10
+point p1 5 0
+point p2 0 0
+circ2d3Tan tan1 c1 p1 p2
+
+checklength tan1_1 -l 31.415926535897931
+checklength tan1_2 -l 31.415926535897931
diff --git a/tests/geometry/circ2d3Tan/CirclePointPoint_23 b/tests/geometry/circ2d3Tan/CirclePointPoint_23
new file mode 100644 (file)
index 0000000..722f6e8
--- /dev/null
@@ -0,0 +1,6 @@
+qcircle c1 0 0 10
+point p1 5 0
+point p2 -10 0
+
+set log [circ2d3Tan tan1 c1 p1 p2]
+if {[llength $log]} {puts "Error:Incorrect circle is created"}
diff --git a/tests/geometry/circ2d3Tan/CirclePointPoint_24 b/tests/geometry/circ2d3Tan/CirclePointPoint_24
new file mode 100644 (file)
index 0000000..daad0d9
--- /dev/null
@@ -0,0 +1,6 @@
+qcircle c1 0 0 10
+point p1 5 0
+point p2 0 10
+circ2d3Tan tan1 c1 p1 p2
+
+checklength tan1_1 -l 39.269908169872416
diff --git a/tests/geometry/circ2d3Tan/CirclePointPoint_31 b/tests/geometry/circ2d3Tan/CirclePointPoint_31
new file mode 100644 (file)
index 0000000..c937be9
--- /dev/null
@@ -0,0 +1,6 @@
+qcircle c1 0 0 10
+point p1 10 0
+point p2 0 10
+circ2d3Tan tan1 c1 p1 p2
+
+checklength tan1_1 -l 62.831853071795862
diff --git a/tests/geometry/circ2d3Tan/LinLinLin_11 b/tests/geometry/circ2d3Tan/LinLinLin_11
new file mode 100644 (file)
index 0000000..688602c
--- /dev/null
@@ -0,0 +1,9 @@
+qline l1 0 0 10 20
+qline l2 0 0 10 -40
+qline l3 160 0 -40 10
+circ2d3Tan tan1 l1 l2 l3
+
+checklength tan1_1 -l 213.09795279419643
+checklength tan1_2 -l 284.90187851033369
+checklength tan1_3 -l 131.38343888467227
+checklength tan1_4 -l 63.235238531994284
diff --git a/tests/geometry/circ2d3Tan/LinLinPoint_11 b/tests/geometry/circ2d3Tan/LinLinPoint_11
new file mode 100644 (file)
index 0000000..297c739
--- /dev/null
@@ -0,0 +1,7 @@
+qline l1 0 0 10 20
+qline l2 0 0 10 -40
+point p1 10 80
+circ2d3Tan tan1 l1 l2 p1
+
+checklength tan1_1 -l 269.03484941268533
+checklength tan1_2 -l 130.52381207643296
diff --git a/tests/geometry/circ2d3Tan/LinPointPoint_11 b/tests/geometry/circ2d3Tan/LinPointPoint_11
new file mode 100644 (file)
index 0000000..0381da1
--- /dev/null
@@ -0,0 +1,7 @@
+qline l1 0 0 10 20
+point p1 10 10
+point p2 100 10
+circ2d3Tan tan1 l1 p1 p2
+
+checklength tan1_1 -l 419.71016104587477
+checklength tan1_2 -l 282.77131205819785
diff --git a/tests/geometry/circ2d3Tan/PointPointPoint_11 b/tests/geometry/circ2d3Tan/PointPointPoint_11
new file mode 100644 (file)
index 0000000..b9590cc
--- /dev/null
@@ -0,0 +1,6 @@
+point p1 0 50
+point p2 30 20
+point p3 150 150
+circ2d3Tan tan1 p1 p2 p3
+
+checklength tan1_1 -l 566.81157580298293
index 2c04e5f..845105e 100644 (file)
@@ -2,12 +2,13 @@
 002 2dbsplinecurve
 003 beziecurve
 004 bsplinecurve
-005 circle
-006 ellipse
-007 hyperbola
-008 iso
-009 law
-010 line
-011 parabola
-012 project
-013 revsurf
+005 circ2d3Tan
+006 circle
+007 ellipse
+008 hyperbola
+009 iso
+010 law
+011 line
+012 parabola
+013 project
+014 revsurf