001/*
002 * To change this template, choose Tools | Templates
003 * and open the template in the editor.
004 */
005package armyc2.c5isr.graphics2d;
006/**
007 *
008*
009 */
010public class Rectangle implements Shape {
011    public int x=0;
012    public int y=0;
013    public int width=0;
014    public int height=0;
015    public Rectangle()
016    {
017        x=0;
018        y=0;
019        width=0;
020        height=0;
021    }
022
023    public Rectangle(Rectangle2D rect)
024    {
025        this((int) rect.x, (int) rect.y, (int) rect.width, (int) rect.height);
026    }
027
028    public Rectangle(Rectangle rect)
029    {
030        this(rect.x, rect.y, rect.width, rect.height);
031    }
032
033    public Rectangle(int x1, int y1, int width1, int height1)
034    {
035        x=x1;
036        y=y1;
037        width=width1;
038        height=height1;
039    }
040    public Rectangle getBounds()
041    {
042        return this;
043    }
044    public PathIterator getPathIterator(AffineTransform at)
045    {
046        return null;
047    }
048    public boolean intersects(Rectangle2D rect)
049    {
050        if(x+width<rect.x)
051            return false;
052        if(x>rect.x+rect.width)
053            return false;
054        if(y+height<rect.y)
055            return false;
056        if(y>rect.y+rect.height)
057            return false;
058        
059        return true;
060    }
061
062    public boolean intersects(Rectangle rect)
063    {
064        return this.intersects(rect.x, rect.y, rect.width, rect.height);
065    }
066
067    public boolean intersects(double x1, double y1, double width1, double height1)
068    {
069        if(x+width<x1)
070            return false;
071        if(x>x1+width1)
072            return false;
073        if(y+height<y1)
074            return false;
075        if(y>y1+height1)
076            return false;
077        
078        return true;
079    }
080    public boolean contains (int x1, int y1)
081    {
082        if(x<=x1 && x1<=x+width  && 
083                y<=y1 && y1<=y+height)
084            return true;
085        else return false;
086    }
087    public boolean contains (int x1, int y1, int width1, int height1)
088    {                             
089        if(this.contains(x1, y1) && this.contains(x1+width1, y1+height1))
090            return true;
091        else return false;
092    }
093    public boolean contains (Point2D pt)
094    {
095        if(x<=pt.getX() && pt.getX()<=x+width  && 
096                y<=pt.getY() && pt.getY()<=y+height)
097            return true;
098        else return false;
099    }
100    public Rectangle2D getBounds2D()
101    {
102        return new Rectangle2D.Double(x,y,width,height);
103    }
104     public int getX()
105    {
106        return x;
107    }
108    public int getY()
109    {
110        return y;
111    }
112    public int getMinX()
113    {
114        return x;
115    }
116    public int getMinY()
117    {
118        return y;
119    }
120    public int getMaxX()
121    {
122        return x+width;
123    }
124    public int getMaxY()
125    {
126        return y+height;
127    }
128    public int getHeight()
129    {
130        return height;
131    }
132    public int getWidth()
133    {
134        return width;
135    }
136
137    public void grow(int h, int v)
138    {
139        long x0 = this.x;
140        long y0 = this.y;
141        long x1 = this.width;
142        long y1 = this.height;
143        x1 += x0;
144        y1 += y0;
145
146        x0 -= h;
147        y0 -= v;
148        x1 += h;
149        y1 += v;
150
151        if (x1 < x0) {
152            // Non-existant in X direction
153            // Final width must remain negative so subtract x0 before
154            // it is clipped so that we avoid the risk that the clipping
155            // of x0 will reverse the ordering of x0 and x1.
156            x1 -= x0;
157            if (x1 < Integer.MIN_VALUE) x1 = Integer.MIN_VALUE;
158            if (x0 < Integer.MIN_VALUE) x0 = Integer.MIN_VALUE;
159            else if (x0 > Integer.MAX_VALUE) x0 = Integer.MAX_VALUE;
160        } else { // (x1 >= x0)
161            // Clip x0 before we subtract it from x1 in case the clipping
162            // affects the representable area of the rectangle.
163            if (x0 < Integer.MIN_VALUE) x0 = Integer.MIN_VALUE;
164            else if (x0 > Integer.MAX_VALUE) x0 = Integer.MAX_VALUE;
165            x1 -= x0;
166            // The only way x1 can be negative now is if we clipped
167            // x0 against MIN and x1 is less than MIN - in which case
168            // we want to leave the width negative since the result
169            // did not intersect the representable area.
170            if (x1 < Integer.MIN_VALUE) x1 = Integer.MIN_VALUE;
171            else if (x1 > Integer.MAX_VALUE) x1 = Integer.MAX_VALUE;
172        }
173
174        if (y1 < y0) {
175            // Non-existant in Y direction
176            y1 -= y0;
177            if (y1 < Integer.MIN_VALUE) y1 = Integer.MIN_VALUE;
178            if (y0 < Integer.MIN_VALUE) y0 = Integer.MIN_VALUE;
179            else if (y0 > Integer.MAX_VALUE) y0 = Integer.MAX_VALUE;
180        } else { // (y1 >= y0)
181            if (y0 < Integer.MIN_VALUE) y0 = Integer.MIN_VALUE;
182            else if (y0 > Integer.MAX_VALUE) y0 = Integer.MAX_VALUE;
183            y1 -= y0;
184            if (y1 < Integer.MIN_VALUE) y1 = Integer.MIN_VALUE;
185            else if (y1 > Integer.MAX_VALUE) y1 = Integer.MAX_VALUE;
186        }
187
188        this.x = (int) x0;
189        this.y = (int) y0;
190        this.width = (int) x1;
191        this.height = (int) y1;
192    }
193
194    public void setRect(Rectangle rect)
195    {
196        x=rect.x;
197        y=rect.y;
198        width=rect.width;
199        height=rect.height;
200    }
201
202    public void setRect(int x, int y, int width, int height) {
203        this.x = x;
204        this.y = y;
205        this.width = width;
206        this.height = height;
207    }
208
209    public void setLocation(int x, int y) {
210        this.x = x;
211        this.y = y;
212    }
213
214    public void add(Point2D pt) {
215        int newx = (int) pt.getX();
216        int newy = (int) pt.getY();
217        if ((width | height) < 0) {
218            this.x = newx;
219            this.y = newy;
220            this.width = this.height = 0;
221            return;
222        }
223        int x1 = this.x;
224        int y1 = this.y;
225        long x2 = this.width;
226        long y2 = this.height;
227        x2 += x1;
228        y2 += y1;
229        if (x1 > newx) x1 = newx;
230        if (y1 > newy) y1 = newy;
231        if (x2 < newx) x2 = newx;
232        if (y2 < newy) y2 = newy;
233        x2 -= x1;
234        y2 -= y1;
235        if (x2 > Integer.MAX_VALUE) x2 = Integer.MAX_VALUE;
236        if (y2 > Integer.MAX_VALUE) y2 = Integer.MAX_VALUE;
237        this.x = x1;
238        this.y = y1;
239        this.width = (int) x2;
240        this.height = (int) y2;
241    }
242
243    public Rectangle union(Rectangle r) {
244        long tx2 = this.width;
245        long ty2 = this.height;
246        if ((tx2 | ty2) < 0) {
247            // This rectangle has negative dimensions...
248            // If r has non-negative dimensions then it is the answer.
249            // If r is non-existant (has a negative dimension), then both
250            // are non-existant and we can return any non-existant rectangle
251            // as an answer.  Thus, returning r meets that criterion.
252            // Either way, r is our answer.
253            return new Rectangle(r);
254        }
255        long rx2 = r.width;
256        long ry2 = r.height;
257        if ((rx2 | ry2) < 0) {
258            return new Rectangle(this);
259        }
260        int tx1 = this.x;
261        int ty1 = this.y;
262        tx2 += tx1;
263        ty2 += ty1;
264        int rx1 = r.x;
265        int ry1 = r.y;
266        rx2 += rx1;
267        ry2 += ry1;
268        if (tx1 > rx1) tx1 = rx1;
269        if (ty1 > ry1) ty1 = ry1;
270        if (tx2 < rx2) tx2 = rx2;
271        if (ty2 < ry2) ty2 = ry2;
272        tx2 -= tx1;
273        ty2 -= ty1;
274        // tx2,ty2 will never underflow since both original rectangles
275        // were already proven to be non-empty
276        // they might overflow, though...
277        if (tx2 > Integer.MAX_VALUE) tx2 = Integer.MAX_VALUE;
278        if (ty2 > Integer.MAX_VALUE) ty2 = Integer.MAX_VALUE;
279        return new Rectangle(tx1, ty1, (int) tx2, (int) ty2);
280    }
281}