Задать вопрос
  • Как составить итерационное уравнение для барицентрических координат?

    @SergeySerge11 Автор вопроса
    Как-то так решил.
    public struct BarycentricInterpolateColor
      {
    
          BaricentricLinearV bar; 
          public Vector3 color;
          public Vector3 c ;
          private Vector3 dfx;
          private Vector3 dfy; 
          public BaricentricInterpolateColor(Vector2 p0, Vector2 p1, Vector2 p2,Vector3 cv0,Vector3 cv1,Vector3 cv2 )
          { 
              bar = new BaricentricLinearV(p0, p1, p2);   
              var p= new Vector2(0,0);
              var w0 = (p1.Y - p2.Y) * (p.X - p2.X) + (p2.X - p1.X) * (p.Y - p2.Y);
              var w1 = (p2.Y - p0.Y) * (p.X - p2.X) + (p0.X - p2.X) * (p.Y - p2.Y);
              var d = (p1.Y - p2.Y) * (p0.X - p2.X) + (p2.X - p1.X) * (p0.Y - p2.Y);
              w0 /= d;
              w1 /= d;
              var w2 = 1f - w0 - w1;  
            // находим  вектора для решения уравнения f(x,y) = kx*x+ky*y + c
              var b = (cv0 * w0 + cv1 * w1 + cv2 * w2);
              color = b;
              c = b; 
    
              dfx = (cv0 * (p1.Y - p2.Y)  + cv1 * (p2.Y - p0.Y)  + cv2 * (1f- (p1.Y - p0.Y)  ))/d;
              dfy = (cv0 * (p2.X - p1.X)  + cv1 * (p0.X - p2.X)  + cv2 * (1f -(-p1.X + p0.X)))/d;
          }
    
          public void Setup(Vector2 leftTop )
          { 
               bar.Setup(leftTop);  
               color = dfy*leftTop.Y + c;
    
          }
    
          public bool IsInsideSafe
          {
              get
              {
                  unsafe
                  { 
                      return bar.IsInsideSafe;
                  }
    
              }
          }
          public void IncX()
          {
              bar.IncX();
              color += dfx;
          }
          public void IncY()
          {
              bar.IncY();
              color += dfy;
          } 
    
      }
    Ответ написан
  • Как разбить треугольник в прямоугольной области на N треугольников?

    @SergeySerge11 Автор вопроса
    Решил довольно 2 способами.
    1. Рекурсивный алгоритм Отсеканием по граням, Top -> Right -> Bottom -> Left ->...
    1. Запускаю функцию drawTriangle(a,b,c, Plane.Top); Начинаю обход с Верхнего разбиения.

    1. проверить все ли точки внутри, тогда нарисовать, выйти.
    2. Для каждой точки вычисляю маску ее положения как по Сазерленду, хотя я сам сначала такой способ битовой локализации знал.
    //x0 y0 x1 y1 координаты точек прямоугольника. 
                byte b0 = (byte)((p0.X < x0 ? 8 : 0) | (p0.X > x1 ? 4 : 0) | (p0.Y < y0 ? 2 : 0) | (p0.Y > y1 ? 1 : 0));
                byte b1 = (byte)((p1.X < x0 ? 8 : 0) | (p1.X > x1 ? 4 : 0) | (p1.Y < y0 ? 2 : 0) | (p1.Y > y1 ? 1 : 0));
                byte b2 = (byte)((p2.X < x0 ? 8 : 0) | (p2.X > x1 ? 4 : 0) | (p2.Y < y0 ? 2 : 0) | (p2.Y > y1 ? 1 : 0));

    3. По плоскости(линии) разрезания, перехожу к функции ее разрезания. Нахожу точки которые к ней относятся. Составляю из них маску.
    //  например  для верхней, взять те где y меньше y0.  то есть чекаю 2 бит
          int _btop = ((b0 & 2) >>1 ) | ((b1&2) ) | ((b2&2)<<1);

    4. В swith проверяю 8 комбинаций. (разрезаем треугольники, есть 2 типа разреза, на 2-1 и на 1-2 по сторонам)
    - Комбинация равная 0b111 = 7 означает что все 3 точки за плоскостью, завершить функцию
    -Комбинация 0b000 = 0 означает, что ни одной точки там нету, тогда повернуть по часовой стрелки, и перейти к 3.
    - Комбинации 1,2,4 означают что одна точка за плоскостью, она локализована значениями 1,2,4. Тогда разрезать на 2 треугольника. Нахожу точки пересечения с данной линии разреза, решаю простое уравнение прямой по 2 точкам, от этой точки, к 2 внутренним точки (a,b)=>(Ab'), (a,c)=>(Ac' ). Нахожу значение функции на пересечении с линией разрезании. то есть подставляю в функцию, для Top Bottom, считаю по y от y0,y1...
    public static float FunByX(float x,Vector2 p0, ,Vector2  p1){
        var dp = p1 - p0;
        return (dp.Y / dp.X) * (x - p0.X) + p0.Y;
    } 
    public static float FunByY(float y, ,Vector2 p0, ,Vector2  p1){}

    Вызываю рекурсивно 2 функции drawTriangle для новых вершин {Ab',Ac',C}, {Ab',a,b} c следующей по часовой стрелки линии разрезания Top-> Right.
    -Для комбинаций, 3,5,6 - 2 точки за линий разрезания. Делю на 1 треугольник, для точек a,b нахожу пересечение линий (a,c) (b,c) с линией разрезания Вызываю drawTriangle для точек {Ac', Bc', c} выхожу из функции.
    Так же способ масштабируется для деления по выпуклому 4 угольнику.
    Второй способ намного сложнее, куча if-ов что забываешь через минуту куда попал.

    66829e242df16739460020.png
    66829e00372ab320748590.png
    Ответ написан
  • У меня самый уродливый код на планете земля, как исправить?

    @SergeySerge11
    https://refactoring.guru/ru/design-patterns/catalog изучи теорию паттернов и рефакторинга, пожалуй это лучший курс и сайт по структуре кода. Там есть теория, плюс пример на всех языках программирования
    Ответ написан
    Комментировать