Geometry 找到重心权重具有特定值的点
我有三角形:Geometry 找到重心权重具有特定值的点,geometry,Geometry,我有三角形:a,b,c。每个顶点都有一个值:va,vb,vc。在我的软件中,用户在三角形内外拖动点p。我使用重心坐标,根据va、vb和vc确定p处的值vp。到目前为止,一切顺利 现在我想限制p,使vp在min和max范围内。如果用户选择p,其中vp是min或>max,我如何找到距离p最近的点,其中vp分别等于min或max 编辑:以下是我测试每个点的示例。浅灰色在min/max范围内。我如何找到构成min/max边界的线的方程式 a = 200, 180 b = 300, 220 c = 300
a
,b
,c
。每个顶点都有一个值:va
,vb
,vc
。在我的软件中,用户在三角形内外拖动点p
。我使用重心坐标,根据va
、vb
和vc
确定p
处的值vp
。到目前为止,一切顺利
现在我想限制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
编辑:FWIW,到目前为止,首先我使用三角形顶点a
,b
,c
(我认为是标准的东西,但看起来很像)得到p
的重心坐标。然后获取vp
:
u = 1 - w - v
vp = va * u + vb * w + vc * v
那很好。我的问题是,我需要min
/max
的直线方程,以便在vp
超出范围时为p
选择一个新位置。p
的新位置是最小或最大行上距离p
最近的点
请注意,p
是XY坐标,vp
是由三角形和每个顶点的值确定的坐标值min
和max
也是值。我需要的两个直线方程将为我提供XY坐标,三角形确定的值为min
或max
在解决方案中是否使用重心坐标并不重要。将您的三角形视为实际的三维三角形,具有点
(ax,ay,va)
,(bx,by,vb)
,和(cx,cy,vc)
。这三个点定义了一个平面,包含通过重心插值获得的所有可能的p,vp
三元组
现在将约束想象为另外两个平面,在
z>=max
和z处,技巧是使用值与笛卡尔距离的比率来延伸每个三角形边,直到它达到最小值或最大值。使用图片更容易看到:
青色线显示三角形边是如何延伸的,绿色X是最小线或最大线上的点。只有其中两个点,我们知道直线的斜率。黄色线表示连接Xs与浅灰色对齐
数学原理如下,首先得到vb和vc之间的值距离:
valueDistBtoC=vc-vb
然后得到从b到c的笛卡尔距离:
cartesianDistBtoC=b.距离(c)
然后获取从b到最大值的距离值:
valueDistBtoMax=max-vb
现在我们可以交叉乘法得到从b到max的笛卡尔距离:
cartesianDistBtoMax=(valueDistBtoMax*cartesianDistBtoC)/valueDistBtoC
对min和a、b和c、a执行相同的操作。这6个点足以限制p的位置。从数学上讲,问题只是坐标的变化。更困难的部分是为所涉及的量找到一个好的符号
有两个坐标系:(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
i、 e
(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
i、 e
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\U fa)*O\U v+(fc fa)*O\U w
外汇=(固定资产净值)*x_v+(固定资产净值)*x_w
财政年度=(固定资产净值)*固定资产净值+(固定资产净值)*固定资产净值
你得到
f(x,y)=q+fx*x+fy*y
请注意,可以从a、b、c、fa、fb、fc计算一次q、fx和fy,如果只更改点p的坐标(x、y),则可以重用它们
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);
}
// 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;
}