1   package fi.jyu.mit.graphics;
2   
3   import java.awt.*;
4   
5   /**
6    * Luokka merkkipisteille.
7    * Oliota voi käyttää prototyyppinä luomaan vastaavanlaisia
8    * merkkejä lisää.
9    * <pre>
10   * Käyttö esimerkiksi:
11   *   Marker malliMerkki = new Marker(0,0,0.25).setMaxR(5).setType(Marker.CIRCLE);
12   *   ...
13   *   ikkuna.add(malliMerkki.create(x,y));  
14   * </pre>
15   * @author Vesa Lappalainen
16   *
17   */
18  public class Marker extends BasicShape {
19      /**
20       * Rajapinta markkerin piirtämiseksi
21       * @author vesal
22       * @version 19.10.2008
23       */
24      public interface MarkerInterface {
25          /**
26           * Piirtää markerin ruudulle 
27           * @param g grafiikkapinta johon piirretään
28           * @param x markerin x-keskipiste skaalattuna kokonaislukuna
29           * @param y markerin y-keskipiste skaalattuna kokonaislukuna
30           * @param r markerin säden skaalattuna kokonaislukuna
31           */
32          public void draw(Graphics g,int x,int y,int r);
33      }
34      
35      
36      /**
37       * Valmis luokka ympyrämerkkien piirtämistä varten
38       */
39      public static class Circle implements MarkerInterface {
40          /**
41           * @see fi.jyu.mit.graphics.Marker.MarkerInterface#draw(java.awt.Graphics, int, int, int)
42           */
43          @Override
44          public void draw(Graphics g,int x,int y,int r) {
45              g.drawOval(Math.round(x-r), Math.round(y-r), 2*r, 2*r);
46          }    
47      }
48      
49      
50      /**
51       * Valmis luokka Plus-merkkien piirtämistä varten
52       */
53      public static class Plus implements MarkerInterface {
54          /**
55           * @see fi.jyu.mit.graphics.Marker.MarkerInterface#draw(java.awt.Graphics, int, int, int)
56           */
57          @Override
58          public void draw(Graphics g,int x,int y,int r) {
59              g.drawLine(x-r-1, y   , x+r+1, y    );
60              g.drawLine(x    ,y+r+1, x    , y-r-1);
61          }    
62      }
63      
64      /**
65       * Valmis luokka X-merkkien piirtämistä varten
66       */
67      public static class Cross implements MarkerInterface {
68          /**
69           * @see fi.jyu.mit.graphics.Marker.MarkerInterface#draw(java.awt.Graphics, int, int, int)
70           */
71          @Override
72          public void draw(Graphics g,int x,int y,int r) {
73              g.drawLine(x-r-1,y-r-1, x+r+1,y+r+1);
74              g.drawLine(x-r-1,y+r+1, x+r+1,y-r-1);
75          }    
76      }
77      
78  
79      /** Ympyrän piirtävä markkeri  */
80      public static final MarkerInterface CIRCLE = new Circle();
81      /** Plussan piirtävä markkeri  */
82      public static final MarkerInterface PLUS   = new Plus();
83      /** X:n piirtävä piirtävä markkeri  */
84      public static final MarkerInterface CROSS  = new Cross();
85      
86      private MarkerInterface marker = CIRCLE; 
87      private final RPoint center;
88      private double r;
89      private int maxR = Integer.MAX_VALUE;
90      private int minR = 1;
91      
92      /**
93       * Luo merkkipisteen
94       * @param x merkin keskipisteen x-koordinaatti
95       * @param y merkin keskipisteen y-koordinaatti
96       * @param r ympyrän säde
97       */
98      public Marker(double x, double y, double r) {
99          super();
100         this.center = new RPoint(x, y);
101         this.r = r;
102         initialize();
103     }
104     
105     /**
106      * Luo merkkipisteen
107      * @param x merkin keskipisteen x-koordinaatti
108      * @param y merkin keskipisteen y-koordinaatti
109      * @param r ympyrän säde
110      * @param type piirrettävän merkin tyyppi
111      */
112     public Marker(double x, double y, double r, MarkerInterface type) {
113         this(x,y,r);
114         marker = type;
115     }
116     
117     /**
118      * Luo uuden ympyrän
119      * @param x ympyrän keskipisteen x-koordinaatti
120      * @param y ympyrän keskipisteen y-koordinaatti
121      * @param z ympyrän keskipisteen z-koordinaatti
122      * @param r ympyrän säde
123      */
124     public Marker(double x, double y, double z, double r) {
125         super();
126         this.center = new RPoint(x, y, z);
127         this.r = r;
128         initialize();
129     }
130     
131     /**
132      * Luo uuden ympyrän
133      * @param x ympyrän keskipisteen x-koordinaatti
134      * @param y ympyrän keskipisteen y-koordinaatti
135      * @param z ympyrän keskipisteen z-koordinaatti
136      * @param r ympyrän säde
137      * @param type piirrettävän merkin tyyppi
138      */
139     public Marker(double x, double y, double z, double r, MarkerInterface type) {
140         this(x,y,z,r);
141         marker = type;
142     }
143     
144     /**
145      * Alustaa markerin asetukset
146      */
147     private void initialize() {
148         //
149     }
150 
151     
152     /**
153      * Asetetaan merkille uusi säde.  Negatiivinen säde
154      * tarkoittaa määrää pikseleinä.  Positiivinen alueen
155      * koordinaatteina.
156      * @param r uusi säteen arvo
157      * @return tämä olio ketjuttamista varten
158      */
159     public Marker setR(double r) {
160         this.r = r;
161         redraw();
162         return this; 
163     }
164 
165     
166     /**
167      * Asetetaan uusi tapa piirtää merkki
168      * @param type merkin piirtäjä
169      * @return tämä olio ketjuttamista varten
170      */
171     public Marker setType(MarkerInterface type) {
172         this.marker = type;
173         redraw();
174         return this;
175     }
176     
177     /**
178      * Asetetaan merkin maksimikoko pikseleinä
179      * @param maxR merkin maksimikoko pikseleinä
180      * @return tämä olio ketjuttamista varten
181      */
182     public Marker setMaxR(int maxR) {
183         this.maxR = maxR;
184         redraw();
185         return this; 
186     }
187 
188 
189     /**
190      * Asetetaan merkin maksimikoko pikseleinä
191      * @param minR merkin maksimikoko pikseleinä
192      * @return tämä olio ketjuttamista varten
193      */
194     public Marker setMinR(int minR) {
195         this.minR = minR;
196         redraw();
197         return this; 
198     }
199 
200 
201     
202     /**
203      * Piirretään merkki
204      * @see fi.jyu.mit.graphics.BasicShape#drawShape(java.awt.Graphics, fi.jyu.mit.graphics.Matrix)
205      */
206     @Override
207     protected void drawShape(Graphics g, Matrix a) {
208         Vector rp = new Vector(); // NOPMD, luulee vääräksi vektoriksi
209         SPoint sp = new SPoint(0,0);
210         Vector spv = new Vector();
211         double r0;
212         int cx,cy,ri = (int)Math.round(-r); 
213         a.transform(center.getX(),center.getY(),center.getZ(),rp,sp);
214         cx = sp.getX();
215         cy = sp.getY();
216         if ( r >= 0 ) {
217             // a.transform(center.getX()-r,center.getY(),center.getZ(),rp,sp);
218             // ri = Math.abs(sp.getX()-cx);                    // TODO: tämä pyöristyy välillä väärin 
219             a.transform(r,0,0,rp,spv);                          // TODO: ei ota perpektiiviä huomioon
220             r0 = spv.a(0);
221             a.transform(0,0,0,rp,spv);                         
222             ri = (int) Math.round(Math.abs(r0-spv.a(0)));
223         }
224         if ( ri > maxR ) ri = maxR;
225         if ( ri < minR ) ri = minR;
226         marker.draw(g, cx, cy, ri);
227     }
228     
229 
230     /**
231      * Metodi joka luo vastaavilla arvoilla olevan merkin
232      * @param x merkin keskipisteen x-koordinaatti
233      * @param y merkin keskipisteen y-koordinaatti
234      * @param z merkin keskipisteen z-koordinaatti
235      * @return uusi merkki
236      */
237     public Marker create(double x, double y, double z) {
238         Marker m = new Marker(x,y,z,r,marker);
239         m.setColor(getColor());
240         m.minR = minR;
241         m.maxR = maxR;
242         return m;   
243     }
244     
245     /**
246      * Metodi joka luo vastaavilla arvoilla olevan merkin
247      * @param x merkin keskipisteen x-koordinaatti
248      * @param y merkin keskipisteen y-koordinaatti
249      * @return uusi merkki
250      */
251     public Marker create(double x, double y) {
252         return create(x,y,0);   
253     }
254     
255 }
256