Skip to main content
summaryrefslogtreecommitdiffstats
blob: 6c9e6bf1f97ad6472d99e6ea896d6a6c82fe6eeb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
package org.eclipse.stem.ui.ge.kml;

/*******************************************************************************
 * Copyright (c) 2006 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
import java.awt.Polygon;
import java.awt.Rectangle;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.StringTokenizer;

import org.eclipse.stem.ui.ge.GELog;

/**
 * Obtain the BoundingBox info for GoogleEarth 
 * from the Servlet.  
 * GoogleEarth sends the current Screen viewing area to the servlet 
 * as a BBOX parameter.  The SlideShowServlet saves this BBOX string
 * each time it is sent.  
 * 
 * This class runs as a thread and every N seconds makes a request to the
 *  BBoxServlet to access the latest BBOX string and return it.
 *  We then convert it to a bounding box rectangle and make it available 
 *  for access.  KMLDisplay will access it and use it to filter out 
 *  display of Admin areas that are not within the screen Bounding box.
 * 
 *
 */
public class BBoxInfo implements Runnable {
    
	private static final long SLEEPTIME = 10*1000;
	
	/**
	 * id used to access the session data in servlet
	 */
	private String servletId = null;
	/**
	 * url to access the servlet
	 */
	private String servletUrl = null;
	
	/**
	 * BoundingBox last gotten from servlet
	 */
	private static Rectangle bBox = null;
	
	private String bboxOld = null;
	/**
	 * constructor
	 * @param url  URL for the servlet server
	 * @param id Id to identify the servlet session.
	 */
	public BBoxInfo(String url,String id) {
		servletId = id;
		servletUrl = url;
	}
	
	
	/**
	 * This thread will sit in a loop and every N seconds it 
	 * will send a request to the SlideShowServlet to give it
	 * the latest BBox info that was sent from GoogleEarth
	 */
	public void run() {
		
		while (true) {
			try {
				Rectangle bbox = readBBox();
				if (bbox != null) 
					setBBox(bbox);
				Thread.sleep(SLEEPTIME);
			} catch (InterruptedException e) {
				
			}
		}

	}
	/**
	 * readBBox 
	 *   read the GoogleEarth BBox info from the servlet.
	 *   GoogleEarth sends the viewport bounding box to the 
	 *   servlet which stores it.  This will request the servelet
	 *   to forward it to us.
	 *   
	 *
	 * @return BBox Rectangle 
	 */
	public  Rectangle  readBBox() {
		Rectangle bbox = null;
		
		try {
			URL url = new URL(servletUrl);
			URLConnection connect = url.openConnection();
			connect.setUseCaches(false);
			connect.setDoInput(true);
			connect.setDoOutput(true);
			connect.setRequestProperty("Content-type", "application/octet-stream");
			
			  // use ByteArray output
			ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
			DataOutputStream output =
				new DataOutputStream(byteOutput);
			// tell it what we want and give key to info
			output.writeUTF("BBOX "+servletId);
			
			output.flush();
			byte[] buf = byteOutput.toByteArray();
			
			connect.setRequestProperty("Content-length", ""+buf.length);
			DataOutputStream dataOutput =
				new DataOutputStream(connect.getOutputStream());
			dataOutput.write(buf);
			dataOutput.flush();
			dataOutput.close();
			
			DataInputStream in = 
				new DataInputStream(connect.getInputStream());
			String stringValue = in.readUTF();
			
			in.close();
			
			
			// TODO convert string to rectangle
			String bboxstr = stringValue.substring(5);
			if (! bboxstr.equals(bboxOld)) {
			   GELog.debug(this,"BBOX: "+bboxstr);
			   // convert to Bounding box rectangle
			   bbox = getBBox(bboxstr);
			   GELog.debug(this,"bbox: "+bbox);
			   bboxOld = bboxstr;
			}
			
			
		} catch (MalformedURLException e) {	
			
			GELog.debug(e.getMessage());
		
			//error ="ERROR Invalid URL "+urlstr;
			
		} catch (IOException e) {			
			GELog.debug(e.getMessage());
			
		}
		
		return bbox;
	}
	/**
	 * Given a BBOX string returned from GoogleEarth 
	 * generate the BoundingBox rectangle.
	 * GoogleEarth returns the BBOX in the following format.
	 *  BBOX x1,y1,x2,y2
	 *  where x1,y1 are latitude/longitude of bottom left point 
	 *  and x2,y2 are latitude/longitude of top right point
	 *  Values are doubles like -114.14578934
	 *   
	 * Note that the Rectangle coordinate system uses the origin  
	 * (0,0) as the top left of the screen, 
	 *  with the x and y values increasing as they move to the right 
	 *  and down respectively.
	 *  
	 * @param String containing BBOX info from GE
	 * @return Rectangle
	 */
	private static Rectangle getBBox(String bboxString) {

		Rectangle bBox = null;

		Polygon polygon = new Polygon();
		//GELog.debug(BBoxInfo.class, "BBOX: " + bboxString);

		StringTokenizer st = new StringTokenizer(bboxString, ",");
		if (st.countTokens() == 4) {
			// GE returns the BBox as bottom left, top right coordinates
			// we have to translate to top left + width+height
			double x1 = Double.parseDouble(st.nextToken());
			double y1 = Double.parseDouble(st.nextToken());
			double x2 = Double.parseDouble(st.nextToken());
			double y2 = Double.parseDouble(st.nextToken());
			double[] longitudes = { x1, x1, x2, x2, x1 };
			double[] latitudes = { y1, y2, y2, y2, y1 };
            // ignore if entire globe
			if (x1 == -180 && x2 == 180) {
				//x1 = -180;
				x2 = 0;
				GELog.debug(BBoxInfo.class,"****** modify BBOX to 180,0 ******");
			}
				
			
			for (int p = 0; p < longitudes.length; p++) {
				double x = longitudes[p];
				double y = latitudes[p];
				int xint = (int) ((x + 180) * 1000);
				int yint = (int) ((y + 90) * 1000);

				polygon.addPoint(xint, yint);
			}
		}
	
		
		bBox = polygon.getBounds();
		
		return bBox;
	}

	/**
	 * @return the bBox
	 */
	public synchronized static Rectangle getBBox() {
		return bBox;
	}


	/**
	 * @param box the bBox to set
	 */
	public synchronized static void setBBox(Rectangle box) {
		bBox = box;
	}
	
	/**
	 * Test  containment of bounding box 1 in Bounding box 2
	 * If any corner of BBox 1 is contained in BBox 2 or any corner
	 * of BBox 2 is contained in BBox 1 then they are adjacent.
	 * 
	 * @param r1  bounding box 1
	 * @param r2  bounding box 2
	 * @return true if adjacent or containment true
	 */
	public static boolean testContainment (Rectangle r1, Rectangle r2) {
		
		// coords of corners of first bounding box
		int xMin1 = r1.x;
		int  xMax1 = r1.x+r1.width;
		int  yMin1 = r1.y-r1.height;
		int  yMax1 = r1.y;
		// test overlap
		if (r2.contains(xMin1,yMin1)) return true;
		if (r2.contains(xMin1,yMax1)) return true;
		if (r2.contains(xMax1,yMax1)) return true;
		if (r2.contains(xMax1,yMin1)) return true;
		
        // coords of corners of second bounding box
		int  xMin2 = r2.x;
		int  xMax2 = r2.x+r2.width;
		int  yMin2 = r2.y-r2.height;
		int  yMax2 = r2.y;
        // test overlap
		if (r1.contains(xMin2,yMin2)) return true;
		if (r1.contains(xMin2,yMax2)) return true;
		if (r1.contains(xMax2,yMax2)) return true;
		if (r1.contains(xMax2,yMin2)) return true;
		 
		return false;
	}
}

Back to the top