我有三角形:a
,b
,c
。每个顶点都有一个值:va
,vb
,vc
。在我的软件中,用户在此三角形的内部和外部拖动点p
。我使用重心坐标根据vp
,p
和va
确定vb
处的值vc
。到目前为止,非常好。
现在我想限制p
,以便vp
在min
和max
范围内。如果用户选择p
,其中vp
是< min
max
或> p
,我怎样才能找到最接近vp
的点,其中min
分别等于max
或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
边界的线的方程?
v
修改:FWIW,到目前为止我首先使用三角形顶点w
得到p
的重心坐标a
,b
,{ {1}},c
(我认为是标准内容,但看起来像this)。然后获得vp
:
u = 1 - w - v
vp = va * u + vb * w + vc * v
一切都很好。我的麻烦在于我需要min
/ max
的线方程,因此当p
超出范围时,我可以选择vp
的新位置。 p
的新位置是最小或最大线上距p
最近的点。
请注意,p
是XY坐标,vp
是由三角形和每个顶点的值确定的坐标值。 min
和max
也是值。我需要的两个线方程将给出XY坐标,三角形确定的值为min
或max
。
如果在解决方案中使用重心坐标,则无关紧要。
答案 0 :(得分:5)
诀窍是使用值与笛卡尔距离的比率来扩展每个三角形边缘,直到达到最小值或最大值。用图片更容易看到:
青色线显示三角形边缘的延伸方式,绿色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>=max
和z<=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 = min
和z = 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
。这是因为不再有两行,其中值分别为最小值或最大值。在这种情况下,您必须在剩余的线或点上选择另一个值。