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

Quick Search    Search Deep

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


1   /*   FILE: VBoolShape.java
2    *   DATE OF CREATION:   Oct 03 2000
3    *   AUTHOR :            Emmanuel Pietriga (emmanuel.pietriga@xrce.xerox.com)
4    *   MODIF:              Thu Jul 10 16:04:57 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.lang.Math;
23  import java.awt.Color;
24  import java.awt.Graphics2D;
25  import java.awt.Font;
26  import java.awt.Shape;
27  import java.awt.Stroke;
28  import java.awt.geom.*;
29  import java.util.Vector;
30  import com.xerox.VTM.engine.*;
31  
32    /**
33     * Boolean shape - defined by a main glyph and a list of boolean operations (applied according to their order in the constructor's array)
34     * -right now we only support RectangularShape derivatives (Ellipse, Rectangle)
35     * @author Emmanuel Pietriga
36     */
37  
38  public class VBoolShape extends Glyph implements Cloneable {
39  
40      /**list of boolean operations (applied in the order given by the array)*/
41      BooleanOps[] booleanShapes;
42      /**main shape size in virtual space*/
43      long szx,szy;
44      /**1=ellipse 2=rectangle*/
45      int shapeType;
46  
47      /**array of projected coordinates - index of camera in virtual space is equal to index of projected coords in this array*/
48      ProjBoolean[] pc;
49  
50      /**
51       *@param x coordinate in virtual space
52       *@param y coordinate in virtual space
53       *@param z altitude in virtual space
54       *@param sx horizontal size in virtual space
55       *@param sy vertical size in virtual space
56       *@param st shape type //1=ellipse 2=rectangle
57       *@param b array of boolean operations
58       *@param c main shape's color
59       */
60      public VBoolShape(long x,long y,float z,long sx,long sy,int st,BooleanOps[] b,Color c){
61    vx=x;
62    vy=y;
63    vz=z;
64    szx=sx;
65    szy=sy;
66    shapeType=st;
67    booleanShapes=b;
68    setColor(c);
69    setBorderColor(Color.black);
70      }
71  
72      /**called when glyph is created in order to create the initial set of projected coordinates wrt the number of cameras in the space
73       *@param nbCam current number of cameras in the virtual space
74       */
75      public void initCams(int nbCam){
76    pc=new ProjBoolean[nbCam];
77    for (int i=0;i<nbCam;i++){
78        pc[i]=new ProjBoolean();
79    }
80      }
81  
82      /**used internally to create new projected coordinates to use with the new camera
83       *@param verifIndex camera index, just to be sure that the number of projected coordinates is consistent with the number of cameras
84       */
85      public void addCamera(int verifIndex){
86    if (pc!=null){
87        if (verifIndex==pc.length){
88      ProjBoolean[] ta=pc;
89      pc=new ProjBoolean[ta.length+1];
90      for (int i=0;i<ta.length;i++){
91          pc[i]=ta[i];
92      }
93      pc[pc.length-1]=new ProjBoolean();
94        }
95        else {System.err.println("VBoolShape:Error while adding camera "+verifIndex);}
96    }
97    else {
98        if (verifIndex==0){
99      pc=new ProjBoolean[1];
100     pc[0]=new ProjBoolean();
101       }
102       else {System.err.println("VBoolShape:Error while adding camera "+verifIndex);}
103   }
104     }
105 
106     /**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*/
107     public void removeCamera(int index){
108   pc[index]=null;
109     }
110 
111     /**reset prevMouseIn for projected coordinates nb i*/
112     public void resetMouseIn(int i){
113   if (pc[i]!=null){pc[i].prevMouseIn=false;}
114     }
115 
116     /**orientation is disabled*/
117     public float getOrient(){return 0;}
118 
119     /**orientation is disabled*/
120     public void orientTo(float angle){}
121 
122     /**orientation is disabled*/
123     public void orientToNS(float angle){}
124 
125     /**size is disabled*/
126     public float getSize(){return 0;}
127 
128     /**size is disabled*/
129     public void sizeTo(float radius){}
130 
131     /**size is disabled*/
132     public void sizeToNS(float radius){}
133 
134     /**get full width*/
135     public long getWidth(){return szx;}
136 
137     /**get full height*/
138     public long getHeight(){return szy;}
139 
140     /**size is disabled*/
141     public void reSize(float factor){}
142 
143     /**used to find out if glyph completely fills the view (in which case it is not necessary to repaint objects at a lower altitude)*/
144     public boolean fillsView(long w,long h,int camIndex){//would be too complex: just say no
145   return false;
146     }
147 
148     /**detects whether the given point is inside this glyph or not 
149      *@param x EXPECTS PROJECTED JPanel COORDINATE
150      *@param y EXPECTS PROJECTED JPanel COORDINATE
151      */
152     public boolean coordInside(int x,int y,int camIndex){
153   if (pc[camIndex].mainArea.contains(x,y)){return true;}
154   else {return false;}
155     }
156 
157     /**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)*/
158     public int mouseInOut(int x,int y,int camIndex){
159   if (coordInside(x,y,camIndex)){//if the mouse is inside the glyph
160       if (!pc[camIndex].prevMouseIn){//if it was not inside it last time, mouse has entered the glyph
161     pc[camIndex].prevMouseIn=true;
162     return 1;
163       }
164       else {return 0;}  //if it was inside last time, nothing has changed
165   }
166   else{//if the mouse is not inside the glyph
167       if (pc[camIndex].prevMouseIn){//if it was inside it last time, mouse has exited the glyph
168     pc[camIndex].prevMouseIn=false;
169     return -1;
170       }
171       else {return 0;}  //if it was not inside last time, nothing has changed
172   }
173     }
174 
175     /**project shape in camera coord sys prior to actual painting*/
176     public void project(Camera c,ViewPanel v){
177   int i=c.getIndex();
178   coef=(float)(c.focal/(c.focal+c.altitude));
179   //find coordinates of object's geom center wrt to camera center and project
180   pc[i].cx=Math.round((vx-c.posx)*coef);
181   pc[i].cy=Math.round((vy-c.posy)*coef);
182   //translate in JPanel coords
183   pc[i].cx=(v.getSize().width/2)+pc[i].cx;
184   pc[i].cy=(v.getSize().height/2)-pc[i].cy;
185   for (int j=0;j<booleanShapes.length;j++){
186       booleanShapes[j].project(coef,pc[i].cx,pc[i].cy);
187   }
188   pc[i].cszx=szx*coef;
189   pc[i].cszy=szy*coef;
190   switch (shapeType) {
191   case 1:{//ellipse
192       pc[i].mainArea=new Area(new Ellipse2D.Float(pc[i].cx-szx/2*coef,pc[i].cy-szy/2*coef,pc[i].cszx,pc[i].cszy));
193       break;
194   }
195   case 2:{//rectangle
196       pc[i].mainArea=new Area(new Rectangle2D.Float(pc[i].cx-szx/2*coef,pc[i].cy-szy/2*coef,pc[i].cszx,pc[i].cszy));
197       break;
198   }
199   default:{//ellipse as default
200       pc[i].mainArea=new Area(new Ellipse2D.Float(pc[i].cx-szx/2*coef,pc[i].cy-szy/2*coef,pc[i].cszx,pc[i].cszy));
201   }
202   }
203   for (int j=0;j<booleanShapes.length;j++){
204       switch (booleanShapes[j].opType) {
205       case 1:{
206     pc[i].mainArea.add(booleanShapes[j].ar);
207     break;
208       }
209       case 2:{
210     pc[i].mainArea.subtract(booleanShapes[j].ar);
211     break;
212       }
213       case 3:{
214     pc[i].mainArea.intersect(booleanShapes[j].ar);
215     break;
216       }
217       case 4:{
218     pc[i].mainArea.exclusiveOr(booleanShapes[j].ar);
219     break;
220       }
221       default:{
222     System.err.println("Error: VBoolShape: boolean operation not defined");
223       }
224       }
225   }
226     }
227 
228     /**draw text associated with this glyph
229      *@param i camera index in the virtual space
230      */
231     void textDraw(Graphics2D g,int i){
232   if ((fontSizePolicy>=0) && (text!=null)) {     //if appli wants text drawn and if there is a text for this glyph
233       if (!text.equals("")){
234     //g.setColor(this.color);
235     textWidth=(int)g.getFontMetrics().getStringBounds(text,g).getWidth();  //get width of this text : draw if conditions are met
236     if ((fontSizePolicy==1) || ((fontSizePolicy==0) && (textWidth<2*pc[i].cszx))) {
237         if (textPos==1){  
238       //textHeight=(int)g.getFontMetrics().getStringBounds(text,g).getHeight();
239       g.drawString(text,pc[i].cx-textWidth/2,pc[i].cy-pc[i].cszy-4);
240         }
241         else if (textPos==-1){  
242       textHeight=(int)g.getFontMetrics().getStringBounds(text,g).getHeight();
243       g.drawString(text,pc[i].cx-textWidth/2,pc[i].cy+pc[i].cszy+textHeight);
244         }
245         else {g.drawString(text,pc[i].cx-textWidth/2,pc[i].cy);}
246     }
247     else if (fontSizePolicy==2) {  //modify font size to make string fit in glyph   THIS OPTION IS RATHER TIME CONSUMING
248         Font tf=new Font(g.getFont().getName(),g.getFont().getStyle(),g.getFont().getSize());
249         int s=1;
250         while (textWidth>2*pc[i].cszx){
251       s=g.getFont().getSize()-2; if (s<0){s=0;break;}
252       g.setFont(new Font(tf.getName(),tf.getStyle(),s));
253       textWidth=(int)g.getFontMetrics().getStringBounds(text,g).getWidth();
254         }
255         if (s>0) {
256       if (textPos==1){
257           //textHeight=(int)g.getFontMetrics().getStringBounds(text,g).getHeight();
258           g.drawString(text,pc[i].cx-textWidth/2,pc[i].cy-pc[i].cszy-4);
259       }
260       else if (textPos==-1){
261           textHeight=(int)g.getFontMetrics().getStringBounds(text,g).getHeight();
262           g.drawString(text,pc[i].cx-textWidth/2,pc[i].cy+pc[i].cszy+textHeight);
263       }
264       else {g.drawString(text,pc[i].cx-textWidth/2,pc[i].cy);}
265         }
266         g.setFont(tf);
267     }
268       }
269   }
270     }
271 
272     /**draw glyph 
273      *@param i camera index in the virtual space
274      */
275     public void draw(Graphics2D g,int vW,int vH,int i,Stroke stdS,AffineTransform stdT){
276   if ((pc[i].mainArea.getBounds().width>2) && (pc[i].mainArea.getBounds().height>2)){
277       if (filled){
278     g.setColor(this.color);
279     g.fill(pc[i].mainArea);
280       }
281       g.setColor(borderColor);
282       if (paintBorder){
283     if (stroke!=null){
284         g.setStroke(stroke);
285         g.draw(pc[i].mainArea);
286         g.setStroke(stdS);
287     }
288     else {
289         g.draw(pc[i].mainArea);
290     }       
291       } 
292       this.textDraw(g,i);
293   }
294   else g.fillRect(pc[i].cx,pc[i].cy,1,1);
295     }
296 
297     /**public only because accessed by svg export module*/
298     public int getMainShapeType(){
299   return shapeType;
300     }
301 
302     /**public only because accessed by svg export module*/
303     public BooleanOps[] getOperations(){
304   return booleanShapes;
305     }
306 
307     /**returns a clone of this object (only basic information is cloned for now: shape, orientation, position, size)*/
308     public Object clone(){
309   return new VBoolShape(vx,vy,0,szx,szy,shapeType,booleanShapes,color);
310     }
311 }