连接android gaphics

时间:2016-05-19 04:03:37

标签: android math graphics trigonometry curve

我想绘制一个圆弧。在两个点之间的一个相当宽的圆弧,在android的画布上。

当然,我在这里进行了详尽的搜索,发现有几个人问了同样的问题(such as),但是尽可能地尝试,我无法做出答案的正面或反面,我无法得到drawArc函数做我需要的!

然后我终于找到了如何做到这一点detailed breakdown

private static void arcBetween(PointF e1, PointF e2, Paint paint, Canvas canvas) {

    float a1Degrees = 36.0f;
    double a1 = Math.toRadians(a1Degrees);
    // l1 is half the length of the line from e1 to e2
    double dx = e2.x - e1.x, dy = e2.y - e1.y;
    double l = Math.sqrt((dx * dx) + (dy * dy));
    double l1 = l / 2.0;
    // h is length of the line from the middle of the connecting line to the
    //  center of the circle.
    double h = l1 / (Math.tan(a1 / 2.0));

    // r is the radius of the circle
    double r = l1 / (Math.sin(a1 / 2.0));
    // a2 is the angle at which L intersects the x axis
    double a2 = Math.atan2(dy, dx);
    // a3 is the angle at which H intersects the x axis
    double a3 = (Math.PI / 2.0) - a2;
    // m is the midpoint of the line from e1 to e2
    double mX = (e1.x + e2.x) / 2.0;
    double mY = (e1.y + e2.y) / 2.0;

    // c is the the center of the circle
    double cY = mY + (h * Math.sin(a3));
    double cX = mX - (h * Math.cos(a3));
    // rect is the square RectF that bounds the "oval"
    RectF oval =
            new RectF((float) (cX - r), (float) (cY - r), (float) (cX + r), (float) (cY + r));
    // a4 is the starting sweep angle
    double rawA4 = Math.atan2(e1.y - cY, e1.x - cX);
    float a4 = (float) Math.toDegrees(rawA4);

    canvas.drawArc(oval, a4, a1Degrees, false, paint);
}

唉,其中的数学超出了我,但我设法将其复制/粘贴到代码中,它确实产生了一个弧(正如你在image中看到的那样)。

但是,出于我的目的,这个弧有三个问题。

  1. 为什么填充封闭区域的直线也是如此?我只需要一条曲线,而不是圆顶。我认为这是drawArc()中的错误所做的,但它已经关闭,似乎没有这样做。

  2. 虽然弧的上角位于正确的位置,但我还放置(并且超级三重检查)下部点位于蓝色元素的边缘,而不是位于底部的屏幕。然而,弧线的角落仍在那里。

  3. 一个非常重要的部分是我需要不同形状的弧形,在中间有更多的凸起。真的,我需要能够以编程方式调整凸起,所以我需要它以某种方式作为变量传递给该函数。

  4. 就是这样,我一直在努力,但没有研究过这个数学而且感到困惑。您的解决方案深受赞赏。

1 个答案:

答案 0 :(得分:0)

您的false' parameter正在响应从弧线端到圆心的半径线 删除填充 - 设置

 paint.setStyle(Paint.Style.STROKE);

你的计算似乎在a2,a3测定之前 - 很容易错过这些角度及其符号的错误,所以中心可能是错误的。我更喜欢矢量方法。您已经有方向向量(dx, dy)。制作标准化的

udx = dx / l
udy = dy / l

在左手坐标系(Y轴向下)中垂直于此向量

px = udy
py = -udx

现在圈中心

cx = mx + px * h
cy = my + py * h

我没有Android设备和Java,但在Windows中快速检查显示正确的绘图(在我的情况下,Arc函数也有边界矩形参数,但没有角度)

var
  e1, e2: TPoint;
  a1degrees, a1, a2, a3, a4, dx, dy, l, l1, h, mx, my, udx, udy, px, py: Double;
  r, cx, cy: Integer;
  rct: TRect;
begin
    e1 := Point(300, 100);
    e2 := Point(200, 200);
    Canvas.Brush.Color := clLime;
    Canvas.Ellipse(e1.X - 3, e1.Y - 3, e1.X + 4, e1.Y + 4);
    Canvas.Ellipse(e2.X - 3, e2.Y - 3, e2.X + 4, e2.Y + 4);
    a1Degrees := 36;
    a1 := DegToRad(a1Degrees);
    dx := e2.x - e1.x;
    dy := e2.y - e1.y;
    mx := (e2.x + e1.x) / 2;
    my := (e2.y + e1.y) / 2;
    l := Sqrt((dx * dx) + (dy * dy));
    l1 := l / 2.0;
    // h is length of the line from the middle of the connecting line to the
    //  center of the circle.
    h := l1 / tan(a1 / 2.0);
    // r is the radius of the circle
    r := Round(l1 / sin(a1 / 2.0));

    udx := dx / l;
    udy := dy / l;
    px := udy;  // for right-handed coordinate system
    py := -udx; // inverse signs
    cx := Round(mx + px * h);
    cy := Round(my + py * h);

    Canvas.Brush.Color := clRed;   //draw center red
    Canvas.Ellipse(cx - 5, cy - 5, cx + 6, cy + 6);

    Canvas.Arc(cX - r, cY - r, cX + r, cY + r, e1.X, e1.Y, e2.X, e2.Y);

弧角36,120和270度的示例: enter image description here