Source code: com/xerox/VTM/glyphs/VDiamond.java
1 /* FILE: VDiamond.java
2 * DATE OF CREATION: Jul 27 2000
3 * AUTHOR : Emmanuel Pietriga (emmanuel.pietriga@xrce.xerox.com)
4 * MODIF: Thu Jul 10 16:31:29 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.AffineTransform;
28 import java.lang.Math;
29 import java.util.Vector;
30 import com.xerox.VTM.engine.*;
31
32 /**
33 * Diamond (losange with height equal to width) cannot be reoriented
34 * @author Emmanuel Pietriga
35 **/
36
37 public class VDiamond extends Glyph implements Cloneable {
38
39 /**height=width in virtual space*/
40 long vs;
41
42 /**array of projected coordinates - index of camera in virtual space is equal to index of projected coords in this array*/
43 ProjDiamond[] pc;
44
45 public VDiamond(){
46 vx=0;
47 vy=0;
48 vz=0;
49 vs=10;
50 computeSize();
51 orient=0;
52 setColor(Color.white);
53 setBorderColor(Color.black);
54 }
55
56 /**
57 *@param x coordinate in virtual space
58 *@param y coordinate in virtual space
59 *@param z altitude
60 *@param s size (width=height) in virtual space
61 *@param c fill color
62 */
63 public VDiamond(long x,long y,float z,long s,Color c){
64 vx=x;
65 vy=y;
66 vz=z;
67 vs=s;
68 computeSize();
69 orient=0;
70 setColor(c);
71 setBorderColor(bColor);
72 }
73
74 /**called when glyph is created in order to create the initial set of projected coordinates wrt the number of cameras in the space
75 *@param nbCam current number of cameras in the virtual space
76 */
77 public void initCams(int nbCam){
78 pc=new ProjDiamond[nbCam];
79 for (int i=0;i<nbCam;i++){
80 pc[i]=new ProjDiamond();
81 }
82 }
83
84 /**used internally to create new projected coordinates to use with the new camera
85 *@param verifIndex camera index, just to be sure that the number of projected coordinates is consistent with the number of cameras
86 */
87 public void addCamera(int verifIndex){
88 if (pc!=null){
89 if (verifIndex==pc.length){
90 ProjDiamond[] ta=pc;
91 pc=new ProjDiamond[ta.length+1];
92 for (int i=0;i<ta.length;i++){
93 pc[i]=ta[i];
94 }
95 pc[pc.length-1]=new ProjDiamond();
96 }
97 else {System.err.println("VDiamond:Error while adding camera "+verifIndex);}
98 }
99 else {
100 if (verifIndex==0){
101 pc=new ProjDiamond[1];
102 pc[0]=new ProjDiamond();
103 }
104 else {System.err.println("VDiamond:Error while adding camera "+verifIndex);}
105 }
106 }
107
108 /**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*/
109 public void removeCamera(int index){
110 pc[index]=null;
111 }
112
113 /**reset prevMouseIn for projected coordinates nb i*/
114 public void resetMouseIn(int i){
115 if (pc[i]!=null){pc[i].prevMouseIn=false;}
116 }
117
118 /**get orientation*/
119 public float getOrient(){return orient;}
120
121 /**set orientation (absolute) - has no effect*/
122 public void orientTo(float angle){}
123
124 /**set orientation (absolute) - has no effect*/
125 // public void orientToNS(float angle){}
126
127 /**get size (bounding circle radius)*/
128 public float getSize(){return size;}
129
130 /**compute size (bounding circle radius)*/
131 void computeSize(){
132 size=(float)vs;
133 }
134
135 /**set absolute size by setting bounding circle radius*/
136 public void sizeTo(float radius){
137 size=radius;
138 vs=Math.round(size);
139 try{vsm.repaintNow();}catch(NullPointerException e){/*System.err.println("VSM null in Glyph "+e);*/}
140 // vsm.constMgr.suggestAValue(this.ID,"sz",size);
141 }
142
143 /**set absolute size by setting bounding circle radius*/
144 // public void sizeToNS(float radius){
145 // size=radius;
146 // vs=Math.round(size);
147 // }
148
149 /**multiply bounding circle radius by factor*/
150 public void reSize(float factor){
151 size*=factor;
152 vs=(long)Math.round(size);
153 try{vsm.repaintNow();}catch(NullPointerException e){/*System.err.println("VSM null in Glyph "+e);*/}
154 // vsm.constMgr.suggestAValue(this.ID,"sz",size);
155 }
156
157 /**used to find out if glyph completely fills the view (in which case it is not necessary to repaint objects at a lower altitude)*/
158 public boolean fillsView(long w,long h,int camIndex){
159 if ((pc[camIndex].p.contains(0,0)) && (pc[camIndex].p.contains(w,0)) && (pc[camIndex].p.contains(0,h)) && (pc[camIndex].p.contains(w,h))){return true;}
160 else {return false;}
161 }
162
163 /**detects whether the given point is inside this glyph or not
164 *@param x EXPECTS PROJECTED JPanel COORDINATE
165 *@param y EXPECTS PROJECTED JPanel COORDINATE
166 */
167 public boolean coordInside(int x,int y,int camIndex){
168 if (pc[camIndex].p.contains(x,y)){return true;}
169 else {return false;}
170 }
171
172 /**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)*/
173 public int mouseInOut(int x,int y,int camIndex){
174 if (coordInside(x,y,camIndex)){//if the mouse is inside the glyph
175 if (!pc[camIndex].prevMouseIn){//if it was not inside it last time, mouse has entered the glyph
176 pc[camIndex].prevMouseIn=true;
177 return 1;
178 }
179 else {return 0;} //if it was inside last time, nothing has changed
180 }
181 else{//if the mouse is not inside the glyph
182 if (pc[camIndex].prevMouseIn){//if it was inside it last time, mouse has exited the glyph
183 pc[camIndex].prevMouseIn=false;
184 return -1;
185 }
186 else {return 0;} //if it was not inside last time, nothing has changed
187 }
188 }
189
190 /**project shape in camera coord sys prior to actual painting*/
191 public void project(Camera c,ViewPanel v){
192 int i=c.getIndex();
193 coef=(float)(c.focal/(c.focal+c.altitude));
194 //find coordinates of object's geom center wrt to camera center and project
195 pc[i].cx=Math.round((vx-c.posx)*coef);
196 pc[i].cy=Math.round((vy-c.posy)*coef);
197 //translate in JPanel coords
198 pc[i].cx=(v.getSize().width/2)+pc[i].cx;
199 pc[i].cy=(v.getSize().height/2)-pc[i].cy;
200 //project height and construct polygon
201 pc[i].cs=Math.round(vs*coef);
202 int[] xcoords={pc[i].cx+pc[i].cs,pc[i].cx,pc[i].cx-pc[i].cs,pc[i].cx};
203 int[] ycoords={pc[i].cy,pc[i].cy+pc[i].cs,pc[i].cy,pc[i].cy-pc[i].cs};
204 pc[i].p=new Polygon(xcoords,ycoords,4);
205 }
206
207 /**draw text associated with this glyph
208 *@param i camera index in the virtual space
209 */
210 void textDraw(Graphics2D g,int i){
211 if ((fontSizePolicy>=0) && (text!=null)) {
212 if (!text.equals("")){
213 //g.setColor(this.color);
214 textWidth=(int)g.getFontMetrics().getStringBounds(text,g).getWidth();
215 if ((fontSizePolicy==1) || ((fontSizePolicy==0) && (textWidth<2*pc[i].cs))) {
216 if (textPos==1){
217 //textHeight=(int)g.getFontMetrics().getStringBounds(text,g).getHeight();
218 g.drawString(text,pc[i].cx-textWidth/2,pc[i].cy-pc[i].cs-4);
219 }
220 else if (textPos==-1){
221 textHeight=(int)g.getFontMetrics().getStringBounds(text,g).getHeight();
222 g.drawString(text,pc[i].cx-textWidth/2,pc[i].cy+pc[i].cs+textHeight);
223 }
224 else {g.drawString(text,pc[i].cx-textWidth/2,pc[i].cy);}
225 }
226 else if (fontSizePolicy==2) { //modify font size to make string fit in glyph THIS OPTION IS RATHER TIME CONSUMING
227 Font tf=new Font(g.getFont().getName(),g.getFont().getStyle(),g.getFont().getSize());
228 int s=1;
229 while (textWidth>2*pc[i].cs){
230 s=g.getFont().getSize()-2; if (s<0){s=0;break;}
231 g.setFont(new Font(tf.getName(),tf.getStyle(),s));
232 textWidth=(int)g.getFontMetrics().getStringBounds(text,g).getWidth();
233 }
234 if (s>0) {
235 if (textPos==1){
236 //textHeight=(int)g.getFontMetrics().getStringBounds(text,g).getHeight();
237 g.drawString(text,pc[i].cx-textWidth/2,pc[i].cy-pc[i].cs-4);
238 }
239 else if (textPos==-1){
240 textHeight=(int)g.getFontMetrics().getStringBounds(text,g).getHeight();
241 g.drawString(text,pc[i].cx-textWidth/2,pc[i].cy+pc[i].cs+textHeight);
242 }
243 else {g.drawString(text,pc[i].cx-textWidth/2,pc[i].cy);}
244 }
245 g.setFont(tf);
246 }
247 }
248 }
249 }
250
251 /**draw glyph
252 *@param i camera index in the virtual space
253 */
254 public void draw(Graphics2D g,int vW,int vH,int i,Stroke stdS,AffineTransform stdT){
255 if (pc[i].cs>1){//repaint only if object is visible
256 if (filled) {
257 g.setColor(this.color);
258 g.fillPolygon(pc[i].p);
259 }
260 g.setColor(borderColor);
261 if (paintBorder){
262 if (stroke!=null) {
263 g.setStroke(stroke);
264 g.drawPolygon(pc[i].p);
265 g.setStroke(stdS);
266 }
267 else {
268 g.drawPolygon(pc[i].p);
269 }
270 }
271 this.textDraw(g,i);
272 }
273 else g.fillRect(pc[i].cx,pc[i].cy,1,1);
274 }
275
276 /**returns a clone of this object (only basic information is cloned for now: shape, orientation, position, size)*/
277 public Object clone(){
278 VDiamond res=new VDiamond(vx,vy,0,vs,color);
279 res.borderColor=this.borderColor;
280 res.selectedColor=this.selectedColor;
281 res.mouseInsideColor=this.mouseInsideColor;
282 res.bColor=this.bColor;
283 return res;
284 }
285
286 }
287