https://youtu.be/7yY3MIyRtPw

не не хватает GraphicsPath в Unity (чтобы заполнить многоугольник, нарисовать его, а также обрисовать в общих чертах и ​​утилиты с формами в целом), поэтому я делаю свою собственную реализацию этого. Ну, мы могли бы также обсудить, какой вариант лучше, но на самом деле я предпочитаю это, потому что я многому учусь.

Идея заключается в следующем: для полигона мы делаем многоугольник смещения (внутрь и наружу) с помощью ClipperLib, а затем с помощью LibTessDotNet мы триангулируем его, выводя это:

Зеленый, синий и желтый пиксели являются сторонами каждого треугольника. LibTessDotNet выводит как 501 треугольник для этой фигуры.

Итак, благодаря@SimpleVar я сделалэто:

public static IEnumerable<T> PointsInTriangle<T>(T pt1, T pt2, T pt3)
   where T : IPoint
{
    /*
         // https://www.geeksforgeeks.org/check-whether-triangle-valid-not-sides-given/
         a + b > c
         a + c > b
         b + c > a
     */

    float a = Vector2.Distance(new Vector2(pt1.x, pt1.y), new Vector2(pt2.x, pt2.y)),
          b = Vector2.Distance(new Vector2(pt2.x, pt2.y), new Vector2(pt3.x, pt3.y)),
          c = Vector2.Distance(new Vector2(pt3.x, pt3.y), new Vector2(pt1.x, pt1.y));

    // (new[] { pt1, pt2, pt3 }).Distinct(new PointComparer()).Count() == 0
    if (a + b <= c || a + c <= b || b + c <= a)
    {
        Debug.LogWarning($"The given points must form a triangle. {{{pt1}, {pt2}, {pt3}}}");
        yield break;
    }

    T tmp;

    if (pt2.x < pt1.x)
    {
        tmp = pt1;
        pt1 = pt2;
        pt2 = tmp;
    }

    if (pt3.x < pt2.x)
    {
        tmp = pt2;
        pt2 = pt3;
        pt3 = tmp;

        if (pt2.x < pt1.x)
        {
            tmp = pt1;
            pt1 = pt2;
            pt2 = tmp;
        }
    }

    var baseFunc = CreateFunc(pt1, pt3);
    var line1Func = pt1.x == pt2.x ? (x => pt2.y) : CreateFunc(pt1, pt2);

    for (var x = pt1.x; x < pt2.x; ++x)
    {
        int maxY;
        int minY = GetRange(line1Func(x), baseFunc(x), out maxY);

        for (int y = minY; y <= maxY; ++y)
            yield return (T)Activator.CreateInstance(typeof(T), x, y);
    }

    var line2Func = pt2.x == pt3.x ? (x => pt2.y) : CreateFunc(pt2, pt3);

    for (var x = pt2.x; x <= pt3.x; ++x)
    {
        int maxY;
        int minY = GetRange(line2Func(x), baseFunc(x), out maxY);

        for (int y = minY; y <= maxY; ++y)
            yield return (T)Activator.CreateInstance(typeof(T), x, y);
    }
}

private static int GetRange(float y1, float y2, out int maxY)
{
    if (y1 < y2)
    {
        maxY = Mathf.FloorToInt(y2);
        return Mathf.CeilToInt(y1);
    }

    maxY = Mathf.FloorToInt(y1);
    return Mathf.CeilToInt(y2);
}

private static Func<int, float> CreateFunc<T>(T pt1, T pt2)
    where T : IPoint
{
    var y0 = pt1.y;

    if (y0 == pt2.y)
        return x => y0;

    float m = (float)(pt2.y - y0) / (pt2.x - pt1.x);

    return x => m * (x - pt1.x) + y0;
}

На самом деле это работает, но не слишком хорошо. Потому что это вызывает переполнение (мне приходится убивать процесс Unity с помощью Process Explorer из-за большого объема ОЗУ, используемого этим кодом).

Я отлаживал эту вещь с помощью точек останова, но я не могу понять, где проблема на самом деле.

Я думаю, что проблема вfor (var x = pt1.x; x < pt2.x; ++x) или жеfor (int y = minY; y <= maxY; ++y) или в следующем блоке ... Но, как я уже сказал, я не могу отлаживать, как я привык к WinForms. Когда переполнение достигнуто, Visual Studio прекращает отладку и происходит сбой Unity, поэтому я немного застрял.

Я пытался сделать DotNetFiddle переполнением, но я ничего не могу понять здесь ... Итак ... Я не знаю, что я могу сделать, чтобы улучшить код.

Объясните мне, что все, что вы найдете, неоптимизировано, а также подходы, которые я мог бы сделать, чтобы улучшить мою главную цель.

Ответы на вопрос(1)

Ваш ответ на вопрос