根据菱形的宽度和角度,获取菱形边缘的 X,Y 坐标
Get the X,Y coordinate at the edge of a rhombus, based on the rhombus' width and angle
我正在开发一个 Processing 草图,给定一个特定的角度,在菱形的边缘画一个点。
我知道菱形的宽度及其位置,但我不确定如何计算位于菱形边缘的点的 x-y 坐标。
这个问题有什么优雅的解决方案吗?欢迎任何有关伪代码的帮助。
根据您的图像,您想要找到两个方程的交集,即角度为 θ 的直线的交集,以及与它相交的正方形边的交集。
假设你的正方形的大小是n
,正方形的方程是y=±(n*(√2/2))±x
(根据毕达哥拉斯定理)。您在图像中相交的边的方程式是 y=n*(√2/2)-x
.
用三角函数可以计算出径向线的方程为y=tan(θ)*x
,其中θ以弧度表示
然后您可以将其求解为 simultaneous equation 以确定交点。请注意,它将与正方形的两侧(上方和下方)相交,因此如果您只想要一个,则必须选择正方形正确一侧的方程式。还要防止 θ 为 π/2 的情况,因为 tan(π/2) 未定义。你可以很容易地解决这种情况,因为 x=0,所以它总是在 y=±(n*(√2/2))
处相交。
在您的示例中,交集出现在 x*(1+tan(θ))=n*(√n/n)
或 x=(n*(√n/n))/(1+tan(θ))
时。您可以计算它,将其插回 y,这就是您的 (x,y) 交点。
设正方形的边长是A
,半边长是H = A/2
。角度Theta
。交点P.
所有坐标都是相对于正方形中心的。
将正方形旋转 -Pi/4
,角度 Alpha = Theta - Pi/4
if Alpha lies in range -Pi/4..Pi/4, then intersection point P' = (H, H*Tan(Alpha))
if Alpha lies in range Pi/4..3*Pi/4, then P' = (H*Cotangent(Alpha), H)
if Alpha lies in range 3*Pi/4..5*Pi/4, then P' = (-H, -H*Tan(Alpha))
if Alpha lies in range 5*Pi/4..7*Pi/4, then P' = (-H*Cotangent(Alpha), -H)
然后将点 P'
旋转 Pi/4
:
S = Sqrt(2)/2
P.X = S * (P'.X - P'.Y)
P.Y = S * (P'.X + P'.Y)
示例(数据类似于您的草图):
A = 200, Theta = 5*Pi/12
H = 200/2 = 100, Alpha =Theta-Pi/4 = Pi/6
P'.X = H = 100
P'.Y = H * Tan(Alpha) = 100 * Tan(Pi/6) ~= 57.7
S = 0.707
P.X = 0.707 * (100 - 57.7) = 30
P.Y = 0.707 * (100 + 57.7) = 111
想象一个半径较大的圆将在您想要的点与您的菱形相交。在该位置绘制的一种方法是使用您平移和旋转的嵌套坐标系。你只需要知道半径和角度。
这是一个非常基本的例子:
float angle = radians(-80.31);
float radius = 128;
float centerX,centerY;
void setup(){
size(320,320);
noFill();
rectMode(CENTER);
centerX = width * 0.5;
centerY = height * 0.5;
}
void draw(){
background(255);
noFill();
//small circle
strokeWeight(1);
stroke(95,105,120);
ellipse(centerX,centerY,210,210);
rhombus(centerX,centerY,210);
//large circle
strokeWeight(3);
stroke(95,105,120);
ellipse(centerX,centerY,radius * 2,radius * 2);
//line at angle
pushMatrix();
translate(centerX,centerY);
rotate(angle);
stroke(162,42,32);
line(0,0,radius,0);
popMatrix();
//debug
fill(0);
text("angle: " + degrees(angle),10,15);
}
void rhombus(float x,float y,float size){
pushMatrix();
translate(x,y);
rotate(radians(45));
rect(0,0,size,size);
popMatrix();
}
void mouseDragged(){
angle = atan2(centerY-mouseY,centerX-mouseX)+PI;
}
你可以试试这里的演示(你可以拖动鼠标改变角度):
var angle;
var radius = 128;
var centerX,centerY;
function setup(){
createCanvas(320,320);
noFill();
rectMode(CENTER);
angle = radians(-80.31);
centerX = width * 0.5;
centerY = height * 0.5;
}
function draw(){
background(255);
noFill();
//small circle
strokeWeight(1);
stroke(95,105,120);
ellipse(centerX,centerY,210,210);
rhombus(centerX,centerY,210);
//large circle
strokeWeight(3);
stroke(95,105,120);
ellipse(centerX,centerY,radius * 2,radius * 2);
//line at angle
push();
translate(centerX,centerY);
rotate(angle);
stroke(162,42,32);
line(0,0,radius,0);
pop();
//debug
fill(0);
noStroke();
text("angle: " + degrees(angle),10,15);
}
function rhombus(x,y,size){
push();
translate(x,y);
rotate(radians(45));
rect(0,0,size,size);
pop();
}
function mouseDragged(){
angle = atan2(centerY-mouseY,centerX-mouseX)+PI;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.0/p5.min.js"></script>
如果要计算位置,可以用极坐标转直角坐标的公式:
x = cos(angle) * radius
y = sin(angle) * radius
这是一个使用它的例子。请注意,绘图是从中心完成的,因此将中心坐标添加到上面:
float angle = radians(-80.31);
float radius = 128;
float centerX,centerY;
void setup(){
size(320,320);
noFill();
rectMode(CENTER);
centerX = width * 0.5;
centerY = height * 0.5;
}
void draw(){
background(255);
noFill();
//small circle
strokeWeight(1);
stroke(95,105,120);
ellipse(centerX,centerY,210,210);
rhombus(centerX,centerY,210);
//large circle
strokeWeight(3);
stroke(95,105,120);
ellipse(centerX,centerY,radius * 2,radius * 2);
//line at angle
float x = centerX+(cos(angle) * radius);
float y = centerX+(sin(angle) * radius);
stroke(162,42,32);
line(centerX,centerY,x,y);
//debug
fill(0);
text("angle: " + degrees(angle),10,15);
}
void rhombus(float x,float y,float size){
pushMatrix();
translate(x,y);
rotate(radians(45));
rect(0,0,size,size);
popMatrix();
}
void mouseDragged(){
angle = atan2(centerY-mouseY,centerX-mouseX)+PI;
}
另一种选择是使用变换矩阵
我正在开发一个 Processing 草图,给定一个特定的角度,在菱形的边缘画一个点。
我知道菱形的宽度及其位置,但我不确定如何计算位于菱形边缘的点的 x-y 坐标。
这个问题有什么优雅的解决方案吗?欢迎任何有关伪代码的帮助。
根据您的图像,您想要找到两个方程的交集,即角度为 θ 的直线的交集,以及与它相交的正方形边的交集。
假设你的正方形的大小是n
,正方形的方程是y=±(n*(√2/2))±x
(根据毕达哥拉斯定理)。您在图像中相交的边的方程式是 y=n*(√2/2)-x
.
用三角函数可以计算出径向线的方程为y=tan(θ)*x
,其中θ以弧度表示
然后您可以将其求解为 simultaneous equation 以确定交点。请注意,它将与正方形的两侧(上方和下方)相交,因此如果您只想要一个,则必须选择正方形正确一侧的方程式。还要防止 θ 为 π/2 的情况,因为 tan(π/2) 未定义。你可以很容易地解决这种情况,因为 x=0,所以它总是在 y=±(n*(√2/2))
处相交。
在您的示例中,交集出现在 x*(1+tan(θ))=n*(√n/n)
或 x=(n*(√n/n))/(1+tan(θ))
时。您可以计算它,将其插回 y,这就是您的 (x,y) 交点。
设正方形的边长是A
,半边长是H = A/2
。角度Theta
。交点P.
所有坐标都是相对于正方形中心的。
将正方形旋转 -Pi/4
,角度 Alpha = Theta - Pi/4
if Alpha lies in range -Pi/4..Pi/4, then intersection point P' = (H, H*Tan(Alpha))
if Alpha lies in range Pi/4..3*Pi/4, then P' = (H*Cotangent(Alpha), H)
if Alpha lies in range 3*Pi/4..5*Pi/4, then P' = (-H, -H*Tan(Alpha))
if Alpha lies in range 5*Pi/4..7*Pi/4, then P' = (-H*Cotangent(Alpha), -H)
然后将点 P'
旋转 Pi/4
:
S = Sqrt(2)/2
P.X = S * (P'.X - P'.Y)
P.Y = S * (P'.X + P'.Y)
示例(数据类似于您的草图):
A = 200, Theta = 5*Pi/12
H = 200/2 = 100, Alpha =Theta-Pi/4 = Pi/6
P'.X = H = 100
P'.Y = H * Tan(Alpha) = 100 * Tan(Pi/6) ~= 57.7
S = 0.707
P.X = 0.707 * (100 - 57.7) = 30
P.Y = 0.707 * (100 + 57.7) = 111
想象一个半径较大的圆将在您想要的点与您的菱形相交。在该位置绘制的一种方法是使用您平移和旋转的嵌套坐标系。你只需要知道半径和角度。
这是一个非常基本的例子:
float angle = radians(-80.31);
float radius = 128;
float centerX,centerY;
void setup(){
size(320,320);
noFill();
rectMode(CENTER);
centerX = width * 0.5;
centerY = height * 0.5;
}
void draw(){
background(255);
noFill();
//small circle
strokeWeight(1);
stroke(95,105,120);
ellipse(centerX,centerY,210,210);
rhombus(centerX,centerY,210);
//large circle
strokeWeight(3);
stroke(95,105,120);
ellipse(centerX,centerY,radius * 2,radius * 2);
//line at angle
pushMatrix();
translate(centerX,centerY);
rotate(angle);
stroke(162,42,32);
line(0,0,radius,0);
popMatrix();
//debug
fill(0);
text("angle: " + degrees(angle),10,15);
}
void rhombus(float x,float y,float size){
pushMatrix();
translate(x,y);
rotate(radians(45));
rect(0,0,size,size);
popMatrix();
}
void mouseDragged(){
angle = atan2(centerY-mouseY,centerX-mouseX)+PI;
}
你可以试试这里的演示(你可以拖动鼠标改变角度):
var angle;
var radius = 128;
var centerX,centerY;
function setup(){
createCanvas(320,320);
noFill();
rectMode(CENTER);
angle = radians(-80.31);
centerX = width * 0.5;
centerY = height * 0.5;
}
function draw(){
background(255);
noFill();
//small circle
strokeWeight(1);
stroke(95,105,120);
ellipse(centerX,centerY,210,210);
rhombus(centerX,centerY,210);
//large circle
strokeWeight(3);
stroke(95,105,120);
ellipse(centerX,centerY,radius * 2,radius * 2);
//line at angle
push();
translate(centerX,centerY);
rotate(angle);
stroke(162,42,32);
line(0,0,radius,0);
pop();
//debug
fill(0);
noStroke();
text("angle: " + degrees(angle),10,15);
}
function rhombus(x,y,size){
push();
translate(x,y);
rotate(radians(45));
rect(0,0,size,size);
pop();
}
function mouseDragged(){
angle = atan2(centerY-mouseY,centerX-mouseX)+PI;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.0/p5.min.js"></script>
如果要计算位置,可以用极坐标转直角坐标的公式:
x = cos(angle) * radius
y = sin(angle) * radius
这是一个使用它的例子。请注意,绘图是从中心完成的,因此将中心坐标添加到上面:
float angle = radians(-80.31);
float radius = 128;
float centerX,centerY;
void setup(){
size(320,320);
noFill();
rectMode(CENTER);
centerX = width * 0.5;
centerY = height * 0.5;
}
void draw(){
background(255);
noFill();
//small circle
strokeWeight(1);
stroke(95,105,120);
ellipse(centerX,centerY,210,210);
rhombus(centerX,centerY,210);
//large circle
strokeWeight(3);
stroke(95,105,120);
ellipse(centerX,centerY,radius * 2,radius * 2);
//line at angle
float x = centerX+(cos(angle) * radius);
float y = centerX+(sin(angle) * radius);
stroke(162,42,32);
line(centerX,centerY,x,y);
//debug
fill(0);
text("angle: " + degrees(angle),10,15);
}
void rhombus(float x,float y,float size){
pushMatrix();
translate(x,y);
rotate(radians(45));
rect(0,0,size,size);
popMatrix();
}
void mouseDragged(){
angle = atan2(centerY-mouseY,centerX-mouseX)+PI;
}
另一种选择是使用变换矩阵