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