use of com.vividsolutions.jts.geom.Point in project Osmand by osmandapp.
the class JtsAdapter method flatFeatureList.
/**
* <p>Recursively convert a {@link Geometry}, which may be an instance of {@link GeometryCollection} with mixed
* element types, into a flat list containing only the following {@link Geometry} types:</p>
* <ul>
* <li>{@link Point}</li>
* <li>{@link LineString}</li>
* <li>{@link Polygon}</li>
* <li>{@link MultiPoint}</li>
* <li>{@link MultiLineString}</li>
* <li>{@link MultiPolygon}</li>
* </ul>
* <p>WARNING: Any other Geometry types that were not mentioned in the list above will be discarded!</p>
* <p>Useful for converting a generic geometry into a list of simple MVT-feature-ready geometries.</p>
*
* @param geom geometry to flatten
* @return list of MVT-feature-ready geometries
*/
public static List<Geometry> flatFeatureList(Geometry geom) {
final List<Geometry> singleGeoms = new ArrayList<>();
final Stack<Geometry> geomStack = new Stack<>();
Geometry nextGeom;
int nextGeomCount;
geomStack.push(geom);
while (!geomStack.isEmpty()) {
nextGeom = geomStack.pop();
if (nextGeom instanceof Point || nextGeom instanceof MultiPoint || nextGeom instanceof LineString || nextGeom instanceof MultiLineString || nextGeom instanceof Polygon || nextGeom instanceof MultiPolygon) {
singleGeoms.add(nextGeom);
} else if (nextGeom instanceof GeometryCollection) {
// Push all child geometries
nextGeomCount = nextGeom.getNumGeometries();
for (int i = 0; i < nextGeomCount; ++i) {
geomStack.push(nextGeom.getGeometryN(i));
}
}
}
return singleGeoms;
}
use of com.vividsolutions.jts.geom.Point in project Osmand by osmandapp.
the class MvtReader method readPoints.
/**
* Create {@link Point} or {@link MultiPoint} from MVT geometry drawing commands.
*
* @param geomFactory creates JTS geometry
* @param geomCmds contains MVT geometry commands
* @param cursor contains current MVT extent position
* @return JTS geometry or null on failure
*/
private static Geometry readPoints(GeometryFactory geomFactory, List<Integer> geomCmds, Vec2d cursor) {
// Guard: must have header
if (geomCmds.isEmpty()) {
return null;
}
/**
* Geometry command index
*/
int i = 0;
// Read command header
final int cmdHdr = geomCmds.get(i++);
final int cmdLength = GeomCmdHdr.getCmdLength(cmdHdr);
final GeomCmd cmd = GeomCmdHdr.getCmd(cmdHdr);
// Guard: command type
if (cmd != GeomCmd.MoveTo) {
return null;
}
// Guard: minimum command length
if (cmdLength < 1) {
return null;
}
// (require header and at least 1 value * 2 params)
if (cmdLength * GeomCmd.MoveTo.getParamCount() + 1 > geomCmds.size()) {
return null;
}
final CoordinateSequence coordSeq = geomFactory.getCoordinateSequenceFactory().create(cmdLength, 2);
int coordIndex = 0;
Coordinate nextCoord;
while (i < geomCmds.size() - 1) {
cursor.add(ZigZag.decode(geomCmds.get(i++)), ZigZag.decode(geomCmds.get(i++)));
nextCoord = coordSeq.getCoordinate(coordIndex++);
nextCoord.setOrdinate(0, cursor.x);
nextCoord.setOrdinate(1, cursor.y);
}
return coordSeq.size() == 1 ? geomFactory.createPoint(coordSeq) : geomFactory.createMultiPoint(coordSeq);
}
use of com.vividsolutions.jts.geom.Point in project OsmAnd by osmandapp.
the class JtsAdapter method toFeature.
/**
* Create and return a feature from a geometry. Returns null on failure.
*
* @param geom flat geometry via {@link #flatFeatureList(Geometry)} that can be translated to a feature
* @param cursor vector tile cursor position
* @param layerProps layer properties for tagging features
* @return new tile feature instance, or null on failure
*/
private static VectorTile.Tile.Feature toFeature(Geometry geom, Vec2d cursor, MvtLayerProps layerProps, IUserDataConverter userDataConverter) {
// Guard: UNKNOWN Geometry
final VectorTile.Tile.GeomType mvtGeomType = JtsAdapter.toGeomType(geom);
if (mvtGeomType == VectorTile.Tile.GeomType.UNKNOWN) {
return null;
}
final VectorTile.Tile.Feature.Builder featureBuilder = VectorTile.Tile.Feature.newBuilder();
final boolean mvtClosePath = MvtUtil.shouldClosePath(mvtGeomType);
final List<Integer> mvtGeom = new ArrayList<>();
featureBuilder.setType(mvtGeomType);
if (geom instanceof Point || geom instanceof MultiPoint) {
// Encode as MVT point or multipoint
mvtGeom.addAll(ptsToGeomCmds(geom, cursor));
} else if (geom instanceof LineString || geom instanceof MultiLineString) {
// Encode as MVT linestring or multi-linestring
for (int i = 0; i < geom.getNumGeometries(); ++i) {
mvtGeom.addAll(linesToGeomCmds(geom.getGeometryN(i), mvtClosePath, cursor, 1));
}
} else if (geom instanceof MultiPolygon || geom instanceof Polygon) {
// Encode as MVT polygon or multi-polygon
for (int i = 0; i < geom.getNumGeometries(); ++i) {
final Polygon nextPoly = (Polygon) geom.getGeometryN(i);
boolean valid = true;
// Add exterior ring
final LineString exteriorRing = nextPoly.getExteriorRing();
// Area must be non-zero
final double exteriorArea = CGAlgorithms.signedArea(exteriorRing.getCoordinates());
if (((int) Math.round(exteriorArea)) == 0) {
continue;
}
// Check CCW Winding (must be positive area)
if (exteriorArea < 0d) {
CoordinateArrays.reverse(exteriorRing.getCoordinates());
}
final List<Integer> nextPolyGeom = new ArrayList<>(linesToGeomCmds(exteriorRing, mvtClosePath, cursor, 2));
// Add interior rings
for (int ringIndex = 0; ringIndex < nextPoly.getNumInteriorRing(); ++ringIndex) {
final LineString nextInteriorRing = nextPoly.getInteriorRingN(ringIndex);
// Area must be non-zero
final double interiorArea = CGAlgorithms.signedArea(nextInteriorRing.getCoordinates());
if (((int) Math.round(interiorArea)) == 0) {
continue;
}
// Check CW Winding (must be negative area)
if (interiorArea > 0d) {
CoordinateArrays.reverse(nextInteriorRing.getCoordinates());
}
// Interior ring area must be < exterior ring area, or entire geometry is invalid
if (Math.abs(exteriorArea) <= Math.abs(interiorArea)) {
valid = false;
break;
}
nextPolyGeom.addAll(linesToGeomCmds(nextInteriorRing, mvtClosePath, cursor, 2));
}
if (valid) {
mvtGeom.addAll(nextPolyGeom);
}
}
}
if (mvtGeom.size() < 1) {
return null;
}
featureBuilder.addAllGeometry(mvtGeom);
// Feature Properties
userDataConverter.addTags(geom.getUserData(), layerProps, featureBuilder);
return featureBuilder.build();
}
use of com.vividsolutions.jts.geom.Point in project OsmAnd by osmandapp.
the class MvtReader method readPolys.
/**
* Create {@link Polygon} or {@link MultiPolygon} from MVT geometry drawing commands.
*
* @param geomFactory creates JTS geometry
* @param geomCmds contains MVT geometry commands
* @param cursor contains current MVT extent position
* @param ringClassifier
* @return JTS geometry or null on failure
*/
private static Geometry readPolys(GeometryFactory geomFactory, List<Integer> geomCmds, Vec2d cursor, RingClassifier ringClassifier) {
// Guard: must have header
if (geomCmds.isEmpty()) {
return null;
}
/**
* Geometry command index
*/
int i = 0;
int cmdHdr;
int cmdLength;
GeomCmd cmd;
List<LinearRing> rings = new ArrayList<>(1);
CoordinateSequence nextCoordSeq;
Coordinate nextCoord;
while (i <= geomCmds.size() - MIN_POLYGON_LEN) {
// --------------------------------------------
// Expected: MoveTo command of length 1
// --------------------------------------------
// Read command header
cmdHdr = geomCmds.get(i++);
cmdLength = GeomCmdHdr.getCmdLength(cmdHdr);
cmd = GeomCmdHdr.getCmd(cmdHdr);
// Guard: command type and length
if (cmd != GeomCmd.MoveTo || cmdLength != 1) {
break;
}
// Update cursor position with relative move
cursor.add(ZigZag.decode(geomCmds.get(i++)), ZigZag.decode(geomCmds.get(i++)));
// --------------------------------------------
// Expected: LineTo command of length > 1
// --------------------------------------------
// Read command header
cmdHdr = geomCmds.get(i++);
cmdLength = GeomCmdHdr.getCmdLength(cmdHdr);
cmd = GeomCmdHdr.getCmd(cmdHdr);
// Guard: command type and length
if (cmd != GeomCmd.LineTo || cmdLength < 2) {
break;
}
// (require at least (2 values * 2 params) + (current index 'i') + (1 for ClosePath))
if ((cmdLength * GeomCmd.LineTo.getParamCount()) + i + 1 > geomCmds.size()) {
break;
}
nextCoordSeq = geomFactory.getCoordinateSequenceFactory().create(2 + cmdLength, 2);
// Set first point from MoveTo command
nextCoord = nextCoordSeq.getCoordinate(0);
nextCoord.setOrdinate(0, cursor.x);
nextCoord.setOrdinate(1, cursor.y);
// Set remaining points from LineTo command
for (int lineToIndex = 0; lineToIndex < cmdLength; ++lineToIndex) {
// Update cursor position with relative line delta
cursor.add(ZigZag.decode(geomCmds.get(i++)), ZigZag.decode(geomCmds.get(i++)));
nextCoord = nextCoordSeq.getCoordinate(lineToIndex + 1);
nextCoord.setOrdinate(0, cursor.x);
nextCoord.setOrdinate(1, cursor.y);
}
// --------------------------------------------
// Expected: ClosePath command of length 1
// --------------------------------------------
// Read command header
cmdHdr = geomCmds.get(i++);
cmdLength = GeomCmdHdr.getCmdLength(cmdHdr);
cmd = GeomCmdHdr.getCmd(cmdHdr);
if (cmd != GeomCmd.ClosePath || cmdLength != 1) {
break;
}
// Set last point from ClosePath command
nextCoord = nextCoordSeq.getCoordinate(nextCoordSeq.size() - 1);
nextCoord.setOrdinate(0, nextCoordSeq.getOrdinate(0, 0));
nextCoord.setOrdinate(1, nextCoordSeq.getOrdinate(0, 1));
rings.add(geomFactory.createLinearRing(nextCoordSeq));
}
// Classify rings
final List<Polygon> polygons = ringClassifier.classifyRings(rings, geomFactory);
if (polygons.size() < 1) {
return null;
} else if (polygons.size() == 1) {
return polygons.get(0);
} else {
return geomFactory.createMultiPolygon(polygons.toArray(new Polygon[0]));
}
}
use of com.vividsolutions.jts.geom.Point in project OsmAnd by osmandapp.
the class MapillaryVectorLayer method getImagesFromPoint.
private void getImagesFromPoint(RotatedTileBox tb, PointF point, List<? super MapillaryImage> images) {
Map<QuadPointDouble, Map<?, ?>> points = this.visiblePoints;
float ex = point.x;
float ey = point.y;
final int rp = getRadius(tb);
int radius = rp * 3 / 2;
float x, y;
double minSqDist = Double.NaN;
double sqDist;
MapillaryImage img = null;
for (Entry<QuadPointDouble, Map<?, ?>> entry : points.entrySet()) {
double tileX = entry.getKey().x;
double tileY = entry.getKey().y;
Map<?, ?> userData = entry.getValue();
PointF pixel = NativeUtilities.getPixelFromLatLon(getMapRenderer(), tb, MapUtils.getLatitudeFromTile(MIN_IMAGE_LAYER_ZOOM, tileY), MapUtils.getLongitudeFromTile(MIN_IMAGE_LAYER_ZOOM, tileX));
x = pixel.x;
y = pixel.y;
if (Math.abs(x - ex) <= radius && Math.abs(y - ey) <= radius) {
sqDist = (x - ex) * (x - ex) + (y - ey) * (y - ey);
if (img == null || minSqDist > sqDist) {
minSqDist = sqDist;
double lat = MapUtils.getLatitudeFromTile(MIN_IMAGE_LAYER_ZOOM, tileY);
double lon = MapUtils.getLongitudeFromTile(MIN_IMAGE_LAYER_ZOOM, tileX);
img = new MapillaryImage(lat, lon);
if (!img.setData(userData)) {
img = null;
}
}
}
}
if (img != null) {
images.add(img);
}
}
Aggregations