2015-05-03 71 views
4

我有一個弧,我希望在0,45,90,135,180度繪製比例標記,任何人都可以幫助我實現點5和30的x,y所需的數學在這個小品?:Android - 計算弧角

enter image description here

這裏是我繪製1個刻度代碼。

private void drawScale(Canvas canvas) { 
     //canvas.drawOval(scaleRect, scalePaint); 

     canvas.save(); 

     Paint p = new Paint(); 
     p.setColor(Color.WHITE); 
     p.setStrokeWidth(10f); 
     canvas.drawLine(rectF.left-getWidth()/20, rectF.height()/2, rectF.left, rectF.height()/2, p); 


    canvas.restore(); 
} 

回答

11

可以使用sincos計算其旋轉的結果。讓我們假設你有零點A並且想把它旋轉到旋轉30°的點B。 事情是這樣的:

enter image description here

基本上新的點在(cx+x,cy+y)。在sincos這種特殊情況下的定義是下一個:

sin = x/R 
cos = y/R 

不難得到確切xy。因此,要在特定的角度圓圈,我們需要在接下來的方式來計算座標知道半徑旋轉點:

x = cx + sin(angle) * R; 
y = cy + cos(angle) * R; 

現在,讓我們回到Android和帆布!

@Override 
protected void onDraw(Canvas canvas) { 
    super.onDraw(canvas); 

    canvas.save(); 
    float cx = getWidth()/2f; 
    float cy = getHeight()/2f; 

    float scaleMarkSize = getResources().getDisplayMetrics().density * 16; // 16dp 
    float radius = Math.min(getWidth(), getHeight())/2; 

    for (int i = 0; i < 360; i += 45) { 
     float angle = (float) Math.toRadians(i); // Need to convert to radians first 

     float startX = (float) (cx + radius * Math.sin(angle)); 
     float startY = (float) (cy - radius * Math.cos(angle)); 

     float stopX = (float) (cx + (radius - scaleMarkSize) * Math.sin(angle)); 
     float stopY = (float) (cy - (radius - scaleMarkSize) * Math.cos(angle)); 

     canvas.drawLine(startX, startY, stopX, stopY, scalePaint); 
    } 

    canvas.restore(); 
} 

代碼將以45°的步長繪製標記。請注意,您需要將角度轉換爲弧度,而對於Y軸,我在畫布上使用減號原因將其翻轉。以下是我有:

enter image description here

+1

不錯,你可以使用['Canvas.translate '](http://developer.android.com/reference/android/graphics/Canvas.html#translate(float,%20float))來設置中心,那麼你可以忘掉它。它看起來像你想過的,因爲你保存和恢復畫布矩陣。 – weston

+0

'canvas.translate(-cx,-cy)';然後刪除所有其他對'cx','cy'的引用 – weston

4

如果你知道圓的中心點和圓的半徑,如果你使用向量來獲得優勢,它變得非常容易。

首先你會需要的單位向量在每個角度

  • 0度 - >(-1,0)
  • 45度 - >( - 1/SQRT(2),(1/SQRT(2))
  • 90度 - >(0,1)
  • 135度 - >(1/SQRT(2),(1/SQRT(2))
  • 180度 - >(1 ,0)

您可以然後使用下面的公式計算必要點數

point = center + (unit vector * distance from center) 

這是一個更具體的例子,因爲安德魯增加了一個。

private static final float RADIUS = 400.0f; 
private static final float MARK_LENGTH = 30.0f; 
private static final UnitVector[] UNIT_VECTORS = new UnitVector[] { 
     new UnitVector(-1,0), // 0 deg 
     new UnitVector((float) (-1/Math.sqrt(2)), (float) (1/Math.sqrt(2))), // 45 deg 
     new UnitVector(0, 1), // 90 deg 
     new UnitVector((float) (1/Math.sqrt(2)), (float) (1/Math.sqrt(2))), // 135 deg 
     new UnitVector(1, 0), // 180 deg 
     new UnitVector((float) (1/Math.sqrt(2)), (float) (-1/Math.sqrt(2))), // 225 deg 
     new UnitVector(0, -1), // 270 deg 
     new UnitVector((float) (-1/Math.sqrt(2)), (float) (-1/Math.sqrt(2))), // 315 deg 
}; 

static class UnitVector { 
    final float x; 
    final float y; 

    UnitVector(final float x, final float y) { 
     this.x = x; 
     this.y = y; 
    } 
} 

// Call this from onDraw 
public void drawMarks(final Canvas canvas) { 
    for (final UnitVector unitVector : UNIT_VECTORS) { 
     this.drawMarkWithVector(unitVector, canvas); 
    } 
} 

private void drawMarkWithVector(final UnitVector unitVector, final Canvas canvas) { 
    final float centerPointX = this.getWidth()/2; 
    final float centerPointY = this.getHeight()/2; 
    final float startX = centerPointX + (unitVector.x * RADIUS); 
    final float startY = centerPointY + (unitVector.y * RADIUS); 
    final float endX = centerPointX + (unitVector.x * (RADIUS + MARK_LENGTH)); 
    final float endY = centerPointY + (unitVector.y * (RADIUS + MARK_LENGTH)); 
    canvas.drawLine(startX, startY, endX, endY, this.paint); 
} 

下面是代碼的上述 Result of the code

+0

首先,感謝你的幫助,第二,我不是所有的偉大在這種數學的,所以如果你能請澄清對我來說: 1.什麼是單位矢量? 2。有什麼意義? 3.標記長度是多少? 再次感謝您的幫助 –

+0

認爲單位矢量的簡化方法是將其視爲指向特定方向的長度線。這意味着如果你想在單位矢量的方向上移動一個特定長度的點,只需將單位矢量乘以所需的長度並將其添加到原始點。得出的結論是我在等式中提到的一點。一些更多信息在這裏https://www.mathsisfun.com/algebra/vector-unit.html 標記長度是你畫的線條的長度。 –

+0

添加了一個更具體的例子,因爲安德魯增加了一個。這兩種方法都很好,並且有上升趨勢。安德魯斯解決方案更通用,並允許您更改標記繪製的角度。我的解決方案在計算上花費較少,因爲它可以避免執行trig數學運算。 –