コード例 #1
0
ファイル: DataSeries_Funcs.cs プロジェクト: danm36/CLRGraph
 public static DataSeries SetSeriesDrawMode(DataSeries series, DrawMode mode)
 {
     series.SetDrawMode(mode);
     return series;
 }
コード例 #2
0
ファイル: HullGenerator.cs プロジェクト: danm36/CLRGraph
        public static DataSeries CreateHullFromSeries(DataSeries source, int iterationCount)
        {
            GraphPoint[] edges = source.GetEdgemostPoints(true);

            if (edges == null)
                return null;

            MaxIterationCount = iterationCount;

            for (int i = 0; i < edges.Length; i++)
                edges[i] = new GraphPoint(edges[i]);

            PendingFaces.Clear();
            ActiveFaces.Clear();

            List<GraphPoint> AvailablePoints = new List<GraphPoint>();
            foreach (object point in source.DataPoints)
                AvailablePoints.Add(new GraphPoint((GraphPoint)point));

            //DataSeries hullSeries = new DataSeries(source.Name + "_Hull", source.DrawColor);
            DataSeries hullSeries = new DataSeries(source.Name + "_Hull", null);
            GraphPoint baseLine1 = null, baseLine2 = null, farthestBaseLine = null, farthestBaseFace = null;

            double bestDist = 0, curDist = 0;
            for (int i = 0; i < edges.Length; i++)
            {
                for (int j = 1; j < edges.Length; j++)
                {
                    if (i == j)
                        continue;

                    curDist = edges[i].DistanceFromSq(edges[j]);
                    if (curDist > bestDist)
                    {
                        baseLine1 = edges[i];
                        baseLine2 = edges[j];
                        bestDist = curDist;
                    }
                }
            }

            bestDist = 0;
            for (int i = 0; i < edges.Length; i++)
            {
                if (edges[i].pos == baseLine1.pos || edges[i].pos == baseLine2.pos)
                    continue;

                curDist = edges[i].DistanceFromLineSegSq(baseLine1, baseLine2);
                if (curDist > bestDist)
                {
                    farthestBaseLine = edges[i];
                    bestDist = curDist;
                }
            }

            Vector3 triangleNormal = GetTriangleNormal(baseLine1.pos, baseLine2.pos, farthestBaseLine.pos);
            Vector3 triangleCenter = GetTriangleCenter(baseLine1.pos, baseLine2.pos, farthestBaseLine.pos);
            float triangleDot = Vector3.Dot(triangleNormal, baseLine1.pos);
            bestDist = 0;

            bool bFlipWinding = false;

            for (int i = 0; i < AvailablePoints.Count; i++)
            {
                if (AvailablePoints[i] == baseLine1 || AvailablePoints[i] == baseLine2 || AvailablePoints[i] == farthestBaseLine)
                    continue;

                //curDist = (AvailablePoints[i].pos - triangleCenter).LengthSquared;
                curDist = Math.Abs(Vector3.Dot(AvailablePoints[i].pos, triangleNormal) - triangleDot);
                if (curDist > bestDist)
                {
                    farthestBaseFace = AvailablePoints[i];
                    bestDist = curDist;

                    bFlipWinding = Vector3.Dot(triangleNormal, (AvailablePoints[i].pos - triangleCenter).Normalized()) > 0;
                }
            }

            if (farthestBaseFace == null) //2D series
            {
                ClojureEngine.Log("[HULL BUILD] Series is 2D, and the hull builder cannot currently work with 2D data sets");
                return null;
            }

            if (bFlipWinding)
            {
                GraphPoint temp = baseLine1;
                baseLine1 = baseLine2;
                baseLine2 = temp;
            }

            List<HullFace> initialFaces = new List<HullFace>() {
                new HullFace(baseLine2, baseLine1, farthestBaseLine),
                new HullFace(baseLine1, baseLine2, farthestBaseFace),
                new HullFace(baseLine1, farthestBaseFace, farthestBaseLine),
                new HullFace(baseLine2, farthestBaseLine, farthestBaseFace),
             };

            AssignPointsToFaces(AvailablePoints, initialFaces);

            for (int i = 0; i < initialFaces.Count; i++)
            {
                ActiveFaces.Add(initialFaces[i]);
                if(initialFaces[i].points.Count > 0)
                    PendingFaces.Add(initialFaces[i]);
            }

            BuildFromStack(0);

            int unassignedPoints = 0;
            for (int i = 0; i < ActiveFaces.Count; i++)
            {
                ActiveFaces[i].a.AddEdges(ActiveFaces[i].b, ActiveFaces[i].c);
                ActiveFaces[i].b.AddEdges(ActiveFaces[i].a, ActiveFaces[i].c);
                ActiveFaces[i].c.AddEdges(ActiveFaces[i].a, ActiveFaces[i].b);

                hullSeries.AddDataPoints(new List<GraphPoint>() { ActiveFaces[i].a, ActiveFaces[i].b, ActiveFaces[i].c });

                unassignedPoints += ActiveFaces[i].points.Count;

                //if(ActiveFaces[i].points.Count > 0)
                //    new DataSeries(PersistentVector.create1(ActiveFaces[i].points));
            }

            if(unassignedPoints > 0)
                ClojureEngine.Log("[HULL BUILD] " + unassignedPoints + " points remain outside the hull");
            else
                ClojureEngine.Log("[HULL BUILD] All points are contained within the hull");

            hullSeries.SetDrawMode(DrawMode.Triangles);
            return hullSeries;
        }