blob: 65ec1ff156ad473e7605a5b581fb32d74e4b8075 [file] [log] [blame]
package org.eclipse.stem.ui.ge;
/*******************************************************************************
* 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.text.DecimalFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.stem.definitions.adapters.spatial.geo.LatLong;
import org.eclipse.stem.definitions.adapters.spatial.geo.LatLong.Segment;
import org.eclipse.stem.ui.ge.views.GEPreferencePage;
/**
* Store info about a geographic location and SEIR status in STEM.
* It would represent an area such as a US county and
* contains an id and the border expressed as one or more
* list of points. The points are Longitude and latitude.
*
* Note that (perhaps for an island group) there may be
* more than 1 list of points.
*
* It also contains the values for various aspects relative to Population
* For SEIR diceases, these aspects would be Susceptible,Exposed,
* Infectious, and Recovered There may be more or less aspects.
* These are stored in a Map keyed by aspect code.
*
*/
public class GEData {
/**
* Name of the Admin area involved
*/
private String name = "";
/**
* Can be set by the creater with setDescription.
* Usually used for the list of relative values
*/
private String description = "";
/**
* used to set the kml id
*/
private String id = "";
/**
* used to format the longitude/latitude values
* default of DecimalFormat() would result in 3 digit precision
*/
private static final DecimalFormat df = new DecimalFormat("####.##");
/**
* A LatLong instance is a collection of latitude/longitude data pairs partititioned
* into one or more "segments". Each segment is a sequence of latitude/longitude
* data pairs. A segment could form a closed polygon or it could be a path.
* In our case this should always be a closed polygon.
* <pre>
* Each LatLong describes 1 or more polygon border. There may be
* more than one polygon in the case of an island or ...
*
* </pre>
*/
private LatLong polygons = null;
/**
* Contains the aspect values for the area
* Keyed by the aspect code.
* For Example. with an SEIR disease you would have
* keyed entries for "S", "E", "I" and "R"
*/
private final Map<String,Double> valueMap = new HashMap<String,Double>(8);
/**
* Bounding Box for this LatLong polygon.
* If LatLong contains more than 1 polygon this is the
* union of the BoundingBox for each polygon
*/
private Rectangle bBox = null;
private double[] placemark = null;
/**
* Create an instance of GEData with LatLong
* @param name
* @param areas
*/
public GEData(String name, LatLong areas) {
super();
this.name = name;
this.id = name;
this.polygons = areas;
//if (areas.size() > 1) {
// GELog.debug(this,name+": "+areas.size());
//}
if (GEPreferencePage.isBBOX()) {
this.bBox = getBBox(areas);
}
}
/**
* Create an instance of GEData with LatLong
* @param id admin area id
* @param name admin area name
* @param areas lat/long border of 1 of more polygons
*/
public GEData(String id, String name, LatLong areas) {
super();
this.name = name;
this.id = id;
this.polygons = areas;
//if (areas.size() > 1) {
// GELog.debug(this,name+": "+areas.size());
//}
if (GEPreferencePage.isBBOX()) {
this.bBox = getBBox(areas);
}
}
/**
*
* format needed by KML
* long,lat long,lat ...
*
* By default DecimalFormat will return
* doubles as nnnn.ddd
*
* @param numArea Normally 0 if just 1 contagious area
* but it could be a set of islands or
* other multiple areas.
* @return the coordinates as a String in the form
* long1,lat1 long2,lat2 ...
*/
public String getCoordinatesAsString(int numArea) {
Segment segment = polygons.getSegments().get(numArea);
// we don't care about altitude
StringBuffer strbuf = new StringBuffer(400);
final int size = segment.size();
for (int i=0; i< size; i++) {
strbuf.append(df.format(segment.longitude(i)));
strbuf.append(",");
strbuf.append(df.format(segment.latitude(i) ));
strbuf.append(" ");
}
return strbuf.toString();
}
/**
*
*Get the aspect values as a String
*
*
* @return the values as a String in the form
* a1: v1 a2:v2 ...
*/
public String getValuesAsString() {
StringBuffer strbuf = new StringBuffer(64);
for(Map.Entry<String, Double> entry: valueMap.entrySet() ) {
strbuf.append(entry.getKey());
strbuf.append(":");
strbuf.append(df.format(entry.getValue()));
strbuf.append(" ");
}
return strbuf.toString();
}
/**
* get the number of areas described by the geographic points.
*
* @return number of polygons described
*/
public int getNumAreas() {
if (polygons != null)
return polygons.size();
else
return 0;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @return the bBox rectangle
*/
public Rectangle getBBox() {
return bBox;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the id
*/
public String getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(String id) {
this.id = id;
}
/**
* set the coordinates of a point within a polygon
* @param latitude
* @param longitude
*/
public void setPoint(double latitude, double longitude) {
placemark = new double[2];
placemark[0] = latitude;
placemark[1] = longitude;
}
/**
* Return the coordiantes of a point
*
* @return Double[] or null
*/
public double[] getPoint() {
return placemark;
}
/**
* Given a LatLong, generate the overall BoundingBoxes.
*
* @param latLong
* @return Rectangle
*/
private static Rectangle getBBox(LatLong latLong) {
List<Segment> list = latLong.getSegments();
int numareas = list.size();
Rectangle bBox = null;
for (int i=0; i<numareas; i++) {
final Polygon polygon = new Polygon();
final Segment segment = list.get(i);
final int size = segment.size();
for (int p=0; p< size; p++) {
double x = segment.longitude(p);
double y = segment.latitude(p);
int xint = (int)((x+180)*1000);
int yint = (int)((y+90)*1000);
polygon.addPoint(xint, yint);
} // for
if (bBox == null)
bBox = polygon.getBounds();
else
bBox = bBox.union(polygon.getBounds());
}
return bBox;
}
/**
* debug helper
*/
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("GEData: ");
sb.append(this.getValuesAsString());
sb.append(" BBox:"+bBox);
sb.append(" : ");
for (int i=0; i< polygons.size(); i++) {
sb.append(this.getCoordinatesAsString(i));
}
return sb.toString();
}
/**
* @return the valueMap for the specified area so
* we can store values into it.
*/
public Map<String,Double> getValueMap() {
return valueMap;
}
/**
* @param aspect
* @return the value for the specified alpect
*/
public double getValue(Aspect aspect) {
return valueMap.get(aspect.getCode());
}
/**
* Store the value in the data store for the area.
*
* @param aspect The aspect that this value is for.
* @param value the value for the specified aspect
*/
public void setValue(Aspect aspect, double value) {
valueMap.put(aspect.getCode(),value);
}
/**
* @return the center of the BBox as longitude and latitude.
*/
public double[] getBBoxCenter() {
if (bBox == null) {
bBox = getBBox(polygons);
}
if (bBox != null ) {
// convert back to double value.
double longitude = bBox.getCenterX();
longitude = (longitude-180000)/1000;
double latitude = bBox.getCenterY();
latitude = (latitude-90000)/1000;
double[] center = new double[] {longitude,latitude};
return center;
}
return null;
}
/**
* @return the description
*/
public String getDescription() {
return description;
}
/**
* @param description the description to set
*/
public void setDescription(String description) {
this.description = description;
}
}