2010-08-15 5 views
7

Używam Java AWT do rysowania linii na panelu (Line2D i Graphics2D.drawLine()) i zastanawiam się, jak mogę narysować linię ze znacznikami, podobne do:Java - Narysuj linijkę (linia z zaznaczonymi znakami pod kątem 90 stopni)

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

Znam pozycje, z których chciałabym wcześniej wybrać kleszcze.

Linie mogą być w dowolnej pozycji, więc tyknięcia należy narysować pod kątem odpowiednim do samej linii.

Moja podstawowa geometria & zdolność do zastosowania go w Javie mnie zawodzi. :)

+0

Chcesz wyciągnąć „Władcy” linie w dowolnych kierunkach? Czy tyknięcia są w ustalonych odstępach czasu, czy też chcesz, żeby się pojawiły, powiedzmy 0%, 33%, 66%, 100%? – aioobe

+0

Opis ogólny grafiki znajduje się poniżej. Znaki tyknięcia będą równomiernie rozmieszczone z dowolnymi odstępami. (IE: Potrzebuję rozwiązania, w którym mogę posegmentować linię i narysować dowolną liczbę tych tyknięć wzdłuż jej długości w każdym segmencie) – Matt

+0

daj mi znać, co myślisz o mojej odpowiedzi. – jjnguy

Odpowiedz

13

Proponuję

  1. wdrożyć linijką rysunek-metodę, która rysuje prostą poziomą linijkę od lewej do prawej
  2. Dowiedzieć się żądanym kątem wykorzystaniem Math.atan2.
  3. Zastosuj AffineTransform z tłumaczeniem i obróceniem przed wywołaniem metody rysowania linijki.

Oto pełny program testowy. (Metoda Graphics.create służy do tworzenia kopii oryginalnej grafiki obiekt, więc nie bałagan oryginalny przekształcać.)

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

Uwaga, że ​​można tak łatwo wyciągnąć numery powyżej kleszczy. Wywołania drawString przechodziłyby tę samą transformację i były ładnie "przechylane" wzdłuż linii.

+0

Interesujące, moim zdaniem "AffineTransform" jest słowem kluczowym, którego szukałem. Google wyprodukował ten samouczek z bardzo podobnymi komponentami: http://www.glyphic.com/transform/applet/1intro.html Teraz muszę tylko zrozumieć, jak zastosować to do mojego problemu. – Matt

+0

Stosuje się go najpierw poprzez przesunięcie (przesunięcie) do pożądanego punktu początkowego, a następnie obrót o pożądany kąt (atan2 (dy, dx)). Połącz dwie transformacje z AffineTransform.concatenate. – aioobe

+1

To wygląda świetnie. Muszę się lepiej zapoznać z materiałem Transform. – jjnguy

1

elementy wymagające odnotowując:

  • linii prostopadłej ma nachylenie -1/oldslope.
  • Aby obsługiwać linie w dowolnym kierunku, trzeba to zrobić parametrycznie
  • W ten sposób masz dy i dx na pierwotnej linii, co oznacza, że ​​newdx=dy; newdy=-1*dx.
  • Jeśli masz go taki, że <dx, dy> jest wektorem jednostkowym (sqrt(dx*dx+dy+dy)==1 lub dx==cos(theta); dy=sin(theta) dla niektórych theta), musisz po prostu wiedzieć, jak daleko od siebie mają znaczniki.
  • sx, sy są twoje początek x i y
  • długość to długość linii
  • seglength jest długość kresek
  • dx, dy jest stoki pierwotnej linii
  • newdx, newdy są (obliczona powyżej) zbocza poprzecznych linii

Zatem

  1. narysować linia od <sx,sy> (start X, Y) do <sx+dx*length,sy+dy*length>
  2. Draw zestaw wierszy (for (i = 0; i < = długość; i + = przedział) od <sx+dx*i-newdx*seglength/2,sy+dy*i-newdy*seglength/2> do <sx+dx*i+newdx*seglength/2,sy+dy*i+newdy*seglength/2>
+0

Bardzo podoba mi się ta odpowiedź, ponieważ próbuje wyjaśnić geometrię. Niestety, mam problem z owinięciem głowy. Podłączyłem formuły, które opisałeś i otrzymuję bardzo dziwne wyniki dla newdy & newdx. (wartości ujemne, które mieszczą się daleko poza zakresem współrzędnych na moim panelu) Znowu moja geometria jest w najlepszym wypadku elementarna, ale zastanawiam się, czy wzór dotyczy układu współrzędnych kartezjańskich.Współrzędne Java umieszczają 0,0 w lewym górnym rogu panelu. – Matt

1

Mam nadzieję, że wiesz, macierz mnożenie. Aby obrócić linię, musisz ją zliczyć za pomocą macierzy rotacji. (I coudln't zwrócić odpowiedniej matrycy, ale zakładać zarówno linii nie są rozdzielone)

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

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

Stare punkty X, Y i nowe, to x „y”. Zilustrujmy przykładem, powiedzmy, że masz pionową linię od (0,0) do (0,1), teraz chcesz ją obrócić o 90 stopni. (0,0) pozostanie zerem więc pozwala tylko zobaczyć, co się dzieje (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| 

można dostać się do linii poziomej (0,0),(0,1), jak można się spodziewać.

Nadzieja pomaga,
Roni

Powiązane problemy