/**************************************************************************
OSMemory library for OSM data processing.
Copyright (C) 2014 Aleś Bułojčyk <alex73mail@gmail.com>
This is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This software 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/
package org.alex73.osmemory.geometry;
import org.alex73.osmemory.IOsmNode;
import org.alex73.osmemory.IOsmObject;
import org.alex73.osmemory.IOsmWay;
import org.alex73.osmemory.MemoryStorage;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.LineString;
/**
* Class for cache some extended information about way, like boundary, geometry, etc.
*/
public class ExtendedWay implements IExtendedObject {
private final IOsmWay way;
private final MemoryStorage storage;
private BoundingBox boundingBox;
private boolean allPointsDefined;
private Coordinate[] points;
private IOsmNode[] nodes;
private LineString line;
private Geometry area;
public ExtendedWay(IOsmWay way, MemoryStorage storage) {
this.way = way;
this.storage = storage;
}
@Override
public IOsmObject getObject() {
return way;
}
public BoundingBox getBoundingBox() {
checkProcessed();
return boundingBox;
}
public boolean isAllPointsDefined() {
checkNodes();
return allPointsDefined;
}
public boolean isClosed() {
long[] nids = way.getNodeIds();
return nids.length >= 3 && nids[0] == nids[nids.length - 1];
}
public synchronized LineString getLine() throws Exception {
checkProcessed();
if (!allPointsDefined) {
return null;
}
if (line == null) {
try {
line = GeometryHelper.createLine(points);
} catch (Exception ex) {
throw new Exception("Impossible to create line from way #" + way.getId() + ": "
+ ex.getMessage());
}
if (!line.isValid()) {
throw new Exception("not valid line");
}
if (!line.isSimple()) {
throw new Exception("self-intersected");
}
}
return line;
}
public synchronized Geometry getArea() {
checkProcessed();
if (!isClosed()) {
throw new RuntimeException("Impossible to create polygon from way #" + way.getId()
+ ": non-closed way");
}
if (!allPointsDefined) {
throw new RuntimeException("Impossible to create polygon from way #" + way.getId()
+ ": not all points defined");
}
if (area == null) {
try {
area = GeometryHelper.createPolygon(points);
} catch (Exception ex) {
throw new RuntimeException("Impossible to create polygon from way #" + way.getId() + ": "
+ ex.getMessage());
}
if (!area.isValid()) {
throw new RuntimeException("Impossible to create polygon from way #" + way.getId()
+ ": it is not valid");
}
}
return area;
}
protected synchronized void checkProcessed() {
if (boundingBox != null) {
return; // already loaded
}
checkNodes();
boundingBox = new BoundingBox();
points = new Coordinate[nodes.length];
for (int i = 0; i < nodes.length; i++) {
IOsmNode n = nodes[i];
if (n != null) {
boundingBox.expandToInclude(n.getLat(), n.getLon());
points[i] = GeometryHelper.coord(n.getLongitude(), n.getLatitude());
}
}
}
protected synchronized void checkNodes() {
if (nodes != null) {
return; // already filled
}
allPointsDefined = true;
nodes = new IOsmNode[way.getNodeIds().length];
for (int i = 0; i < way.getNodeIds().length; i++) {
long nid = way.getNodeIds()[i];
nodes[i] = storage.getNodeById(nid);
if (nodes[i] == null) {
allPointsDefined = false;
}
}
}
public Boolean iterateNodes(NodesIterator iterator) {
checkNodes();
for (IOsmNode n : nodes) {
if (n != null) {
Boolean r = iterator.processNode(n);
if (r != null) {
return r;
}
}
}
return null;
}
}