pthotspot._java


	// Hotspot parameters. This should really be a separate class, but 
	// then we have two class files...
	
	Vector hotspots = null;
	
 	int numhs 				= 0 ; 			// Number of Hotspots;
 	int curhs 				= -1; 			// Current active hotspot, if exists, else -1.
	Object	hs_image = null;				// hotspot image

   	double   	hs_xp[];					// x-coordinate in panorama
   	double   	hs_yp[];					// y-coordinate in panorama
   	double   	hs_up[];					// u-coordinate in panorama
   	double   	hs_vp[];					// v-coordinate in panorama
  	int 		hs_xv[];					// x-coordinate in viewport
  	int 		hs_yv[];					// y-coordinate in viewport
	Color 		hs_hc[];					// color of hotspot marker
	String		hs_name[];					// name displayed in status bar
	String		hs_url[];					// url linked to hotspot
	String		hs_target[];				// target in url, if any
	Object		hs_him[];					// image displayed while mouse is over hotspot
	String		hs_mask[];					// name of maskimage for hotspotshape
	boolean		hs_visible[];				// is hotspot inside viewport?
	int			hs_imode[];					// 0 - normal, 1 - popup, 2 - always visible
	int			hs_link[];					// Same hotspot location as?

	static final double NO_UV 			= -200.0;	// impossible u/v coordinate
	static final int HSIZE = 12; 				// Size of Hotspot
	
	static final int IMODE_NORMAL = 0;
	static final int IMODE_POPUP  = 1;
	static final int IMODE_ALWAYS = 2;
	static final int IMODE_WARP   = 4;
	static final int IMODE_WHS 	  = 8;
	static final int IMODE_TEXT   = 16;		// Text image

	void hs_init(){
		hotspots = new Vector();
	}

	void hs_allocate(int n){
		try{
	    	hs_xp 		= new double	[n];
        	hs_yp 		= new double	[n];
	    	hs_up 		= new double	[n];
        	hs_vp 		= new double	[n];
			hs_xv 		= new int		[n];
			hs_yv 		= new int		[n];
			hs_hc 		= new Color		[n];
			hs_name 	= new String	[n];
			hs_url 		= new String	[n];
			hs_target	= new String	[n];
			hs_him 		= new Object	[n];
			hs_visible	= new boolean	[n];
			hs_imode	= new int		[n];
			hs_mask		= new String	[n];
			hs_link		= new int		[n];
			numhs = n;
		}catch(Exception e){
			numhs = 0;
		}
		
	}
	
	void hs_dispose(){
		int i;
		
		for(i=0; i<numhs; i++){
	    	if(hs_him[i] != null){
	    		hs_him[i] = null;
	    	}
			hs_hc[i] 		= null;
			hs_name[i]		= null;
			hs_url[i] 		= null;
			hs_target[i]	= null;
			hs_mask[i]		= null;
	    }
	    numhs 		= 0;
		hotspots.removeAllElements();

        hs_xp 		= null;
        hs_yp 		= null;
        hs_up 		= null;
        hs_vp 		= null;
		hs_xv 		= null;
		hs_yv 		= null;
		hs_hc 		= null;
		hs_name 	= null;
		hs_url 		= null;
		hs_him 		= null;
		hs_visible	= null;
		hs_target	= null;
		hs_mask		= null;
		hs_imode	= null;
		hs_link		= null;
		
		hs_image = null;	

	}

	// Parse one Hotspotdescription line for 
	// Hotspot No n
	   	
   	void ParseHotspotLine( String s, int n )
   	{
   		int i=0,length = s.length();
   		StringBuffer w = new StringBuffer();
   		
   		// Set defaults
   		
   		hs_xp[n] 	= 0.0;
        hs_yp[n] 	= 0.0;
   		hs_up[n] 	= NO_UV;
        hs_vp[n] 	= NO_UV;
		hs_xv[n] 	= 0;
		hs_yv[n] 	= 0;
		hs_hc[n] 	= null;
		hs_name[n] 	= null;
		hs_url[n] 	= null;
		hs_target[n]= null;
		hs_him[n] 	= null;
		hs_visible[n] = false;
		hs_imode[n] = IMODE_NORMAL;
		hs_mask[n]	= null;
		hs_link[n]	= -1;

   		
   		while(i<length)
   		{
   			switch( s.charAt(i++))
   			{
   				case 'x': i = getNextWord(i,s,w); hs_xp[n] = Double.valueOf(w.toString()).doubleValue();  break;
    			case 'X': i = getNextWord(i,s,w); hs_xp[n] = -Double.valueOf(w.toString()).doubleValue(); break;
   				case 'y': i = getNextWord(i,s,w); hs_yp[n] = Double.valueOf(w.toString()).doubleValue();  break;	
   				case 'Y': i = getNextWord(i,s,w); hs_yp[n] = -Double.valueOf(w.toString()).doubleValue(); break;	
   				case 'a': i = getNextWord(i,s,w); hs_up[n] = Double.valueOf(w.toString()).doubleValue();  break;	
    			case 'A': i = getNextWord(i,s,w); hs_up[n] = -Double.valueOf(w.toString()).doubleValue(); break;	
   				case 'b': i = getNextWord(i,s,w); hs_vp[n] = Double.valueOf(w.toString()).doubleValue();  break;	
   				case 'B': i = getNextWord(i,s,w); hs_vp[n] = -Double.valueOf(w.toString()).doubleValue(); break;	
   				case 'c': i = getNextWord(i,s,w); hs_hc[n] = new Color( Integer.parseInt(w.toString(),16) ); break;	
   				case 'n': i = getNextWord(i,s,w); hs_name[n] = w.toString(); break;
  				case 'm': i = getNextWord(i,s,w); hs_mask[n] = w.toString(); break;
  				case 'p': hs_imode[n] |= IMODE_POPUP; break;	
  				case 'q': hs_imode[n] |= IMODE_ALWAYS;break;	
 				case 'w': hs_imode[n] |= IMODE_WARP;  break;	
 				case 'e': hs_imode[n] |= IMODE_TEXT;  break;	
   				case 'u': i = getNextWord(i,s,w); hs_url[n] = w.toString(); break;
   				case 'i': i = getNextWord(i,s,w); hs_him[n] = w.toString(); break;
   				case 't': i = getNextWord(i,s,w); hs_target[n] = w.toString(); break;
   			}
   		}
   	}
  
  	void hs_read(){
 		// Set up hotspot structures
 		if( hotspots.size() == 0 )
 			return;
 		
 		hs_allocate(hotspots.size());
 		for(int i=0; i<numhs; i++){
			ParseHotspotLine( (String)hotspots.elementAt(i), i );
		}
		hs_setLinkedHotspots();
	}  		 		

	void hs_setup(int[][] pd){
		if( pd == null ) return;
  		int ph = pd.length, pw = pd[0].length;
  		PixelGrabber pg;
 		int	i,x,y,cy;
 		
 		hs_read();
		
             
        int[] tdata;

		// Load Hotspotimages, if not done
		
		for(i=0; i<numhs; i++){
			if( hs_him[i] != null && ((hs_imode[i] & IMODE_TEXT) == 0) ){
				String s = (String)hs_him[i];

				if( !(s.startsWith("ptviewer:") || s.startsWith("javascript:"))){
 					hs_him[i] = loadImage( s ) ;
 				}
 			}
 		}	


		hs_rel2abs(pw, ph);
 
		// Process global hotspot image
		
		if( hs_image != null ) hs_image = loadImage( (String)hs_image );
	    if( hs_image != null && 	hs_image instanceof Image &&
	        pw 	== ((Image)hs_image).getWidth (null)  && 
	        ph == ((Image)hs_image).getHeight(null) ){
	        ptImageToAlpha( pd, (Image)hs_image );
 	    }else{
			// Set hotspot masks
		
			for(i=0; i<numhs && i<255 ; i++){ // only 255 indices
				if( hs_link[i] == -1 ){ // Linked Hotspots don't get masks
					if( hs_up[i] != NO_UV && hs_vp[i] != NO_UV){
						SetPAlpha( (int)hs_xp[i], (int)hs_yp[i], 
								   (int)hs_up[i], (int)hs_vp[i], i, pd );
						if(hs_up[i] >= hs_xp[i]){ 
							hs_xp[i] += (hs_up[i] - hs_xp[i])/2;
							hs_up[i] =  hs_up[i] - hs_xp[i];
						}else{
							hs_xp[i] += (hs_up[i] + pw - hs_xp[i])/2;
							hs_up[i] =  hs_up[i] + pw - hs_xp[i];
						}
						hs_yp[i] =  (hs_yp[i] + hs_vp[i])/2;
						hs_vp[i] =  Math.abs(hs_yp[i] - hs_vp[i]);
					}else if((hs_imode[i] &	IMODE_WARP) > 0  && 
						 (hs_him[i] != null) && hs_him[i] instanceof Image &&
						 hs_mask[i]== null){// warped image without mask 
						hs_up[i] = ((Image)hs_him[i]).getWidth(null);
						hs_vp[i] = ((Image)hs_him[i]).getHeight(null);
						SetPAlpha( (int)(hs_xp[i]-hs_up[i]/2.0), (int)(hs_yp[i]-hs_vp[i]/2.0), 
								   (int)(hs_xp[i]+hs_up[i]/2.0), (int)(hs_yp[i]+hs_vp[i]/2.0), i, pd );
					}else if(hs_mask[i] != null){

						Image mim = loadImage(hs_mask[i]);
						if( mim != null ){
							tdata = new int[ mim.getWidth(null)*mim.getHeight(null) ];
							pg = new PixelGrabber( mim, 0, 0, mim.getWidth(null), mim.getHeight(null), tdata, 0, mim.getWidth(null) );
        					try { pg.grabPixels(); } catch (InterruptedException e) { continue; }

        					int hs_y = (int)hs_yp[i], hs_x = (int)hs_xp[i];
 							int hmask = (i<<24) + 0x00ffffff;
        					int k=0;
 
        					for(y=0; y<mim.getHeight(null) && hs_y<ph; y++,hs_y++){
        						cy = y*mim.getWidth(null);
         						for(x=0, hs_x=(int)hs_xp[i]; x<mim.getWidth(null) && hs_x<pw; x++,hs_x++){
         							if( (tdata[cy +x] & 0x00ffffff) == 0x00ffffff ){ // inside mask
         								pd[hs_y][hs_x] &= hmask;k++;
        							}
        						}
        					}
        					hs_yp[i] += mim.getHeight(null)/2;
        					hs_xp[i] += mim.getWidth(null)/2;
        					hs_up[i] =  mim.getWidth(null); // width
 							hs_vp[i] =  mim.getHeight(null); // height
 							mim = null; tdata = null;
       					}
         			}
        		}
        	}
        }
        
		for(i=0; i<numhs; i++)
			if( hs_link[i] != -1 ){
				hs_xp[i] = hs_xp[hs_link[i]];
				hs_yp[i] = hs_yp[hs_link[i]];
        		hs_up[i] = hs_up[hs_link[i]];
 				hs_vp[i] = hs_vp[hs_link[i]];
			}
		        

		// Get and set pixel data for warped hotspots

		for(i=0; i<numhs; i++){
			if( (hs_imode[i] &	IMODE_WARP) > 0  && hs_him[i] != null){
					if( hs_him[i] instanceof Image){
						Image p = (Image)hs_him[i];
		
						int w = p.getWidth(null);
						int h = p.getHeight(null);
						int xp = (int)hs_xp[i] - w/2;
						int yp = (int)hs_yp[i] - h/2;
						
						// System.out.println( xp + " " +yp + " " +w+" "+h);
				
						if( xp>=0 && yp>=0 && w + xp <= pw && h + yp <= ph){
							int[] buf = new int[ w * h * 2 ];
       						pg = new PixelGrabber( p, 0, 0, w, h,  buf, 0, w );
        					try { pg.grabPixels(); } 
        					catch (InterruptedException e){
             					continue;
        					}

        					im_extractRect( pd, xp, yp, buf, w, 0, h, w, h );
        					hs_him[i] = buf;
        					hs_up[i]  = w;
        					hs_vp[i]  = h;
        				}else
        					System.out.println("Image for Hotspot No " + i + " outside main panorama");
        			}
        		
        	}
        }
        					
	}
	

// Insert warped images into panorama pd
// Return true if pd has been changed	
boolean hs_drawWarpedImages(int[][] pd, int chs, boolean shs){
	int i,w,h,xp,yp;
	boolean result = false;
	
	if( pd == null ) return false;
 		
 	for(i=0; i<numhs; i++){
 		if( (hs_imode[i] & IMODE_WARP) > 0 && 
 		     hs_him[i] != null &&
 		     hs_him[i] instanceof int[] ){
				w  =  (int)hs_up[i]; 		h  =  (int)hs_vp[i];
				xp =  (int)hs_xp[i] - w/2;	yp =  (int)hs_yp[i] - h/2;
 				if( shs || (hs_imode[i] & IMODE_ALWAYS) > 0 
	       				|| ( i == chs && (hs_imode[i] & IMODE_POPUP) > 0)
	       			    || ( chs >= 0 && hs_link[i] == chs && (hs_imode[i] & IMODE_POPUP) > 0 )){
	       			if( (hs_imode[i] & IMODE_WHS) == 0 ){
	       				im_insertRect( pd, xp, yp, (int[])hs_him[i], w, 0, 0, w, h );
	       				hs_imode[i] |= IMODE_WHS;
	       				result = true;
	       			}
	       		}else{
	       			if( (hs_imode[i] & IMODE_WHS) > 0 ){
	       				im_insertRect( pd, xp, yp, (int[])hs_him[i], w, 0, h, w, h );
	       				hs_imode[i] &= ~IMODE_WHS;
	       				result = true;
	       			}
	       		}
	       	}
	}
	return result;
}  	


// Convert relative to absolute hotspot coordinates
void hs_rel2abs(int pw, int ph){
	int i;
		
	for(i=0; i<numhs; i++){
		if(hs_xp[i] < 0.0){
			hs_xp[i] = -hs_xp[i] * (double)pw / 100.0;
			if( hs_xp[i] >= pw ) hs_xp[i] = pw - 1;
		}
		if(hs_yp[i] < 0.0){
			hs_yp[i] = -hs_yp[i] * (double)ph / 100.0;
			if( hs_yp[i] >= ph ) hs_yp[i] = ph - 1;
		}
		if(hs_up[i] < 0.0 && hs_up[i] != NO_UV){
			hs_up[i] = -hs_up[i] * (double)pw / 100.0;
			if( hs_up[i] >= pw ) hs_up[i] = pw - 1;
		}
		if(hs_vp[i] < 0.0 && hs_vp[i] != NO_UV){
			hs_vp[i] = -hs_vp[i] * (double)ph / 100.0;
			if( hs_vp[i] >= ph ) hs_vp[i] = ph - 1;
		}
	}
}


// Draw hotspot marker

void hs_draw(Graphics g, int off_x, int off_y, int width, int height, int chs, boolean shs){
	int i;
 		
 	// g.setClip( off_x, off_y, width, height ); // Draw only into viewer window; does not work in NC4.04
 		 		
 	for(i=0; i<numhs; i++){
		if( hs_visible[i] ){
	       	if( shs || (hs_imode[i] & IMODE_ALWAYS) > 0 
	       			|| (i == chs && (hs_imode[i] & IMODE_POPUP) > 0) 
	       			|| (chs >= 0 && hs_link[i] == chs && (hs_imode[i] & IMODE_POPUP) > 0)){
      			if( hs_him[i] == null ){ // default circle
      	 			if( hs_hc[i] == null )
        				g.setColor(Color.red);
        			else
        				g.setColor(hs_hc[i]);
      	 			g.drawOval(hs_xv[i] - 10 + off_x, hs_yv[i] - 10 + off_y,20,20);
      	 			g.fillOval(hs_xv[i] -  5 + off_x, hs_yv[i] -  5 + off_y,10,10);
       			}else if( hs_him[i] instanceof Image ){ // Draw image
       				Image p = (Image)hs_him[i];
        			g.drawImage(	p,
        							hs_xv[i] - p.getWidth(null) /2 + off_x,
        							hs_yv[i] - p.getHeight(null)/2 + off_y,
        							this	);
        		}else if( (hs_imode[i] & IMODE_TEXT) > 0 &&
        				   hs_him[i] instanceof String ){ // Text window
        			String s = (String)hs_him[i];
        			Dimension d = string_textWindowSize( g, s );
        			if( hs_xv[i] >=0 && hs_xv[i] < width &&
        				hs_yv[i] >=0 && hs_yv[i] < height ){
        				int xt=0,yt=0,corner=0;
        				if( hs_xv[i] + d.width < width ){
        					if( hs_yv[i] - d.height > 0 ){
        						xt=hs_xv[i]; yt=hs_yv[i] - d.height;corner=1;
        					}else if( hs_yv[i] + d.height < width ){
        						xt=hs_xv[i]; yt=hs_yv[i];corner=2;
        					}
        				}else if( hs_xv[i] - d.width >= 0 ){
        					if( hs_yv[i] - d.height > 0 ){
        						xt=hs_xv[i]- d.width; yt=hs_yv[i] - d.height;corner=3;
        					}else if( hs_yv[i] + d.height < width ){
        						xt=hs_xv[i]- d.width; yt=hs_yv[i];corner=4;
        					}
        				}
        				if(corner!=0){
        					string_drawTextWindow( g, xt + off_x, yt + off_y, d, hs_hc[i], s, corner);
      					}
      				}
         		}
         	}
        }
  	}
}

final void hs_exec_popup( int chs ){
 	for(int i=0; i<numhs; i++){
		if( hs_visible[i] ){
        	if(  hs_him[i] != null && ( i == chs  || ( chs >= 0 && hs_link[i] == chs)) ){
        		if( hs_him[i] instanceof String && (hs_imode[i] & IMODE_TEXT) == 0 ){
        			JumpToLink( (String)hs_him[i], null );
        		}
        	}
        }
 	}
}



final void hs_setLinkedHotspots(){
  		int i,k=0;
  		
  		for(i=0; i<numhs; i++){
  			for(k=i+1; k<numhs; k++){
  				if( hs_xp[i] == hs_xp[k] && hs_yp[i] == hs_yp[k] && hs_link[i]==-1 )
  					hs_link[k] = i;
  			}
  		}
  	}

final void hs_setCoordinates(int vw, int vh, int pw, int ph, double pan, double tilt, double fov){
		double		a,p;							// field of view in rad
		double		mt[][];
		int 		i,k;
		double 		v0,v1,v2;
		double		x,y,z, theta, phi;
		int 		sw2 =  pw/2;
		int 		sh2 =  ph/2 ;

		mt = new double[3][3];
	
		a  =  fov * 2.0 * Math.PI / 360.0;	// field of view in rad		
		p  = (double)vw / (2.0 * Math.tan( a / 2.0 ) );

		SetMatrix(  -tilt * 2.0 * Math.PI / 360.0, 
					-pan   * 2.0 * Math.PI / 360.0, 
					mt, 
					0 );
		for(i=0; i<numhs; i++)
		{
			x = hs_xp[i] - sw2;
			y = pheight - (hs_yp[i] - sh2);
			
			theta = (x / sw2) * Math.PI;
			phi   = (y / sh2) * Math.PI / 2.0;
			
			if( Math.abs(theta) > Math.PI / 2.0 ) 
				v2 = 1.0;
			else
				v2 = -1.0;
				
			v0 = v2 * Math.tan( theta );
			v1 = Math.sqrt( v0 * v0 + v2 * v2 ) * Math.tan( phi );
			
			x = mt[0][0] * v0 + mt[1][0] * v1 + mt[2][0] * v2;
			y = mt[0][1] * v0 + mt[1][1] * v1 + mt[2][1] * v2;
			z = mt[0][2] * v0 + mt[1][2] * v1 + mt[2][2] * v2;
			
			hs_xv[i] = (int)( x * p/z + vw / 2.0);
			hs_yv[i] = (int)( y * p/z + vh / 2.0 );
         	if(debug)
            	System.out.println("Hotspot Coordinates: x = " + hs_xv[i] + "  y = " + hs_yv[i] + " z = " + z);
            
            int hs_vis_hor = HSIZE;
            int hs_vis_ver = HSIZE;
            
            if( hs_him[i] != null &&  hs_him[i] instanceof Image ){
            	hs_vis_hor = ((Image)hs_him[i]).getWidth(null)/2;
            	hs_vis_ver = ((Image)hs_him[i]).getHeight(null)/2;
            }else if( hs_him[i] != null &&  hs_him[i] instanceof String &&
            		 (hs_imode[i] & IMODE_TEXT) > 0 ){
             	hs_vis_hor = 100; // This should be more intelligent
            	hs_vis_ver = 100;
            }else if( hs_up[i] != NO_UV && hs_vp[i] != NO_UV ){
            	hs_vis_hor = 100; // This should be more intelligent
            	hs_vis_ver = 100;
            }
             	
            
            
            if( hs_xv[i] >= -hs_vis_hor && hs_xv[i] < vwidth +hs_vis_hor && 
            	hs_yv[i] >= -hs_vis_ver && hs_yv[i] < vheight+hs_vis_ver && 
            	z < 0.0){
            	hs_visible[i] = true;
            }else
            	hs_visible[i] = false;
		}
	}


 	


// Final brace for ptviewer.class
}

Back