vtm/vtm-web-app/src/org/oscim/web/client/WKTReader.java
2016-07-12 19:53:47 +03:00

241 lines
7.4 KiB
Java

/*
* Copyright 2013 Hannes Janetzek
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.web.client;
import org.oscim.core.GeometryBuffer;
public class WKTReader {
private final static String POINT = "POINT";
private final static String LINE = "LINESTRING";
private final static String POLY = "POLYGON";
private final static String MULTI = "MULTI";
private final static int SKIP_POINT = POINT.length();
private final static int SKIP_LINE = LINE.length();
private final static int SKIP_POLY = POLY.length();
private final static int SKIP_MULTI = MULTI.length();
public void parse(String wkt, GeometryBuffer geom) throws Exception {
// return position.
int[] pos = new int[]{0};
int len = wkt.length();
if (wkt.startsWith(POINT, pos[0])) {
pos[0] += SKIP_POINT;
geom.startPoints();
ensure(wkt, pos, '(');
parsePoint(geom, wkt, len, pos);
ensure(wkt, pos, ')');
} else if (wkt.startsWith(LINE, pos[0])) {
pos[0] += SKIP_LINE;
geom.startLine();
parseLine(geom, wkt, len, pos);
} else if (wkt.startsWith(POLY, pos[0])) {
pos[0] += SKIP_POLY;
geom.startPolygon();
parsePoly(geom, wkt, len, pos);
} else if (wkt.startsWith(MULTI, pos[0])) {
pos[0] += SKIP_MULTI;
if (wkt.startsWith(POINT, pos[0])) {
pos[0] += SKIP_POINT;
geom.startPoints();
ensure(wkt, pos, '(');
parsePoint(geom, wkt, len, pos);
while (wkt.charAt(pos[0]) == ',') {
pos[0]++;
parsePoint(geom, wkt, len, pos);
}
ensure(wkt, pos, ')');
} else if (wkt.startsWith(LINE, pos[0])) {
pos[0] += SKIP_LINE;
geom.startLine();
ensure(wkt, pos, '(');
parseLine(geom, wkt, len, pos);
while (wkt.charAt(pos[0]) == ',') {
pos[0]++;
geom.startLine();
parseLine(geom, wkt, len, pos);
}
ensure(wkt, pos, ')');
} else if (wkt.startsWith(POLY, pos[0])) {
pos[0] += SKIP_POLY;
geom.startPolygon();
ensure(wkt, pos, '(');
parsePoly(geom, wkt, len, pos);
while (wkt.charAt(pos[0]) == ',') {
pos[0]++;
geom.startPolygon();
parsePoly(geom, wkt, len, pos);
}
ensure(wkt, pos, ')');
} else
throw new Exception("usupported geometry ");
} else
throw new Exception("usupported geometry ");
}
private static void ensure(String wkt, int[] pos, char c) throws Exception {
if (wkt.charAt(pos[0]) != c)
throw new Exception();
pos[0]++;
}
private static void parsePoly(GeometryBuffer geom, String wkt, int len, int[] adv)
throws Exception {
// outer ring
ensure(wkt, adv, '(');
parseLine(geom, wkt, len, adv);
while (wkt.charAt(adv[0]) == ',') {
adv[0]++;
geom.startHole();
parseLine(geom, wkt, len, adv);
}
ensure(wkt, adv, ')');
}
private static void parseLine(GeometryBuffer geom, String wkt, int len, int[] adv)
throws Exception {
ensure(wkt, adv, '(');
parsePoint(geom, wkt, len, adv);
while (wkt.charAt(adv[0]) == ',') {
adv[0]++;
parsePoint(geom, wkt, len, adv);
}
ensure(wkt, adv, ')');
}
private static void parsePoint(GeometryBuffer geom, String wkt, int len, int[] adv) {
float x = parseNumber(wkt, len, adv);
// skip ' '
adv[0]++;
float y = parseNumber(wkt, len, adv);
geom.addPoint(x, y);
}
static float parseNumber(String wkt, int len, int[] adv) {
int pos = adv[0];
boolean neg = false;
if (wkt.charAt(pos) == '-') {
neg = true;
pos++;
}
float val = 0;
int pre = 0;
char c = 0;
for (; pos < len; pos++, pre++) {
c = wkt.charAt(pos);
if (c < '0' || c > '9') {
if (pre == 0)
throw new NumberFormatException("s " + c);
break;
}
val = val * 10 + (int) (c - '0');
}
if (pre == 0)
throw new NumberFormatException();
if (c == '.') {
float div = 10;
for (pos++; pos < len; pos++) {
c = wkt.charAt(pos);
if (c < '0' || c > '9')
break;
val = val + ((int) (c - '0')) / div;
div *= 10;
}
}
if (c == 'e' || c == 'E') {
// advance 'e'
pos++;
// check direction
int dir = 1;
if (wkt.charAt(pos) == '-') {
dir = -1;
pos++;
}
// skip leading zeros
for (; pos < len; pos++)
if (wkt.charAt(pos) != '0')
break;
int shift = 0;
for (pre = 0; pos < len; pos++, pre++) {
c = wkt.charAt(pos);
if (c < '0' || c > '9') {
// nothing after 'e'
if (pre == 0)
throw new NumberFormatException("e " + c);
break;
}
shift = shift * 10 + (int) (c - '0');
}
// guess it's ok for sane values of E
if (dir > 0) {
while (shift-- > 0)
val *= 10;
} else {
while (shift-- > 0)
val /= 10;
}
}
adv[0] = pos;
return neg ? -val : val;
}
// public static void main(String[] args) {
// WKTReader r = new WKTReader();
// GeometryBuffer geom = new GeometryBuffer(10, 10);
// try {
// String wkt = "MULTIPOINT(0 0,1 0)";
// r.parse(wkt, geom);
// for (int i = 0; i < geom.index.length; i++) {
// int len = geom.index[i];
// if (len < 0)
// break;
// for (int p = 0; p < len; p += 2)
// System.out.println(len + ": " + geom.points[p] + "," + geom.points[p + 1]);
// }
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
}