public static WavefrontFormat DrawLine(this WavefrontFormat wf, string color, Point2d point, Vector2d v, double ext = 1000) { wf.UseMaterial(color); Point2d p0 = point.Sub(v.Mul(ext)); Point2d p1 = point.Add(v.Mul(ext)); wf.AddLines(new Point2d[] { p0, p1 }, false); return(wf); }
public SquareJig(Point3d first) : base(new Polyline()) { // Store the first point _fstPt = first; // And draw a pline using this point Point2d firstPointPlane = first.Convert2d(new Plane()); Polyline pline = base.Entity as Polyline; pline.AddVertexAt(0, firstPointPlane, 0, 0, 0); pline.AddVertexAt( 1, firstPointPlane.Add(new Vector2d(10, 0)), 0, 0, 0 ); pline.AddVertexAt( 2, firstPointPlane.Add(new Vector2d(10, 10)), 0, 0, 0 ); pline.AddVertexAt( 3, firstPointPlane.Add(new Vector2d(0, 10)), 0, 0, 0 ); pline.Closed = true; }
/// <summary> /// Obtiene el centro de la circunferencia que pasa por los 2 puntos, con el radio indicado. /// Dependiendo del criterio (leftRule), se interpreta el signo del radio: /// Si leftRule entonces el radio se multiplica por la normal a la izquierda (leftNormal) para obtener el centro de la /// circunferencia. /// Si rightRule (!leftRule) entonces el radio se multiplica por la normal a la derecha (rightNormal) para obtener el /// centro de la circunferencia. /// Clip utiliza un criterio rightRule. /// <p /> /// Criterio rightRule: /// <c><![CDATA[ /// _ _ /// _ / \c /// _/ O pf O /// _/ / / \ /// / _/ radio - _/ | /// / /| radio + <-- /| | /// | / --> / / /// / / / _/ /// |/ / _/ /// O pi O__/ /// \ _/ /// ]]></c> /// <![CDATA[ /// p1 a/2 pm a/2 p2 /// x---------+-------->x /// \ | / /// \ | / /// \ | / /// \ |b / /// \ | / r /// \ | / /// \ | / /// \ | / /// \|/ /// pc /// ]]> /// Teniendo como dato p1, p2 y r, tenemos que obtener el centro del circulo que pasa por /// p1 y p2, con radio r. /// Con el vector 1-2 obtenemos la distancia a. /// b es calculado mediante la fórmula b = raizcua(r * r + a/2 * a/2). /// Creamos un vector perpendicular al 1-2 a una distacion a/2 desde p1 y obtenemos /// el punto central de la circunferencia. /// Con este dato y conociendo el radio ya simplemente calculamos la esquina del rectangulo. /// Si el radio es positivo, avanza en sentido contrario a las agujas del reloj. /// Si el radio es negativo, avanza en sentido de las agujas del reloj. /// <![CDATA[ /// + p2 /// /|\ /// | /// /____ | ____\ /// \ \___ | ___/ / /// \__ | __/ /// \_ | _/ /// radio - \ | / radio + /// (giro \ | / (giro horario) /// antihorario) \|/ /// | /// + p1 /// ]]> /// </summary> /// <exception cref="CalculoImposibleException"> /// Indica que no se puede calcular el /// centro. /// </exception> public static Point2d EvaluateCenter(Point2d pt0, Point2d pt1, double radius, bool leftRule) { // Vector direccion normalizado y longitud. Vector2d dir = pt1.Sub(pt0); double a = dir.Length; if (a.EpsilonEquals(0)) { throw new Exception("CalculoImposible: Puntos coincidentes."); } dir = dir.Div(a); // Punto medio. Point2d pm = pt0.Lerp(pt1, 0.5); // Se tratan radios erroneos que no permitan generar un circunferencia. double v = radius * radius - a * a / 4; if (v.EpsilonEquals(0)) { return(pm); } if (v < 0) { throw new Exception("CalculoImposible: Radio erroneo."); } double b = SysMath.Sign(radius) * SysMath.Sqrt(v); Vector2d normal; if (leftRule) { // Vector normal a la izquierda. normal = dir.PerpLeft; } else { // Vector normal a la derecha. normal = dir.PerpLeft; } Vector2d vectorm1 = normal.Mul(b); return(pm.Add(vectorm1)); }
/// <summary> /// Calcula el centro de la circunferencia que pasa por los 3 puntos. /// </summary> public static Point2d GetCenter(Point2d p1, Point2d p2, Point2d p3) { Vector2d v1 = p2.Sub(p1); Vector2d v2 = p3.Sub(p1); Vector2d v3 = p3.Sub(p2); double l1 = v1.LengthSquared; double l2 = v2.LengthSquared; double l3 = v3.LengthSquared; LenP1P2Dir[] vs = { Tuple.Create(l1, p1, p2, v1), Tuple.Create(l2, p1, p3, v2), Tuple.Create(l3, p2, p3, v3) }; Array.Sort(vs, Length2Comparar.Instance); // Para mejorar el calculo, se toman los segmentos mas alejados. Point2d pm_a = vs[1].Item2.Lerp(vs[1].Item3, 0.5); Vector2d d_a = vs[1].Item4.PerpLeft; Point2d pm_b = vs[2].Item2.Lerp(vs[2].Item3, 0.5); Vector2d d_b = vs[2].Item4.PerpLeft; // Se resuelve la ecuacion: d_a * t1 + pm_a = d_b * t2 + pm_b // Maxima: // e1: d_ax * t1 + pm_ax = d_bx * t2 + pm_bx; // e2: d_ay * t1 + pm_ay = d_by * t2 + pm_by; // algsys ([e1, e2], [t1, t2]); double div = (d_a.Y * d_b.X - d_a.X * d_b.Y); if (div.EpsilonEquals(0)) { throw new Exception("Cálculo imposible"); } double t1 = (d_b.X * (pm_b.Y - pm_a.Y) - d_b.Y * (pm_b.X - pm_a.X)) / div; //double t2 = (d_a.X * (pm_b.Y - pm_a.Y) - d_a.Y * (pm_b.X - pm_a.X)) / div; return(pm_a.Add(d_a.Mul(t1))); }
private Arc AlignmentArcToSpeckle(CivilDB.AlignmentSubEntityArc arc) { // calculate midpoint of chord as between start and end point Point2d chordMid = new Point2d((arc.StartPoint.X + arc.EndPoint.X) / 2, (arc.StartPoint.Y + arc.EndPoint.Y) / 2); // calculate sagitta as radius minus distance between arc center and chord midpoint var sagitta = arc.Radius - arc.CenterPoint.GetDistanceTo(chordMid); // get unit vector from arc center to chord mid var midVector = arc.CenterPoint.GetVectorTo(chordMid); var unitMidVector = midVector.DivideBy(midVector.Length); // get midpoint of arc by moving chord mid point the length of the sagitta along mid vector var midPoint = chordMid.Add(unitMidVector.MultiplyBy(sagitta)); // find arc plane (normal is in clockwise dir) var center3 = new Point3d(arc.CenterPoint.X, arc.CenterPoint.Y, 0); Acad.Plane plane = (arc.Clockwise) ? new Acad.Plane(center3, Vector3d.ZAxis.MultiplyBy(-1)) : new Acad.Plane(center3, Vector3d.ZAxis); // calculate start and end angles var startVector = new Vector3d(arc.StartPoint.X - center3.X, arc.StartPoint.Y - center3.Y, 0); var endVector = new Vector3d(arc.EndPoint.X - center3.X, arc.EndPoint.Y - center3.Y, 0); var startAngle = startVector.AngleOnPlane(plane); var endAngle = endVector.AngleOnPlane(plane); // calculate total angle. // TODO: This needs to be improved with more research into autocad .AngleOnPlane() return values (negative angles, etc). var totalAngle = (arc.Clockwise) ? System.Math.Abs(endAngle - startAngle) : System.Math.Abs(endAngle - startAngle); // create arc var _arc = new Arc(PlaneToSpeckle(plane), arc.Radius, startAngle, endAngle, totalAngle, ModelUnits); _arc.startPoint = PointToSpeckle(arc.StartPoint); _arc.endPoint = PointToSpeckle(arc.EndPoint); _arc.midPoint = PointToSpeckle(midPoint); _arc.domain = IntervalToSpeckle(new Acad.Interval(0, 1, tolerance)); _arc.length = arc.Length; return(_arc); }
public void TestPointInPolyNonZero_Extended_Robust() { Circle2 c = new Circle2(new Point2d(0, 0), 5); double tmin = c.TMin; double tmax = c.TMax; double tinc = (tmax - tmin) / 5; Point2d p0 = c.GetPosition(tmin); Point2d p1 = c.GetPosition(tmin + tinc); Point2d p2 = c.GetPosition(tmin + 2 * tinc); Point2d p3 = c.GetPosition(tmin + 3 * tinc); Point2d p4 = c.GetPosition(tmin + 4 * tinc); IList <Point2d> points = DuplicatePoints(AsList(p0, p2, p4, p1, p3)); PointInPoly pip1 = PolygonUtils.PointInPolyNonZero(points, new Point2d(4, 0), true, true, MathUtils.EPSILON); Assert.AreEqual(PointInPoly.Inside, pip1); PointInPoly pip2 = PolygonUtils.PointInPolyNonZero(points, new Point2d(-2, 2), true, true, MathUtils.EPSILON); Assert.AreEqual(PointInPoly.Inside, pip2); PointInPoly pip3 = PolygonUtils.PointInPolyNonZero(points, new Point2d(-2, -2), true, true, MathUtils.EPSILON); Assert.AreEqual(PointInPoly.Inside, pip3); PointInPoly pip4 = PolygonUtils.PointInPolyNonZero(points, new Point2d(0, 0), true, true, MathUtils.EPSILON); Assert.AreEqual(PointInPoly.Inside, pip4); PointInPoly pip5 = PolygonUtils.PointInPolyNonZero(points, new Point2d(10, 0), true, true, MathUtils.EPSILON); Assert.AreEqual(PointInPoly.Outside, pip5); PointInPoly pip6 = PolygonUtils.PointInPolyNonZero(points, new Point2d(4, 3), true, true, MathUtils.EPSILON); Assert.AreEqual(PointInPoly.Outside, pip6); PointInPoly pip7 = PolygonUtils.PointInPolyNonZero(points, new Point2d(4, -3), true, true, MathUtils.EPSILON); Assert.AreEqual(PointInPoly.Outside, pip7); PointInPoly pip8 = PolygonUtils.PointInPolyNonZero(points, new Point2d(1, 1), true, true, MathUtils.EPSILON); Assert.AreEqual(PointInPoly.Inside, pip8); PointInPoly pip9 = PolygonUtils.PointInPolyNonZero(points, new Point2d(1, -1), true, true, MathUtils.EPSILON); Assert.AreEqual(PointInPoly.Inside, pip9); PointInPoly pip10 = PolygonUtils.PointInPolyNonZero(points, p4.Add(p1.Sub(p4).Unit.Mul(0.7)), true, true, MathUtils.EPSILON); Assert.AreEqual(PointInPoly.On, pip10); PointInPoly pip11 = PolygonUtils.PointInPolyNonZero(points, p4.Add(p1.Sub(p4).Unit.Mul(0.3)), true, true, MathUtils.EPSILON); Assert.AreEqual(PointInPoly.On, pip11); PointInPoly pip12 = PolygonUtils.PointInPolyNonZero(points, p1.Add(p3.Sub(p1).Unit.Mul(0.7)), true, true, MathUtils.EPSILON); Assert.AreEqual(PointInPoly.On, pip12); PointInPoly pip13 = PolygonUtils.PointInPolyNonZero(points, p1.Add(p3.Sub(p1).Unit.Mul(0.3)), true, true, MathUtils.EPSILON); Assert.AreEqual(PointInPoly.On, pip13); }
public static void AddSpline() { if (!Ativacao()) { MessageBox.Show("Esta API não está ativada. Entre em contato com a SELTTE!"); return; } pt1x = GetPoint(); // Caso não se clique em lugar algum, o comando é finalizado if (pt1x.X == 0.0 && pt1x.Y == 0.0) { Editor editor = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor; editor.WriteMessage("\n-> Cancelado!\n"); return; } pt2x = GetPoint(); // Caso não se clique em lugar algum, o comando é finalizado if (pt2x.X == 0.0 && pt2x.Y == 0.0) { Editor editor = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor; editor.WriteMessage("\n-> Cancelado!\n"); return; } pt1 = new Point2d(pt1x.X, pt1x.Y); pt2 = new Point2d(pt2x.X, pt2x.Y); if (pt1.X > pt2.X || pt1.Y > pt2.Y) { Point2d ptx = pt1; pt1 = pt2; pt2 = ptx; } // Get the current document and database Document acDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; Database acCurDb = acDoc.Database; Editor ed = acDoc.Editor; // Start a transaction using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction()) { // Open the Block table for read BlockTable acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) as BlockTable; // Open the Block table record Model space for write BlockTableRecord acBlkTblRec = acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord; double anglePt1Pt2 = pt1.GetVectorTo(pt2).Angle; if (anglePt1Pt2 > Math.PI) { anglePt1Pt2 -= Math.PI; } //PolarPoints(pt1.Add((pt2.Subtract(pt1.GetAsVector()) / 4).GetAsVector()), pt1.GetVectorTo(pt2).GetAngleTo(pt2.GetAsVector()) + Math.PI / 2, 10); Point2d pt3 = PolarPoints(pt1.Add(pt1.GetVectorTo(pt2) / 4), anglePt1Pt2 + Math.PI / 2, pt1.GetDistanceTo(pt2) * 0.1); Point2d pt4 = PolarPoints(pt2.Subtract((pt2.Subtract(pt1.GetAsVector()) / 4).GetAsVector()), anglePt1Pt2 - Math.PI / 2, pt1.GetDistanceTo(pt2) * 0.1); Point3d pt5 = new Point3d(pt1.X, pt1.Y, 0); // pt1 em 3d Point3d pt6 = new Point3d(pt3.X, pt3.Y, 0); // pt3 em 3d Point3d pt7 = new Point3d(pt4.X, pt4.Y, 0); // pt4 em 3d Point3d pt8 = new Point3d(pt2.X, pt2.Y, 0); // pt2 em 3d // Define the fit points for the spline Point3dCollection ptColl = new Point3dCollection { pt5, pt6, pt7, pt8 }; // Create a spline through (0, 0, 0), (5, 5, 0), and (10, 0, 0) with a // start and end tangency of (0.5, 0.5, 0.0) using (Spline acSpline = new Spline(ptColl, new Point3d(0.0000, 0.0000, 0.0000).GetAsVector(), new Point3d(0.0000, 0.0000, 0.0000).GetAsVector(), 0, 0.0)) { // Add the new object to the block table record and the transaction acBlkTblRec.AppendEntity(acSpline); acTrans.AddNewlyCreatedDBObject(acSpline, true); } acDoc.SendStringToExecute("Trim ", true, false, false); // Save the new line to the database acTrans.Commit(); } }
private void DrawBar(Point2d p, double ang) { using (Transaction transaction = _document.TransactionManager.StartTransaction()) { BlockTable blockTable = transaction.GetObject(_database.BlockTableId, OpenMode.ForRead) as BlockTable; BlockTableRecord blockTableRecord = transaction.GetObject(blockTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord; Layer.ChangeLayer(transaction, Layer.CreateLayer("Опорная плита стойки", Color.FromColorIndex(ColorMethod.ByAci, 50), LineWeight.LineWeight018), _database); const double w = 200; const double h = 120; Polyline bar = new Polyline(); bar.AddVertexAt(0, p.Add(new Vector2d(w / 2, h - 35)), 0, 0, 0); bar.AddVertexAt(0, p.Add(new Vector2d(-w / 2, h - 35)), 0, 0, 0); bar.AddVertexAt(0, p.Add(new Vector2d(-w / 2, -h + 85)), 0, 0, 0); bar.AddVertexAt(0, p.Add(new Vector2d(w / 2, -h + 85)), 0, 0, 0); bar.AddVertexAt(0, p.Add(new Vector2d(w / 2, h - 35)), 0, 0, 0); /* * bar.AddVertexAt(0, p.Add(new Vector2d(w / 2, h / 2)), 0, 0, 0); * bar.AddVertexAt(0, p.Add(new Vector2d(-w / 2, h / 2)), 0, 0, 0); * bar.AddVertexAt(0, p.Add(new Vector2d(-w / 2, -h / 2)), 0, 0, 0); * bar.AddVertexAt(0, p.Add(new Vector2d(w / 2, -h / 2)), 0, 0, 0); * bar.AddVertexAt(0, p.Add(new Vector2d(w / 2, h / 2)), 0, 0, 0); */ bar.Closed = true; Matrix3d matrix3D = _document.Editor.CurrentUserCoordinateSystem; CoordinateSystem3d curUcs = matrix3D.CoordinateSystem3d; bar.TransformBy(Matrix3d.Rotation(ang, curUcs.Zaxis, new Point3d(p.X, p.Y, 0))); if (blockTableRecord != null) { blockTableRecord.AppendEntity(bar); transaction.AddNewlyCreatedDBObject(bar, true); } Layer.ChangeLayer(transaction, Layer.CreateLayer("Стойки ограждений", Color.FromColorIndex(ColorMethod.ByAci, 70), LineWeight.LineWeight040), _database); const double wr1 = 50; const double wr2 = 30.4; const double hr1 = 10.8; const double hr2 = 30; const double rad = 0.414213562373095; Polyline rack = new Polyline(); rack.AddVertexAt(0, p.Add(new Vector2d(-wr1 / 2, hr1 / 2)), 0, 0, 0); rack.AddVertexAt(0, p.Add(new Vector2d(-wr2 / 2, hr2 / 2)), rad, 0, 0); rack.AddVertexAt(0, p.Add(new Vector2d(wr2 / 2, hr2 / 2)), 0, 0, 0); rack.AddVertexAt(0, p.Add(new Vector2d(wr1 / 2, hr1 / 2)), rad, 0, 0); rack.AddVertexAt(0, p.Add(new Vector2d(wr1 / 2, -hr1 / 2)), 0, 0, 0); rack.AddVertexAt(0, p.Add(new Vector2d(wr2 / 2, -hr2 / 2)), rad, 0, 0); rack.AddVertexAt(0, p.Add(new Vector2d(-wr2 / 2, -hr2 / 2)), 0, 0, 0); rack.AddVertexAt(0, p.Add(new Vector2d(-wr1 / 2, -hr1 / 2)), rad, 0, 0); rack.AddVertexAt(0, p.Add(new Vector2d(-wr1 / 2, hr1 / 2)), 0, 0, 0); rack.Closed = true; rack.TransformBy(Matrix3d.Rotation(ang + Math.PI / 2, curUcs.Zaxis, new Point3d(p.X, p.Y, 0))); if (blockTableRecord != null) { blockTableRecord.AppendEntity(rack); transaction.AddNewlyCreatedDBObject(rack, true); DBObjectCollection acDbObjColl = rack.GetOffsetCurves(-4); foreach (Entity acEnt in acDbObjColl) { blockTableRecord.AppendEntity(acEnt); transaction.AddNewlyCreatedDBObject(acEnt, true); } } transaction.Commit(); } }
private Point2d MovePoint(Point2d p1, Point2d p2, double dist) { Vector2d p12 = p1.GetVectorTo(p2); return(p1.Add(p12.GetNormal().MultiplyBy(dist))); }
public static WavefrontFormat DrawClotho(this WavefrontFormat wf, bool invertY, double a, string clothoColor, string dirColor, string normalColor, string radColor) { List <int> indices = new List <int>(); List <Tuple <int, int> > normals = new List <Tuple <int, int> >(); List <Tuple <int, int> > dirs = new List <Tuple <int, int> >(); List <Tuple <int, int> > radius = new List <Tuple <int, int> >(); int c = 100; for (int i = -c; i <= c; i++) { double lmax = ClothoUtils.GetMaxL(a); double s = i * lmax / c; Point2d xy = ClothoUtils.Clotho(s, invertY, a); int v0 = wf.AddVertex(xy); indices.Add(v0); Vector2d n = ClothoUtils.ClothoLeftNormal(s, invertY, a).Unit; int v1 = wf.AddVertex(xy.Add(n)); normals.Add(Tuple.Create(v0, v1)); double dir = ClothoUtils.ClothoTangent(s, invertY, a); Vector2d d = Vector2d.NewRotate(dir); int v2 = wf.AddVertex(xy.Add(d.Mul(5))); dirs.Add(Tuple.Create(v0, v2)); double r = ClothoUtils.ClothoRadius(s, invertY, a); if (double.IsInfinity(r)) { r = SysMath.Sign(r) * 100; } int v3 = wf.AddVertex(xy.Add(n.Mul(r))); radius.Add(Tuple.Create(v0, v3)); //double dx, dy; //MathUtils.DClotho(s, r, a, out dx, out dy); } wf.UseMaterial(clothoColor); wf.AddLines(indices, false); wf.UseMaterial(normalColor); foreach (Tuple <int, int> normal in normals) { wf.AddLines(new[] { normal.Item1, normal.Item2 }, false); } wf.UseMaterial(dirColor); foreach (Tuple <int, int> dir in dirs) { wf.AddLines(new[] { dir.Item1, dir.Item2 }, false); } wf.UseMaterial(radColor); foreach (Tuple <int, int> rr in radius) { wf.AddLines(new[] { rr.Item1, rr.Item2 }, false); } return(wf); }
public static WavefrontFormat DrawFigure(this WavefrontFormat wf, string color, WaveFigure figure, Point2d point, double size) { wf.UseMaterial(color); switch (figure) { case WaveFigure.Circle: { wf.AddLines(MathUtils.For(0, 2 * SysMath.PI, 20).Select(t => point.Add(Vector2d.NewRotate(t).Mul(size))), true); break; } case WaveFigure.Rectangle: { wf.AddLines(new[] { point.Add(new Vector2d(size, size)), point.Add(new Vector2d(-size, size)), point.Add(new Vector2d(-size, -size)), point.Add(new Vector2d(size, -size)), }, true); break; } case WaveFigure.Diamond: { wf.AddLines(new[] { point.Add(new Vector2d(0, size)), point.Add(new Vector2d(-size, 0)), point.Add(new Vector2d(0, -size)), point.Add(new Vector2d(size, 0)), }, true); break; } case WaveFigure.Plus: { wf.AddLines(new[] { point.Add(new Vector2d(0, size)), point.Add(new Vector2d(0, -size)), }, false); wf.AddLines(new[] { point.Add(new Vector2d(size, 0)), point.Add(new Vector2d(-size, 0)), }, false); break; } case WaveFigure.X: { wf.AddLines(new[] { point.Add(new Vector2d(size, size)), point.Add(new Vector2d(-size, -size)), }, false); wf.AddLines(new[] { point.Add(new Vector2d(-size, size)), point.Add(new Vector2d(size, -size)), }, false); break; } default: { throw new Exception(); } } return(wf); }
/// <summary> /// Prueba el constructor ClothoidArc2d(double,Point2d,Point2d,double,double). /// </summary> private static void TestClotho(double a, bool invertY, bool negX, double tg0, double tg1, Point2d p0, Vector2d dir, string fileName = null, bool toWavefront = false) { //double a = 5; //bool invertY = true; //double tg0 = -4 * SysMath.PI / 10; //double tg1 = -SysMath.PI / 10; // Si se indica negX, se invierten las tangentes. int sign = 1; if (negX) { sign = -1; } double l0 = sign * ClothoUtils.FindTangent(invertY, a, tg0); double l1 = sign * ClothoUtils.FindTangent(invertY, a, tg1); double r0 = ClothoUtils.ClothoRadious(l0, invertY, a); double r1 = ClothoUtils.ClothoRadious(l1, invertY, a); Point2d pp0 = ClothoUtils.Clotho(l0, invertY, a); Point2d pp1 = ClothoUtils.Clotho(l1, invertY, a); //Point2d p0 = new Point2d(5, 5); Point2d p1 = p0.Add(dir.Mul(pp1.Sub(pp0).Length)); ClothoidArc2 arc = new ClothoidArc2(l0, p0, p1, r0, r1); Assert.IsTrue(arc.Point0.EpsilonEquals(p0, ERROR)); Assert.IsTrue(arc.Point1.EpsilonEquals(p1, ERROR)); Assert.IsTrue(arc.GetRadius(arc.TMin).EpsilonEquals(r0, ERROR)); Assert.IsTrue(arc.GetRadius(arc.TMax).EpsilonEquals(r1, ERROR)); // <- Assert.IsTrue(arc.InvertY == invertY); Assert.IsTrue(arc.A.EpsilonEquals(a, ERROR)); // Salida por fichero de la prueba. if ((fileName != null) && toWavefront) { double figSize = 0.5; string mtl = Path.ChangeExtension(fileName, "mtl"); using (MaterialFormat mf = new MaterialFormat(mtl)) { mf.DefaultColors(); } using (WavefrontFormat wf = new WavefrontFormat(fileName)) { wf.LoadMaterialLib(Path.GetFileName(mtl)); wf.DrawLine("Yellow", Point2d.Zero, new Point2d(1, 0), 50); wf.DrawLine("Yellow", Point2d.Zero, new Point2d(0, 1), 50); wf.DrawFigure("Blue", WaveFigure.X, ClothoUtils.Clotho(l0, invertY, a), figSize); wf.DrawFigure("Olive", WaveFigure.X, ClothoUtils.Clotho(l1, invertY, a), figSize); wf.DrawClotho(invertY, a, "Red"); wf.DrawClotho("Magenta", arc); wf.DrawFigure("Blue", WaveFigure.X, p0, figSize); wf.DrawFigure("Olive", WaveFigure.X, p1, figSize); } } }