📄 whereline.java
字号:
package org.trinet.util.gazetteer.TN;
import org.trinet.util.gazetteer.*;
import java.sql.*;
import java.io.*;
import java.util.*;
import oracle.sql.*;
//import oracle.jdbc.driver.*;
public abstract class WhereLine extends WhereAmI {
private int maxBufferBytes = 96000;
private byte [] byteBuffer = new byte [maxBufferBytes];
// Replace with java2 list
private int numberOfLines;
private int maxLines = 100;
private LineData [] lineData = new LineData[maxLines];
/** Default constructor does not set a reference point or a database connection */
public WhereLine() {
super();
}
/** Constructor sets the database connection, does not set a reference point. */
public WhereLine(Connection conn) {
super(conn);
}
/** Constructor sets the database connection and reference point. */
public WhereLine(Connection conn, Geoidal reference) {
super(conn, reference);
}
/** Constructor sets the reference point, does not set a database connection. */
public WhereLine(Geoidal reference) {
super(reference);
}
/** Constructor sets the reference point, does not set a database connection.
* Elevation/depth input parameter is assumed to be in km units.
*/
public WhereLine(double lat, double lon, double z) {
super(lat, lon, z);
}
protected abstract Vector getDatabaseData();
abstract String getLineTypeName() ;
private static double deltaDegrees(double lat, double lon, double latRef, double lonRef) {
return Math.abs(latRef - lat) + Math.abs(lonRef - lon);
}
/** Returns Vector of WhereItems constructed using station database data. */
protected Vector getDatabaseData(String sql) {
if (items != null) {
items.removeAllElements();
items = getDataFromCache();
return items;
}
items = new Vector(maxLines);
try {
Statement sm = conn.createStatement();
ResultSet rs = sm.executeQuery(sql);
numberOfLines = 0;
while (rs.next()) {
String name = rs.getString("NAME");
int line = rs.getInt("LINE");
String format = rs.getString("FORMAT");
int bytesPerPoint = getBytesPerPoint(format);
String remark = "NULL";
// String remark = rs.getString("REMARK");
// if (rs.wasNull()) remark = "NULL";
oracle.sql.BLOB points = (oracle.sql.BLOB) rs.getObject("POINTS");
if (points == null) throw new NullPointerException("WhereLine: getDatabaseData null points object");
int blobPts = ((int) points.length())/bytesPerPoint;
// System.out.println(name + " " + line + " " + format + " " + bytesPerPoint + " " + remark + " Pts: " + blobPts);
lineData[numberOfLines] = new LineData(name, line, format, remark, blobPts);
makeWhereItem(lineData[numberOfLines], points);
numberOfLines++;
}
rs.close();
sm.close();
}
catch (SQLException ex) {
System.out.println(ex.getMessage());
ex.printStackTrace();
return null;
}
return items;
}
protected int getBytesPerPoint(String format) {
if (format.equalsIgnoreCase("double")) {return 16;}
else if (format.equalsIgnoreCase("float")) {return 8;}
else if (format.equalsIgnoreCase("int")) {return 8;}
else if (format.equalsIgnoreCase("long")) {return 16;}
else if (format.equalsIgnoreCase("char")) {return 2;}
else if (format.equalsIgnoreCase("byte")) {return 1;}
return -1;
}
protected Vector getDataFromCache() {
for (int index=0; index < numberOfLines; index++) {
makeWhereItem(lineData[index]);
}
return items;
}
protected void addWhereItemToList(BasicGazetteerPt bgp, LineData lineData) {
bgp.setName(lineData.name);
bgp.setRemark(getLineTypeName());
items.addElement(new WhereItem(reference, bgp));
}
protected void makeWhereItem(LineData lineData) {
BasicGazetteerPt bgp = getClosestPoint(lineData); // try binary search
// BasicGazetteerPt bgp = getClosestPoint(lineData, reference.getLat(), reference.getLon());
if (bgp == null) throw new NullPointerException("WhereLine: getDataFromCache null point returned from getClosestPoint");
addWhereItemToList(bgp, lineData);
}
protected void makeWhereItem(LineData lineData, BLOB points) {
BasicGazetteerPt bgp = getClosestPoint(lineData, reference.getLat(), reference.getLon(), points);
if (bgp == null) throw new NullPointerException("WhereLine: makeWhereItem null point returned from getClosestPoint");
addWhereItemToList(bgp, lineData);
}
protected BasicGazetteerPt getClosestPoint(LineData lineData, double latRef, double lonRef) {
double minDeg = 360.;
double minLat = 90.;
double minLon = 180.;
double degDiff = 0.;
for ( int index=0; index < lineData.numberOfPoints; index++) {
degDiff = deltaDegrees(lineData.lat[index], lineData.lon[index], latRef, lonRef);
if (degDiff < minDeg) {
minLat = lineData.lat[index];;
minLon = lineData.lon[index];;
minDeg = degDiff;
}
}
return new BasicGazetteerPt(minLat, minLon);
}
protected BasicGazetteerPt getClosestPoint(LineData lineData) {
int minIndex = 0;
double latRef = reference.getLat();
double lonRef = reference.getLon();
double lat1 = lineData.lat[minIndex];
double lon1 = lineData.lon[minIndex];
int maxIndex = lineData.lat.length - 1;
double lat2 = lineData.lat[maxIndex];
double lon2 = lineData.lon[maxIndex];
double dist1 = deltaDegrees(lat1, lon1, latRef, lonRef);
double dist2 = deltaDegrees(lat2, lon2, latRef, lonRef);
// do a binary search
int pointsToMiddle = (maxIndex - minIndex)/2;
while (pointsToMiddle >= 1) {
int middleIndex = minIndex + pointsToMiddle;
if (dist1 < dist2) {
maxIndex = middleIndex;
lat2 = lineData.lat[middleIndex];
lon2 = lineData.lon[middleIndex];
dist2 = deltaDegrees(lat2, lon2, latRef, lonRef);
}
else {
minIndex = middleIndex;
lat1 = lineData.lat[middleIndex];
lon1 = lineData.lon[middleIndex];
dist1 = deltaDegrees(lat1, lon1, latRef, lonRef);
}
pointsToMiddle = (maxIndex - minIndex)/2;
}
if (dist1 < dist2) return new BasicGazetteerPt(lat1, lon1);
else return new BasicGazetteerPt(lat2, lon2);
}
protected BasicGazetteerPt getClosestPoint(LineData lineData, double latRef, double lonRef, BLOB points) {
double minDeg = 360.;
double minLat = 90.;
double minLon = 180.;
long bytesToRead = 0;
long bytesRead = 0;
BufferedInputStream bis;
try {
bytesToRead = points.length();
bis = new BufferedInputStream(points.getBinaryStream());
// byte [] byteBuffer = points.getBytes(0l, (int) bytesToRead); // error with 8i, contrary to doc on BLOB.getBytes()
}
catch (SQLException ex) {
System.out.println(ex.getMessage());
ex.printStackTrace();
return null;
}
int index = 0;
try {
while (bytesRead < bytesToRead) {
int bytesInput = bis.read(byteBuffer);
if (bytesInput == -1 ) break;
bytesRead += bytesInput;
DataInputStream dis = new DataInputStream(new ByteArrayInputStream(byteBuffer));
int bytesDone = 0;
int bytesPerPoint = getBytesPerPoint(lineData.format);
try {
while (bytesDone < bytesInput) {
lineData.lat[index] = dis.readDouble();
lineData.lon[index] = dis.readDouble();
bytesDone += bytesPerPoint;
double degDiff = deltaDegrees(lineData.lat[index], lineData.lon[index], latRef, lonRef);
if (degDiff < minDeg) {
minLat = lineData.lat[index];
minLon = lineData.lon[index];
minDeg = degDiff;
}
index++;
}
}
catch (EOFException ex) {
System.out.println(ex.getMessage());
ex.printStackTrace();
}
dis.close();
}
bis.close();
}
catch (IOException ex) {
System.out.println(ex.getMessage());
ex.printStackTrace();
return null;
}
return new BasicGazetteerPt(minLat, minLon);
}
}
// Use java2 collections
// A more generic solution would be to store data in byte buffers then use DataInputStreams and get/set methods on lat,lon
// Or store points as Object and use format type to determine data Object creation types (interface).
// Or use factory methods for creating different LineData morphs and use get/set method overrides to manipulate data.
class LineData {
String name;
int lineSegment;
String format;
String remark;
int numberOfPoints;
double [] lat;
double [] lon;
LineData(String name, int lineSegment, String format, String remark, int numberOfPoints) {
this.name = name;
this.lineSegment = lineSegment;
this.format = format;
this.remark = remark;
this.numberOfPoints = numberOfPoints;
lat = new double [numberOfPoints];
lon = new double [numberOfPoints];
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -