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

Quick Search    Search Deep

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


1   /*   FILE: VCbCurve.java
2    *   DATE OF CREATION:   Oct 03 2001
3    *   AUTHOR :            Emmanuel Pietriga (emmanuel.pietriga@xrce.xerox.com)
4    *   MODIF:              Thu Jul 10 16:06:43 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.Font;
24  import java.awt.Graphics2D;
25  import java.awt.Polygon;
26  import java.awt.Stroke;
27  import java.awt.geom.*;
28  import java.awt.geom.AffineTransform;
29  import java.lang.Math;
30  import java.util.Vector;
31  import com.xerox.VTM.engine.*;
32  
33  /**
34   * Cubic Curve -  can be reoriented -  CANNOT DETECT ENTRY/EXIT in curves, even when filled (they look as, but are not, closed shapes) <br> a cubic curve is a curved segment that has two endpoints and two control points. Each control point determines the shape of the curve by controlling one of the endpoint tangent vectors. <br> for this particular glyph, vx and vy correspond to the center of the imaginary segment linking the curve's start and end points <br> the coordinates of the control points are expressed respectively w.r.t start and end points in polar coordinates (orient=0 on segment linking start and end points, meaning that if orient=0 for both control points, start control1 control2 and end points are aligned) 
35   * @author Emmanuel Pietriga
36   **/
37  
38  public class VCbCurve extends Glyph implements Cloneable {
39  
40      /**size (distance between start and end point)*/
41      long vs;
42  
43      /**control points, polar coordinates - origin is vx,vy - orient=0 on segment linking start and end points*/
44      long vrad1;
45      float ang1;
46      long vrad2;
47      float ang2;
48  
49      /**array of projected coordinates - index of camera in virtual space is equal to index of projected coords in this array*/
50      ProjCbCurve[] pc;
51  
52      /**
53       *@param x coordinate in virtual space
54       *@param y coordinate in virtual space
55       *@param z altitude
56       *@param s size (distance between start and end points) in virtual space
57       *@param c fill color
58       *@param or orientation
59       *@param ctrlDist1 distance of control point (polar coords origin=start point)
60       *@param or1 orientation of control point (polar coords origin=start point)
61       *@param ctrlDist2 distance of control point (polar coords origin=end point)
62       *@param or2 orientation of control point (polar coords origin=end point)
63       */
64      public VCbCurve(long x,long y,float z,long s,Color c,float or,long ctrlDist1,float or1,long ctrlDist2,float or2){
65    vx=x;
66    vy=y;
67    vz=z;
68    vs=s;
69    sensit=false;
70    orient=or;
71    vrad1=ctrlDist1;
72    ang1=or1;
73    vrad2=ctrlDist2;
74    ang2=or2;
75    computeSize();
76    filled=false;
77    setColor(c);
78    setBorderColor(bColor);
79      }
80  
81      /**set position of control point 1 (polar coords w.r.t start point)*/
82      public void setCtrlPoint1(long d,float o){
83    vrad1=d;
84  //   if (o>2*Math.PI){ang1=o%2*(float)Math.PI;}
85  //   else {ang1=o;}
86    ang1=o;
87    try{vsm.repaintNow();}catch(NullPointerException e){/*System.err.println("VSM null in Glyph "+e);*/}
88      }
89  
90      /**set position of control point 2 (polar coords w.r.t end point)*/
91      public void setCtrlPoint2(long d,float o){
92    vrad2=d;
93  //   if (o>2*Math.PI){ang2=o%2*(float)Math.PI;}
94  //   else {ang2=o;}
95    ang2=o;
96    try{vsm.repaintNow();}catch(NullPointerException e){/*System.err.println("VSM null in Glyph "+e);*/}
97      }
98  
99      /**get distance from start point to control point 1 (polar coords)*/
100     public long getCtrlPointRadius1(){return vrad1;}
101 
102     /**get orientation of control point 1 (polar coords)*/
103     public float getCtrlPointAngle1(){return ang1;}
104 
105     /**get distance from start point to control point 2 (polar coords)*/
106     public long getCtrlPointRadius2(){return vrad2;}
107 
108     /**get orientation of control point 2 (polar coords)*/
109     public float getCtrlPointAngle2(){return ang2;}
110 
111     /**called when glyph is created in order to create the initial set of projected coordinates wrt the number of cameras in the space
112      *@param nbCam current number of cameras in the virtual space
113      */
114     public void initCams(int nbCam){
115   pc=new ProjCbCurve[nbCam];
116   for (int i=0;i<nbCam;i++){
117       pc[i]=new ProjCbCurve();
118   }
119     }
120 
121     /**used internally to create new projected coordinates to use with the new camera
122      *@param verifIndex camera index, just to be sure that the number of projected coordinates is consistent with the number of cameras
123      */
124     public void addCamera(int verifIndex){
125   if (pc!=null){
126       if (verifIndex==pc.length){
127     ProjCbCurve[] ta=pc;
128     pc=new ProjCbCurve[ta.length+1];
129     for (int i=0;i<ta.length;i++){
130         pc[i]=ta[i];
131     }
132     pc[pc.length-1]=new ProjCbCurve();
133       }
134       else {System.err.println("VCbCurve:Error while adding camera "+verifIndex);}
135   }
136   else {
137       if (verifIndex==0){
138     pc=new ProjCbCurve[1];
139     pc[0]=new ProjCbCurve();
140       }
141       else {System.err.println("VCbCurve:Error while adding camera "+verifIndex);}
142   }
143     }
144 
145     /**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*/
146     public void removeCamera(int index){
147   pc[index]=null;
148     }
149 
150     /**reset prevMouseIn for projected coordinates nb i*/
151     public void resetMouseIn(int i){
152   if (pc[i]!=null){pc[i].prevMouseIn=false;}
153     }
154 
155     /**get orientation*/
156     public float getOrient(){return orient;}
157 
158     /**set orientation (absolute)*/
159     public void orientTo(float angle){
160   orient=angle;
161   try{vsm.repaintNow();}catch(NullPointerException e){/*System.err.println("VSM null in Glyph "+e);*/}
162 //   vsm.constMgr.suggestAValue(this.ID,"or",orient);
163   //computeOrientCoords();
164     }
165 
166     /**set orientation (absolute)*/
167 //     public void orientToNS(float angle){
168 //   orient=angle;
169 //   //computeOrientCoords();
170 //     }
171 
172     /**get size (bounding circle radius)*/
173     public float getSize(){return size;}
174 
175     /**compute curve from VTM object model*/
176     void computeSize(){
177   size=(float)vs;
178     }
179 
180     /**set absolute size by setting bounding circle radius*/
181     public void sizeTo(float radius){
182   vrad1=Math.round(vrad1*radius/size);
183   vrad2=Math.round(vrad2*radius/size);
184   size=radius;
185   vs=Math.round(size);
186   try{vsm.repaintNow();}catch(NullPointerException e){/*System.err.println("VSM null in Glyph "+e);*/}
187 //   vsm.constMgr.suggestAValue(this.ID,"sz",size);
188     }
189 
190     /**set absolute size by setting bounding circle radius*/
191 //     public void sizeToNS(float radius){
192 //   vrad1=Math.round(vrad1*radius/size);
193 //   vrad2=Math.round(vrad2*radius/size);
194 //   size=radius;
195 //   vs=Math.round(size);
196 //     }
197 
198     /**multiply bounding circle radius by factor*/
199     public void reSize(float factor){
200   size*=factor;
201   vs=(long)Math.round(size);
202   vrad1=Math.round(vrad1*factor);
203   vrad2=Math.round(vrad2*factor);
204   try{vsm.repaintNow();}catch(NullPointerException e){/*System.err.println("VSM null in Glyph "+e);*/}
205 //   vsm.constMgr.suggestAValue(this.ID,"sz",size);
206     }
207 
208     /**used to find out if glyph completely fills the view (in which case it is not necessary to repaint objects at a lower altitude)*/
209     public boolean fillsView(long w,long h,int camIndex){
210   return false;
211     }
212 
213     /**detects whether the given point is inside this glyph or not 
214      *@param x EXPECTS PROJECTED JPanel COORDINATE
215      *@param y EXPECTS PROJECTED JPanel COORDINATE
216      */
217     public boolean coordInside(int x,int y,int camIndex){
218   return false;
219     }
220 
221     /**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)*/
222     public int mouseInOut(int x,int y,int camIndex){
223   return 0;
224     }
225 
226     /**project shape in camera coord sys prior to actual painting*/
227     public void project(Camera c,ViewPanel v){
228   int i=c.getIndex();
229   coef=(float)(c.focal/(c.focal+c.altitude));
230   //find coordinates of object's geom center wrt to camera center and project
231   pc[i].cx=Math.round((vx-c.posx)*coef);
232   pc[i].cy=Math.round((vy-c.posy)*coef);
233   //translate in JPanel coords
234   pc[i].cx=(v.getSize().width/2)+pc[i].cx;
235   pc[i].cy=(v.getSize().height/2)-pc[i].cy;
236   //project height and construct curve
237   pc[i].cs=Math.round(vs*coef);
238   if (pc[i].cs>1){
239       pc[i].start.setLocation(pc[i].cx+pc[i].cs*Math.cos(orient),pc[i].cy+pc[i].cs*Math.sin(orient));
240       pc[i].end.setLocation(pc[i].cx-pc[i].cs*Math.cos(orient),pc[i].cy-pc[i].cs*Math.sin(orient));
241       
242       pc[i].ctrlStart.setLocation(pc[i].start.x+(int)Math.round(coef*vrad1*Math.cos(orient-ang1)),pc[i].start.y+(int)Math.round(coef*vrad1*Math.sin(orient-ang1)));
243       pc[i].ctrlEnd.setLocation(pc[i].end.x+(int)Math.round(coef*vrad2*Math.cos(orient-ang2)),pc[i].end.y+(int)Math.round(coef*vrad2*Math.sin(orient-ang2)));
244       pc[i].quad.setCurve(pc[i].start,pc[i].ctrlStart,pc[i].ctrlEnd,pc[i].end);
245   }
246     }
247 
248     /**draw text associated with this glyph
249      *@param i camera index in the virtual space
250      */
251     void textDraw(Graphics2D g,int i){
252   if ((fontSizePolicy>=0) && (text!=null)) {
253       if (!text.equals("")){
254     //g.setColor(this.color);
255     textWidth=(int)g.getFontMetrics().getStringBounds(text,g).getWidth();
256     if ((fontSizePolicy==1) || ((fontSizePolicy==0) && (textWidth<2*pc[i].cs))) {
257         if (textPos==1){
258       //textHeight=(int)g.getFontMetrics().getStringBounds(text,g).getHeight();
259       g.drawString(text,pc[i].cx-textWidth/2,pc[i].cy-pc[i].cs-4);
260         }
261         else if (textPos==-1){
262       textHeight=(int)g.getFontMetrics().getStringBounds(text,g).getHeight();
263       g.drawString(text,pc[i].cx-textWidth/2,pc[i].cy+pc[i].cs+textHeight);
264         }
265         else {g.drawString(text,pc[i].cx-textWidth/2,pc[i].cy);}
266     }
267     else if (fontSizePolicy==2) {  //modify font size to make string fit in glyph   THIS OPTION IS RATHER TIME CONSUMING
268         Font tf=new Font(g.getFont().getName(),g.getFont().getStyle(),g.getFont().getSize());
269         int s=1;
270         while (textWidth>2*pc[i].cs){
271       s=g.getFont().getSize()-2; if (s<0){s=0;break;}
272       g.setFont(new Font(tf.getName(),tf.getStyle(),s));
273       textWidth=(int)g.getFontMetrics().getStringBounds(text,g).getWidth();
274         }
275         if (s>0) {
276       if (textPos==1){
277           //textHeight=(int)g.getFontMetrics().getStringBounds(text,g).getHeight();
278           g.drawString(text,pc[i].cx-textWidth/2,pc[i].cy-pc[i].cs-4);
279       }
280       else if (textPos==-1){
281           textHeight=(int)g.getFontMetrics().getStringBounds(text,g).getHeight();
282           g.drawString(text,pc[i].cx-textWidth/2,pc[i].cy+pc[i].cs+textHeight);
283       }
284       else {g.drawString(text,pc[i].cx-textWidth/2,pc[i].cy);}
285         }
286         g.setFont(tf);
287     }
288       }
289   }
290     }
291 
292     /**draw glyph 
293      *@param i camera index in the virtual space
294      */
295     public void draw(Graphics2D g,int vW,int vH,int i,Stroke stdS,AffineTransform stdT){
296   if (pc[i].cs>1){//repaint only if object is visible
297       if (filled) {
298     g.setColor(this.color);
299     g.fill(pc[i].quad);
300     g.setColor(borderColor);
301     g.drawLine((int)pc[i].start.x,(int)pc[i].start.y,(int)pc[i].end.x,(int)pc[i].end.y);
302       }
303       else {//if not filled (common case), paint curve with main color, not border color
304     g.setColor(this.color);
305       }
306       if (stroke!=null) {
307     g.setStroke(stroke);
308     g.draw(pc[i].quad);
309     g.setStroke(stdS);
310       }
311       else {
312     g.draw(pc[i].quad);
313       }
314       this.textDraw(g,i);
315   }
316   else g.fillRect(pc[i].cx,pc[i].cy,1,1);
317     }
318 
319     /**returns a clone of this object (only basic information is cloned for now: shape, orientation, position, size)*/
320     public Object clone(){
321   return new VCbCurve(vx,vy,0,vs,color,orient,vrad1,ang1,vrad2,ang2);
322     }
323 
324 }
325