【问题标题】:Get the X,Y coordinate at the edge of a rhombus, based on the rhombus' width and angle根据菱形的宽度和角度获取菱形边缘的 X,Y 坐标
【发布时间】:2016-05-16 11:22:07
【问题描述】:

我正在开发一个Processing 草图,给定一个特定的角度,在菱形的边缘绘制一个点。

我知道菱形的宽度及其位置,但我不确定如何计算位于其边缘的点的 x-y 坐标。

这个问题有什么优雅的解决方案吗?欢迎任何关于伪代码的帮助。

【问题讨论】:

标签: math processing trigonometry


【解决方案1】:

让我们的正方形边长是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

【讨论】:

  • P' = (H, Tan(Alpha)), P' = (Cotangent(Alpha), H) 等是什么符号?
  • P' = (X, Y) - 旋转点。 Tan(Alpha) - 正切函数。注释编辑 - 添加 H 乘法
【解决方案2】:

根据您的图像,您希望找到两个方程的交点,即角度为 θ 的直线的交点,以及与其相交的正方形边的交点。

假设你的正方形的大小是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) 交点。

【讨论】:

    【解决方案3】:

    想象一个半径较大的圆将在您想要的点与您的菱形相交。在该位置绘制的一种方法是使用您平移和旋转的嵌套坐标系。您只需要知道半径和角度即可。

    这是一个非常基本的例子:

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

    另一种选择是使用转换矩阵

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-21
      • 2019-08-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多