如何使用javascript使用两个坐标绘制椭圆?

如何使用javascript使用两个坐标绘制椭圆?,javascript,algorithm,graphics,2d,ellipse,Javascript,Algorithm,Graphics,2d,Ellipse,就像图中的blow一样,我有两个坐标,我想画一个长轴边缘与这两点匹配的椭圆 我试着得到这两个坐标之间的中点,然后在这一个坐标的基础上画一个椭圆。下面的代码函数返回椭圆点数组,这正是我想要的: function add_oval(centre, x, y) { var assemble = new Array(); var angle; var dot; var tangent = x / y; for (i = 0; i < 36; i++) {

就像图中的blow一样,我有两个坐标,我想画一个长轴边缘与这两点匹配的椭圆

我试着得到这两个坐标之间的中点,然后在这一个坐标的基础上画一个椭圆。下面的代码函数返回椭圆点数组,这正是我想要的:

 function add_oval(centre, x, y) {
    var assemble = new Array();
    var angle;
    var dot;
    var tangent = x / y;
    for (i = 0; i < 36; i++) {
        angle = (2 * Math.PI / 36) * i;
        dot = [centre.lng + Math.sin(angle) * y * tangent, centre.lat + Math.cos(angle) * y];
        assemble.push(dot);
    }
    return assemble;
}
功能添加_椭圆(中心,x,y){
var assemble=新数组();
var角;
var点;
var切线=x/y;
对于(i=0;i<36;i++){
角度=(2*Math.PI/36)*i;
点=[center.lng+Math.sin(角度)*y*切线,center.lat+Math.cos(角度)*y];
组装。推(点);
}
返回装配;
}
但问题是,这些只能画一个水平椭圆,我不知道如何改变角度

有人知道如何解决我的问题吗?

提示

如果javascript中没有旋转椭圆特性,一个解决方法是使用贝塞尔立方近似。关于如何用四个贝塞尔圆弧近似圆,请参阅文章。然后一个椭圆就是一个拉伸的圆,它足以以同样的方式拉伸控制点

从单位圆开始,按轴长度缩放控制点,应用所需旋转并平移到所需中心。可以从给定的长轴(加上短轴的长度)绘制缩放和旋转参数


另一种方法是使用椭圆的参数方程并将其绘制为多段线。

我将使用基向量

  • 椭圆定义

    所以我们知道
    A,B
    2D点。您还需要定义标量短半轴大小
    |b |
    来定义椭圆。因此,我们知道:

    A=!
    B=!
    |b|=!
    
  • 中点C

    这很容易,它是
    A,B

    C.x=A.x + (B.x-A.x)/2
    C.y=A.y + (B.y-A.y)/2
    
    C.x = (A.x+B.x)/2
    C.y = (A.y+B.y)/2
    
    A、B的平均值

    C.x=A.x + (B.x-A.x)/2
    C.y=A.y + (B.y-A.y)/2
    
    C.x = (A.x+B.x)/2
    C.y = (A.y+B.y)/2
    
    选择你更喜欢哪一个(哪一个无关紧要)。该点
    C
    将用作基向量原点

  • 基向量
    a,b

    长半轴很简单,因为它由
    CB
    CA
    定义(对于全椭圆,哪一个也不重要)

    您也可以使用一半的
    AB

    a.x = (B.x-A.x)/2
    a.y = (B.y-A.y)/2
    
    短半轴
    b
    更糟糕,我们知道它垂直于
    a
    ,因此在3D ad重缩放中利用
    a
    与向量
    (0,0,1)
    的叉积,或者利用这样一个事实,如果将
    (x,y)
    交换到
    (y,-x)
    (-y,x)
    在2D中获得90度旋转。并从大小
    |a |
    重新缩放到大小
    |b |
    ,以便:

    |a| = sqrt( a.x*a.x + a.y*a.y )
    b.x = a.y * |b|/|a|
    b.y =-a.x * |b|/|a|
    
  • 椭圆

    现在我们终于得到了渲染所需的一切。椭圆上的任何点通过角度
    ang=
    参数化,其中
    M_PI=3.1415926535897932384626433832795
    很容易:

    x = C.x + a.x*cos(ang) + b.x*sin(ang)
    y = C.y + a.y*cos(ang) + b.y*sin(ang)
    
    因此,要么将其添加到for循环中,然后像现在一样使用点渲染椭圆。或将椭圆渲染为带直线的多段线。。。例如,VCL/GDI中的类似内容(很抱歉,我不使用javascript):

  • 注释

    • 二维中的点和向量定义为两个坐标的集合
      (x,y)
    • 标量是单个值(标准编号)
    • | a |
      表示向量的大小
      a
    • 上述计算不需要
      |a |>|b |
    • 如果
      |b |
      未知,可以使用
      |a |
      的缩放比例,例如让
      |b |/| a |=0.3

    为了绘制椭圆,还必须定义短轴。@Teemu,我可以为短轴指定一个特定的值,这无关紧要。如果我想得到椭圆的所有坐标,但不想“绘制”它呢。实际上,画法不是我控制的。我只能为该方法提供点列表。@JackZhang然后您忽略moveto/line to,而是将
    (x,y)
    添加到点列表中。您还需要更改
    dang
    步骤,以便获得足够的分数。计算精确的相邻像素位置对于旋转来说是一个非常困难的问题,因为它会导致超越问题。。。使用更小的
    dang
    步长和重复像素的风险更容易、更快。为了更好地估计,您可以使用圆近似。。。所以如果我没有弄错的话