Android – рассчитать угол дуги

У меня есть дуга, и я хочу рисовать масштабные отметки в 0, 45, 90, 135, 180 градусов, может ли кто-нибудь помочь мне с математикой, необходимой для достижения x, y точек 5 и 30 на этом эскизе ?:

Введите описание изображения здесь

Вот мой код для рисования 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(); } 

Вы можете рассчитать его вращение, используя sin и cos . Предположим, что у вас есть нулевая точка A и вы хотите повернуть ее в точку B которая поворачивается на 30 °. Что-то вроде этого:

Введите описание изображения здесь

В основном новая точка находится в (cx+x,cy+y) . В этом конкретном случае определение sin и cos будет следующим:

 sin = x/R cos = y/R 

Нетрудно получить точные x и y . Поэтому для поворота точки на определенный угол по кругу с радиусом знания нам нужно вычислить координаты следующим образом:

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

Теперь вернемся к Android и Canvas!

 @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 я использовал минус, потому что на холсте он переворачивается. Вот что я получил:

Введите описание изображения здесь

Если вы знаете точку в центре круга и радиус круга, становится довольно легко, если вы используете векторы в своих интересах.

Сначала вам понадобятся единичные векторы под каждым углом

  • 0 deg -> (-1,0)
  • 45 град -> (-1 / sqrt (2), (1 / sqrt (2))
  • 90 град -> (0,1)
  • 135 deg -> (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); } 

Вот результат приведенного выше кода Результат кода