沿路径螺旋绘制点

时间:2018-11-30 13:51:21

标签: c# unity3d computational-geometry bresenham douglas-peucker

好吧,我正在尝试优化我在这里所做的工作(Smoothing noises with different amplitudes (Part 2))。

由于这个原因,我从头开始进行了新的实现(https://youtu.be/o7pVEXhh3TI)来绘制路径:

    private void Start()
    {
        Polygon pol = File.ReadAllText(PolyPath).Deserialize<Polygon>();

        // Create tex object

        var list = pol.Vertices.AsEnumerable();
        tex = list.CreateTextureObject(pol.Position, offset);

        exampleTexture = new Texture2D(tex.Width, tex.Height);
        exampleTexture.SetPixels32(new Color32[tex.Width * tex.Height]);
        exampleTexture.Apply();

        vertices = pol.Vertices.Select(v => (v - pol.Position) + offset).Clone().ToList();

        _ss = new List<Segment>(pol.Segments.Select(s => new Segment((s.start + pol.Center - pol.Position) + offset, (s.end + pol.Center - pol.Position) + offset)));

        foreach (Segment curSeg in _ss)
            for (int i = -effectDistance; i < effectDistance; ++i)
            {
                Vector2 perp = Vector2.Perpendicular(((Vector2)curSeg.start - (Vector2)curSeg.end)).normalized;

                segments.Add((Vector2)curSeg.start + perp * i);

                F.DrawLine((Vector2)curSeg.start + perp * i, (Vector2)curSeg.end + perp * i, (x, y) => layers.Add(new Point(x, y)));
            }

        Debug.Log("Layer Count: " + layers.Count);

        drawPath = true;
    }

    private void OnGUI()
    {
        if (exampleTexture == null)
            return;

        GUI.DrawTexture(new Rect((Screen.width - tex.Width) / 2, (Screen.height - tex.Height) / 2, tex.Width, tex.Height), exampleTexture);

        if (drawPath)
        {
            {
                Point? cur = layers.Count > 0 ? (Point?)layers.First() : null;

                if (cur.HasValue)
                {
                    exampleTexture.SetPixel(cur.Value.x, cur.Value.y, new Color32(170, 0, 0, 255));
                    exampleTexture.Apply();

                    layers.Remove(cur.Value);
                }
            }

            {
                Point? cur = segments.Count > 0 ? (Point?)segments.First() : null;

                if (cur.HasValue)
                {
                    exampleTexture.SetPixel(cur.Value.x, cur.Value.y, new Color32(0, 170, 0, 255));
                    exampleTexture.Apply();

                    segments.Remove(cur.Value);
                }
            }

            {
                Point? cur = vertices.Count > 0 ? (Point?)vertices.First() : null;

                //Debug.Log(cur);

                if (cur.HasValue)
                {
                    exampleTexture.SetPixel(cur.Value.x, cur.Value.y, new Color32(255, 128, 0, 255));
                    exampleTexture.Apply();

                    vertices.Remove(cur.Value);
                }
            }

            if (vertices.Count == 0 && segments.Count == 0 && layers.Count == 0)
                drawPath = false;
        }
    }

这是DrawLines的实际作用:

public static class F 
{
    public static void DrawLine(Point p1, Point p2, Action<int, int> action)
    {
        DrawLine(p1.x, p1.y, p2.x, p2.y, action);
    }

    public static void DrawLine(int x0, int y0, int x1, int y1, Action<int, int> action)
    {
        int sx = 0,
            sy = 0;

        int dx = Mathf.Abs(x1 - x0),
            dy = Mathf.Abs(y1 - y0);

        if (x0 < x1) { sx = 1; } else { sx = -1; }
        if (y0 < y1) { sy = 1; } else { sy = -1; }

        int err = dx - dy,
            e2 = 0;

        while (true)
        {
            action?.Invoke(x0, y0);

            if ((x0 == x1) && (y0 == y1))
                break;

            e2 = 2 * err;

            if (e2 > -dy)
            {
                err = err - dy;
                x0 = x0 + sx;
            }
            if (e2 < dx)
            {
                err = err + dx;
                y0 = y0 + sy;
            }
        }
    }
}

这是Bresenham algorithm的实现。

此实现更好,因为我将迭代次数从280k降低到了6k,但是有一个问题,因为您可以看到这是不准确的...

首先,要获取形状上每个线段的垂直线(绿色像素),然后在该线段的起点和终点之间绘制直线。使用Ramer-Douglas-Peucker algorithm获得分段。

因此,我正在考虑螺旋式绘制“橙色”路径。我基本上不知道如何解释这一点,但是获得了相同的路径,但是使用了比例尺(Translating/transforming? list of points from its center with an offset/distance),但是我想我将拥有相同的无知感。

任何指南将不胜感激。我可以使用哪种算法绘制带有“图层”的路径?

1 个答案:

答案 0 :(得分:1)

Following some of the information here,您也许可以使用“向内/向外多边形偏移”(也称为“多边形缓冲”)来获得您感兴趣的结果。

诸如Clipper之类的工具可以提供帮助。

一旦可以向外偏移形状,请执行以下操作:

首先,绘制外形(下面的黑色区域),然后向外偏移内部形状,直到达到需要为止,然后使用适当的噪点/颜色将其绘制在外形顶部(下面的棕色区域)方案:

gradient 1/3

然后,应用较小的偏移,然后使用其他噪声/颜色方案(在下面的橙色区域)在顶部绘制该形状。

gradient 2/3

重复操作,直到您拥有所需的渐变为止:

all gradients

最后,绘制其内部形状,使其噪声/配色方案没有任何偏移:

gradient plus inner shape