/* *********************************************************************** * This is used by the MysqlGeometryLayer. * This program is distributed freely and 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. * * Copyright 2003 by the Author * * Author name: Uwe Baier uwe.baier@gmx.net * Version 1.0 * *********************************************************************** */ package com.bbn.openmap.layer.mysql; import java.util.Vector; import com.bbn.openmap.util.Debug; /** * This class represents the Factory class do create the different * Geometry Objects. It takes as input a WKT Representation (text) of * the Geometry. It should have less performance than one which * manipulates WKB (binary) (TODO). * <p> * * Copyright 2003 by the Author * <p> * * @author Uwe Baier uwe.baier@gmx.net * @version 1.0 */ public class MysqlWKTGeometryFactory { // private Vector coordStringsVector = new Vector(); public static MysqlGeometry createGeometry(String geotext) { WKTNode wktRoot = parseGeometryText(geotext); String type = geotext.substring(0, geotext.indexOf("(")); return util(wktRoot, type); } protected static MysqlGeometry util(WKTNode wktRoot, String type) { if (type.equals(MysqlGeometry.POINTTYPE)) { return createPoint(wktRoot.getChildByNumber(0).getGeoWKT()); } else if (type.equals(MysqlGeometry.LINESTRINGTYPE)) { return createLine(wktRoot.getChildByNumber(0).getGeoWKT()); } else if (type.equals(MysqlGeometry.POLYGONTTYPE)) { return createPolygon(wktRoot); } else if (type.equals(MysqlGeometry.GEOMETRYCOLLECTIONTYPE)) { MysqlCollection g = new MysqlCollection(); WKTNode n = wktRoot.getChildByNumber(0); String elementTypes = n.getGeoWKT(); Vector typeVector = parseStringByToken(elementTypes, ','); if (typeVector.size() == n.countChildren()) { for (int i = 0; i < typeVector.size(); i++) { WKTNode newRoot = new WKTNode(); newRoot.setRoot(true); newRoot.adChild(n.getChildByNumber(i)); MysqlGeometry newGeometry = util(newRoot, (String) typeVector.elementAt(i)); g.addElement(newGeometry); } } else { Debug.error("MysqlWKTGeometryFactory: Error in GeometryCollection"); } return g; } else if (type.equals(MysqlGeometry.MULTIPOINTTYPE)) { MysqlMultiPoint g = new MysqlMultiPoint(); WKTNode n = wktRoot.getChildByNumber(0); String pointString = n.getGeoWKT(); Vector pointVector = parseStringByToken(pointString, ','); for (int i = 0; i < pointVector.size(); i++) { g.addElement(createPoint((String) pointVector.elementAt(i))); } return g; } else if (type.equals(MysqlGeometry.MULTILINESTRINGTYPE)) { MysqlMultiLineString g = new MysqlMultiLineString(); WKTNode n = wktRoot.getChildByNumber(0); for (int i = 0; i < n.countChildren(); i++) { String lineString = n.getChildByNumber(i).getGeoWKT(); g.addElement(createLine(lineString)); } return g; } else if (type.equals(MysqlGeometry.MULTIPOLYGONTYPE)) { MysqlMultiPolygon g = new MysqlMultiPolygon(); WKTNode n = wktRoot.getChildByNumber(0); for (int i = 0; i < n.countChildren(); i++) { WKTNode newRoot = new WKTNode(); newRoot.setRoot(true); newRoot.adChild(n.getChildByNumber(i)); g.addElement(createPolygon(newRoot)); } return g; } else { Debug.output("MysqlWKTGeometryFactory: Type " + type + " not implemented"); return null; } } protected static MysqlPoint createPoint(String s) { MysqlPoint g = new MysqlPoint(); Vector v = parseStringByToken(s, ' '); double[] d = createDoubleLatLongArray(v); g.setNorthings(d[0]); g.setEastings(d[1]); return g; } protected static MysqlLine createLine(String s) { MysqlLine g = new MysqlLine(); Vector v = parseStringByToken(s.replaceAll(",", " "), ' '); double[] d = createDoubleLatLongArray(v); g.setCoordinateArray(d); return g; } protected static MysqlPolygon createPolygon(WKTNode wktRoot) { MysqlPolygon g = new MysqlPolygon(); WKTNode n = wktRoot.getChildByNumber(0); Vector rings = new Vector(); for (int i = 0; i < n.countChildren(); i++) { Vector v = parseStringByToken(n.getChildByNumber(i) .getGeoWKT() .replaceAll(",", " "), ' '); double[] d = createDoubleLatLongArray(v); rings.add(d); } g.setRings(rings); return g; } protected static void iterateWKTNodeTree(WKTNode n) { if (Debug.debugging("mysql")) { Debug.output("------------"); } for (int i = 0; i < n.countChildren(); i++) { WKTNode child = n.getChildByNumber(i); if (Debug.debugging("mysql")) { Debug.output(child.getGeoWKT() + " " + child.isLeaf()); } iterateWKTNodeTree(child); } } protected static WKTNode parseGeometryText(String coordString) { int i = coordString.indexOf("("); int j = coordString.lastIndexOf(")") + 1; coordString = coordString.substring(i, j); char[] ca = coordString.toCharArray(); WKTNode rootnode = new WKTNode(); rootnode.setRoot(true); WKTNode actualNode; actualNode = rootnode; char actualDelimiter = '#'; for (int k = 0; k < ca.length; k++) { if (ca[k] == '(') { WKTNode n = new WKTNode(); n.setParent(actualNode); actualNode.adChild(n); actualNode = n; actualDelimiter = '('; } else if (ca[k] == ')') { if (actualDelimiter == '(') { actualNode.setLeaf(true); } actualNode = actualNode.getParent(); actualDelimiter = ')'; } else { char[] c = new char[1]; c[0] = ca[k]; actualNode.adToGeoWKT(c); } } return rootnode; } // private static Vector iterateString(String s) { // int low = 0; // int up = 0; // s = s.replaceAll(","," "); // Vector coordVector = new Vector(); // while(up != -1) // { // up = s.indexOf(" "); // if (up != -1 ) { // Double d = new Double(s.substring(low,up)); // coordVector.addElement(d); // s = s.substring(up+1,s.length()); // } // else // { // Double d = new Double(s); // coordVector.addElement(d); // } // } // return coordVector; // } // private static double[] createDoubleLatLongArray(Vector v) { // int i = v.size(); // double[] darray = new double[i]; // for (int j = 0; j < i / 2; j++) { // for(int k = 0; k < 2; k++){ // if (j == 0) { // Double d = (Double) v.elementAt(1 - k); // darray[k] = d.doubleValue(); // } else { // Double d = (Double) v.elementAt(2 * j + 1 - k); // darray[2 * j + k] = d.doubleValue(); // } // } // } // return darray; // } protected static double[] createDoubleLatLongArray(Vector v) { int i = v.size(); double[] darray = new double[i]; for (int j = 0; j < i / 2; j++) { for (int k = 0; k < 2; k++) { if (j == 0) { try { Double d = new Double((String) v.elementAt(1 - k)); darray[k] = d.doubleValue(); } catch (Exception e) { Debug.error((String) v.elementAt(1 - k)); } } else { Double d = new Double((String) v.elementAt(2 * j + 1 - k)); darray[2 * j + k] = d.doubleValue(); } } } return darray; } protected static Vector parseStringByToken(String s, char token) { char[] ca = s.toCharArray(); char[] charArray; if (ca[ca.length - 1] != token) { char[] tk = new char[1]; tk[0] = token; String s1 = s.concat(new String(tk)); charArray = s1.toCharArray(); } else { charArray = ca; } String t = new String(); Vector v = new Vector(); for (int i = 0; i < charArray.length; i++) { if (charArray[i] == token) { v.add(t); t = ""; } else { char[] c = new char[1]; c[0] = charArray[i]; t = t.concat(new String(c)); } } return v; } }