Android – calcular el ángulo del arco
Tengo un arco y deseo dibujar marcas de escala a 0, 45, 90, 135, 180 grados, ¿puede alguien ayudarme con las matemáticas necesarias para obtener la x, y de los puntos 5 y 30 en este bosquejo ?:
- Android: ¿Cómo usar el método onDraw en una clase que extiende Actividad?
- Lona de Android - Dibuja un agujero
- Dibuja un texto en una ruta circular en android
- Dibujar superposición (HUD) en Android VideoView?
- Cómo dibujar la forma de triángulo y añadirlo en la distribución relativa o lineal de android
Aquí está mi código para dibujar la marca de 1 escala.
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(); }
- Cómo dibujar Arco entre dos puntos en el lienzo?
- Dibujo 2D eficiente en Android
- Por qué mi invocación de Canvas.drawText () simplemente no funciona
- ¿Cómo establecer el tamaño de la lona?
- PorterduffXfermode: borra una sección de un mapa de bits
- drawBitmap no es de pantalla completa
- Tratando de obtener el tamaño de visualización de una imagen en un ImageView
- Dibujo sobre lienzo fuera del método onDraw ()
Se puede calcular su rotación usando sin
y cos
. Supongamos que tiene el punto cero A
y desea girarlo al punto B
que se gira por 30 °. Algo como esto:
Básicamente, el nuevo punto está en (cx+x,cy+y)
. En este caso particular, la definición de sin
y cos
sería la siguiente:
sin = x/R cos = y/R
No es difícil obtener exacta y
. Así que para girar el punto en el ángulo particular en el círculo con el radio saber que necesitamos para calcular las coordenadas de la siguiente manera:
x = cx + sin(angle) * R; y = cy + cos(angle) * R;
Ahora vamos a volver a Android y lienzo!
@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(); }
El código dibujará marcas con un paso de 45 °. Tenga en cuenta que necesita convertir el ángulo a radianes y para el eje Y que utilicé menos causa en el lienzo se voltea. Esto es lo que tengo:
Si conoce el punto en el centro del círculo y el radio del círculo se vuelve bastante fácil si utiliza vectores a su ventaja.
Primero vas a necesitar los vectores unitarios en cada ángulo
- 0 grados -> (-1,0)
- 45 grados -> (-1 / sqrt (2), (1 / sqrt (2))
- 90 grados -> (0,1)
- 135 grados -> (1 / sqrt (2), (1 / sqrt (2))
- 180 grados -> (1,0)
A continuación, puede calcular los puntos necesarios utilizando la fórmula siguiente
point = center + (unit vector * distance from center)
He aquí un ejemplo más concreto, ya que andrew agregó uno.
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); }
Aquí está el resultado del código anterior
- ¿Cómo utilizar textview en la pantalla de Preferencias de Android?
- Android spinner performClick onItemSelected