예제 #1
0
        public static void addToQueue(FlatQueue <float> queue, DelaunatorSharp.Delaunator delauny
                                      , DelaunatorSharp.IPoint[] points, Circumcircles circumcircles, bool[] onEdge, bool[] visited, int i)
        {
            onEdge[i] = true;

            visited[delauny.Triangles[i]] = true;

            DelaunatorSharp.IPoint p0 = points[delauny.Triangles[i]];
            DelaunatorSharp.IPoint p1 = points[delauny.Triangles[i % 3 == 2 ? i - 2 : i + 1]];

            float r = circumcircles.r[i];
            float x = circumcircles.x[i];
            float y = circumcircles.y[i];


            float x0 = (float)p0.X;
            float y0 = (float)p0.Y;

            float x1 = (float)p1.X;
            float y1 = (float)p1.Y;

            // var [x0, y0] = p0;
            // var[x1, y1] = p1;

            float area = (y - y0) * (x1 - x) - (x - x0) * (y1 - y);
            float cx   = (x0 + x1) / 2;
            float cy   = (y0 + y1) / 2;
            float d    = (float)System.Math.Sqrt(System.Math.Pow(cx - x, 2) + System.Math.Pow(cy - y, 2));

            // if the center of a circumcircle on the edge lies outside the advancing polygon,
            // or inside but less than 0.2 circumradiuses away from the edge, queue it for collapsing
            if (area >= 0f || d / r < 0.2f)
            {
                queue.Push(i, -r);
            }
        }
예제 #2
0
        // https://observablehq.com/@mourner/adaptive-concave-hull
        // https://mapbox.github.io/delaunator/
        public static void ComputeHull()
        {
            string jsonFile = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "..", "..", "..", "DelaunatorPoints.json");

            jsonFile = System.IO.Path.GetFullPath(jsonFile);

            string json = System.IO.File.ReadAllText(jsonFile, System.Text.Encoding.UTF8);

            // DelaunatorSharp.IPoint[] points = Newtonsoft.Json.JsonConvert.DeserializeObject<DelaunatorSharp.IPoint[]>(json);
            DelaunatorSharp.IPoint[] points = Newtonsoft.Json.JsonConvert.DeserializeObject <DelaunatorSharp.Point[]>(json).Cast <DelaunatorSharp.IPoint>().ToArray();
            points = EnhancePointDensity(points, 10);
            // string json = Newtonsoft.Json.JsonConvert.SerializeObject(points);
            // System.IO.File.WriteAllText(jsonFile, json,System.Text.Encoding.UTF8);

            BoundingBox bbox = GetBbox(points);

            // float width = bbox.maxX - bbox.minX;
            float width   = bbox.maxX * 6;
            float padding = (float)System.Math.Round(width * 0.02);
            float scale   = (width - 2 * padding) / (bbox.maxX - bbox.minX);
            float height  = (float)System.Math.Ceiling(scale * (bbox.maxY - bbox.minY)) + 2 * padding;

            width = width + 2 * padding;


            DelaunatorSharp.Delaunator delauny = new DelaunatorSharp.Delaunator(points);
            Circumcircles circumcircles        = ComputeCircumcircles(points, delauny);

            FlatQueue <float> queue = new FlatQueue <float>();

            bool[] onEdge  = new bool[delauny.Halfedges.Length];
            bool[] visited = new bool[points.Length];


            for (int i = 0; i < delauny.Halfedges.Length; i++)
            {
                if (delauny.Halfedges[i] == -1)
                {
                    addToQueue(queue, delauny, points, circumcircles, onEdge, visited, i); // start with convex hull edges
                }
            }

            // var ctx = DOM.context2d(width, height);

            int imageCount = 0;

            System.Drawing.Bitmap bmp = new System.Drawing.Bitmap((int)width, (int)height);

            using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bmp))
            {
                // Draw(delauny, points, bbox, circumcircles, g, padding, scale, queue, onEdge);
                // bmp.Save(@"D:\TestImage" + imageCount + ".png", System.Drawing.Imaging.ImageFormat.Png);
                // imageCount++;

                while (true)
                {
                    int?i = queue.Pop();
                    if (i == null)
                    {
                        break;
                    }

                    int i1 = delauny.Halfedges[i.Value % 3 == 2 ? i.Value - 2 : i.Value + 1];
                    int i2 = delauny.Halfedges[i.Value % 3 == 0 ? i.Value + 2 : i.Value - 1];
                    if (i1 != -1 && i2 != -1 && !visited[delauny.Triangles[i1]])
                    {
                        addToQueue(queue, delauny, points, circumcircles, onEdge, visited, i1);
                        addToQueue(queue, delauny, points, circumcircles, onEdge, visited, i2);
                        onEdge[i.Value] = false;
                    }

                    // yield draw(ctx, queue, onEdge);
                    // Draw(delauny, points, bbox, circumcircles, g, padding, scale, queue, onEdge);

                    // if(System.Environment.OSVersion.Platform == PlatformID.Unix)
                    //     bmp.Save(@"TestImage" + imageCount + ".png", System.Drawing.Imaging.ImageFormat.Png);
                    // else
                    //     bmp.Save(@"D:\TestImage" + imageCount + ".png", System.Drawing.Imaging.ImageFormat.Png);

                    // imageCount++;
                } // Whend

                Draw(delauny, points, bbox, circumcircles, g, padding, scale, queue, onEdge);

                if (System.Environment.OSVersion.Platform == System.PlatformID.Unix)
                {
                    bmp.Save(@"TestImage.png", System.Drawing.Imaging.ImageFormat.Png);
                }
                else
                {
                    bmp.Save(@"D:\TestImage.png", System.Drawing.Imaging.ImageFormat.Png);
                }
            } // End Using g

            System.Console.Write("finished");
        }
예제 #3
0
        public static void Draw(
            DelaunatorSharp.Delaunator delaunay
            , DelaunatorSharp.IPoint[] points
            , BoundingBox bbox
            , Circumcircles circumcircles
            , System.Drawing.Graphics ctx
            , float padding
            , float scale
            , FlatQueue <float> queue
            , bool[] onEdge
            )
        {
            // ctx.clearRect(0, 0, width, height);
            ctx.Clear(System.Drawing.Color.White);


            System.Drawing.Drawing2D.GraphicsPath path1 = new System.Drawing.Drawing2D.GraphicsPath();

            int[] t = delaunay.Triangles;
            for (int i = 0; i < t.Length; i += 3)
            {
                DelaunatorSharp.IPoint pt1 = points[t[i + 0]];
                float ax = (float)pt1.X;
                float ay = (float)pt1.Y;


                DelaunatorSharp.IPoint pt2 = points[t[i + 1]];
                float bx = (float)pt2.X;
                float by = (float)pt2.Y;


                DelaunatorSharp.IPoint pt3 = points[t[i + 2]];
                float cx = (float)pt3.X;
                float cy = (float)pt3.Y;

                path1.StartFigure();
                path1.AddLine(projX(ax, padding, scale, bbox), projY(ay, padding, scale, bbox), projX(bx, padding, scale, bbox), projY(by, padding, scale, bbox));
                path1.AddLine(projX(bx, padding, scale, bbox), projY(by, padding, scale, bbox), projX(cx, padding, scale, bbox), projY(cy, padding, scale, bbox));
                path1.CloseFigure();
            }

            System.Drawing.Pen trianglePen = new System.Drawing.Pen(System.Drawing.Color.FromArgb((int)(0.4 * 255), 0, 200, 0));
            trianglePen.Width     = 0.5f;
            trianglePen.Alignment = System.Drawing.Drawing2D.PenAlignment.Center;
            ctx.DrawPath(trianglePen, path1);

            System.Drawing.Drawing2D.GraphicsPath path2 = new System.Drawing.Drawing2D.GraphicsPath();


            // for (const [x, y] of points)
            foreach (DelaunatorSharp.IPoint thisPoint in points)
            {
                float sx = projX((float)thisPoint.X, padding, scale, bbox);
                float sy = projY((float)thisPoint.Y, padding, scale, bbox);
                float r  = 1.5f;
                r = 5;

                path2.StartFigure();
                path2.AddArc(sx - r / 2.0f, sy - r / 2.0f, r, r, 0.0f, 360.0f);
                path2.CloseFigure();
            }

            System.Drawing.Brush blackBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black);
            ctx.FillPath(blackBrush, path2);



            // ctx.beginPath();
            System.Drawing.Drawing2D.GraphicsPath path3 = new System.Drawing.Drawing2D.GraphicsPath();
            // path3.StartFigure();
            for (int i = 0; i < onEdge.Length; i++)
            {
                if (!onEdge[i])
                {
                    continue;
                }

                DelaunatorSharp.IPoint pt1 = points[t[i]];
                float ax = (float)pt1.X;
                float ay = (float)pt1.Y;

                DelaunatorSharp.IPoint pt2 = points[t[i % 3 == 2 ? i - 2 : i + 1]];
                float bx = (float)pt2.X;
                float by = (float)pt2.Y;

                path3.StartFigure();
                path3.AddLine(projX(ax, padding, scale, bbox), projY(ay, padding, scale, bbox), projX(bx, padding, scale, bbox), projY(by, padding, scale, bbox));
                path3.CloseFigure();
                // ctx.moveTo(projX(ax), projY(ay));
                // ctx.lineTo(projX(bx), projY(by));
                // ctx.closePath();
            }
            // path3.CloseFigure();
            System.Drawing.Pen hullPen = new System.Drawing.Pen(System.Drawing.Color.Blue);
            hullPen.Width = 2.0f;
            ctx.DrawPath(hullPen, path3);



            System.Drawing.Drawing2D.GraphicsPath path4 = new System.Drawing.Drawing2D.GraphicsPath();
            foreach (int i in queue.ids)
            {
                // ctx.beginPath();
                path4.StartFigure();
                float sr = circumcircles.r[i] * scale;
                float sx = projX(circumcircles.x[i], padding, scale, bbox);
                float sy = projY(circumcircles.y[i], padding, scale, bbox);
                //ctx.moveTo(sx + sr, sy);
                //ctx.arc(sx, sy, sr, 0, Math.PI* 2, false);
                //ctx.strokeStyle = 'rgba(200,0,0,1)';
                //ctx.lineWidth = 1;
                //ctx.stroke();
                //ctx.fillStyle = 'rgba(255,255,0,0.2)';
                //ctx.fill();

                path4.AddArc(sx - sr / 2.0f, sy - sr / 2.0f, sr, sr, 0.0f, 360.0f);
                path4.CloseFigure();
            }

            System.Drawing.SolidBrush circleBrush = new System.Drawing.SolidBrush(System.Drawing.Color.FromArgb((int)(0.2 * 255), 255, 255, 0));
            System.Drawing.Pen        redCircle   = new System.Drawing.Pen(System.Drawing.Color.FromArgb(255, 200, 0, 0));
            redCircle.Width     = 1;
            redCircle.Alignment = System.Drawing.Drawing2D.PenAlignment.Center;
            ctx.FillPath(circleBrush, path4);
            ctx.DrawPath(redCircle, path4);
        }