Рисование точек вдоль пути по спирали - PullRequest
0 голосов
/ 30 ноября 2018

Ну, я пытаюсь оптимизировать то, что я сделал здесь ( Сглаживание шумов с разными амплитудами (часть 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;
            }
        }
    }
}

Это реализация алгоритма Брезенхема .

Эта реализация лучше, потому что я снизил количество итераций с 280 К до 6 КБ, но есть проблема, поскольку вы можете видеть, что это неточно ...

Первый способ - получитьперпендикулярно каждому сегменту фигуры (зеленые пиксели), а затем рисует линии между начальной и конечной точкой этого сегмента. Сегменты получают с использованием алгоритма Рамера-Дугласа-Пекера .

Я думал о том, чтобы нарисовать «оранжевый» путь по спирали. Я не знаю, как объяснить это, в основном, получая тот же путь, но со шкалой ( Translating / transform? Список точек из его центра с выкл.et / distance ) но я думаю, что у меня будет такая же неточность.

Любое руководство будет оценено.Какой алгоритм я могу использовать, чтобы нарисовать путь со «слоями»?

1 Ответ

0 голосов
/ 04 декабря 2018

Следуя некоторой информации здесь , вы можете использовать «смещение полигонов внутрь / наружу» (иначе «буферизация полигонов»), чтобы получить интересующий вас результат.

Инструмент, такой как Clipper может помочь.

Как только у вас есть способ сместить вашу фигуру наружу, сделайте следующее:

Сначала нарисуйте внешнюю форму (черныйобласть ниже), затем сместите внутреннюю форму наружу настолько, насколько вам нужно, и нарисуйте ее поверх внешней формы (коричневая область ниже), используя соответствующую схему шума / цвета:

gradient 1/3

Затем примените меньшее смещение, затем нарисуйте эту форму сверху, используя другую схему шума / цвета (оранжевая область внизу).

gradient 2/3

Повторяйте, пока у вас не будет столько градиентов, сколько вам нужно:

all gradients

Наконец, нарисуйте внутреннюю форму без какого-либо смещения с помощьюего шумовая / цветовая схема:

gradient plus inner shape

...