Задать вопрос
@SergeySerge11

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

Как составить уравнения ввида на основе барицентрических координат.
f(x+dx)= f(x) + f'(x)*dx
И вместо условно функции, которую нужно считывать допустим для точек (0,0) и (0,1)
public static Vector3 interopatateColor (Vector2 p0, Vector2 p1, Vector2 p2,  Vector2 p,  Vector3 c0,  Vector3 c1,  Vector3 c2)
  {
      float w0 = (p1.Y - p2.Y) * (p.X - p2.X) + (p2.X - p1.X) * (p.Y - p2.Y);
      float w1 = (p2.Y - p0.Y) * (p.X - p2.X) + (p0.X - p2.X) * (p.Y - p2.Y);
      float d =    (p1.Y - p2.Y) * (p0.X - p2.X) + (p2.X - p1.X) * (p0.Y - p2.Y);
      w0 /= d;
      w1 /= d; 
      float w2 = 1f - w0 - w1;  
      return  (c0 * w0 + c1 * w1 + c2 * w2);  // из этого же уравнения можно легко найти производные по x,y, 
  }

Получить что-то вроде
public static Vector3 IncX( Vector3 color_f, Vector3 inc_color)
  {
       return color_f+ inc_color;  
  }


Что бы для Точек P(x,y) и P(x+1,y) не пересчитывать все уравнение а просто инкрементировать производную.
Допустим есть такая функция, в цикле проходит по всем точкам слева, например простая оптимизация для проверки попадания точки, а я перечитал 100 учебников и не где не нашел, ускоряет любые базовые реализации из учебников в разы.
var bar  = new  BarycentricInterpolateColor(p0,p1,p2,c0,c1,c2);
 for (int y = 0; y < 650; y++)
 { 
     bar .Setup(new Vector2(0, y) ); // решить уравнение  от (0,y) найти начальный цвет 
     for (int x = 0; x < 750; x++)
     { 
        Vector2 p = new Vector2(x, y); 
         if ( barC.IsInsideSafe)  // проверить попадание точки, 
         {
             var c = barC.color;
             DrawPoint( p,  bar.Value);  
         }
         bar.IncX(); // инкрементировать  к примеру реализовал для проверки стороны таким способом, а как цвет 
   интерполировать.
     } 
 }

pubcliv struct   BarycentricInterpolateColor{
  BarycentricLinear   bar;
   //...  похожая логика для цветов вершин
}
 public struct BarycentricLinear  
 {
     
     internal Vector3 aX;
     internal Vector3 aY;
     internal Vector3 b;
     internal Vector3 c; 
     public Vector3 res=>b; // aX*x+bX*y+c;

     public BarycentricLinear(Vector2 p0, Vector2 p1,  Vector2 p2 )
     { 
       // CheckSide разбираем это уравнение, 
       // bool isInTriangle= (q.Y - p1.Y) * (p2.X - p1.X) > (q.X - p1.X) * (p2.Y - p1.Y);
       //выносит kx, ky,  c =   (- p1.Y) * (p2.X - p1.X) -(- p1.X) * (p2.Y - p1.Y);
         aX = new Vector3(calcKx(p0, p1), calcKx(p1, p2), calcKx(p2, p0));
         aY = new Vector3(calcKy(p0, p1), calcKy(p1, p2), calcKy(p2, p0));
         c = new Vector3(calcC(p0, p1), calcC(p1, p2), calcC(p2, p0));

     } 



     public void Setup(SKPoint leftTop)
     {
         b = aX * leftTop.X + aY * leftTop.Y + c;
     }
     public void IncX()
     {
         b += aX;
     }
     public void IncY()
     { 
         b += aY;
     }
     public bool IsInsideUnsafe
     {
         get
         {
             unsafe
             { 
                 return (((((*(int*)Unsafe.AsPointer(ref b.X)) ^ (*(int*)Unsafe.AsPointer(ref b.Y))) | ((*(int*)Unsafe.AsPointer(ref b.Y)) ^ (*(int*)Unsafe.AsPointer(ref b.Z))))) > 0);
             }

         }
     }
     public bool IsInsideSafe
     {
         get
         {
             unsafe
             {

                 return (b.X>0 == b.Y>0) && (b.Y > 0 == b.Z > 0);
             }

         }
     }



     private static float calcC(Vector2 p1, Vector2 p2)
   {
       return -p1.Y * (p2.X - p1.X) + p1.X * (p2.Y - p1.Y);
   }
   private static float calcKx(Vector2 p1,Vector2 p2)
   {
       return -(p2.Y - p1.Y);
   }
   private static float calcKy(Vector2 p1, Vector2 p2)
   {
       return (p2.X - p1.X);
   }
 }


https://codeplea.com/triangular-interpolation
  • Вопрос задан
  • 108 просмотров
Подписаться 1 Средний Комментировать
Пригласить эксперта
Ответы на вопрос 1
@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;
      } 

  }
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы