cx
给定圆心和cy
圆心圆的半径,如何绘制等边三角形?
我如何找到一个点是否在三角形内?
PS:我正在为 构建这个android
,但这个问题与语言无关。
cx
给定圆心和cy
圆心圆的半径,如何绘制等边三角形?
我如何找到一个点是否在三角形内?
PS:我正在为 构建这个android
,但这个问题与语言无关。
上图中的 C 点很简单,就是 (cx, cy + r)。
我可以想到两种相当简单的方法来获得点 a 和 b:
第一种方法:假设 (cx,cy) 是原点,将点 C 旋转 60 度和 120 度以获得 a 和 b。这可以通过以下公式来完成:
另请查看wikipedia 上的这篇文章。
第二种方法:画一条穿过 (cx, cy) 且斜率为 -30 度的线。该线与圆相交的地方将是点b。圆由以下等式定义:
( x - c.x )^2 + ( y - c.y )^2 = r^2
(注意,会有两个交点,所以选择正确的一个)。
然后对通过 (cx, cy) 的正 30 度角线执行相同操作,得到点 a。
你的线会有斜率:1 / sqrt(3) 和 -1 / sqrt(3)
一旦有了形成等边三角形的点 A、B 和 C,检测点 (x,y) 是否位于三角形中的最快和最简单的方法之一就是基于叉积和向量。
基本上,看看 (x,y) 是否在“向量”A->B 的左侧。然后看看它是否在B->C的左边。然后检查它是否在 C->A 的左侧。
此处引用的以下方法可让您检查点是否在向量的左侧。
public bool isLeft(Point A, Point B, Point C){
return ((B.x - A.x)*(C.y - A.y) - (B.y - A.y)*( C.x - A.x)) > 0;
}
在方法 A = line point1、b = line point2 和 c = 要检查的点。
对于任何只想在单位圆上获得等边三角形坐标的懒惰人(比如我):
A: (-0.866, -0.5)
B: (0.866, -0.5)
C: (0.0, 1.0)
对于不同的位置和/或半径,将所有值乘以r
,然后添加cx
到x
坐标和cy
s y
。
此刻,我只能回答你的第二个问题。只要您存储了定义三角形的点,就可以进行点线相交测试。您可以在计算机图形书籍中找到许多相关的算法。
编辑:我想了一种方法来解决您的基本问题(找到定义等边三角形的 3 个点,其中 cx、cy 和半径作为给定数据)。它依赖于任何三角形的 3 个角之和为 180 度的性质。我需要一些时间做进一步的检查,以确保它是正确的。然后,我将编辑我的答案以发布它。
编辑完整答案:此算法草图的实现依赖于您选择的编程语言和图形 API:
希望有帮助。我将尝试添加一些图纸以进一步阐明此方法的步骤。此外,我将对这些步骤进行编程和测试,以确保正确解决您的问题。
我需要使用 SVG 和 Javascript 绘制一个等边三角形...
我尝试了 Xantix 对第一个问题的回答,以便在给定中心点 (cx,cy) 和外接圆半径 (r) 的情况下绘制等边三角形,正如所指出的,这很容易解决点 C 的坐标 (cx, cy + r)。
但是,我无法弄清楚如何获得旋转方程来求解点 A 和 B 的任一坐标,因此我的解决方案如下。
数学时间 - 求解 x
假设 cx = 9, cy = 9, r = 6, 水平底。
首先,求三角形 (a,b,c) 的边长:
9r^2 = a^2 + b^2 + c^2
r^2 = 36, 9r^2 = 324, 324/3 = 108, sqrt(432) = 10.39
一旦我们知道三角形每一边的长度(s = 10.39),我们就可以计算 x 坐标。Bx (14.2) 将 s/2 (5.2) 加到 cx 中,Ax (3.8) 从 cx 中减去 s/2。
x 解决了现在需要 y
说到 s/2,如果我们将三角形垂直分成两半(从点 C 到点 A 和 B 之间的中点),我们可以求解 y(最终给我们 Ay 和 By):
a^2 + b^2 = c^2
a^2 + 27.04 (1/2 s squared) = 107.95 (length s squared)
a^2 = 80.91
sqrt(80.91) = 8.99
从 cy + r (15 - 8.99 = 6.01) 中减去这个 y 值,我们就得到了点 A 和 B 的新 y 图。
Center ( 9.00, 9.00)
C ( 9.00,15.00)
B (14.20, 6.01)
A ( 3.80, 6.01)
结论
一旦我们知道等边三角形的边长,就可以在给定中心点、外接圆半径和水平底边的情况下计算点坐标。
这是我在java(android)上绘制三角形的方法:
mA = new PointD();
mB = new PointD();
mC = new PointD();
mCos120 = Math.cos(AppHelper.toRadians(120));
mSin120 = Math.sin(AppHelper.toRadians(120));
mCos240 = Math.cos(AppHelper.toRadians(240));
mSin240 = Math.sin(AppHelper.toRadians(240));
double r = 30; // this is distance from the center to one of triangle's point.
mA.set(0 + r, 0);
mB.x = mA.x * mCos120 - mA.y * mSin120;
mB.y = mA.x * mSin120 + mA.y * mCos120;
mC.x = mA.x * mCos240 - mA.y * mSin240;
mC.y = mA.x * mSin240 + mA.y * mCos240;
mA = AppHelper.toScreenCoordinates(mCenterPoint, mA);
mB = AppHelper.toScreenCoordinates(mCenterPoint, mB);
mC = AppHelper.toScreenCoordinates(mCenterPoint, mC);
mPlayPath.reset();
mPlayPath.moveTo(mA.getX(), mA.getY());
mPlayPath.lineTo(mB.getX(), mB.getY());
mPlayPath.lineTo(mC.getX(), mC.getY());
mPlayPath.lineTo(mA.getX(), mA.getY());
mPlayPath.close();
public static PointD toScreenCoordinates(PointD center, PointD point) {
return new PointD(point.x + center.x, center.y - point.y);
}
其中 PointD 与 PointF 类似,但具有 double 类型。
这是我的Python实现,希望对您有所帮助:
def construct_eq_triangle(centroid, radius):
side_length = radius * math.sqrt(3)
# Calculate three vertices of the triangle
a = [centroid[0], centroid[1] + (math.sqrt(3) / 3) * side_length] # Top vertex
b = [centroid[0] - (side_length / 2), centroid[1] - (math.sqrt(3) / 6) * side_length] # Bottom left vertex
c = [centroid[0] + (side_length / 2), centroid[1] - (math.sqrt(3) / 6) * side_length] # Bottom right vertex
return a, b, c
您可以side_length
用任意值替换,也centroid
可以是带有 2 个元素的 atuple
或 a list
,第一个是 the x
,第二个是y
。