예제 #1
0
        public static Line3 FitLine(IList <Vector3> points)
        {
            var n = points.Count;

            if (n < 2)
            {
                throw new ArgumentException("At least two points are required to fit a line.");
            }

            var x        = new double[n, 3];
            var centroid = Vector3.Centroid(points);

            for (int i = 0; i < n; i++)
            {
                x[i, 0] = points[i].X - centroid.X;
                x[i, 1] = points[i].Y - centroid.Y;
                x[i, 2] = points[i].Z - centroid.Z;
            }

            double[] w;
            double[,] u, vt;
            const int uNeeded  = 0;                  // don't need left singular vectors
            const int vtNeeded = 1;                  // need first set of right singular vectors
            const int extraMemoryAllowedSetting = 2; // it's ok to use more memory for performance

            alglib.rmatrixsvd(x, n, 3, uNeeded, vtNeeded, extraMemoryAllowedSetting, out w, out u, out vt);


            // because alglib.rmatrixsvd promises to return singular values, w, in descending order, we can be sure that w[0] is the greatest
            const int IndexOfGreatestSingularValue = 0;

            var a = vt[IndexOfGreatestSingularValue, 0];
            var b = vt[IndexOfGreatestSingularValue, 1];
            var c = vt[IndexOfGreatestSingularValue, 2];

            var direction = new Vector3(a, b, c);

            return(Line3.FromPointAndDirection(centroid, direction));
        }
예제 #2
0
        static void ClowWater()
        {
            List <Vector3> p3 = new List <Vector3>();

            p3.Add(new Vector3(1.1, 0.9, 1.0));
            p3.Add(new Vector3(6.9, 7.1, 7.0));

            var line3fit = AutomationLibrary.Mathematics.Fitting.GeometricFits.FitLine(p3);

            var line3   = Line3.FromPointAndDirection(new Vector3(0.5, 0.5, 0.5), new Vector3(1, 1, 1));
            var nearest = line3.GetClosestPoint(new Vector3(27, -1.4, 19));

            List <Vector2> points = new List <Vector2>();

            using (var reader = System.IO.File.OpenText(@"C:\Users\douglas\desktop\pipe.csv"))
            {
                reader.ReadLine(); // skip header
                while (true)
                {
                    var line = reader.ReadLine();
                    if (line == null)
                    {
                        break;
                    }
                    var nums   = line.Split(',');
                    var values = nums.Select(n => double.Parse(n)).ToArray();
                    points.Add(new Vector2(values[0], values[1]));
                }
            }

            var ellipse = AutomationLibrary.Mathematics.Fitting.GeometricFits.FitEllipse(points);

            var ellipseFunc       = AutomationLibrary.Mathematics.Curves.CircularFunction.FromCartesianPoints(ellipse.Center, points);
            var smoothEllipseFunc = ellipseFunc.SavitzkyGolaySmooth(3, 21);


            points.Clear();
            points.AddRange(GeneratePointsOnEllipticalArc(new Vector2(0.37, -2.4), 21, 24.26, 96.3 * Math.PI / 180.0, .020, -95.0 * Math.PI / 180.0, 97.0 * Math.PI / 180.0).Take(1000));


            var pointSet = new PointCloud2(points);

            var voronoi = AutomationLibrary.Mathematics.Geometry.Voronoi.VoronoiDiagram.ComputeForPoints(points);

            voronoi = voronoi.Filter(0); // build map of nearest points

            var centersOfInfiniteCells = new HashSet <Vector2>();

            foreach (var edge in voronoi.Edges)
            {
                if (edge.IsPartlyInfinite)
                {
                    centersOfInfiniteCells.Add(edge.LeftData);
                    centersOfInfiniteCells.Add(edge.RightData);
                }
            }

            var pointSet2 = new PointCloud2(centersOfInfiniteCells);

            var mcc = pointSet2.ComputeMinimumCircumscribingCircle();
            var mic = ComputeMaximumInscribedCircle(pointSet, voronoi, mcc);
            var lsc = GeometricFits.FitCircle(points);

            using (var writer = System.IO.File.CreateText(@"C:\users\douglas\desktop\circlepoints.csv"))
            {
                writer.WriteLine("X,Y");
                foreach (var point in pointSet)
                {
                    writer.WriteLine("{0},{1}", point.X, point.Y);
                }
            }

            Console.WriteLine("n = {0}", points.Count);
            Console.WriteLine("MIC @ ({0}), r = {1}", mic.Center, mic.Radius);
            Console.WriteLine("LSC @ ({0}), r = {1}", lsc.Center, lsc.Radius);
            Console.WriteLine("MCC @ ({0}), r = {1}", mcc.Center, mcc.Radius);

            Console.WriteLine();

            Console.WriteLine("draw.circle({0}, {1}, {2}, border='{3}')", mic.Center.X, mic.Center.Y, mic.Radius, "red");
            Console.WriteLine("draw.circle({0}, {1}, {2}, border='{3}')", lsc.Center.X, lsc.Center.Y, lsc.Radius, "blue");
            Console.WriteLine("draw.circle({0}, {1}, {2}, border='{3}')", mcc.Center.X, mcc.Center.Y, mcc.Radius, "green");

            Console.ReadLine();
        }