Ejemplo n.º 1
0
    /// <summary>
    ///     The spiral of Theodorus is a spiral composed of contiguous right triangles
    /// </summary>
    /// <param name="numberRot">Determines the number of turns in the spiral</param>
    /// <search>square root,einstein,pythagorean</search>
    public static NurbsCurve Theodorus(int numberRot = 100)
    {
        if (numberRot == 0)
        {
            throw new ArgumentException("The angle value can't be 0.", "angle");
        }

        if (numberRot < 0)
        {
            numberRot = numberRot * -1;
        }

        var    pts       = new List <Point>();
        double radius    = 1;
        double currAngle = 0;

        for (int i = 1; i <= numberRot; ++i)
        {
            radius = Math.Sqrt(i);
            double xVal = radius * Math.Cos(currAngle);
            double yVal = radius * Math.Sin(currAngle);


            pts.Add(Point.ByCoordinates(xVal, yVal, 0));

            currAngle = currAngle + Math.Atan(1 / Math.Sqrt(i));
        }

        return(NurbsCurve.ByControlPoints(pts, 1, false));
    }
Ejemplo n.º 2
0
        public void NurbsCurve_Basic()
        {
            var pts = new[]
            {
                Point.ByCoordinates(10, 2, 3)
                , Point.ByCoordinates(0, 2, 2)
                , Point.ByCoordinates(10, 4, 8)
                , Point.ByCoordinates(10, 2, 8)
                , Point.ByCoordinates(5, 5, 5)
            };

            var bspline = NurbsCurve.ByControlPoints(pts, 3);

            var revitCurve = bspline.ToRevitType();

            Assert.NotNull(revitCurve);
            Assert.IsAssignableFrom <Autodesk.Revit.DB.NurbSpline>(revitCurve);

            var revitSpline = (Autodesk.Revit.DB.NurbSpline)revitCurve;

            Assert.AreEqual(bspline.Degree, revitSpline.Degree);
            Assert.AreEqual(bspline.ControlPoints().Count(), revitSpline.CtrlPoints.Count);

            // ClosestPointTo fails in ProtoGeometry

            var tessPts = revitSpline.Tessellate();

            //assert the tesselation is very close to original curve
            //what's the best tolerance to use here?
            foreach (var pt in tessPts)
            {
                var closestPt = bspline.GetClosestPoint(pt.ToPoint());
                Assert.Less(closestPt.DistanceTo(pt.ToPoint()), 1e-6);
            }
        }
Ejemplo n.º 3
0
        public void ByPointsOnCurve_ValidInput()
        {
            // create spline
            var pts = new Autodesk.DesignScript.Geometry.Point[]
            {
                Point.ByCoordinates(0, 0, 0),
                Point.ByCoordinates(1, 0, 0),
                Point.ByCoordinates(3, 0, 0),
                Point.ByCoordinates(10, 0, 0),
                Point.ByCoordinates(12, 0, 0),
            };

            var spline = NurbsCurve.ByControlPoints(pts, 3);

            Assert.NotNull(spline);

            // build model curve from spline
            var modCurve = ModelCurve.ByCurve(spline);

            Assert.NotNull(modCurve);

            // obtain the family from the document
            var fs = FamilySymbol.ByName("3PointAC");

            // build the AC
            var parms = new double[]
            {
                0, 0.5, 1
            };

            var ac = AdaptiveComponent.ByParametersOnCurveReference(parms, modCurve.ElementCurveReference, fs);

            Assert.NotNull(ac);
        }
Ejemplo n.º 4
0
        public void NurbsCurve_Basic()
        {
            var pts = new[]
            {
                Point.ByCoordinates(10, 2, 3)
                , Point.ByCoordinates(0, 2, 2)
                , Point.ByCoordinates(10, 4, 8)
                , Point.ByCoordinates(10, 2, 8)
                , Point.ByCoordinates(5, 5, 5)
            };

            var bspline = NurbsCurve.ByControlPoints(pts, 3);

            var revitCurve = bspline.ToRevitType(false);

            Assert.NotNull(revitCurve);
            Assert.IsAssignableFrom <Autodesk.Revit.DB.NurbSpline>(revitCurve);

            var revitSpline = (Autodesk.Revit.DB.NurbSpline)revitCurve;

            Assert.AreEqual(bspline.Degree, revitSpline.Degree);
            Assert.AreEqual(bspline.ControlPoints().Count(), revitSpline.CtrlPoints.Count);

            var tessPts = revitSpline.Tessellate().Select(x => x.ToPoint(false));

            //assert the tesselation is very close to original curve
            foreach (var pt in tessPts)
            {
                var closestPt = bspline.ClosestPointTo(pt);
                Assert.Less(closestPt.DistanceTo(pt), 1e-6);
            }
        }
Ejemplo n.º 5
0
        public void Points()
        {
            // create spline
            var pts = new[]
            {
                Point.ByCoordinates(0, 0, 0),
                Point.ByCoordinates(1, 0, 0),
                Point.ByCoordinates(3, 0, 0),
                Point.ByCoordinates(10, 0, 0),
                Point.ByCoordinates(12, 0, 0)
            };

            var spline = NurbsCurve.ByControlPoints(pts, 3);

            Assert.NotNull(spline);

            // build model curve from spline
            var modCurve = ModelCurve.ByCurve(spline);

            Assert.NotNull(modCurve);

            // build dividedPath
            var divPath = DividedPath.ByCurveAndDivisions(modCurve.ElementCurveReference, 5);

            Assert.NotNull(divPath);

            foreach (var pt in divPath.Points)
            {
                Assert.IsTrue(pts.Any(x => x.ShouldBeApproximately(pt)));
            }
        }
Ejemplo n.º 6
0
        public void ByCurveAndEqualDivisions_ValidArgs()
        {
            // create spline
            var pts = new[]
            {
                Point.ByCoordinates(0, 0, 0),
                Point.ByCoordinates(1, 0, 0),
                Point.ByCoordinates(3, 0, 0),
                Point.ByCoordinates(10, 0, 0),
                Point.ByCoordinates(12, 0, 0)
            };

            var spline = NurbsCurve.ByControlPoints(pts, 3);

            Assert.NotNull(spline);

            // build model curve from spline
            var modCurve = ModelCurve.ByCurve(spline);

            Assert.NotNull(modCurve);

            // build dividedPath
            var divPath = DividedPath.ByCurveAndDivisions(modCurve.ElementCurveReference, 5);

            Assert.NotNull(divPath);
        }
Ejemplo n.º 7
0
    /// <summary>
    ///     A golden spiral is a logarithmic spiral whose growth factor is φ, the golden ratio.
    /// </summary>
    /// <param name="angle">360 completes 1 circulation</param>
    /// <search>golden,fibonacci</search>
    public static NurbsCurve Golden(double angle = 720)
    {
        if (angle == 0.0)
        {
            throw new ArgumentException("The angle and scale values can't be 0.");
        }

        angle = (angle < 0.0) ? -1 * angle : angle;

        int numPts = 1000;
        var pts    = new List <Point>();

        double b = Math.Log(goldenRatio()) / (Math.PI / 2);
        double c = Math.Pow(Math.E, b);

        angle = degToRad(angle);


        for (int i = 0; i < numPts; ++i)
        {
            double currAngle = (double)i / 1000.0 * angle;
            double radius    = Math.Pow(c, currAngle);

            double xVal = Math.Cos(currAngle) * Math.Pow(c, currAngle);
            double yVal = Math.Sin(currAngle) * Math.Pow(c, currAngle);

            pts.Add(Point.ByCoordinates(xVal, yVal, 0));
        }

        return(NurbsCurve.ByControlPoints(pts));
    }
Ejemplo n.º 8
0
        public static List <Curve> MorphTo(this Curve curve1, Curve curve2, int numberOfLines, int precision = 10, double offset = 0)
        {
            numberOfLines++;

            Surface virtualSurface = Surface.ByLoft(new List <Curve>()
            {
                curve1, curve2
            });

            Vector direction = virtualSurface.NormalAtParameter(0.5, 0.5);

            List <Curve> curves = new List <Curve>();

            // Divide both curves using the precision factor
            Point[] pointsCurve1 = curve1.PointDivide(precision);
            Point[] pointsCurve2 = curve2.PointDivide(precision);

            // Create a Matrix for the morphed points
            Point[][] points = new Point[precision + 1][];

            // If the Curves are in different directions, flip them.
            if (pointsCurve1[0].DistanceTo(pointsCurve2[pointsCurve2.Length - 1]) < pointsCurve1[0].DistanceTo(pointsCurve2[0]))
            {
                Array.Reverse(pointsCurve2);
            }


            // Draw construction lines between the two curves using the division points
            for (int i = 0; i < pointsCurve1.Length; i++)
            {
                Line line = Line.ByStartPointEndPoint(pointsCurve1[i], pointsCurve2[i]);

                // Divide the construction line into the number of curves to create
                // Add the divsion points to the matrix
                points[i] = line.PointDivide(numberOfLines);
            }

            // Create an empty Array holding the pointWeights
            double[] pointWeights = new double[numberOfLines];

            // Flip the Matrix to create new curves from
            Point[][] transposedPoints = points.TransposeRowsAndColumns();

            // Create Curves from the Matrix
            for (int i = 1; i < transposedPoints.Length - 1; i++)
            {
                NurbsCurve curve          = NurbsCurve.ByControlPoints(transposedPoints[i].ToList());
                Curve      curveToSegment = (offset != 0) ? (Curve)curve.Translate(direction, offset) : curve;

                curves.Add(curveToSegment);
            }

            return(curves);
        }
Ejemplo n.º 9
0
        public void ByPointsOnCurve_ProducesValidAdaptiveComponentAndLocations()
        {
            // create spline
            var pts = new Autodesk.DesignScript.Geometry.Point[]
            {
                Point.ByCoordinates(0, 0, 0),
                Point.ByCoordinates(1, 0, 0),
                Point.ByCoordinates(3, 0, 0),
                Point.ByCoordinates(10, 0, 0),
                Point.ByCoordinates(12, 0, 0),
            };

            var spline = NurbsCurve.ByControlPoints(pts, 3);

            Assert.NotNull(spline);

            // build model curve from spline
            var modCurve = ModelCurve.ByCurve(spline);

            Assert.NotNull(modCurve);

            // obtain the family from the document
            var ft = FamilyType.ByName("3PointAC");

            // build the AC
            var parms = new double[]
            {
                0, 0.5, 1
            };

            var ac = AdaptiveComponent.ByParametersOnCurveReference(parms, modCurve.ElementCurveReference, ft);

            // with unit conversion
            foreach (var pt in ac.Locations)
            {
                spline.DistanceTo(pt).ShouldBeApproximately(0);
            }

            // without unit conversion
            var unconvertedPoints = GetInternalPoints((FamilyInstance)ac.InternalElement);

            foreach (var pt in unconvertedPoints)
            {
                spline.DistanceTo(pt.ToPoint()).ShouldBeApproximately(0);
            }

            Assert.NotNull(ac);
        }
Ejemplo n.º 10
0
    /// <summary>
    ///     Breaks the continous spiral into a series of straight lines
    /// </summary>
    /// <param name="spiral">The spiral to break</param>
    /// <param name="numBreaks">The number of lines to generate</param>
    /// <search>break,divide</search>
    public static NurbsCurve getBrokenSpiral(Curve spiral, int numBreaks = 100)
    {
        if (numBreaks == 0)
        {
            throw new ArgumentException("The numPts needs to be non-zero positive integer");
        }

        numBreaks = (int)Math.Abs(numBreaks);
        var pts = new List <Point>();

        for (int i = 0; i <= numBreaks; ++i)
        {
            pts.Add(spiral.PointAtParameter((double)i / (double)numBreaks));
        }

        return(NurbsCurve.ByControlPoints(pts, 1, false));
    }
Ejemplo n.º 11
0
        public static void CanDoSimpleLoft()
        {
            var points0 = new Point[10];
            var points1 = new Point[10];

            for (int i = 0; i < 10; ++i)
            {
                points0[i] = Point.ByCoordinates(i, 0, 0);
                points1[i] = Point.ByCoordinates(i, 10, 10);
            }

            var crv0 = NurbsCurve.ByControlPoints(points0);
            var crv1 = NurbsCurve.ByControlPoints(points1);

            var srf = Surface.ByLoft(new[] { crv0, crv1 });

            Assert.NotNull(srf);

            Console.WriteLine(srf.PointAtParameter(0.5, 0.5));
        }
Ejemplo n.º 12
0
        public void ToRevitType_ExtensionMethod_DoesExpectedUnitConversion()
        {
            // testing
            var pts = new[]
            {
                Point.ByCoordinates(10, 2, 3)
                , Point.ByCoordinates(0, 2, 2)
                , Point.ByCoordinates(10, 4, 8)
                , Point.ByCoordinates(10, 2, 8)
                , Point.ByCoordinates(5, 5, 5)
            };

            var bspline = NurbsCurve.ByControlPoints(pts, 3);

            // do scaling for check
            var metersToFeet  = 1 / 0.3048;
            var bsplineScaled = (NurbsCurve)bspline.Scale(metersToFeet);

            // by default, performs conversion
            var revitCurve = bspline.ToRevitType();

            Assert.NotNull(revitCurve);
            Assert.IsAssignableFrom <Autodesk.Revit.DB.NurbSpline>(revitCurve);

            var revitSpline = (Autodesk.Revit.DB.NurbSpline)revitCurve;

            Assert.AreEqual(bsplineScaled.Degree, revitSpline.Degree);
            Assert.AreEqual(bsplineScaled.ControlPoints().Count(), revitSpline.CtrlPoints.Count);

            // We tesselate but not convert units. We are trying to find out if
            // ToRevitType did the conversion properly by comparing to a scaled
            // version of the original bspline (bsplineScaled)
            var tessPts = revitSpline.Tessellate().Select(x => x.ToPoint(false));

            //assert the tesselation is very close to original curve
            foreach (var pt in tessPts)
            {
                var closestPt = bsplineScaled.ClosestPointTo(pt);
                Assert.Less(closestPt.DistanceTo(pt), 1e-6);
            }
        }
Ejemplo n.º 13
0
        internal static Curve CurveFromMfnNurbsCurveFromDag(MDagPath dagPath, MSpace.Space space)
        {
            Point3DCollection controlVertices;
            List <double>     weights, knots;
            int  degree;
            bool closed, rational;

            decomposeMayaCurve(dagPath, space, out controlVertices, out weights, out knots, out degree, out closed,
                               out rational);

            // var controlPoints = new List<Point>(controlVertices.Count);
            var curvePoints = new PointList(controlVertices.Count);

            if (MGlobal.isYAxisUp)
            {
                curvePoints.AddRange(controlVertices.Select(cv => Point.ByCoordinates(cv.X, -cv.Z, cv.Y)));
            }
            else
            {
                curvePoints.AddRange(controlVertices.Select(cv => Point.ByCoordinates(cv.X, cv.Y, cv.Z)));
            }

            Curve theCurve;

            if (closed)
            {
                theCurve = NurbsCurve.ByControlPoints(curvePoints, degree, true);
            }
            else
            {
                theCurve = NurbsCurve.ByControlPointsWeightsKnots(curvePoints, weights.ToArray(), knots.ToArray(),
                                                                  degree);
            }


            curvePoints.Dispose();

            return(theCurve);
        }
Ejemplo n.º 14
0
        public void ByCurveAndEqualDivisions_InvalidDivisions()
        {
            // create spline
            var pts = new[]
            {
                Point.ByCoordinates(0, 0, 0),
                Point.ByCoordinates(1, 0, 0),
                Point.ByCoordinates(3, 0, 0),
                Point.ByCoordinates(10, 0, 0),
                Point.ByCoordinates(12, 0, 0)
            };

            var spline = NurbsCurve.ByControlPoints(pts, 3);

            Assert.NotNull(spline);

            // build model curve from spline
            var modCurve = ModelCurve.ByCurve(spline);

            Assert.NotNull(modCurve);

            // build dividedPath
            Assert.Throws(typeof(Exception), () => DividedPath.ByCurveAndDivisions(modCurve.ElementCurveReference, 0));
        }
Ejemplo n.º 15
0
        public void Points()
        {
            // create spline
            var pts = new[]
            {
                Point.ByCoordinates(0, 0, 0),
                Point.ByCoordinates(1, 0, 0),
                Point.ByCoordinates(3, 0, 0),
                Point.ByCoordinates(10, 0, 0),
                Point.ByCoordinates(12, 0, 0)
            };

            var spline = NurbsCurve.ByControlPoints(pts, 3);

            Assert.NotNull(spline);

            // build model curve from spline
            var modCurve = ModelCurve.ByCurve(spline);

            Assert.NotNull(modCurve);

            // build dividedPath
            var divPath = DividedPath.ByCurveAndDivisions(modCurve.ElementCurveReference, 5);

            Assert.NotNull(divPath);

            var divPathPts = divPath.Points;

            Assert.AreEqual(5, divPathPts.Count());

            foreach (var pt in divPathPts)
            {
                // all of the points should be along the curve
                spline.DistanceTo(pt).ShouldBeApproximately(0);
            }
        }
Ejemplo n.º 16
0
        public static void ToMaya(Curve CurveToSend, string name)
        {
            NurbsCurve ctsAsNurb = null;

            if (CurveToSend is Rectangle)
            {
                Rectangle rec = (Rectangle)CurveToSend;
                ctsAsNurb = NurbsCurve.ByControlPoints(rec.Points, 1, true);
            }
            else if (CurveToSend is Polygon)
            {
                Polygon rec = (Polygon)CurveToSend;
                ctsAsNurb = NurbsCurve.ByControlPoints(rec.Points, 1, true);
            }
            else
            {
                ctsAsNurb = CurveToSend.ToNurbsCurve();
            }

            var ncd = new MFnNurbsCurveData();


            MFnNurbsCurveForm mfnform;

            if (ctsAsNurb.IsClosed)
            {
                mfnform = MFnNurbsCurveForm.kClosed;
            }
            else
            {
                mfnform = MFnNurbsCurveForm.kOpen;
            }

            var mayaCurve = new MFnNurbsCurve();

            var vtxs = new MPointArray();

            var cvs = ctsAsNurb.ControlPoints();
            var yUp = MGlobal.isYAxisUp;

            if (yUp)
            {
                foreach (var cv in cvs)
                {
                    var pt = new MPoint(cv.X, cv.Z, -cv.Y);
                    vtxs.Add(pt);
                    //pt.Dispose();
                }
            }
            else
            {
                foreach (var cv in cvs)
                {
                    var pt = new MPoint(cv.X, cv.Y, cv.Z);
                    vtxs.Add(pt);
                    //pt.Dispose();
                }
            }

            var knots    = ctsAsNurb.Knots();
            var crvKnots = new MDoubleArray(knots);

            crvKnots.RemoveAt(0);
            crvKnots.RemoveAt(crvKnots.Count - 1);

            MDagPath node       = null;
            var      nodeExists = false;

            Task checkNode  = null;
            Task deleteNode = null;

            try
            {
                node       = DMInterop.getDagNode(name);
                nodeExists = true;
            }
            catch (Exception)
            {
                nodeExists = false;
            }

            MObject obj;

            if (nodeExists)
            {
                MDagPath nodeShape = node;
                nodeShape.extendToShape();
                var modifyCrv = new MDGModifier();
                mayaCurve = new MFnNurbsCurve(nodeShape);

                try
                {
                    MFnNurbsCurveData dataCreator  = new MFnNurbsCurveData();
                    MObject           outCurveData = dataCreator.create();
                    var    span   = (vtxs.Count - ctsAsNurb.Degree);
                    string rblCmd = $"rebuildCurve -rt 0 -s {span} -d {ctsAsNurb.Degree} {name}";

                    if (mayaCurve.numCVs != vtxs.Count || mayaCurve.degree != ctsAsNurb.Degree)
                    {
                        MGlobal.executeCommand(rblCmd);
                    }

                    mayaCurve.setCVs(vtxs);
                    mayaCurve.setKnots(crvKnots, 0, crvKnots.length - 1);
                    mayaCurve.updateCurve();
                    modifyCrv.doIt();

                    if (CurveToSend.GetType() == typeof(Circle))
                    {
                        span   = 8;
                        rblCmd = $"rebuildCurve -rt 0 -s {span} {name}";
                        MGlobal.executeCommand(rblCmd);
                    }
                }
                catch (Exception e)
                {
                    MGlobal.displayWarning(e.Message);
                }
            }

            else
            {
                obj = mayaCurve.create(vtxs, crvKnots, (uint)ctsAsNurb.Degree, (MFnNurbsCurve.Form)mfnform,
                                       false, ctsAsNurb.IsRational);
                MFnDependencyNode nodeFn = new MFnDagNode(obj);
                nodeFn.setName(name);
            }
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Returns the list of Dynamo curves that defines the Alignment.
        /// </summary>
        /// <returns>A list of lines and arcs that decribe the Alignment.</returns>
        /// <remarks>The tool returns only lines and arcs.</remarks>
        public IList <Curve> GetCurves()
        {
            Utils.Log("Alignment.GetCurves Started...");

            IList <Curve> output = new List <Curve>();

            foreach (AeccAlignmentEntity e in this._entities)
            {
                switch (e.Type)
                {
                case AeccAlignmentEntityType.aeccTangent:
                {
                    AeccAlignmentTangent a = e as AeccAlignmentTangent;

                    output.Add(Line.ByStartPointEndPoint(
                                   Point.ByCoordinates(a.StartEasting, a.StartNorthing),
                                   Point.ByCoordinates(a.EndEasting, a.EndNorthing)));
                    break;
                }

                case AeccAlignmentEntityType.aeccArc:
                {
                    AeccAlignmentArc a = e as AeccAlignmentArc;

                    Arc arc = null;
                    if (!a.Clockwise)
                    {
                        arc = Arc.ByCenterPointStartPointEndPoint(
                            Point.ByCoordinates(a.CenterEasting, a.CenterNorthing),
                            Point.ByCoordinates(a.StartEasting, a.StartNorthing),
                            Point.ByCoordinates(a.EndEasting, a.EndNorthing));
                    }
                    else
                    {
                        arc = Arc.ByCenterPointStartPointEndPoint(
                            Point.ByCoordinates(a.CenterEasting, a.CenterNorthing),
                            Point.ByCoordinates(a.EndEasting, a.EndNorthing),
                            Point.ByCoordinates(a.StartEasting, a.StartNorthing));
                    }


                    output.Add(arc);

                    //var p1 = a.PassThroughPoint1;
                    //var p2 = a.PassThroughPoint2;
                    //var p3 = a.PassThroughPoint3;

                    //output.Add(Arc.ByThreePoints(Point.ByCoordinates(p1.X, p1.Y),
                    //   Point.ByCoordinates(p2.X, p2.Y),
                    //   Point.ByCoordinates(p3.X, p3.Y)));
                    break;
                }

                case AeccAlignmentEntityType.aeccSpiralCurveSpiralGroup:
                {
                    AeccAlignmentSCSGroup a = e as AeccAlignmentSCSGroup;

                    AeccAlignmentEntity before = this._entities.Item(e.EntityBefore);
                    AeccAlignmentEntity after  = this._entities.Item(e.EntityAfter);

                    Curve beforeCurve = null;
                    Curve afterCurve  = null;

                    if (before.Type == AeccAlignmentEntityType.aeccTangent)
                    {
                        AeccAlignmentTangent b = before as AeccAlignmentTangent;

                        beforeCurve = Line.ByStartPointEndPoint(
                            Point.ByCoordinates(b.StartEasting, b.StartNorthing),
                            Point.ByCoordinates(b.EndEasting, b.EndNorthing));
                    }
                    else if (before.Type == AeccAlignmentEntityType.aeccArc)
                    {
                        AeccAlignmentArc b = before as AeccAlignmentArc;

                        beforeCurve = Arc.ByCenterPointStartPointEndPoint(
                            Point.ByCoordinates(b.CenterEasting, b.CenterNorthing),
                            Point.ByCoordinates(b.StartEasting, b.StartNorthing),
                            Point.ByCoordinates(b.EndEasting, b.EndNorthing));
                    }

                    if (after.Type == AeccAlignmentEntityType.aeccTangent)
                    {
                        AeccAlignmentTangent b = after as AeccAlignmentTangent;

                        afterCurve = Line.ByStartPointEndPoint(
                            Point.ByCoordinates(b.StartEasting, b.StartNorthing),
                            Point.ByCoordinates(b.EndEasting, b.EndNorthing));
                    }
                    else if (after.Type == AeccAlignmentEntityType.aeccArc)
                    {
                        AeccAlignmentArc b = after as AeccAlignmentArc;

                        afterCurve = Arc.ByCenterPointStartPointEndPoint(
                            Point.ByCoordinates(b.CenterEasting, b.CenterNorthing),
                            Point.ByCoordinates(b.StartEasting, b.StartNorthing),
                            Point.ByCoordinates(b.EndEasting, b.EndNorthing));
                    }

                    if (afterCurve != null && beforeCurve != null)
                    {
                        output.Add(Curve.ByBlendBetweenCurves(beforeCurve, afterCurve));
                    }

                    // Andrew Milford wrote the code for the spirals using Fourier approximation
                    // Get some parameters
                    int entCnt = a.SubEntityCount;

                    for (int i = 0; i < entCnt; i++)
                    {
                        AeccAlignmentEntity     subEnt    = a.SubEntity(i);
                        AeccAlignmentEntityType alignType = subEnt.Type;

                        switch (alignType)
                        {
                        case AeccAlignmentEntityType.aeccTangent:
                            break;

                        case AeccAlignmentEntityType.aeccArc:
                            AeccAlignmentArc arc = subEnt as AeccAlignmentArc;
                            Arc dArc             = null;
                            if (!arc.Clockwise)
                            {
                                dArc = Arc.ByCenterPointStartPointEndPoint(
                                    Point.ByCoordinates(arc.CenterEasting, arc.CenterNorthing),
                                    Point.ByCoordinates(arc.StartEasting, arc.StartNorthing),
                                    Point.ByCoordinates(arc.EndEasting, arc.EndNorthing));
                            }
                            else
                            {
                                dArc = Arc.ByCenterPointStartPointEndPoint(
                                    Point.ByCoordinates(arc.CenterEasting, arc.CenterNorthing),
                                    Point.ByCoordinates(arc.EndEasting, arc.EndNorthing),
                                    Point.ByCoordinates(arc.StartEasting, arc.StartNorthing));
                            }

                            output.Add(dArc);

                            break;

                        case AeccAlignmentEntityType.aeccSpiral:

                            // calculate the spiral intervals
                            AeccAlignmentSpiral s = subEnt as AeccAlignmentSpiral;
                            double radIn          = s.RadiusIn;
                            double radOut         = s.RadiusOut;
                            double length         = s.Length;
                            AeccAlignmentSpiralDirectionType dir = s.Direction;

                            // Identify the spiral is the start or end
                            bool isStart = true;

                            double radius;
                            if (Double.IsInfinity(radIn))
                            {
                                // Start Spiral
                                radius = radOut;
                            }
                            else
                            {
                                // End Spiral
                                radius  = radIn;
                                isStart = false;
                            }

                            double A  = s.A;            // Flatness of spiral
                            double RL = radius * length;
                            //double A = Math.Sqrt(radius * length);

                            List <Point> pts      = new List <Point>();
                            double       n        = 0;
                            double       interval = 2;        // 2 meters intervals TODO what if the curve is shorter than 2 meters?
                            int          num      = Convert.ToInt32(Math.Ceiling(length / interval));
                            double       step     = length / num;

                            double dirStart = s.StartDirection;
                            double dirEnd   = s.EndDirection;

                            Point  ptPI    = Point.ByCoordinates(s.PIEasting, s.PINorthing, 0);
                            Point  ptStart = Point.ByCoordinates(s.StartEasting, s.StartNorthing, 0);
                            Point  ptEnd   = Point.ByCoordinates(s.EndEasting, s.EndNorthing, 0);
                            Point  pt;
                            double angRot;

                            /*
                             * Paolo Serra - Implementation of Fourier's Transform for the clothoid for a given number of terms
                             * x = Sum[(-1)^t * n ^(4*t+1) / ((2*t)!*(4*t+1)*(2*RL)^(2*t))] for t = 0 -> N
                             * y = Sum[(-1)^t * n ^(4*t+3) / ((2^t + 1)!*(4*t+3)*(2*RL)^(2*t + 1))] for t = 0 -> N
                             */

                            for (int j = 0; j <= num; j++)
                            {
                                double x = 0;
                                double y = 0;

                                for (int t = 0; t < 8; t++)              // first 8 terms of the transform
                                {
                                    x += Math.Pow(-1, t) * Math.Pow(n, 4 * t + 1) / (Factorial(2 * t) * (4 * t + 1) * Math.Pow(2 * RL, 2 * t));
                                    y += Math.Pow(-1, t) * Math.Pow(n, 4 * t + 3) / (Factorial(2 * t + 1) * (4 * t + 3) * Math.Pow(2 * RL, 2 * t + 1));
                                }

                                //double x = n - ((Math.Pow(n, 5)) / (40 * Math.Pow(RL, 2))) + ((Math.Pow(n, 9)) / (3456 * Math.Pow(RL, 4))) - ((Math.Pow(n, 13)) / (599040 * Math.Pow(RL, 6))) + ((Math.Pow(n, 17)) / (175472640 * Math.Pow(RL, 8)));
                                //double y = ((Math.Pow(n, 3)) / (6 * RL)) - ((Math.Pow(n, 7)) / (336 * Math.Pow(RL, 3))) + (Math.Pow(n, 11) / (42240 * Math.Pow(RL, 5))) - (Math.Pow(n, 15) / (9676800 * Math.Pow(RL, 7)));

                                // Flip the Y offset if start spiral is CW OR end spiral is CCW
                                if ((isStart && dir == AeccAlignmentSpiralDirectionType.aeccAlignmentSpiralDirectionRight) ||
                                    (!isStart && dir == AeccAlignmentSpiralDirectionType.aeccAlignmentSpiralDirectionLeft)
                                    )
                                {
                                    y *= -1;
                                }

                                pts.Add(Point.ByCoordinates(x, y, 0));
                                n += step;
                            }

                            // Create spiral at 0,0
                            NurbsCurve spiralBase = NurbsCurve.ByControlPoints(pts, 3);              // Degree by default is 3

                            if (isStart)
                            {
                                pt     = ptStart;
                                angRot = 90 - (dirStart * (180 / Math.PI));
                            }
                            else
                            {
                                pt     = ptEnd;
                                angRot = 270 - (dirEnd * (180 / Math.PI));
                            }


                            // Coordinate system on outer spiral point
                            CoordinateSystem csOrig = CoordinateSystem.ByOrigin(pt);
                            CoordinateSystem cs     = csOrig.Rotate(pt, Vector.ZAxis(), angRot);

                            NurbsCurve spiral = (NurbsCurve)spiralBase.Transform(cs);

                            output.Add(spiral);

                            break;

                        default:
                            break;
                        }
                    }

                    break;
                }
                }
            }

            output = SortCurves(output);

            Utils.Log("Alignment.GetCurves Completed.");

            return(output);
        }