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

Quick Search    Search Deep

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


1   /*   FILE: RectangleNR.java
2    *   DATE OF CREATION:   Thu Dec 05 13:53:36 2002
3    *   AUTHOR :            Emmanuel Pietriga (emmanuel@w3.org)
4    *   MODIF:              Thu Jul 10 16:20:55 2003 by Emmanuel Pietriga (emmanuel@w3.org, emmanuel@claribole.net)
5    *   Copyright (c) Emmanuel Pietriga, 2002. All Rights Reserved
6    *   Licensed under the GNU LGPL. For full terms see the file COPYING.
7    */
8   
9   package com.xerox.VTM.glyphs;
10  
11  import java.awt.Color;
12  import java.awt.Graphics2D;
13  import java.awt.Font;
14  import java.awt.Stroke;
15  import java.awt.geom.AffineTransform;
16  import java.lang.Math;
17  import java.util.Vector;
18  import com.xerox.VTM.engine.*;
19  import com.xerox.VTM.glyphs.Glyph;
20  import com.xerox.VTM.glyphs.RectangularShape;
21  import com.xerox.VTM.glyphs.ProjRectangle;
22  
23  /**
24   * RectangleNR - not sensitive to zoom (will keep its size no matter the camera's altitude) - cannot be reoriented <br> used for instance to create resizing handles
25   * @author Emmanuel Pietriga
26   **/
27  
28  public class RectangleNR extends Glyph implements RectangularShape,Cloneable {
29  
30      /**half width and height in virtual space*/
31      long vw,vh;
32      /**aspect ratio (width divided by height)*/
33      float ar;
34  
35      ProjRectangle[] pc;
36  
37      public RectangleNR(){
38    vx=0;
39    vy=0;
40    vz=0;
41    vw=5;
42    vh=5;
43    computeSize();
44    ar=(float)vw/(float)vh;
45    orient=0;
46    setColor(Color.black);
47    setBorderColor(Color.black);
48      }
49  
50      /**
51       *@param x coordinate in virtual space
52       *@param y coordinate in virtual space
53       *@param z altitude
54       *@param w half width in virtual space
55       *@param h half height in virtual space
56       *@param c fill color
57       */
58      public RectangleNR(long x,long y,float z,long w,long h,Color c){
59    vx=x;
60    vy=y;
61    vz=z;
62    vw=w;
63    vh=h;
64    computeSize();
65    if (vw==0 && vh==0){ar=1.0f;}
66    else {ar=(float)vw/(float)vh;}
67    //if (vh!=0){ar=vw/vh;}else{ar=0;}
68    orient=0;
69    setColor(c);
70    setBorderColor(Color.black);
71      }
72  
73      /**called when glyph is created in order to create the initial set of projected coordinates wrt the number of cameras in the space
74       *@param nbCam current number of cameras in the virtual space
75       */
76      public void initCams(int nbCam){
77    pc=new ProjRectangle[nbCam];
78    for (int i=0;i<nbCam;i++){
79        pc[i]=new ProjRectangle();
80        pc[i].cw=(int)vw;
81        pc[i].ch=(int)vh;
82    }
83      }
84  
85      /**used internally to create new projected coordinates to use with the new camera
86       *@param verifIndex camera index, just to be sure that the number of projected coordinates is consistent with the number of cameras
87       */
88      public void addCamera(int verifIndex){
89    if (pc!=null){
90        if (verifIndex==pc.length){
91      ProjRectangle[] ta=pc;
92      pc=new ProjRectangle[ta.length+1];
93      for (int i=0;i<ta.length;i++){
94          pc[i]=ta[i];
95      }
96      pc[pc.length-1]=new ProjRectangle();
97      pc[pc.length-1].cw=(int)vw;
98      pc[pc.length-1].ch=(int)vh;
99        }
100       else {System.err.println("RectangleNR:Error while adding camera "+verifIndex);}
101   }
102   else {
103       if (verifIndex==0){
104     pc=new ProjRectangle[1];
105     pc[0]=new ProjRectangle();
106     pc[0].cw=(int)vw;
107     pc[0].ch=(int)vh;
108       }
109       else {System.err.println("RectangleNR:Error while adding camera "+verifIndex);}
110   }
111     }
112 
113     /**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*/
114     public void removeCamera(int index){
115   pc[index]=null;
116     }
117 
118     /**reset prevMouseIn for projected coordinates nb i*/
119     public void resetMouseIn(int i){
120   if (pc[i]!=null){pc[i].prevMouseIn=false;}
121     }
122 
123     /**get orientation*/
124     public float getOrient(){return 0;}
125 
126     /**set orientation (absolute) - has no effect*/
127     public void orientTo(float angle){}
128 
129     /**get size (bounding circle radius)*/
130     public float getSize(){return size;}
131 
132     /**get half width*/
133     public long getWidth(){return vw;}
134 
135     /**get half height*/
136     public long getHeight(){return vh;}
137 
138     /**compute size (bounding circle radius)*/
139     void computeSize(){
140   size=(float)Math.sqrt(Math.pow(vw,2)+Math.pow(vh,2));
141     }
142 
143     /**set absolute size by setting bounding circle radius*/
144     public void sizeTo(float radius){  //new bounding circle radius
145   size=radius;
146   vw=(long)Math.round((size*ar)/(Math.sqrt(Math.pow(ar,2)+1)));
147   vh=(long)Math.round((size)/(Math.sqrt(Math.pow(ar,2)+1)));
148   updateProjectedWH();
149   try{vsm.repaintNow();}catch(NullPointerException e){}
150     }
151 
152     /**set absolute half width*/
153     public void setWidth(long w){ 
154   vw=w;
155   computeSize();
156   updateProjectedWH();
157   try{vsm.repaintNow();}catch(NullPointerException e){}
158     }
159 
160     /**set absolute half height*/
161     public void setHeight(long h){
162   vh=h;
163   computeSize();
164   updateProjectedWH();
165   try{vsm.repaintNow();}catch(NullPointerException e){}
166     }
167 
168     /**multiply bounding circle radius by factor*/
169     public void reSize(float factor){//resizing factor
170   size*=factor;
171   vw=(long)Math.round((size*ar)/(Math.sqrt(Math.pow(ar,2)+1)));
172   vh=(long)Math.round((size)/(Math.sqrt(Math.pow(ar,2)+1)));
173   updateProjectedWH();
174   try{vsm.repaintNow();}catch(NullPointerException e){}
175     }
176 
177     private void updateProjectedWH(){
178   if (pc!=null){
179       for (int i=0;i<pc.length;i++){
180     try {
181         pc[i].cw=(int)vw;
182         pc[i].ch=(int)vh;
183     }//some pc[i] might be null (if cameras were deleted from the virtual space)
184     catch (NullPointerException e){}
185       }
186   }
187     }
188 
189     /**used to find out if it is necessary to project and draw the glyph in the current view*/
190     public boolean drawMe(long w1,long h1,long w2,long h2,int i){//i should be the camera's index (used only by some glyph classes redefining this method)
191   if ((vx>=w2) && (vx<=w1) && (vy>=h2) && (vy<=h1)){ //if glyph hotspot is in the region, it is obviously visible
192       return true;
193   }
194   else {
195       if (((vx-pc[i].cw)<=w1) && ((vx+pc[i].cw)>=w2) && ((vy-pc[i].ch)<=h1) && ((vy+pc[i].ch)>=h2)){
196     //if glyph is at least partially in region (we approximate using the glyph
197     // bounding circle, meaning that some glyphs not actually visible can 
198     return true;  //be projected and drawn  (but they won't be displayed))
199       } 
200       else return false;   //otherwise the glyph is not visible
201   }
202     }
203 
204     /**used to find out if glyph completely fills the view (in which case it is not necessary to repaint objects at a lower altitude)*/
205     public boolean fillsView(long w,long h,int camIndex){//width and height of view - pc[i].c? are JPanel coords
206   if ((w<=pc[camIndex].cx+pc[camIndex].cw) && (0>=pc[camIndex].cx-pc[camIndex].cw) && (h<=pc[camIndex].cy+pc[camIndex].ch) && (0>=pc[camIndex].cy-pc[camIndex].ch)){return true;}
207   else {return false;}
208     }
209 
210     /**detects whether the given point is inside this glyph or not 
211      *@param x EXPECTS PROJECTED JPanel COORDINATE
212      *@param y EXPECTS PROJECTED JPanel COORDINATE
213      */
214     public boolean coordInside(int x,int y,int camIndex){
215   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;}
216   else {return false;}
217     }
218 
219     /**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)*/
220     public int mouseInOut(int x,int y,int camIndex){
221   if (coordInside(x,y,camIndex)){//if the mouse is inside the glyph
222       if (!pc[camIndex].prevMouseIn){//if it was not inside it last time, mouse has entered the glyph
223     pc[camIndex].prevMouseIn=true;
224     return 1;
225       }
226       else {return 0;}  //if it was inside last time, nothing has changed
227   }
228   else{//if the mouse is not inside the glyph
229       if (pc[camIndex].prevMouseIn){//if it was inside it last time, mouse has exited the glyph
230     pc[camIndex].prevMouseIn=false;
231     return -1;
232       }
233       else {return 0;}  //if it was not inside last time, nothing has changed
234   }
235     }
236 
237     /**project shape in camera coord sys prior to actual painting*/
238     public void project(Camera c,ViewPanel v){
239   int i=c.getIndex();
240   coef=(float)(c.focal/(c.focal+c.altitude));
241   //find coordinates of object's geom center wrt to camera center and project
242   pc[i].cx=Math.round((vx-c.posx)*coef);
243   pc[i].cy=Math.round((vy-c.posy)*coef);
244   //translate in JPanel coords
245   pc[i].cx=(v.getSize().width/2)+pc[i].cx;
246   pc[i].cy=(v.getSize().height/2)-pc[i].cy;
247     }
248 
249     /**draw text associated with this glyph
250      *@param i camera index in the virtual space
251      */
252     void textDraw(Graphics2D g,int i){
253   if ((fontSizePolicy>=0) && (text!=null)) {     //if appli wants text drawn and if there is a text for this glyph
254       if (!text.equals("")){
255     //g.setColor(this.color);
256     textWidth=(int)g.getFontMetrics().getStringBounds(text,g).getWidth();  //get width of this text : draw if conditions are met
257     if ((fontSizePolicy==1) || ((fontSizePolicy==0) && (textWidth<2*pc[i].cw))) {
258         if (textPos==1){  
259       //textHeight=(int)g.getFontMetrics().getStringBounds(text,g).getHeight();
260       g.drawString(text,pc[i].cx-textWidth/2,pc[i].cy-pc[i].ch-4);  //-4 for things like g, j, p, q, y
261         }
262         else if (textPos==-1){  
263       textHeight=(int)g.getFontMetrics().getStringBounds(text,g).getHeight();
264       g.drawString(text,pc[i].cx-textWidth/2,pc[i].cy+pc[i].ch+textHeight);
265         }
266         else {g.drawString(text,pc[i].cx-textWidth/2,pc[i].cy);}
267     }
268     else if (fontSizePolicy==2) {  //modify font size to make string fit in glyph   THIS OPTION IS RATHER TIME CONSUMING
269         Font tf=new Font(g.getFont().getName(),g.getFont().getStyle(),g.getFont().getSize());
270         int s=1;
271         while (textWidth>2*pc[i].cw){
272       s=g.getFont().getSize()-2; if (s<0){s=0;break;}
273       g.setFont(new Font(tf.getName(),tf.getStyle(),s));
274       textWidth=(int)g.getFontMetrics().getStringBounds(text,g).getWidth();
275         }
276         if (s>0) {
277       if (textPos==1){
278           //textHeight=(int)g.getFontMetrics().getStringBounds(text,g).getHeight();
279           g.drawString(text,pc[i].cx-textWidth/2,pc[i].cy-pc[i].ch-4);
280       }
281       else if (textPos==-1){
282           textHeight=(int)g.getFontMetrics().getStringBounds(text,g).getHeight();
283           g.drawString(text,pc[i].cx-textWidth/2,pc[i].cy+pc[i].ch+textHeight);
284       }
285       else {g.drawString(text,pc[i].cx-textWidth/2,pc[i].cy);}
286         }
287         g.setFont(tf);
288     }
289       }
290   }
291     }
292 
293     /**draw glyph 
294      *@param i camera index in the virtual space
295      *@param vW view width - used to determine if contour should be drawn or not (when it is dashed and object too big)
296      *@param vH view height - used to determine if contour should be drawn or not (when it is dashed and object too big)
297      */
298     public void draw(Graphics2D g,int vW,int vH,int i,Stroke stdS,AffineTransform stdT){
299   if ((pc[i].cw>1) && (pc[i].ch>1)) {//repaint only if object is visible
300       if (filled) {
301     g.setColor(this.color);
302     g.fillRect(pc[i].cx-pc[i].cw,pc[i].cy-pc[i].ch,2*pc[i].cw,2*pc[i].ch);
303       }
304       g.setColor(borderColor);
305       if (paintBorder){
306     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       }   
308       this.textDraw(g,i);
309   }
310   else if ((pc[i].cw<=1) ^ (pc[i].ch<=1)) {//repaint only if object is visible  (^ means xor)
311       g.setColor(this.color);
312       if (pc[i].cw<=1){
313     g.fillRect(pc[i].cx,pc[i].cy-pc[i].ch,1,2*pc[i].ch);
314       }
315       else if (pc[i].ch<=1){
316     g.fillRect(pc[i].cx-pc[i].cw,pc[i].cy,2*pc[i].cw,1);
317       }
318   }
319   else g.fillRect(pc[i].cx,pc[i].cy,1,1);
320     }
321 
322     /**returns a clone of this object (only basic information is cloned for now: shape, orientation, position, size)*/
323     public Object clone(){
324   RectangleNR res=new RectangleNR(vx,vy,0,vw,vh,color);
325   res.borderColor=this.borderColor;
326   res.selectedColor=this.selectedColor;
327   res.mouseInsideColor=this.mouseInsideColor;
328   res.bColor=this.bColor;
329   return res;
330     }
331 
332 }