Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/xerox/VTM/glyphs/VImage.java


1   /*   FILE: VImage.java
2    *   DATE OF CREATION:   Jan 09 2001
3    *   AUTHOR :            Emmanuel Pietriga (emmanuel.pietriga@xrce.xerox.com)
4    *   MODIF:              Thu Jul 10 16:42:10 2003 by Emmanuel Pietriga (emmanuel@w3.org, emmanuel@claribole.net)
5    *   Copyright (c) Xerox Corporation, XRCE/Contextual Computing, 2002. All Rights Reserved
6    *
7    * This library is free software; you can redistribute it and/or
8    * modify it under the terms of the GNU Lesser General Public
9    * License as published by the Free Software Foundation; either
10   * version 2.1 of the License, or (at your option) any later version.
11   * 
12   * This library is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15   * Lesser General Public License for more details.
16   *
17   * For full terms see the file COPYING.
18   */
19  
20  package com.xerox.VTM.glyphs;
21  
22  import java.awt.Color;
23  import java.awt.Graphics2D;
24  import java.awt.Font;
25  import java.awt.Stroke;
26  import java.awt.BasicStroke;
27  import java.awt.Image;
28  import java.awt.geom.AffineTransform;
29  import java.lang.Math;
30  import java.util.Vector;
31  import javax.swing.*;
32  import com.xerox.VTM.engine.*;
33  
34  /**
35   * Image (rectangular) - cannot be reoriented
36   * @author Emmanuel Pietriga
37   **/
38  
39  public class VImage extends Glyph implements RectangularShape,Cloneable {
40  
41      public static short DRAW_BORDER_NEVER=0;
42      public static short DRAW_BORDER_MOUSE_INSIDE=1;
43      public static short DRAW_BORDER_ALWAYS=2;
44  
45      /**half width and height in virtual space*/
46      long vw,vh;
47      /**aspect ratio (width divided by height)*/
48      float ar;
49  
50      AffineTransform at;
51  
52      /**draw border policy 0=never draw border 1=draw border if cursor inside 2=always draw border*/
53      short drawBorder=DRAW_BORDER_NEVER;
54  
55      ProjImage[] pc;
56  
57      Image image;
58  
59      boolean zoomSensitive=true;
60  
61      float scaleFactor=1.0f;
62  
63      float trueCoef=1.0f;
64  
65      /**
66       *@param img image to be displayed
67       */
68      public VImage(Image img){
69    vx=0;
70    vy=0;
71    vz=0;
72    image=img;
73    vw=image.getWidth(null)/2;
74    vh=image.getHeight(null)/2;
75    if (vw==0 && vh==0){ar=1.0f;}
76    else {ar=(float)vw/(float)vh;}
77    computeSize();
78    orient=0;
79    setColor(Color.black);  //not actually used
80    setBorderColor(Color.black);
81      }
82  
83      /**
84       *@param x coordinate in virtual space
85       *@param y coordinate in virtual space
86       *@param z altitude
87       *@param img image to be displayed
88       */
89      public VImage(long x,long y,float z,Image img){
90    vx=x;
91    vy=y;
92    vz=z;
93    image=img;
94    vw=Math.round(image.getWidth(null)/2.0);
95    vh=Math.round(image.getHeight(null)/2.0);
96    if (vw==0 && vh==0){ar=1.0f;}
97    else {ar=(float)vw/(float)vh;}
98    computeSize();
99    orient=0;
100   setColor(Color.black);  //not actually used
101   setBorderColor(Color.black);
102     }
103 
104     /**called when glyph is created in order to create the initial set of projected coordinates wrt the number of cameras in the space
105      *@param nbCam current number of cameras in the virtual space
106      */
107     public void initCams(int nbCam){
108   pc=new ProjImage[nbCam];
109   for (int i=0;i<nbCam;i++){
110       pc[i]=new ProjImage();
111   }
112     }
113 
114     /**used internally to create new projected coordinates to use with the new camera
115      *@param verifIndex camera index, just to be sure that the number of projected coordinates is consistent with the number of cameras
116      */
117     public void addCamera(int verifIndex){
118   if (pc!=null){
119       if (verifIndex==pc.length){
120     ProjImage[] ta=pc;
121     pc=new ProjImage[ta.length+1];
122     for (int i=0;i<ta.length;i++){
123         pc[i]=ta[i];
124     }
125     pc[pc.length-1]=new ProjImage();
126       }
127       else {System.err.println("VImage:Error while adding camera "+verifIndex);}
128   }
129   else {
130       if (verifIndex==0){
131     pc=new ProjImage[1];
132     pc[0]=new ProjImage();
133       }
134       else {System.err.println("VImage:Error while adding camera "+verifIndex);}
135   }
136     }
137 
138     /**if a camera is removed from the virtual space, we should delete the corresponding projected coordinates, but do not modify the array it self because we do not want to change other cameras' index - just point to null*/
139     public void removeCamera(int index){
140   pc[index]=null;
141     }
142 
143     /**reset prevMouseIn for projected coordinates nb i*/
144     public void resetMouseIn(int i){
145   if (pc[i]!=null){pc[i].prevMouseIn=false;}
146     }
147 
148     /**get orientation*/
149     public float getOrient(){return orient;}
150 
151     /**set orientation (absolute) - has no effect*/
152     public void orientTo(float angle){}
153 
154     /**get size (bounding circle radius)*/
155     public float getSize(){return size;}
156 
157     /**compute size (bounding circle radius)*/
158     void computeSize(){
159   size=(float)Math.sqrt(Math.pow(vw,2)+Math.pow(vh,2));
160     }
161 
162     /**set absolute half width - aspect ratio is automatically maintained (height modified accordingly)*/
163     public void setWidth(long w){
164   vw=w;
165   vh=Math.round((float)vw/ar);
166   computeSize();
167   scaleFactor=(float)(size/Math.sqrt(Math.pow(image.getWidth(null)/2,2)+Math.pow(image.getHeight(null)/2,2)));
168   try{vsm.repaintNow();}catch(NullPointerException e){}
169     }
170 
171     /**set absolute half height (no effect: use setImage)*/
172     public void setHeight(long h){
173   vh=h;
174   vw=Math.round(vh*ar);
175   computeSize();
176   scaleFactor=(float)(size/Math.sqrt(Math.pow(image.getWidth(null)/2,2)+Math.pow(image.getHeight(null)/2,2)));
177   try{vsm.repaintNow();}catch(NullPointerException e){}
178     }
179 
180     /**get half width*/
181     public long getWidth(){return vw;}
182 
183     /**get half height*/
184     public long getHeight(){return vh;}
185 
186     /**set absolute size by setting bounding circle radius */
187     public void sizeTo(float radius){
188   size=radius;
189   vw=(long)Math.round((size*ar)/(Math.sqrt(Math.pow(ar,2)+1)));
190   vh=(long)Math.round((size)/(Math.sqrt(Math.pow(ar,2)+1)));
191   scaleFactor=(float)(size/Math.sqrt(Math.pow(image.getWidth(null)/2,2)+Math.pow(image.getHeight(null)/2,2)));
192   try{vsm.repaintNow();}catch(NullPointerException e){}
193     }
194 
195     /**multiply bounding circle radius by factor*/
196     public void reSize(float factor){
197   size*=factor;
198   vw=(long)Math.round((size*ar)/(Math.sqrt(Math.pow(ar,2)+1)));
199   vh=(long)Math.round((size)/(Math.sqrt(Math.pow(ar,2)+1)));
200   scaleFactor=(float)(size/Math.sqrt(Math.pow(image.getWidth(null)/2,2)+Math.pow(image.getHeight(null)/2,2)));
201   try{vsm.repaintNow();}catch(NullPointerException e){}
202     }
203 
204     /**set image to be displayed*/
205     public void setImage(Image i){
206   image=i;
207   vw=Math.round(image.getWidth(null)/2.0);
208   vh=Math.round(image.getHeight(null)/2.0);
209   ar=(float)vw/(float)vh;
210   computeSize();
211   try{vsm.repaintNow();}catch(NullPointerException e){}
212     }
213 
214     /**get the bitmap image to be displayed*/
215     public Image getImage(){
216   return image;
217     }
218 
219     /**if false, image size is not sensitive to zoom (but its size can be changed)*/
220     public void setZoomSensitive(boolean b){
221   if (zoomSensitive!=b){
222       zoomSensitive=b;
223       try{vsm.repaintNow();}catch(NullPointerException e){}
224   }
225     }
226 
227     /**if false, text size is not sensitive to zoom*/
228     public boolean isZoomSensitive(){
229   return zoomSensitive;
230     }
231 
232     /**
233      *@param p one of VImage.DRAW_BORDER_*
234      */
235     public void setDrawBorderPolicy(short p){
236   if (drawBorder!=p){
237       drawBorder=p;
238       try{vsm.repaintNow();}catch(NullPointerException e){/*System.err.println("VSM null in Glyph "+e);*/}
239   }
240     }
241 
242     /**used to find out if glyph completely fills the view (in which case it is not necessary to repaint objects at a lower altitude)*/
243     public boolean fillsView(long w,long h,int camIndex){
244   return false; //can contain transparent pixel (we have no way of knowing without analysing the image data -could be done when constructing the object or setting the image)
245     }
246 
247     /**detects whether the given point is inside this glyph or not 
248      *@param x EXPECTS PROJECTED JPanel COORDINATE
249      *@param y EXPECTS PROJECTED JPanel COORDINATE
250      */
251     public boolean coordInside(int x,int y,int camIndex){
252   if ((x>=(pc[camIndex].cx-pc[camIndex].cw)) && (x<=(pc[camIndex].cx+pc[camIndex].cw)) && (y>=(pc[camIndex].cy-pc[camIndex].ch)) && (y<=(pc[camIndex].cy+pc[camIndex].ch))){return true;}
253   else {return false;}
254     }
255 
256     /**returns 1 if mouse has entered the glyph, -1 if it has exited the glyph, 0 if nothing has changed (meaning it was already inside or outside it)*/
257     public int mouseInOut(int x,int y,int camIndex){
258   if (coordInside(x,y,camIndex)){//if the mouse is inside the glyph
259       if (!pc[camIndex].prevMouseIn){//if it was not inside it last time, mouse has entered the glyph
260     pc[camIndex].prevMouseIn=true;
261     return 1;
262       }
263       else {return 0;}  //if it was inside last time, nothing has changed
264   }
265   else{//if the mouse is not inside the glyph
266       if (pc[camIndex].prevMouseIn){//if it was inside it last time, mouse has exited the glyph
267     pc[camIndex].prevMouseIn=false;
268     return -1;
269       }
270       else {return 0;}  //if it was not inside last time, nothing has changed
271   }
272     }
273 
274     /**project shape in camera coord sys prior to actual painting*/
275     public void project(Camera c,ViewPanel v){
276   int i=c.getIndex();
277   coef=(float)(c.focal/(c.focal+c.altitude));
278   //find coordinates of object's geom center wrt to camera center and project
279   pc[i].cx=Math.round((vx-c.posx)*coef);
280   pc[i].cy=Math.round((vy-c.posy)*coef);
281   //translate in JPanel coords
282   pc[i].cx=(v.getSize().width/2)+pc[i].cx;
283   pc[i].cy=(v.getSize().height/2)-pc[i].cy;
284   //project width and height
285   if (zoomSensitive){pc[i].cw=Math.round(vw*coef);pc[i].ch=Math.round(vh*coef);}else{pc[i].cw=(int)vw;pc[i].ch=(int)vh;}
286     }
287 
288     /**draw glyph
289      *@param i camera index in the virtual space
290      *@param vW view width - used to determine if contour should be drawn or not (when it is dashed and object too big)
291      *@param vH view height - used to determine if contour should be drawn or not (when it is dashed and object too big)
292      */
293     public void draw(Graphics2D g,int vW,int vH,int i,Stroke stdS,AffineTransform stdT){
294   if ((pc[i].cw>1) && (pc[i].ch>1)){
295       if (zoomSensitive){trueCoef=scaleFactor*coef;}else{trueCoef=scaleFactor;}
296       if (Math.abs(trueCoef-1.0f)<0.01f){trueCoef=1.0f;} //a threshold greater than 0.01 causes jolts when zooming-unzooming around the 1.0 scale region
297       if (trueCoef!=1.0f){
298     g.setTransform(AffineTransform.getTranslateInstance(pc[i].cx-pc[i].cw,pc[i].cy-pc[i].ch));
299     g.drawImage(image,AffineTransform.getScaleInstance(trueCoef,trueCoef),null);
300     g.setTransform(stdT);
301     if (drawBorder==1){if (pc[i].prevMouseIn){g.setColor(borderColor);g.drawRect(pc[i].cx-pc[i].cw,pc[i].cy-pc[i].ch,2*pc[i].cw-1,2*pc[i].ch-1);}}
302     else if (drawBorder==2){g.setColor(borderColor);g.drawRect(pc[i].cx-pc[i].cw,pc[i].cy-pc[i].ch,2*pc[i].cw-1,2*pc[i].ch-1);}
303       }
304       else {
305     g.drawImage(image,pc[i].cx-pc[i].cw,pc[i].cy-pc[i].ch,null);
306     if (drawBorder==1){if (pc[i].prevMouseIn){g.setColor(borderColor);g.drawRect(pc[i].cx-pc[i].cw,pc[i].cy-pc[i].ch,2*pc[i].cw-1,2*pc[i].ch-1);}}
307     else if (drawBorder==2){g.setColor(borderColor);g.drawRect(pc[i].cx-pc[i].cw,pc[i].cy-pc[i].ch,2*pc[i].cw-1,2*pc[i].ch-1);}
308       }
309   }
310   else {g.fillRect(pc[i].cx,pc[i].cy,1,1);}
311     }
312 
313 
314     /**returns a clone of this object (only basic information is cloned for now: shape, orientation, position, size)*/
315     public Object clone(){
316   VImage res=new VImage(vx,vy,0,image);
317   res.setWidth(vw);
318   res.setHeight(vh);
319   res.borderColor=this.borderColor;
320   res.selectedColor=this.selectedColor;
321   res.mouseInsideColor=this.mouseInsideColor;
322   res.bColor=this.bColor;
323   res.setDrawBorderPolicy(drawBorder);
324   res.setZoomSensitive(zoomSensitive);
325   return res;
326     }
327 
328 }