找到重心权重具有特定值的点

时间:2013-11-28 17:36:28

标签: geometry

我有三角形:abc。每个顶点都有一个值:vavbvc。在我的软件中,用户在此三角形的内部和外部拖动点p。我使用重心坐标根据vppva确定vb处的值vc。到目前为止,非常好。

现在我想限制p,以便vpminmax范围内。如果用户选择p,其中vp是< min max或> p,我怎样才能找到最接近vp的点,其中min分别等于maxmin

编辑:以下是我测试每个点的示例。浅灰色在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 边界的线的方程?

example

v

修改:FWIW,到目前为止我首先使用三角形顶点w得到p的重心坐标ab,{ {1}},c(我认为是标准内容,但看起来像this)。然后获得vp

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

一切都很好。我的麻烦在于我需要min / max的线方程,因此当p超出范围时,我可以选择vp的新位置。 p的新位置是最小或最大线上距p最近的点。

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

如果在解决方案中使用重心坐标,则无关紧要。

4 个答案:

答案 0 :(得分:5)

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

enter image description here

青色线显示三角形边缘的延伸方式,绿色Xs是最小或最大线条上的点。只有这两个点,我们知道线的斜率。黄色线条表示连接Xs与浅灰色对齐。

数学运算方式如下,首先得到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的位置。

答案 1 :(得分:4)

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

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

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

答案 2 :(得分:2)

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

你有两个坐标系:(x,y)是显示器的笛卡尔坐标,(v,w)是相对于矢量(ca)的圆心坐标,(ba)确定另一个(非正交) )系统。

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

要实现这一点,您可以明确地找到要从(x,y)坐标传递到(v,w)坐标并返回的矩阵。您正在使用toBaryCoords的函数进行此计算以从(x,y)中找到坐标(v,w),并且我们可以重用该函数。 我们想要找到从 world 坐标(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作为baricenter坐标。因此,在下文中,我的意思是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)> gt; max,您可以轻松地在达到最大值的行上投影(x,y)。投影的坐标是:

(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);
}

答案 3 :(得分:2)

我们想到的问题如下:三个点被解释为一个三角形漂浮在3D空间取值为Z轴,并映射到X轴的直角坐标和Y轴分别。

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

如果你找到了一个点p,其中v(p)&gt; max或v(p)&lt;我们需要朝着最陡的斜坡(渐变)方向前进,直到v(p + k * g) = max或分钟。 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。这是因为不再有两行,其中值分别为最小值或最大值。在这种情况下,您必须在剩余的线或点上选择另一个值。