【问题标题】:find point where barycentric weights have a specific value找到重心权重具有特定值的点
【发布时间】:2013-11-28 17:36:27
【问题描述】:

我有三角形:abc。每个顶点都有一个值:vavbvc。在我的软件中,用户在这个三角形的内外拖动点p。我使用重心坐标根据vavbvc 确定p 处的值vp。到目前为止,一切顺利。

现在我想限制p 使vpminmax 范围内。如果用户选择p,其中vp 是min 或> max,我如何找到最接近p 的点,其中vp 分别等于minmax

编辑:这是我测试每个点的示例。浅灰色在min/max 内。如何找到构成min/max 边界的线的方程?

a = 200, 180
b = 300, 220
c = 300, 300
va = 1
vb = 1.4
vc = 3.2
min = 0.5
max = 3.5

编辑: FWIW,到目前为止,首先我使用三角形顶点 abc 获得 p 的重心坐标 vw(标准我想的东西,但看起来像this)。然后获取vp

u = 1 - w - v
vp = va * u + vb * w + vc * v

没关系。我的麻烦是我需要min/max 的直线方程,所以当vp 超出范围时,我可以为p 选择一个新位置。 p 的新位置是最小或最大线上最接近 p 的点。

请注意,p 是 XY 坐标,vp 是由三角形和每个顶点的值确定的坐标值。 minmax 也是值。我需要的两条线方程将给我 XY 坐标,由三角形确定的值是 minmax

解决方案中是否使用重心坐标无关紧要。

【问题讨论】:

    标签: geometry


    【解决方案1】:

    诀窍是使用值与笛卡尔距离的比率来扩展每个三角形边缘,直到达到最小值或最大值。用图片更容易看到:

    青色线显示三角形边缘是如何延伸的,绿色 X 是最小或最大线上的点。只需其中 2 个点,我们就知道直线的斜率。黄线表示连接 X 与浅灰色对齐。

    数学是这样的,首先得到vb和vc之间的值距离: valueDistBtoC = vc - vb

    然后得到b到c的笛卡尔距离: CartesianDistBtoC = b.distance(c)

    然后得到从b到max的值距离: valueDistBtoMax = max - vb

    现在我们可以交叉乘法得到从 b 到 max 的笛卡尔距离: CartesianDistBtoMax = (valueDistBtoMax * cartesianDistBtoC) / valueDistBtoC

    对 min 以及 a,b 和 c,a 执行相同的操作。这6个点足以限制p的位置。

    【讨论】:

      【解决方案2】:

      假设您的三角形实际上是一个 3D 三角形,具有点 (ax,ay,va)(bx,by,vb)(cx,cy,vc)。这三个点定义了一个平面,包含通过重心插值获得的所有可能的p,vp 三元组。

      现在将您的约束视为另外两个平面,z>=maxz<=min。这些平面中的每一个都沿着无限线与您的三角形平面相交;它们之间的无限光束,向下投影到 xy 平面,表示满足约束的点的区域。一旦你有了线(向下投影),你就可以找到哪个(如果有的话)被特定点违反,并将其移动到该约束上(沿着垂直于约束的向量)。

      不过,现在我不确定你的六边形。这不是我所期望的形状。

      【讨论】:

      • 您在 3D 中的思考方式似乎是正确的,但很难将解决方案转化为代码。我已经用解决方案的可能线索更新了这个问题。我很想听听您对此的看法。感谢您的帮助!
      【解决方案3】:

      从数学上讲,这个问题只是坐标的变化。更困难的部分是为所涉及的数量找到一个好的符号。

      您有两个坐标系统:(x,y) 是您的显示器的笛卡尔坐标,(v,w) 是相对于向量 (c-a),(b-a) 的重心坐标,它们确定另一个(非正交) 系统。

      你只需要在 (x,y) 系统中找到两条线的方程,然后将点 p 投影到这些线上就很容易了。

      要实现这一点,您可以明确地找到从 (x,y) 坐标传递到 (v,w) 坐标并返回的矩阵。您正在使用的函数toBaryCoords 进行此计算以从 (x,y) 中找到坐标 (v,w),我们可以重用该函数。 我们想要找到从 世界 坐标 (x,y) 到 重心 坐标 (v,w) 的变换系数。格式必须是

      v = O_v + x_v * x + y_v * y

      w = O_w + x_w * x + y_w * y

      (v,w) = (O_v,O_w) + (x_v,y_y) * (x,y)

      你可以通过计算toBaryCoord(0,0)来确定(O_v,O_w),然后通过计算(1,0)的坐标找到(x_v,x_w),找到(y_v,y_w)=toBaryCoord(1, 0) - (O_v,O_w) 然后通过计算 (y_v,y_w) = toBaryCoord(0,1)-(O_v,O_w) 找到 (y_v,y_w)。

      此计算需要调用 toBaryCoord 三次,但实际上每次都在该例程中计算系数,因此您可以修改它以一次计算所有六个值。

      你的函数 vp 的值可以计算如下。我将使用 f 而不是 v 因为我们使用 v 作为重心坐标。因此,以下我的意思是 f(x,y) = vp, fa = va, fb = vb, fc = vc。

      你有:

      f(v,w) = fa + (fb-fa)*v + (fc-fa)*w

      f(x,y) = fa + (fb-fa) (O_v + x_v * x + y_v * y) + (fc-fa) (O_w + x_w * x + y_w * y)

      其中 (x,y) 是您的点 p 的坐标。您可以通过插入三个顶点 a、b、c 的坐标来检查该等式的有效性,并验证您是否获得了三个值 fa、fb 和 fc。请记住,a 的重心坐标是 (0,0),因此 O_v + x_v * a_x + y_v * a_y = 0 等等...(a_x 和 a_y 是点 a 的 x,y 坐标)。

      如果你让

      q = fa + (fb_fa)*O_v + (fc-fa)*O_w

      fx = (fb-fa)*x_v + (fc-fa) * x_w

      fy = (fb-fa)*y_v + (fc-fa) * y_w

      你得到

      f(x,y) = q + fx*x + fy * y

      请注意,q、fx 和 fy 可以从 a,b,c,fa,fb,fc 计算一次,如果您只更改点 p 的坐标 (x,y),则可以重复使用它们。

      现在如果 f(x,y)>max,您可以轻松地将 (x,y) 投影到达到 max 的那条线上。投影坐标为:

      (x',y') = (x,y) - [(x,y) * (fx,fy) - max + q]/[(fx,fy) * (fx,fy)] (fx ,fy)

      现在。您想拥有代码。那么这里有一些-代码:

      toBarycoord(Vector2(0,0),a,b,c,O);
      toBarycoord(Vector2(1,0),a,b,c,X);
      toBarycoord(Vector2(0,1),a,b,c,Y);
      X.sub(O); // X = X - O
      Y.sub(O); // Y = Y - O
      
      V = Vector2(fb-fa,fc-fa);
      
      q =  fa + V.dot(O); // q = fa + V*O
      N = Vector2(V.dot(X),V.dot(Y)); // N = (V*X,V*Y)
      
      // p is the point to be considered
      
      f = q + N.dot(p); // f = q + N*p
      
      if (f > max) {
        Vector2 tmp;
        tmp.set(N);
        tmp.multiply((N.dot(p) - max + q)/(N.dot(N))); // scalar multiplication
        p.sub(tmp);
      }
      
      if (f < min) {
        Vector2 tmp;
        tmp.set(N);
        tmp.multiply((N.dot(p) - min + q)/(N.dot(N))); // scalar multiplication
        p.sum(tmp);
      }
      

      【讨论】:

      • 这看起来很棒,所以你得到了 500 代表的赏金。谢谢!
      【解决方案4】:

      我们认为问题如下:这三个点被解释为一个漂浮在 3D 空间中的三角形,其值为 Z 轴,笛卡尔坐标分别映射到 X 轴和 Y 轴。

      那么问题是找到由三个点定义的平面的梯度。平面与z = minz = max 平面相交的线是您要限制点的线。

      如果你找到了一个点 p,其中 v(p) > max 或 v(p) v(p + k * g) = max 或 min。 g 是渐变的方向,k 是我们需要找到的因子。您要查找的坐标(在笛卡尔坐标中)是p + k * g 的对应分量。

      为了确定g,我们使用叉积计算垂直于由三个点确定的平面的正交向量:

      // input:  px, py, pz, 
      // output: p2x, p2y
      
      // local variables
      var v1x, v1y, v1z, v2x, v2y, v2z, nx, ny, nz, tp, k,
      
      // two vectors pointing from b to a and c respectively
      v1x = ax - bx;
      v1y = ay - by;
      v1z = az - bz;
      
      v2x = cx - bx;
      v2y = cy - by;
      v2z = cz - bz;
      
      // the cross poduct
      nx = v2y * v1z - v2z * v1y;
      ny = v2z * v1x - v2x * v1z;
      nz = v2x * v1y - v2y * v1x;
      
      // using the right triangle altitude theorem
      // we can calculate the vector that is perpendicular to n
      // in our triangle we are looking for q where p is nz, and h is sqrt(nx*nx+ny*ny)
      // the theorem says p*q = h^2 so p = h^2 / q  - we use tp to disambiguate with the point p - we need to negate the value as it points into the opposite Z direction
      tp = -(nx*nx + ny*ny) / nz;
      
      // now our vector g = (nx, ny, tp) points into the direction of the steepest slope 
      // and thus is perpendicular to the bounding lines
      
      // given a point p (px, py, pz) we can now calculate the nearest point p2 (p2x, p2y, p2z) where min <= v(p2z) <= max
      
      if (pz > max){
        // find k
        k = (max - pz) / tp;
        p2x = px + k * nx;
        p2y = py + k * ny;
        // proof: p2z = v = pz + k * tp = pz + ((max - pz) / tp) * tp = pz + max - pz = max
      } else if (pz < min){
        // find k
        k = (min - pz) / tp;
        p2x = px + k * nx;
        p2y = py + k * ny;
      } else {
        // already fits
        p2x = px;
        p2y = py;
      }
      

      请注意,显然如果三角形是垂直方向的(在 2D 中,它实际上不再是三角形),nz 变为零,tp 无法计算。这是因为不再有两条线的值分别为最小值或最大值。对于这种情况,您必须在剩余的线或点上选择另一个值。

      【讨论】:

        猜你喜欢
        • 2015-08-29
        • 1970-01-01
        • 2012-09-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-07
        • 1970-01-01
        相关资源
        最近更新 更多