/******************************************************************************* * Copyright (c) 2014 Open Door Logistics (www.opendoorlogistics.com) * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser Public License 3.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/lgpl.html * ******************************************************************************/ package com.opendoorlogistics.core.geometry.functions; import com.opendoorlogistics.core.formulae.Function; import com.opendoorlogistics.core.formulae.FunctionImpl; import com.opendoorlogistics.core.formulae.FunctionParameters; import com.opendoorlogistics.core.formulae.Functions; import com.opendoorlogistics.core.geometry.ODLGeomImpl; import com.opendoorlogistics.core.geometry.ODLLoadedGeometry; import com.opendoorlogistics.core.geometry.Spatial; import com.opendoorlogistics.core.utils.Numbers; import com.opendoorlogistics.core.utils.strings.Strings; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.LinearRing; /** * Function to create a geometry * @author Phil * */ public final class FmGeom extends FunctionImpl { private final FmGeom.GeomType type; public enum GeomType { POINT, LINESTRING, POLYGON, } public FmGeom(FmGeom.GeomType type, Function... longlatcoords) { super(longlatcoords); this.type = type; if (longlatcoords.length == 0 || longlatcoords.length % 2 != 0) { throw new RuntimeException("Incorrect number of longitude-latitude arguments into formula: " + Strings.convertEnumToDisplayFriendly(type)); } } @Override public Object execute(FunctionParameters parameters) { Spatial.initSpatial(); Object[] children = executeChildFormulae(parameters, true); if (children == null) { return Functions.EXECUTION_ERROR; } // turn into coordinates Coordinate[] coords = new Coordinate[children.length / 2]; for (int i = 0; i < coords.length; i++) { Double longObj = Numbers.toDouble(children[i * 2]); Double latObj = Numbers.toDouble(children[i * 2 + 1]); if (longObj == null || latObj == null) { return Functions.EXECUTION_ERROR; } coords[i] = new Coordinate(longObj, latObj); } GeometryFactory factory = new GeometryFactory(); Geometry geometry = null; switch (type) { case POINT: geometry = factory.createPoint(coords[0]); break; case LINESTRING: geometry = factory.createLineString(coords); break; case POLYGON: // ensure joined up if (coords[0].equals(coords[coords.length - 1]) == false) { Coordinate[] tmp = new Coordinate[coords.length + 1]; System.arraycopy(coords, 0, tmp, 0, coords.length); tmp[coords.length] = coords[0]; coords = tmp; } LinearRing lr = factory.createLinearRing(coords); geometry = factory.createPolygon(lr, null); break; } ODLGeomImpl ret = new ODLLoadedGeometry(geometry); return ret; } @Override public Function deepCopy() { return new FmGeom(type, deepCopy(children)); } @Override public String toString() { return toString(type.name().toLowerCase()); } }