1   package fi.jyu.mit.graphics;
2   
3   import java.awt.*;
4   
5   /**
6    * Luokka monikulmioille
7    * @author Markus Kivioja
8    *
9    */
10  public class Polygon extends BasicShape {
11  
12      protected RPoint[] ps;
13      protected int count;
14      
15      public Polygon() {
16          super();
17      }
18  
19      /**
20       * Luo monikulmion annetuista kulmapisteiden
21       * x- ja y-koordinaateista
22       * @param xpoints taulukko kulmapisteiden x-koordinaateista
23       * @param ypoints taulukko kulmapisteiden y-koordinaateista
24       */
25      public Polygon(double[] xpoints, double[] ypoints) {
26          super();
27          if (xpoints.length < ypoints.length) this.count = xpoints.length;
28          else this.count = ypoints.length;
29          initialize();
30          for (int i = 0; i < getCount(); i++) this.ps[i] = new RPoint(xpoints[i], ypoints[i]); // NOPMD, pakko luoda
31      }
32      
33      /**
34       * Luo monikulmion jonka kulmapisteiden x-koordinaatit lähtevät
35       * annetusta pisteestä x ja kasvavat siitä annetun määrän dx,
36       * y-koordinaatit annetaan taulukkona ypoints, esimerkiksi:
37       * <pre>
38       *     double[] ypoints = {0, 1, 2, 1, 0};
39       *     Polygon p = new Polygon(0, 1, ypoints);
40       *     
41       *     Luo monikulmion jonka kärkipisteet ovat (0,0), (1,1), (2,2), (3,1), (4,0) 
42       * </pre>
43       * @param x ensimmäisen pisteen x-koordinaatti
44       * @param dx pisteiden etäisyys toisistaan x-akselin suunnassa
45       * @param ypoints taulukko pisteiden y-koordinaateista
46       */
47      public Polygon(double x, double dx, double[] ypoints) {
48          super();
49          this.count = ypoints.length;
50          initialize();
51          for (int i = 0; i < getCount(); i++) this.ps[i] = new RPoint(x+i*dx, ypoints[i]); // NOPMD, pakko luoda
52      }
53      
54      /**
55       * Luo monikulmion annetuista kulmapisteiden
56       * x-, y- ja z-koordinaateista
57       * @param xpoints taulukko kulmapisteiden x-koordinaateista
58       * @param ypoints taulukko kulmapisteiden y-koordinaateista
59       * @param zpoints taulikko kulmapisteiden z-koordinaateista
60       */
61      public Polygon(double[] xpoints, double[] ypoints, double[] zpoints) {
62          super();
63          if (xpoints.length < ypoints.length) this.count = xpoints.length;
64          else this.count = ypoints.length;
65          initialize();
66          for (int i = 0; i < this.count; i++) this.ps[i] = new RPoint(xpoints[i], ypoints[i], zpoints[i]); // NOPMD, pakko luoda
67      }
68      
69      /**
70       * Luo kaksi- tai kolmiulotteisen monikulmion annetuista kulmapisteistä, esimerkiksi:
71       * <pre>
72       *      double[][] points = {{2, 6}, {5, 5}, {-1, 2.5}}
73       *      Polygon p = new Poylgon(points);
74       *      
75       *      Luo täytetyn monikulmion jonka kärkipisteet ovat (2, 6), (5, 5) ja (-1, 2.5)
76       * </pre>
77       * @param points 
78       */
79      public Polygon(double[][] points) {
80          super();
81          int dim = 4;
82          for (int i = 0; i < points.length; i++) {
83              if (points[i].length < dim) dim = points[i].length;
84          }
85          this.count = points.length;
86          initialize();
87          for (int i = 0; i < getCount(); i++) {
88              if (dim == 2) this.ps[i] = new RPoint(points[i][0], points[i][1]); // NOPMD, pakko luoda
89              if (dim == 3) this.ps[i] = new RPoint(points[i][0], points[i][1], points[i][2]); // NOPMD, pakko luoda
90          }
91      }
92      
93      /**
94       * Asettaa uudet kulmapisteet
95       * @param points uudet kulmapisteet
96       */
97      public void setPoints(double[][] points) {
98          int dim = 4;
99          for (int i = 0; i < points.length; i++) {
100             if (points[i].length < dim) dim = points[i].length;
101         }
102         this.count = points.length;
103         initialize();
104         for (int i = 0; i < this.count; i++) {
105             if (dim == 2) this.ps[i] = new RPoint(points[i][0], points[i][1]); // NOPMD, pakko luoda
106             if (dim == 3) this.ps[i] = new RPoint(points[i][0], points[i][1], points[i][2]); // NOPMD, pakko luoda
107         }
108         redraw();
109     }
110     
111     /**
112      * Asettaa uudet kulmapisteet
113      * @param points uudet kulmapisteet
114      */
115     public void setPoints(RPoint[] points) {
116          this.count = points.length;
117          initialize();
118          for (int i = 0; i < this.count; i++) {
119              this.ps[i] = points[i];
120          }
121          redraw();
122     }
123     
124     /**
125      * Luo monikulmion annetuista kulmapisteistä jotka ovat RPoint olioita
126      * @param points taulukko kulmapisteistä jotka ovat RPoint-olioita
127      */
128     public Polygon(RPoint[] points) {
129         super();
130         this.count = points.length;
131         initialize();
132         for (int i = 0; i < points.length; i++) {
133             this.ps[i] = points[i];
134         }
135     }
136     
137     /**
138      * Luo monikulmion kulmapisteille oikean kokoisen RPoint-taulukon
139      */
140     protected void initialize() {
141         this.ps = new RPoint[getCount()];
142     }
143     
144     /**
145      * Muuntaa monikulmion oikeat kärkipisteet näytän pisteiksi annetulla muunnosmatriisilla
146      * @param a muunnosmatriisi
147      * @return monikulmion kärkipisteiden koordinaatit näytällä
148      */
149     protected int[][] makeScreenPoints(Matrix a) {
150         int[][] sPoints = new int[2][getCount()];
151         SPoint sp = new SPoint(0,0);
152         for (int i = 0; i < this.getCount(); i++) {
153             a.transform(this.ps[i],sp);
154             sPoints[0][i] = sp.getX();
155             sPoints[1][i] = sp.getY();
156         }
157         return sPoints;
158     }    
159     
160     /**
161      * Antaa kärkipisteiden lukumäärän
162      * @return kärkipisteiden lukumäärä
163      */
164     public final int getCount() {
165         return count;
166     }
167     
168     /**
169      * Lisää monikulmioon yhden kärkipisteen joka on RPoint-oli
170      * @param point lisättävä kärkipiste
171      * @return tämä monikulmio lisäyksen jälkeen
172      */
173     public Polygon add(RPoint point) {
174         if ( ps.length <= this.count ) {
175             RPoint newps[] = new RPoint[getCount() + 20];
176             for (int i=0; i<this.count; i++)
177                 newps[i] = ps[i];
178             ps = newps;
179         }
180         ps[this.count++] = point;
181         redraw();
182         return this;
183     }
184     
185     /**
186      * Lisää monikulmioon yhden kärkipisteen
187      * @param x lisättävän kärkipisteen x-koordinaatti
188      * @param y lisättävän kärkipisteen y-koordinaatti
189      * @return tämä monikulmio lisäyksen jälkeen
190      */
191     public Polygon add(double x, double y) {
192         return add(new RPoint(x,y));   
193     }
194     
195     /**
196      * Lisää monikulmioon yhden kärkipisteen
197      * @param x lisättävän kärkipisteen x-koordinaatti
198      * @param y lisättävän kärkipisteen y-koordinaatti
199      * @param z lisättävän kärkipisteen z-koordinaatti
200      * @return tämä monikulmio lisäyksen jälkeen
201      */
202     public Polygon add(double x, double y, double z) {
203         return add(new RPoint(x,y,z));   
204     }
205     
206     @Override
207     protected void drawShape(Graphics g, Matrix a) {
208         int[][] sPoints = makeScreenPoints(a);
209         g.drawPolygon(sPoints[0], sPoints[1], getCount());
210     }   
211 }
212