001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one or more
003 *  contributor license agreements.  See the NOTICE file distributed with
004 *  this work for additional information regarding copyright ownership.
005 *  The ASF licenses this file to You under the Apache License, Version 2.0
006 *  (the "License"); you may not use this file except in compliance with
007 *  the License.  You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 *  Unless required by applicable law or agreed to in writing, software
012 *  distributed under the License is distributed on an "AS IS" BASIS,
013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 *  See the License for the specific language governing permissions and
015 *  limitations under the License.
016 */
017/**
018 * @author Denis M. Kishenko
019 * @version $Revision$
020 */
021//THIS CLASS MODIFIED TO WORK ON ANDROID
022
023package armyc2.c5isr.graphics2d;
024
025
026import android.graphics.Path;
027import android.graphics.RectF;
028import java.util.Arrays;
029
030/**
031 *
032*
033 */
034public class Polygon {
035
036    /**
037     * The points buffer capacity
038     */
039    private static final int BUFFER_CAPACITY = 4;
040
041    public int npoints;
042    public int xpoints[];
043    public int ypoints[];
044    protected Rectangle bounds;
045
046    public Polygon() {
047        xpoints = new int[BUFFER_CAPACITY];
048        ypoints = new int[BUFFER_CAPACITY];
049    }
050
051    /**
052     *
053     * @param xpoints
054     * @param ypoints
055     * @param npoints
056     */
057    public Polygon(int xpoints[], int ypoints[], int npoints) {
058
059        if (npoints > xpoints.length || npoints > ypoints.length) {
060            // awt.111=Parameter npoints is greater than array length
061            throw new IndexOutOfBoundsException("Parameter npoints is greater than array length");
062        }
063
064        if (npoints < 0) {
065            // awt.112=Negative number of points
066            throw new NegativeArraySizeException("Negative number of points");
067        }
068
069        this.npoints = npoints;
070        this.xpoints = Arrays.copyOf(xpoints, npoints);
071        this.ypoints = Arrays.copyOf(ypoints, npoints);
072    }
073
074    public void reset() {
075        npoints = 0;
076        bounds = null;
077    }
078    public void invalidate() {
079        bounds = null;
080    }
081
082
083    public void addPoint(int px, int py) {
084        if (npoints == xpoints.length) {
085            int[] tmp;
086
087            tmp = new int[xpoints.length + BUFFER_CAPACITY];
088            System.arraycopy(xpoints, 0, tmp, 0, xpoints.length);
089            xpoints = tmp;
090
091            tmp = new int[ypoints.length + BUFFER_CAPACITY];
092            System.arraycopy(ypoints, 0, tmp, 0, ypoints.length);
093            ypoints = tmp;
094        }
095        xpoints[npoints] = px;
096        ypoints[npoints] = py;
097        npoints++;
098        if (bounds != null) {
099
100            Rectangle temp = new Rectangle(Math.min(bounds.getMinX(), px),
101                    Math.min(bounds.getMinY(), py),
102                    Math.max(bounds.getMaxX() - bounds.getMinX(), px - bounds.getMinX()),
103                    Math.max(bounds.getMaxY() - bounds.getMinY(), py - bounds.getMinY()));
104
105            bounds.setRect(temp.getX(), temp.getY(), temp.getWidth(), temp.getHeight());
106        }
107    }
108
109
110    public Rectangle getBounds() {
111        if (bounds != null) {
112            return bounds;
113        }
114        if (npoints == 0) {
115            return new Rectangle();
116        }
117
118        int bx1 = xpoints[0];
119        int by1 = ypoints[0];
120        int bx2 = bx1;
121        int by2 = by1;
122
123        for (int i = 1; i < npoints; i++) {
124            int x = xpoints[i];
125            int y = ypoints[i];
126            if (x < bx1) {
127                bx1 = x;
128            } else if (x > bx2) {
129                bx2 = x;
130            }
131            if (y < by1) {
132                by1 = y;
133            } else if (y > by2) {
134                by2 = y;
135            }
136        }
137
138        return bounds = new Rectangle(bx1, by1, bx2 - bx1, by2 - by1);
139
140    }
141
142    public Rectangle getBoundingBox() {
143        return getBounds();
144    }
145
146    public boolean contains(Point p) {
147        return contains(p.x, p.y);
148    }
149
150    public boolean contains(int x, int y) {
151        return contains((double) x, (double) y);
152    }
153
154
155
156    public Rectangle2D getBounds2D() {
157        //return getBounds();
158        return null;
159    }//
160
161
162    public boolean contains(double x, double y) {
163        if (npoints <= 2 || !getBoundingBox().contains((int)x, (int)y)) {
164            return false;
165        }
166        int hits = 0;
167
168        int lastx = xpoints[npoints - 1];
169        int lasty = ypoints[npoints - 1];
170        int curx, cury;
171
172        for (int i = 0; i < npoints; lastx = curx, lasty = cury, i++) {
173            curx = xpoints[i];
174            cury = ypoints[i];
175
176            if (cury == lasty) {
177                continue;
178            }
179
180            int leftx;
181            if (curx < lastx) {
182                if (x >= lastx) {
183                    continue;
184                }
185                leftx = curx;
186            } else {
187                if (x >= curx) {
188                    continue;
189                }
190                leftx = lastx;
191            }
192
193            double test1, test2;
194            if (cury < lasty) {
195                if (y < cury || y >= lasty) {
196                    continue;
197                }
198                if (x < leftx) {
199                    hits++;
200                    continue;
201                }
202                test1 = x - curx;
203                test2 = y - cury;
204            } else {
205                if (y < lasty || y >= cury) {
206                    continue;
207                }
208                if (x < leftx) {
209                    hits++;
210                    continue;
211                }
212                test1 = x - lastx;
213                test2 = y - lasty;
214            }
215
216            if (test1 < (test2 / (lasty - cury) * (lastx - curx))) {
217                hits++;
218            }
219        }
220
221        return ((hits & 1) != 0);
222    }
223
224
225
226    public boolean contains(Point2D p) {
227        return contains(p.getX(), p.getY());
228    }
229
230
231    public boolean intersects(double x, double y, double w, double h) {
232        if (npoints <= 0 || !getBoundingBox().intersects(x, y, w, h)) {
233            return false;
234        }
235
236        if (bounds != null) {
237            float fx = (float) x;
238            float fy = (float) y;
239            float fw = (float) w;
240            float fh = (float) h;
241//not sure if math is correct here
242            Path that = new Path();
243//start
244            that.moveTo(fx, fy);
245//go right
246            that.lineTo(fx + fw, fy);
247//go down
248            that.lineTo(fx + fw, fy - fh);
249//go left
250            that.lineTo(fx, fy - fh);
251//close
252            that.close();
253//bounds holder
254            RectF thatBounds = new RectF();
255            RectF rectf=new RectF((float)bounds.x,(float)bounds.y,(float)bounds.x+(float)bounds.width,(float)bounds.y+(float)bounds.height);
256            return RectF.intersects(rectf, thatBounds);
257        } 
258        else 
259        {
260            return false;
261        }        
262    }
263
264    public boolean intersects(Rectangle2D r) {
265        return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
266    }
267
268    public boolean contains(double x, double y, double w, double h) {
269        if (npoints <= 0 || !getBoundingBox().intersects(x, y, w, h)) {
270            return false;
271        }
272
273        return false;
274    }
275
276    public boolean contains(Rectangle2D r) {
277        return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
278    }
279
280
281    public PathIterator getPathIterator(AffineTransform at) {
282
283        PathIterator pi=new PathIterator(null);
284        int j=0;
285        if(npoints>0)
286        {
287            pi.moveTo(xpoints[0], ypoints[0]);
288            for(j=1;j<npoints;j++)
289            {
290                pi.lineTo(xpoints[j], ypoints[j]);
291            }
292        }
293        pi.reset();
294        return pi;        
295    }
296    public PathIterator getPathIterator(AffineTransform at, double flatness) {
297        return getPathIterator(at);
298    }
299}