我需要从线段绘制三角形 - 如何找到中心点?
I need to draw a triangle from a line segment - How do I find the center point?
在我的 javascript 应用程序中,我有一条线段 - 基本上是 canvas 上的两个已知点。我需要从最大线是两个点并且两条匹配线是从中心点到边缘的那些点动态绘制一个钝角等腰三角形。
所以我想问题是,如何找到任意两个给定点之间的中心点?
我对 javascript 没意见,但对数学不太满意。对于这个问题,我能找到的每个现实世界的答案都提到了一个指南针,但我不确定它是如何转化为代码的?我可以画线,只是找不到重点。感谢您的帮助!
在大多数情况下,在二维坐标中工作时,这一切都可以通过基本代数来完成。您需要确定原始直线的中心点和斜率,根据这两条信息,您可以轻松绘制垂直点。
寻找中心点
要找到两点之间的中心点,您应该能够得到各自的 x 和 y 坐标之间的差异并除以二,然后将其添加到起始值:
function getCenterPoint(a, b) {
return { x: (b.x - a.x) / 2 + a.x, y: (b.y - a.y) / 2 + a.y };
}
var p1 = { x: 10, y: 10 }
var p2 = { x: 90, y: 40 }
var center = getCenterPoint(pt1, pt2); // { x: 50, y: 25 }
求斜率
你可以在它的 运行 上上升的线的斜率:
function getSlope(a, b) {
return (b.y - a.y) / (b.x - a.x);
}
var slope = getSlope(p1, p2);
要获得垂直斜率,您可以取反并反转它:
var perpendicularSlope = -(1 / slope);
使用斜率绘制点
您现在可以在垂直于中心点的线上绘制任意点。在您的示例中,要超出您的线,您使用小于中心点的 x 值,要低于您的线,您使用大于您的中心点的 x 值。要确定 y 值,请将斜率乘以 x 值。
var pAbove = { x: center.x - 10, y: (center.x - 10) * perpendicularSlope };
var pBelow = { x: center.x + 10, y: (center.x + 10) * perpendicularSlope };
让我们更简单地尝试一下,只用线性代数和几何
生成等腰三角形
您正在寻找的点与您已有的两个点等距(这就是 "isosceles" 的意思)。因此它在 the bisector (the line perpendicular to the segment and cutting it in two equal halves) :
(来源:free.fr)
线段 [BC] 的正交向量 u
是 ( -(c.y-b.y), c.x-b.x )
,因此所有具有 t 任意标量(即数字)的 A = I + t * u
形式的点,用 B
和 C
组成一个等腰三角形。
为了构建这个向量 u
,我们采用 [BC] 段的方向,由从 B 到 C 的向量给出,(c.x-b.x, c.y-b.y)
,我们知道对于任何向量 (x,y)
,矢量 (-y,x)
垂直于它:尝试它们之间的标量积。
I
的坐标是微不足道的:B 和 C ( (b.x + c.x)/2, (b.y + c.y)/2 )
的平均值(实际上是重心)
让他们变钝
为了使角度为钝角,距离 AB
和 AC
(相同)必须小于 A 处的角度为 90° 的值.
当A的角度为90°时,我们要看AIC三角形。它在 A 中的角是 90°/2=45°,因为它在 I 中的角是 90°,三角形内角的总和总是 180°,所以 AIC 在 C 中的角也是 45°。两个相等的角就像两条相等的边一样,是等腰三角形的特征。
因此,AI = IC
并且由于 IC = BC / 2
,AI
的限制值为 BC / 2
。
所以现在我们必须选择 t
使得 AI < BC / 2
,其中 AI = abs(t) * |u|
.
请记住,我们没有为 u
采用归一化向量,所以
|u| = sqrt( (-c.y+b.y)^2 + (c.x-b.x)^2 )
,
我们还有 BC = sqrt( (b.x-c.x)^2 + (c.y-b.y)^2 )
,因此 |u| = BC
.
所以我们可以得出结论abs(t) < BC / (2 * |u|) = 1/2
。
最终算法:越简单越好
- 在
[-0.5,0]
或 [0,0.5]
之间选择一个 t
,不包括边界。
a.x = (b.x-c.x)/2 - t*(c.y-b.y)
a.y = (b.y+c.y)/2 + t*(c.x-b.x)
最后一点,试试看:
function draw()
{
var t = parseFloat(document.getElementById('t').value);
a.x = (b.x+c.x)/2 - t*(c.y-b.y);
a.y = (b.y+c.y)/2 + t* (c.x-b.x);
// end of the math, do the drawing
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.moveTo(a.x,a.y);
ctx.lineTo(b.x,b.y);
ctx.lineTo(c.x,c.y);
ctx.closePath();
ctx.stroke();
}
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
var b = {x:420, y:190}, c = {x:50, y:160}, a = {x:0, y:0};
ctx.fillRect(b.x,b.y,2,2);
ctx.fillRect(c.x,c.y,2,2);
document.getElementById('t').onchange = draw;
draw();
<p>t=<input type="text" id ="t" value="0.2" /></p>
<canvas id="c" width="500" height="300" />
在我的 javascript 应用程序中,我有一条线段 - 基本上是 canvas 上的两个已知点。我需要从最大线是两个点并且两条匹配线是从中心点到边缘的那些点动态绘制一个钝角等腰三角形。
所以我想问题是,如何找到任意两个给定点之间的中心点?
我对 javascript 没意见,但对数学不太满意。对于这个问题,我能找到的每个现实世界的答案都提到了一个指南针,但我不确定它是如何转化为代码的?我可以画线,只是找不到重点。感谢您的帮助!
在大多数情况下,在二维坐标中工作时,这一切都可以通过基本代数来完成。您需要确定原始直线的中心点和斜率,根据这两条信息,您可以轻松绘制垂直点。
寻找中心点
要找到两点之间的中心点,您应该能够得到各自的 x 和 y 坐标之间的差异并除以二,然后将其添加到起始值:
function getCenterPoint(a, b) {
return { x: (b.x - a.x) / 2 + a.x, y: (b.y - a.y) / 2 + a.y };
}
var p1 = { x: 10, y: 10 }
var p2 = { x: 90, y: 40 }
var center = getCenterPoint(pt1, pt2); // { x: 50, y: 25 }
求斜率
你可以在它的 运行 上上升的线的斜率:
function getSlope(a, b) {
return (b.y - a.y) / (b.x - a.x);
}
var slope = getSlope(p1, p2);
要获得垂直斜率,您可以取反并反转它:
var perpendicularSlope = -(1 / slope);
使用斜率绘制点
您现在可以在垂直于中心点的线上绘制任意点。在您的示例中,要超出您的线,您使用小于中心点的 x 值,要低于您的线,您使用大于您的中心点的 x 值。要确定 y 值,请将斜率乘以 x 值。
var pAbove = { x: center.x - 10, y: (center.x - 10) * perpendicularSlope };
var pBelow = { x: center.x + 10, y: (center.x + 10) * perpendicularSlope };
让我们更简单地尝试一下,只用线性代数和几何
生成等腰三角形
您正在寻找的点与您已有的两个点等距(这就是 "isosceles" 的意思)。因此它在 the bisector (the line perpendicular to the segment and cutting it in two equal halves) :
(来源:free.fr)
线段 [BC] 的正交向量 u
是 ( -(c.y-b.y), c.x-b.x )
,因此所有具有 t 任意标量(即数字)的 A = I + t * u
形式的点,用 B
和 C
组成一个等腰三角形。
为了构建这个向量 u
,我们采用 [BC] 段的方向,由从 B 到 C 的向量给出,(c.x-b.x, c.y-b.y)
,我们知道对于任何向量 (x,y)
,矢量 (-y,x)
垂直于它:尝试它们之间的标量积。
I
的坐标是微不足道的:B 和 C ( (b.x + c.x)/2, (b.y + c.y)/2 )
让他们变钝
为了使角度为钝角,距离 AB
和 AC
(相同)必须小于 A 处的角度为 90° 的值.
当A的角度为90°时,我们要看AIC三角形。它在 A 中的角是 90°/2=45°,因为它在 I 中的角是 90°,三角形内角的总和总是 180°,所以 AIC 在 C 中的角也是 45°。两个相等的角就像两条相等的边一样,是等腰三角形的特征。
因此,AI = IC
并且由于 IC = BC / 2
,AI
的限制值为 BC / 2
。
所以现在我们必须选择 t
使得 AI < BC / 2
,其中 AI = abs(t) * |u|
.
请记住,我们没有为 u
采用归一化向量,所以
|u| = sqrt( (-c.y+b.y)^2 + (c.x-b.x)^2 )
,
我们还有 BC = sqrt( (b.x-c.x)^2 + (c.y-b.y)^2 )
,因此 |u| = BC
.
所以我们可以得出结论abs(t) < BC / (2 * |u|) = 1/2
。
最终算法:越简单越好
- 在
[-0.5,0]
或[0,0.5]
之间选择一个t
,不包括边界。 a.x = (b.x-c.x)/2 - t*(c.y-b.y)
a.y = (b.y+c.y)/2 + t*(c.x-b.x)
最后一点,试试看:
function draw()
{
var t = parseFloat(document.getElementById('t').value);
a.x = (b.x+c.x)/2 - t*(c.y-b.y);
a.y = (b.y+c.y)/2 + t* (c.x-b.x);
// end of the math, do the drawing
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.moveTo(a.x,a.y);
ctx.lineTo(b.x,b.y);
ctx.lineTo(c.x,c.y);
ctx.closePath();
ctx.stroke();
}
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
var b = {x:420, y:190}, c = {x:50, y:160}, a = {x:0, y:0};
ctx.fillRect(b.x,b.y,2,2);
ctx.fillRect(c.x,c.y,2,2);
document.getElementById('t').onchange = draw;
draw();
<p>t=<input type="text" id ="t" value="0.2" /></p>
<canvas id="c" width="500" height="300" />