2010-08-15 32 views
7

Estoy usando Java AWT para dibujar líneas en un panel (Line2D y Graphics2D.drawLine()) y me pregunto cómo puedo trazar una línea con marcas, similar a:Java - Dibuje una regla (línea con marcas en un ángulo de 90 grados)

| ---- | ---- | ---- | ---- | ---- |

Conozco los puestos a los que me gustaría llamar la atención con anticipación.

Las líneas podrían estar en cualquier posición, por lo que las marcas se deben dibujar en un ángulo relativo a la línea misma.

Mi geometría básica & capacidad para aplicarlo en Java me está fallando. :)

+0

¿Quieres dibujar las líneas "regla" en direcciones arbitrarias? ¿Están los tics a intervalos fijos, o quieres que aparezcan, digamos 0%, 33%, 66%, 100%? – aioobe

+0

Consulte a continuación la descripción de los gráficos en general. Las marcas de graduación estarán espaciadas uniformemente con espaciado arbitrario. (IE: Necesito una solución donde pueda segmentar una línea y dibujar un número arbitrario de estos tics a lo largo de su longitud en cada segmento) – Matt

+0

déjame saber lo que piensas de mi respuesta. – jjnguy

Respuesta

13

que sugieren que

  1. implementar un método con regla de dibujo que dibuja una línea horizontal sencilla de izquierda a derecha
  2. averiguar el ángulo deseado usando Math.atan2.
  3. Aplicar un AffineTransform con traducción y rotación antes de invocar la regla-drawing-method.

Aquí hay un programa de prueba completo. (El método Graphics.create se utiliza para crear una copia de los gráficos originales objeto, por lo que no estropear el original transformada.)

import java.awt.*; 

public class RulerExample { 

    public static void main(String args[]) { 
     JFrame f = new JFrame(); 
     f.add(new JComponent() { 

      private final double TICK_DIST = 20; 

      void drawRuler(Graphics g1, int x1, int y1, int x2, int y2) { 
       Graphics2D g = (Graphics2D) g1.create(); 

       double dx = x2 - x1, dy = y2 - y1; 
       double len = Math.sqrt(dx*dx + dy*dy); 
       AffineTransform at = AffineTransform.getTranslateInstance(x1, y1); 
       at.concatenate(AffineTransform.getRotateInstance(Math.atan2(dy, dx))); 
       g.transform(at); 

       // Draw horizontal ruler starting in (0, 0) 
       g.drawLine(0, 0, (int) len, 0); 
       for (double i = 0; i < len; i += TICK_DIST) 
        g.drawLine((int) i, -3, (int) i, 3); 
      } 

      public void paintComponent(Graphics g) { 
       drawRuler(g, 10, 30, 300, 150); 
       drawRuler(g, 300, 150, 100, 100); 
       drawRuler(g, 100, 100, 120, 350); 
       drawRuler(g, 50, 350, 350, 50); 
      } 
     }); 

     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.setSize(400, 400); 
     f.setVisible(true); 
    } 
} 

enter image description here

Tenga en cuenta, que sólo puede dibujar tan fácilmente números por encima de los tics. Las drawString-calls pasarían por la misma transformación y se "inclinarían" muy bien a lo largo de la línea.

+0

Interesante, creo que 'AffineTransform' es la palabra clave que estaba buscando. Google produjo este tutorial con componentes muy similares: http://www.glyphic.com/transform/applet/1intro.html Ahora solo tengo que entender cómo aplicarlo a mi problema. – Matt

+0

Lo aplica traduciendo primero (moviéndose) al punto de inicio deseado y luego girando en el ángulo deseado (atan2 (dy, dx)). Combine las dos transformaciones con AffineTransform.concatenate. – aioobe

+1

Eso se ve genial. Necesito familiarizarme más con las cosas de Transform. – jjnguy

1

cosas que necesitan Teniendo en cuenta:

  • Una línea perpendicular tiene una pendiente de -1/oldslope.
  • Para soportar líneas en cualquier dirección, debe hacerlo paramétricamente
  • Por lo tanto, tiene dy dx en la línea original, lo que significa que newdx=dy; newdy=-1*dx.
  • Si lo tiene de manera que <dx, dy> es un vector unitario (sqrt(dx*dx+dy+dy)==1, o dx==cos(theta); dy=sin(theta) para algunos theta), solo necesita saber qué tan lejos desea las marcas de graduación.
  • sx, sy son su inicio xey
  • longitud es la longitud de la línea
  • seglength es la longitud de los guiones
  • dx, dy es la ladera de la línea original
  • newdx, newdy son los (calculado anteriormente) pendientes de las líneas transversales

Por lo tanto,

  1. Dibuje una línea de <sx,sy> (inicio x, y) a <sx+dx*length,sy+dy*length>
  2. Dibuje un conjunto de líneas (para (i = 0; i < = longitud; i + = intervalo) de <sx+dx*i-newdx*seglength/2,sy+dy*i-newdy*seglength/2> a <sx+dx*i+newdx*seglength/2,sy+dy*i+newdy*seglength/2>
+0

Me gusta mucho esta respuesta porque intenta explicar la geometría. Lamentablemente, estoy teniendo problemas para entenderlo. Conecté las fórmulas que describiste y obtengo resultados muy extraños para newdy y newdx. (valores negativos que quedan fuera del rango de coordenadas en mi panel) De nuevo, mi geometría es elemental en el mejor de los casos, pero me pregunto si la fórmula es para un sistema de coordenadas cartesianas.Las coordenadas de Java ponen 0,0 en la esquina superior izquierda de un panel. – Matt

1

espero que sepas matriz multiplicación. Para rotar una línea, debes multiplicarla por matriz de rotación. (I desvivían dibujar una matriz adecuada pero asumir tanto la línea no están separados)

|x'| = |cos(an) -sin(an)| |x| 

|y`| = |sin(an) cos(an)| |y| 

Los puntos viejos son X, Y y el nuevo es x 'y'. Déjenos ilustrar con un ejemplo, digamos que tiene una línea vertical de (0,0) a (0,1), ahora quiere girarla 90 grados. (0,0) seguirá siendo cero así que simplemente ver lo que sucede a (0,1)

|x'| = |cos(90) -sin(90)| |0| 

|y`| = |sin(90) cos(90)| |1| 

==

|1 0| |0| 

|0 1| |1| 

==

| 1*0 + 0*1| 

| 0*0 + 1*1| 

== |0| 

    |1| 

se llega a la línea horizontal (0,0),(0,1) como es de esperar.

creo que sirve,
Roni

Cuestiones relacionadas