// **********************************************************************
//
// <copyright>
//
// BBN Technologies
// 10 Moulton Street
// Cambridge, MA 02138
// (617) 873-8000
//
// Copyright (C) BBNT Solutions LLC. All rights reserved.
//
// </copyright>
// **********************************************************************
//
// $Source: /cvs/distapps/openmap/src/corba/com/bbn/openmap/layer/specialist/shape/ShapeSpecialist.java,v $
// $RCSfile: ShapeSpecialist.java,v $
// $Revision: 1.5 $
// $Date: 2007/06/21 21:39:44 $
// $Author: dietrick $
//
// **********************************************************************
package com.bbn.openmap.layer.specialist.shape;
import java.awt.Color;
import java.util.Properties;
import java.util.Vector;
import com.bbn.openmap.corba.CSpecialist.MouseEvent;
import com.bbn.openmap.corba.CSpecialist.UGraphic;
import com.bbn.openmap.corba.CSpecialist.WidgetChange;
import com.bbn.openmap.layer.shape.ESRIRecord;
import com.bbn.openmap.layer.shape.SpatialIndex;
import com.bbn.openmap.layer.specialist.SColor;
import com.bbn.openmap.layer.specialist.SGraphic;
import com.bbn.openmap.layer.specialist.Specialist;
import com.bbn.openmap.proj.ProjMath;
import com.bbn.openmap.util.Debug;
import com.bbn.openmap.util.PropUtils;
/**
* Implements the Specialist interface so that we can serve graphics to OpenMap
* via CORBA. This specialist handles shape files, with the coordinates in the
* shape files being in decimal degrees, not pre-projected x-y coordinates. The
* specialist looks for a property file to know where where the shape file and
* spatial index file is, and how to color the shapes.
*/
public class ShapeSpecialist
extends Specialist {
/** The name of the property that holds the name of the shape file. */
public final static String shapeFileProperty = "shapeFile";
/**
* The name of the property that holds the name of the spatial index file.
*/
public final static String spatialIndexProperty = "spatialIndex";
/**
* The name of the property that holds the line color of the graphics.
*/
public final static String lineColorProperty = "lineColor";
/**
* The name of the property that holds the fill color of the graphics.
*/
public final static String fillColorProperty = "fillColor";
/** The spatial index to use to pick the graphics to return. */
protected SpecialistSpatialIndex spatialIndex;
/** The read-in properties. */
protected Properties properties = null;
/** The color to outline the shapes. */
protected SColor lineColor = null;
/** The color to fill the shapes. */
protected SColor fillColor = null;
// final private static SColor nullColor = new SColor((short) 0, (short) 0,
// (short) 0);
// final private static EStipple nullStipple = new EStipple(null, (short) 0,
// (short) 0, new byte[0]);
// final private static EComp nullComp = new EComp(null, "");
// final private static XYPoint nullP1 = new XYPoint((short) 0, (short) 0);
// final private static XYPoint[] nullPA = new XYPoint[0];
// final private static LLPoint nullLL1 = new LLPoint(0.0f, 0.0f);
/**
* default constructor is called when we're loading the class directly into
* OpenMap. Not used.
*/
public ShapeSpecialist() {
super("ShapeSpecialist", (short) 2, false);
}
/**
* The real constructor to use.
*
* @param shapeFile the shapefile.
*/
public ShapeSpecialist(String shapeFile) {
super("ShapeSpecialist", (short) 2, false);
init(shapeFile);
}
/**
* Loads the spatial index from the shape files.
*
* @param shapeFile the shapefile.
*/
public void init(String shapeFile) {
spatialIndex = locateAndSetShapeData(shapeFile);
}
/**
* Gets the layer graphics.
*
* @param ll1 the upper left LLPoint.
* @param ll2 the lower right LLPoint.
* @return Vector of ESRISpecialistRecords.
*/
protected Vector computeGraphics(com.bbn.openmap.corba.CSpecialist.LLPoint ll1,
com.bbn.openmap.corba.CSpecialist.LLPoint ll2) {
if (spatialIndex == null) {
return new Vector();
}
Vector list = null;
// check for dateline anomaly on the screen. we check for
// ll1.lon >=
// ll2.lon, but we need to be careful of the check for
// equality because
// of floating point arguments...
// Since we don't have the projection scale here, we're going to assume
// that we're not zoomed in.
if (ProjMath.isCrossingDateline(ll1.lon, ll2.lon, 1000000f)) {
if (Debug.debugging("shape")) {
Debug.output("Dateline is on screen");
}
double ymin = (double) Math.min(ll1.lat, ll2.lat);
double ymax = (double) Math.max(ll1.lat, ll2.lat);
try {
ESRIRecord records1[] = spatialIndex.locateRecords(ll1.lon,
ymin,
180.0d,
ymax);
ESRIRecord records2[] = spatialIndex.locateRecords(-180.0d,
ymin,
ll2.lon,
ymax);
int nRecords1 = records1.length;
int nRecords2 = records2.length;
list = new Vector(nRecords1 + nRecords2);
for (int i = 0; i < nRecords1; i++) {
((ESRISpecialistRecord) records1[i]).writeGraphics(list,
lineColor,
fillColor);
}
for (int i = 0; i < nRecords2; i++) {
((ESRISpecialistRecord) records2[i]).writeGraphics(list,
lineColor,
fillColor);
}
} catch (java.io.IOException ex) {
ex.printStackTrace();
} catch (com.bbn.openmap.io.FormatException fe) {
fe.printStackTrace();
}
} else {
double xmin = (double) Math.min(ll1.lon, ll2.lon);
double xmax = (double) Math.max(ll1.lon, ll2.lon);
double ymin = (double) Math.min(ll1.lat, ll2.lat);
double ymax = (double) Math.max(ll1.lat, ll2.lat);
try {
ESRIRecord records[] = spatialIndex.locateRecords(xmin,
ymin,
xmax,
ymax);
int nRecords = records.length;
list = new Vector(nRecords);
for (int i = 0; i < nRecords; i++) {
((ESRISpecialistRecord) records[i]).writeGraphics(list,
lineColor,
fillColor);
}
} catch (java.io.IOException ex) {
ex.printStackTrace();
} catch (com.bbn.openmap.io.FormatException fe) {
fe.printStackTrace();
}
}
return list;
}
/**
* The CSpecialist function.
*/
public UGraphic[] fillRectangle(
com.bbn.openmap.corba.CSpecialist.CProjection p,
com.bbn.openmap.corba.CSpecialist.LLPoint ll1,
com.bbn.openmap.corba.CSpecialist.LLPoint ll2,
java.lang.String staticArgs,
org.omg.CORBA.StringHolder dynamicArgs,
com.bbn.openmap.corba.CSpecialist.GraphicChange notifyOnChange,
String uniqueID) {
// System.out.println("ShapeSpecialist.fillRectangle()");
try {
Vector list = computeGraphics(ll1, ll2);
int len = list.size();
UGraphic[] ugraphics = new UGraphic[len];
for (int i = 0; i < len; i++) {
SGraphic sg = (SGraphic) list.elementAt(i);
ugraphics[i] = sg.ufill();
}
// System.out.println("ShapeSpecialist.fillRectangle():
// got "+ugraphics.length+" graphics");
return ugraphics;
} catch (Throwable t) {
System.err.println("ShapeSpecialist.fillRectangle(): " + t);
t.printStackTrace();
// Don't throw another one! Try to recover!
// throw new RuntimeException();
return new UGraphic[0];
}
}
protected SpecialistSpatialIndex locateAndSetShapeData(String shapeFileName) {
SpatialIndex si = null;
try {
si = new SpecialistSpatialIndex(shapeFileName);
} catch (java.io.IOException e) {
e.printStackTrace();
}
return (SpecialistSpatialIndex) si;
}
public void signOff(String uniqueID) {
System.out.println("ShapeSpecialist.signOff()");
}
public void receiveGesture(MouseEvent gesture, String uniqueID) {
}
public void makePalette(WidgetChange notifyOnChange, String staticArgs,
org.omg.CORBA.StringHolder dynamicArgs,
String uniqueID) {
}
public void printHelp() {
System.err.println("usage: java [java/vbj args] <specialist class> [specialist args]");
System.err.println("");
System.err.println(" Java Args:");
System.err.println(" -mx<NUM>m Set max Java heap in Megs");
System.err.println("");
System.err.println(" VBJ Args:");
System.err.println(" -DORBmbufSize=8388608 Define the VBJ buffer size");
System.err.println(" -DORBdebug Enable VBJ debugging");
System.err.println("");
System.err.println(" Specialist Args:");
System.err.println(" -ior <iorfile> IOR file");
System.err.println(" -properties \"<file> ...\" Path to properties file");
}
public void parseArgs(String[] args) {
Color lcolor = null;
Color fcolor = null;
for (int i = 0; i < args.length; i++) {
if (args[i].equalsIgnoreCase("-properties") &&
(args.length > (i + 1))) {
properties = loadProps(args[i + 1]);
lcolor = PropUtils.parseColorFromProperties(properties,
lineColorProperty,
"FF000000");
lineColor = new SColor((short) ((lcolor.getRed()) * 65535 / 255), (short) ((lcolor.getGreen()) * 65535 /
255), (short) ((lcolor.getBlue()) * 65535 / 255));
if (properties.getProperty(fillColorProperty) != null) {
fcolor = PropUtils.parseColorFromProperties(properties,
fillColorProperty,
"FF000000");
fillColor = new SColor((short) ((fcolor.getRed()) * 65535 / 255), (short) ((fcolor.getGreen()) *
65535 / 255), (short) ((fcolor.getBlue()) * 65535 / 255));
}
String shp = properties.getProperty(shapeFileProperty);
// System.out.println("Getting " + shp + " and " +
// ssx);
init(shp);
}
}
if (properties == null) {
System.out.println("Need properties file!");
System.out.println("");
System.out.println("#######################################");
System.out.println("shapeFile=<path to shape file (.shp)>");
System.out.println("spatialIndex=<path to spatial index file (.ssx)>");
System.out.println("lineColor=<hex ARGB color> i.e. FF000000 for black");
System.out.println("fillColor=<hex ARGB color> i.e. FF000000 for black>");
System.out.println("#######################################");
System.out.println("");
printHelp();
System.exit(0);
}
super.parseArgs(args);
System.out.println("Using colors -> lcolor = " + lcolor + ", fcolor = " +
fcolor);
}
/**
* Load the named file from the named directory into the given
* <code>Properties</code> instance. If the file is not found a warning is
* issued. If an IOExceptio occurs, a fatal error is printed and the
* application will exit.
*
* @param file the name of the file
* @return the loaded properties
*/
public Properties loadProps(String file) {
java.io.File propsFile = new java.io.File(file);
Properties props = new Properties();
try {
java.io.InputStream propsStream = new java.io.FileInputStream(propsFile);
props.load(propsStream);
} catch (java.io.FileNotFoundException e) {
System.err.println("ShapeSpecialist did not find properties file: \"" +
file + "\"");
System.exit(1);
} catch (java.io.IOException e) {
System.err.println("Caught IO Exception reading configuration file \"" +
propsFile + "\"");
e.printStackTrace();
System.exit(1);
}
return props;
}
public static void main(String[] args) {
Debug.init(System.getProperties());
// Create the specialist server
ShapeSpecialist srv = new ShapeSpecialist();
srv.parseArgs(args);
srv.start(args);
}
}