KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > prefuse > util > display > Clip


1 package prefuse.util.display;
2
3 import java.awt.geom.AffineTransform JavaDoc;
4 import java.awt.geom.Rectangle2D JavaDoc;
5 import java.util.logging.Logger JavaDoc;
6
7 /**
8  * Represents a clipping rectangle in a prefuse <code>Display</code>.
9  *
10  * @author <a HREF="http://jheer.org">jeffrey heer</a>
11  */

12 public class Clip {
13     
14     private static final byte EMPTY = 0;
15     private static final byte INUSE = 1;
16     private static final byte INVALID = 2;
17     
18     private double[] clip = new double[8];
19     private byte status = INVALID;
20     
21     /**
22      * Reset the clip to an empty status.
23      */

24     public void reset() {
25         status = EMPTY;
26     }
27     
28     /**
29      * Invalidate the clip. In this state, the clip contents have no meaning.
30      */

31     public void invalidate() {
32         status = INVALID;
33     }
34        
35     /**
36      * Set the clip contents, and set the status to valid and in use.
37      * @param c the clip whose contents should be copied
38      */

39     public void setClip(Clip c) {
40         status = INUSE;
41         System.arraycopy(c.clip, 0, clip, 0, clip.length);
42     }
43     
44     /**
45      * Set the clip contents, and set the status to valid and in use.
46      * @param r the clip contents to copy
47      */

48     public void setClip(Rectangle2D JavaDoc r) {
49         setClip(r.getX(),r.getY(),r.getWidth(),r.getHeight());
50     }
51     
52     /**
53      * Set the clip contents, and set the status to valid and in use.
54      * @param x the minimum x-coordinate
55      * @param y the minimum y-coorindate
56      * @param w the clip width
57      * @param h the clip height
58      */

59     public void setClip(double x, double y, double w, double h) {
60         status = INUSE;
61         clip[0] = x;
62         clip[1] = y;
63         clip[6] = x+w;
64         clip[7] = y+h;
65     }
66     
67     /**
68      * Transform the clip contents. A new clip region will be created
69      * which is the bounding box of the transformed region.
70      * @param at the affine transform
71      */

72     public void transform(AffineTransform JavaDoc at) {
73         // make the extra corner points valid
74
clip[2] = clip[0]; clip[3] = clip[7];
75         clip[4] = clip[6]; clip[5] = clip[1];
76         
77         // transform the points
78
at.transform(clip,0,clip,0,4);
79         
80         // make safe against rotation
81
double xmin = clip[0], ymin = clip[1];
82         double xmax = clip[6], ymax = clip[7];
83         for ( int i=0; i<7; i+=2 ) {
84             if ( clip[i] < xmin )
85                 xmin = clip[i];
86             if ( clip[i] > xmax )
87                 xmax = clip[i];
88             if ( clip[i+1] < ymin )
89                 ymin = clip[i+1];
90             if ( clip[i+1] > ymax )
91                 ymax = clip[i+1];
92         }
93         clip[0] = xmin; clip[1] = ymin;
94         clip[6] = xmax; clip[7] = ymax;
95     }
96     
97     /**
98      * Limit the clip such that it fits within the specified region.
99      * @param x1 the minimum x-coordinate
100      * @param y1 the minimum y-coorindate
101      * @param x2 the maximum x-coordinate
102      * @param y2 the maximum y-coorindate
103      */

104     public void limit(double x1, double y1, double x2, double y2) {
105         clip[0] = Math.max(clip[0],x1);
106         clip[1] = Math.max(clip[1],y1);
107         clip[6] = Math.min(clip[6],x2);
108         clip[7] = Math.min(clip[7],y2);
109     }
110     
111     /**
112      * Indicates if this Clip intersects the given rectangle expanded
113      * by the additional margin pace.
114      * @param r the rectangle to test for intersect
115      * @param margin additional margin "bleed" to include in the intersection
116      * @return true if the clip intersects the expanded region, false otherwise
117      */

118     public boolean intersects(Rectangle2D JavaDoc r, double margin) {
119         double tw = clip[6]-clip[0];
120         double th = clip[7]-clip[1];
121         double rw = r.getWidth();
122         double rh = r.getHeight();
123         if (rw < 0 || rh < 0 || tw < 0 || th < 0) {
124             return false;
125         }
126         double tx = clip[0];
127         double ty = clip[1];
128         double rx = r.getX()-margin;
129         double ry = r.getY()-margin;
130         rw += rx+2*margin;
131         rh += ry+2*margin;
132         tw += tx;
133         th += ty;
134         // overflow || intersect
135
return ((rw < rx || rw > tx) &&
136                 (rh < ry || rh > ty) &&
137                 (tw < tx || tw > rx) &&
138                 (th < ty || th > ry));
139     }
140       
141     /**
142      * Union this clip with another clip. As a result, this clip
143      * will become a bounding box around the two original clips.
144      * @param c the clip to union with
145      */

146     public void union(Clip c) {
147         if ( status == INVALID )
148             return;
149         if ( status == EMPTY ) {
150             setClip(c);
151             status = INUSE;
152             return;
153         }
154         clip[0] = Math.min(clip[0], c.clip[0]);
155         clip[1] = Math.min(clip[1], c.clip[1]);
156         clip[6] = Math.max(clip[6], c.clip[6]);
157         clip[7] = Math.max(clip[7], c.clip[7]);
158     }
159     
160     /**
161      * Union this clip with another region. As a result, this clip
162      * will become a bounding box around the two original regions.
163      * @param r the rectangle to union with
164      */

165     public void union(Rectangle2D JavaDoc r) {
166         if ( status == INVALID )
167             return;
168         
169         double minx = r.getMinX();
170         double miny = r.getMinY();
171         double maxx = r.getMaxX();
172         double maxy = r.getMaxY();
173         
174         if ( Double.isNaN(minx) || Double.isNaN(miny) ||
175              Double.isNaN(maxx) || Double.isNaN(maxy) ) {
176             Logger.getLogger(getClass().getName()).warning(
177                 "Union with invalid clip region: "+r);
178             return;
179         }
180         
181         if ( status == EMPTY ) {
182             setClip(r);
183             status = INUSE;
184             return;
185         }
186         clip[0] = Math.min(clip[0], minx);
187         clip[1] = Math.min(clip[1], miny);
188         clip[6] = Math.max(clip[6], maxx);
189         clip[7] = Math.max(clip[7], maxy);
190     }
191     
192     /**
193      * Union this clip with another region. As a result, this clip
194      * will become a bounding box around the two original regions.
195      * @param x the x-coordinate of the region to union with
196      * @param y the y-coordinate of the region to union with
197      * @param w the width of the region to union with
198      * @param h the height of the region to union with
199      */

200     public void union(double x, double y, double w, double h) {
201         if ( status == INVALID )
202             return;
203         if ( status == EMPTY ) {
204             setClip(x,y,w,h);
205             status = INUSE;
206             return;
207         }
208         clip[0] = Math.min(clip[0], x);
209         clip[1] = Math.min(clip[1], y);
210         clip[6] = Math.max(clip[6], x+w);
211         clip[7] = Math.max(clip[7], y+h);
212     }
213     
214     /**
215      * Intersect this clip with another region. As a result, this
216      * clip will become the intersecting area of the two regions.
217      * @param c the clip to intersect with
218      */

219     public void intersection(Clip c) {
220         if ( status == INVALID )
221             return;
222         if ( status == EMPTY ) {
223             setClip(c);
224             status = INUSE;
225             return;
226         }
227         clip[0] = Math.max(clip[0], c.clip[0]);
228         clip[1] = Math.max(clip[1], c.clip[1]);
229         clip[6] = Math.min(clip[6], c.clip[6]);
230         clip[7] = Math.min(clip[7], c.clip[7]);
231     }
232     
233     /**
234      * Intersect this clip with another region. As a result, this
235      * clip will become the intersecting area of the two regions.
236      * @param r the rectangle to intersect with
237      */

238     public void intersection(Rectangle2D JavaDoc r) {
239         if ( status == INVALID )
240             return;
241         if ( status == EMPTY ) {
242             setClip(r);
243             status = INUSE;
244             return;
245         }
246         clip[0] = Math.max(clip[0], r.getMinX());
247         clip[1] = Math.max(clip[1], r.getMinY());
248         clip[6] = Math.min(clip[6], r.getMaxX());
249         clip[7] = Math.min(clip[7], r.getMaxY());
250     }
251     
252     /**
253      * Intersect this clip with another region. As a result, this
254      * clip will become the intersecting area of the two regions.
255      * @param x the x-coordinate of the region to intersect with
256      * @param y the y-coordinate of the region to intersect with
257      * @param w the width of the region to intersect with
258      * @param h the height of the region to intersect with
259      */

260     public void intersection(double x, double y, double w, double h) {
261         if ( status == INVALID )
262             return;
263         if ( status == EMPTY ) {
264             setClip(x,y,w,h);
265             status = INUSE;
266             return;
267         }
268         clip[0] = Math.max(clip[0], x);
269         clip[1] = Math.max(clip[1], y);
270         clip[6] = Math.min(clip[6], x+w);
271         clip[7] = Math.min(clip[7], y+h);
272     }
273     
274     /**
275      * Minimally expand the clip such that each coordinate is an integer.
276      */

277     public void expandToIntegerLimits() {
278         clip[0] = Math.floor(clip[0]);
279         clip[1] = Math.floor(clip[1]);
280         clip[6] = Math.ceil(clip[6]);
281         clip[7] = Math.ceil(clip[7]);
282     }
283     
284     /**
285      * Expand the clip in all directions by the given value.
286      * @param b the value to expand by
287      */

288     public void expand(double b) {
289         clip[0] -= b; clip[1] -= b;
290         clip[6] += b; clip[7] += b;
291     }
292
293     /**
294      * Grow the clip width and height by the given value. The minimum
295      * coordinates will be unchanged.
296      * @param b the value to grow the width and height by
297      */

298     public void grow(double b) {
299         clip[6] += b; clip[7] += b;
300     }
301     
302     /**
303      * Get the minimum x-coordinate.
304      * @return the minimum x-coordinate
305      */

306     public double getMinX() {
307         return clip[0];
308     }
309     
310     /**
311      * Get the minimum y-coordinate.
312      * @return the minimum y-coordinate
313      */

314     public double getMinY() {
315         return clip[1];
316     }
317     
318     /**
319      * Get the maximum x-coordinate.
320      * @return the maximum x-coordinate
321      */

322     public double getMaxX() {
323         return clip[6];
324     }
325     
326     /**
327      * Get the maximum y-coordinate.
328      * @return the maximum y-coordinate
329      */

330     public double getMaxY() {
331         return clip[7];
332     }
333     
334     /**
335      * Get the clip's width
336      * @return the clip width
337      */

338     public double getWidth() {
339         return clip[6]-clip[0];
340     }
341
342     /**
343      * Get the clip's height
344      * @return the clip height
345      */

346     public double getHeight() {
347         return clip[7]-clip[1];
348     }
349     
350     /**
351      * Indicates if the clip is set to an empty status.
352      * @return true if the clip is set to empty, false otherwise
353      */

354     public boolean isEmpty() {
355         return status==EMPTY;
356     }
357     
358     /**
359      * Indicates if the clip is set to an invalid status.
360      * @return true if the clip is set to invalid, false otherwise
361      */

362     public boolean isInvalid() {
363         return status==INVALID;
364     }
365     
366     // ------------------------------------------------------------------------
367

368     /**
369      * @see java.lang.Object#equals(java.lang.Object)
370      */

371     public boolean equals(Object JavaDoc o) {
372         if ( o instanceof Rectangle2D JavaDoc ) {
373             Rectangle2D JavaDoc r = (Rectangle2D JavaDoc)o;
374             return ( r.getMinX()==clip[0] && r.getMinY()==clip[1] &&
375                      r.getMaxX()==clip[6] && r.getMaxY()==clip[7] );
376         } else if ( o instanceof Clip ) {
377             Clip r = (Clip)o;
378             if ( r.status == status ) {
379                 if ( status == Clip.INUSE )
380                     return ( r.clip[0]==clip[0] && r.clip[1]==clip[1] &&
381                             r.clip[6]==clip[6] && r.clip[7]==clip[7] );
382                 else
383                     return true;
384             } else {
385                 return false;
386             }
387         } else {
388             return false;
389         }
390     }
391     
392     /**
393      * @see java.lang.Object#toString()
394      */

395     public String JavaDoc toString() {
396         StringBuffer JavaDoc sb = new StringBuffer JavaDoc(20);
397         sb.append("Clip[");
398         switch (status) {
399         case INVALID:
400             sb.append("invalid");
401             break;
402         case EMPTY:
403             sb.append("empty");
404             break;
405         default:
406             sb.append(clip[0]).append(",");
407             sb.append(clip[1]).append(",");
408             sb.append(clip[6]).append(",");
409             sb.append(clip[7]);
410         }
411         sb.append("]");
412         return sb.toString();
413     }
414     
415 } // end of class Clip
416
Popular Tags