Skip to content

Commit

Permalink
Merge pull request #275 from GIScience/fix-checkstyle-util
Browse files Browse the repository at this point in the history
  • Loading branch information
joker234 authored Nov 5, 2020
2 parents 7a0da55 + 19770a5 commit 1da5dfa
Show file tree
Hide file tree
Showing 57 changed files with 1,446 additions and 1,148 deletions.
4 changes: 2 additions & 2 deletions .idea/checkstyle-idea.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package org.heigit.bigspatialdata.oshdb.util;

import org.heigit.bigspatialdata.oshdb.osm.OSMType;

import java.util.Optional;
import org.heigit.bigspatialdata.oshdb.osm.OSMType;

/**
* Names for JDBC-Tables.
Expand Down Expand Up @@ -53,14 +52,21 @@ public String toString() {
return tablename;
}

/**
* Returns the table name with a given {@link String} prepended.
*/
public String toString(String prefix) {
if(prefix != null && !prefix.trim().isEmpty())
return prefix+"_"+this.toString();
if (prefix != null && !prefix.trim().isEmpty()) {
return prefix + "_" + this.toString();
}
return this.toString();
}

/**
* Returns the {@link TableNames} object for a given {@link OSMType}.
*/
public static Optional<TableNames> forOSMType(OSMType type) {
switch(type) {
switch (type) {
case NODE: return Optional.of(T_NODES);
case WAY: return Optional.of(T_WAYS);
case RELATION: return Optional.of(T_RELATIONS);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ public Stream<IterateByTimestampEntry> iterateByTimestamps(GridOSHEntity cell) {
|| !allFullyInside && (
!oshEntity.getBoundingBox().intersects(boundingBox)
|| (isBoundByPolygon && bboxOutsidePolygon.test(oshEntity.getBoundingBox()))
)) {
)) {
// this osh entity doesn't match the prefilter or is fully outside the requested
// area of interest -> skip it
return Stream.empty();
Expand Down Expand Up @@ -312,8 +312,8 @@ public Stream<IterateByTimestampEntry> iterateByTimestamps(GridOSHEntity cell) {
OSHEntities.getByTimestamps(oshEntity, new ArrayList<>(queryTs.keySet()));

List<IterateByTimestampEntry> results = new LinkedList<>();
osmEntityLoop:
for (Map.Entry<OSHDBTimestamp, OSMEntity> entity : osmEntityByTimestamps.entrySet()) {
osmEntityLoop: for (Map.Entry<OSHDBTimestamp, OSMEntity> entity :
osmEntityByTimestamps.entrySet()) {
OSHDBTimestamp timestamp = entity.getKey();
OSMEntity osmEntity = entity.getValue();

Expand Down Expand Up @@ -362,10 +362,8 @@ public Stream<IterateByTimestampEntry> iterateByTimestamps(GridOSHEntity cell) {
geom = constructClippedGeometry(osmEntity, timestamp, fullyInside);
} else {
// old style multipolygons: return only the inner holes of the geometry -> this is then
// used to "fix" the
// results obtained from calculating the geometry on the object's outer way which
// doesn't know about the
// inner members of the multipolygon relation
// used to "fix" the results obtained from calculating the geometry on the object's
// outer way which doesn't know about the inner members of the multipolygon relation
// todo: check if this is all valid?
GeometryFactory gf = new GeometryFactory();
geom = new LazyEvaluatedObject<>(() -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ public LazyEvaluatedContributionTypes(EnumSet<ContributionType> values) {
this.evaluated = EnumSet.allOf(ContributionType.class);
}

/**
* Check if the given {@link ContributionType} {@code t} is contained in the
* {@link ContributionType} set.
*/
public boolean contains(ContributionType t) {
if (!this.evaluated.contains(t)) {
boolean value = this.evaluator.test(t);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,39 @@

import java.util.function.Supplier;

/**
* A lazily evaluated object.
*
* <p>Useful as a wrapper to hold values which are potentially expensive to
* calculate, but might sometimes not be requested.</p>
*
* @param <T> the (arbitrary) type of data to hold
*/
public class LazyEvaluatedObject<T> implements Supplier<T> {
private T value = null;
private boolean evaluated = false;
private Supplier<T> evaluator;

/**
* Constructs a {@link LazyEvaluatedObject} using a {@code evaluator} (supplier function) which
* returns a value of generic type {@code T}, when requested from this object.
*
* @param evaluator a {@link Supplier} function which returns the value of interest when executed
*/
public LazyEvaluatedObject(Supplier<T> evaluator) {
this.evaluator = evaluator;
}

/**
* Constructs a {@link LazyEvaluatedObject} using an already known {@code value} of generic
* type {@code T}.
*
* <p>This simply wraps the value with a supplier method, but can be useful in situations where
* sometimes an expensive to calculate value is already know, but one wants to use the lazy
* evaluated interface for the remaining cases.</p>
*
* @param value the value to store
*/
public LazyEvaluatedObject(T value) {
this.value = value;
this.evaluated = true;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package org.heigit.bigspatialdata.oshdb.util.exceptions;

public class OSHDBKeytablesNotFoundException extends Exception {

/**
* Exception used if the OSHDB keytable cannot be found.
*/
public OSHDBKeytablesNotFoundException() {
super("Keytables database not found, or db doesn't contain the required \"keytables\" tables. "
+ "Make sure you have specified the right keytables database, for example by calling `keytables()` when using the OSHDB-API.");
+ "Make sure you have specified the right keytables database, for example by calling "
+ "`keytables()` when using the OSHDB-API.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ public class FastBboxInPolygon extends FastInPolygon implements Predicate<OSHDBB
Serializable {
private Collection<Envelope> innerBboxes = new ArrayList<>();

/**
* Constructor using a given geometry {@code geom} and geometry type {@code P}.
*
* @param geom geometry object
* @param <P> geometry type
*/
public <P extends Geometry & Polygonal> FastBboxInPolygon(P geom) {
super(geom);

Expand All @@ -32,18 +38,19 @@ public <P extends Geometry & Polygonal> FastBboxInPolygon(P geom) {
polys.add((Polygon)geom);
} else if (geom instanceof MultiPolygon) {
MultiPolygon mp = (MultiPolygon)geom;
for (int i=0; i<mp.getNumGeometries(); i++)
polys.add((Polygon)mp.getGeometryN(i));
for (int i = 0; i < mp.getNumGeometries(); i++) {
polys.add((Polygon) mp.getGeometryN(i));
}
}
for (Polygon poly : polys) {
for (int i=0; i<poly.getNumInteriorRing(); i++) {
for (int i = 0; i < poly.getNumInteriorRing(); i++) {
innerBboxes.add(poly.getInteriorRingN(i).getEnvelopeInternal());
}
}
}

/**
* Tests if the given bounding box is fully inside of the polygon
* Tests if the given bounding box is fully inside of the polygon.
*/
@Override
public boolean test(OSHDBBoundingBox boundingBox) {
Expand All @@ -55,16 +62,19 @@ public boolean test(OSHDBBoundingBox boundingBox) {
Point p2 = gf.createPoint(new Coordinate(boundingBox.getMaxLon(), boundingBox.getMinLat()));
Point p3 = gf.createPoint(new Coordinate(boundingBox.getMaxLon(), boundingBox.getMaxLat()));
Point p4 = gf.createPoint(new Coordinate(boundingBox.getMinLon(), boundingBox.getMaxLat()));
if (crossingNumber(p1, true) != crossingNumber(p2, true) ||
crossingNumber(p3, true) != crossingNumber(p4, true) ||
crossingNumber(p2, false) != crossingNumber(p3, false) ||
crossingNumber(p4, false) != crossingNumber(p1, false)) {
if (crossingNumber(p1, true) != crossingNumber(p2, true)
|| crossingNumber(p3, true) != crossingNumber(p4, true)
|| crossingNumber(p2, false) != crossingNumber(p3, false)
|| crossingNumber(p4, false) != crossingNumber(p1, false)) {
return false; // at least one of the bbox'es edges crosses the polygon
}
for (Envelope innerBBox : innerBboxes) {
if (boundingBox.getMinLat() <= innerBBox.getMinY() && boundingBox.getMaxLat() >= innerBBox.getMaxY() &&
boundingBox.getMinLon() <= innerBBox.getMinX() && boundingBox.getMaxLon() >= innerBBox.getMaxX()) {
return false; // the bounding box fully covers at least one of the polygon's inner rings
if (boundingBox.getMinLat() <= innerBBox.getMinY()
&& boundingBox.getMaxLat() >= innerBBox.getMaxY()
&& boundingBox.getMinLon() <= innerBBox.getMinX()
&& boundingBox.getMaxLon() >= innerBBox.getMaxX()) {
// the bounding box fully covers at least one of the (multi)polygon's inner rings
return false;
}
}
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ public class FastBboxOutsidePolygon extends FastInPolygon implements Predicate<O
Serializable {
private Collection<Envelope> outerBboxes = new ArrayList<>();


/**
* Constructor using a given geometry {@code geom} and geometry type {@code P}.
*
* @param geom geometry object
* @param <P> geometry type
*/
public <P extends Geometry & Polygonal> FastBboxOutsidePolygon(P geom) {
super(geom);

Expand All @@ -32,16 +39,17 @@ public <P extends Geometry & Polygonal> FastBboxOutsidePolygon(P geom) {
polys.add((Polygon)geom);
} else if (geom instanceof MultiPolygon) {
MultiPolygon mp = (MultiPolygon)geom;
for (int i=0; i<mp.getNumGeometries(); i++)
polys.add((Polygon)mp.getGeometryN(i));
for (int i = 0; i < mp.getNumGeometries(); i++) {
polys.add((Polygon) mp.getGeometryN(i));
}
}
for (Polygon poly : polys) {
outerBboxes.add(poly.getEnvelopeInternal());
}
}

/**
* Tests if the given bounding box is fully inside of the polygon
* Tests if the given bounding box is fully outside of the polygon.
*/
@Override
public boolean test(OSHDBBoundingBox boundingBox) {
Expand All @@ -53,16 +61,19 @@ public boolean test(OSHDBBoundingBox boundingBox) {
Point p2 = gf.createPoint(new Coordinate(boundingBox.getMaxLon(), boundingBox.getMinLat()));
Point p3 = gf.createPoint(new Coordinate(boundingBox.getMaxLon(), boundingBox.getMaxLat()));
Point p4 = gf.createPoint(new Coordinate(boundingBox.getMinLon(), boundingBox.getMaxLat()));
if (crossingNumber(p1, true) != crossingNumber(p2, true) ||
crossingNumber(p3, true) != crossingNumber(p4, true) ||
crossingNumber(p2, false) != crossingNumber(p3, false) ||
crossingNumber(p4, false) != crossingNumber(p1, false)) {
if (crossingNumber(p1, true) != crossingNumber(p2, true)
|| crossingNumber(p3, true) != crossingNumber(p4, true)
|| crossingNumber(p2, false) != crossingNumber(p3, false)
|| crossingNumber(p4, false) != crossingNumber(p1, false)) {
return false; // at least one of the bbox'es edges crosses the polygon
}
for (Envelope innerBBox : outerBboxes) {
if (boundingBox.getMinLat() <= innerBBox.getMinY() && boundingBox.getMaxLat() >= innerBBox.getMaxY() &&
boundingBox.getMinLon() <= innerBBox.getMinX() && boundingBox.getMaxLon() >= innerBBox.getMaxX()) {
return false; // the bounding box fully covers at least one of the (multi)polygon's outer rings
if (boundingBox.getMinLat() <= innerBBox.getMinY()
&& boundingBox.getMaxLat() >= innerBBox.getMaxY()
&& boundingBox.getMinLon() <= innerBBox.getMinX()
&& boundingBox.getMaxLon() >= innerBBox.getMaxX()) {
// the bounding box fully covers at least one of the (multi)polygon's outer rings
return false;
}
}
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ private class Segment implements Serializable {
}
}

private final int AVERAGE_SEGMENTS_PER_BAND = 10; // something in the order of 10-20 works fine according to the link above
// something in the order of 10-20 works fine according to the link above
private static final int AVERAGE_SEGMENTS_PER_BAND = 10;

private int numBands;

Expand All @@ -46,10 +47,11 @@ private class Segment implements Serializable {

protected <P extends Geometry & Polygonal> FastInPolygon(P geom) {
MultiPolygon mp;
if (geom instanceof Polygon)
if (geom instanceof Polygon) {
mp = (new GeometryFactory()).createMultiPolygon(new Polygon[]{(Polygon) geom});
else
} else {
mp = (MultiPolygon) geom;
}

List<Segment> segments = new LinkedList<>();
for (int i = 0; i < mp.getNumGeometries(); i++) {
Expand All @@ -69,24 +71,36 @@ protected <P extends Geometry & Polygonal> FastInPolygon(P geom) {
}
}
}
this.numBands = Math.max(1, segments.size() / AVERAGE_SEGMENTS_PER_BAND); // possible optimization: start with this value of numBands, and if the result has over-full bands, increase numBands (e.g. x2) and do it again
// possible optimization: start with this value of numBands, and if the result has over-full
// bands, increase numBands (e.g. x2) and do it again
this.numBands = Math.max(1, segments.size() / AVERAGE_SEGMENTS_PER_BAND);
this.horizBands = new ArrayList<>(numBands);
for (int i = 0; i < numBands; i++) this.horizBands.add(new LinkedList<>());
for (int i = 0; i < numBands; i++) {
this.horizBands.add(new LinkedList<>());
}
this.vertBands = new ArrayList<>(numBands);
for (int i = 0; i < numBands; i++) this.vertBands.add(new LinkedList<>());
for (int i = 0; i < numBands; i++) {
this.vertBands.add(new LinkedList<>());
}

this.env = mp.getEnvelopeInternal();
this.envWidth = env.getMaxX() - env.getMinX();
this.envHeight = env.getMaxY() - env.getMinY();
segments.forEach(segment -> {
int startHorizBand = Math.max(0, Math.min(numBands - 1, (int) Math.floor(((segment.startY - env.getMinY()) / envHeight) * numBands)));
int endHorizBand = Math.max(0, Math.min(numBands - 1, (int) Math.floor(((segment.endY - env.getMinY()) / envHeight) * numBands)));
for (int i = Math.min(startHorizBand, endHorizBand); i <= Math.max(startHorizBand, endHorizBand); i++) {
int startHorizBand = Math.max(0, Math.min(numBands - 1,
(int) Math.floor(((segment.startY - env.getMinY()) / envHeight) * numBands)));
int endHorizBand = Math.max(0, Math.min(numBands - 1,
(int) Math.floor(((segment.endY - env.getMinY()) / envHeight) * numBands)));
for (int i = Math.min(startHorizBand, endHorizBand);
i <= Math.max(startHorizBand, endHorizBand); i++) {
horizBands.get(i).add(segment);
}
int startVertBand = Math.max(0, Math.min(numBands - 1, (int) Math.floor(((segment.startX - env.getMinX()) / envWidth) * numBands)));
int endVertBand = Math.max(0, Math.min(numBands - 1, (int) Math.floor(((segment.endX - env.getMinX()) / envWidth) * numBands)));
for (int i = Math.min(startVertBand, endVertBand); i <= Math.max(startVertBand, endVertBand); i++) {
int startVertBand = Math.max(0, Math.min(numBands - 1,
(int) Math.floor(((segment.startX - env.getMinX()) / envWidth) * numBands)));
int endVertBand = Math.max(0, Math.min(numBands - 1,
(int) Math.floor(((segment.endX - env.getMinX()) / envWidth) * numBands)));
for (int i = Math.min(startVertBand, endVertBand);
i <= Math.max(startVertBand, endVertBand); i++) {
vertBands.get(i).add(segment);
}
});
Expand All @@ -96,9 +110,10 @@ protected <P extends Geometry & Polygonal> FastInPolygon(P geom) {
* ported from http://geomalgorithms.com/a03-_inclusion.html
* which is derived from https://wrf.ecse.rpi.edu//Research/Short_Notes/pnpoly.html
*
* @param point
* @param point {@link Point} to be processed
* @param dir boolean: true -&gt; horizontal test, false -&gt; vertical test
* @return crossing number of this point in the chosen direction, if the value is even the point is outside of the polygon, otherwise it is inside
* @return crossing number of this point in the chosen direction,
* if the value is even the point is outside of the polygon, otherwise it is inside
*/
protected int crossingNumber(Point point, boolean dir) {
return dir ? crossingNumberX(point) : crossingNumberY(point);
Expand All @@ -121,7 +136,8 @@ private int crossingNumberX(Point point) {
if (P.x < V[i].x + vt * (V[i+1].x - V[i].x)) // P.x < intersect
++cn; // a valid crossing of y=P.y right of P.x*/
double vt = (point.getY() - segment.startY) / (segment.endY - segment.startY);
if (point.getX() < segment.startX + vt * (segment.endX - segment.startX)) { // P.x < intersect
if (point.getX() < segment.startX
+ vt * (segment.endX - segment.startX)) { // P.x < intersect
cn++; // a valid crossing of y=P.y right of P.x
}
}
Expand All @@ -137,11 +153,14 @@ private int crossingNumberY(Point point) {

int cn = 0; // crossing number counter
for (Segment segment : band) {
if ((segment.startX <= point.getX() && segment.endX > point.getX()) || // an "upward" crossing
(segment.startX > point.getX() && segment.endX <= point.getX())) { // a "downward" crossing
if ((segment.startX <= point.getX()
&& segment.endX > point.getX()) // an "upward" crossing
|| (segment.startX > point.getX()
&& segment.endX <= point.getX())) { // a "downward" crossing
// compute the actual edge-ray intersect x-coordinate
double vt = (point.getX() - segment.startX) / (segment.endX - segment.startX);
if (point.getY() < segment.startY + vt * (segment.endY - segment.startY)) { // P.y < intersect
if (point.getY() < segment.startY
+ vt * (segment.endY - segment.startY)) { // P.y < intersect
cn++; // a valid crossing of x=P.x below of P.y
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public <P extends Geometry & Polygonal> FastPointInPolygon(P geom) {
}

/**
* Tests if the given bounding box is fully inside of the polygon
* Tests if the given bounding box is fully inside of the polygon.
*/
@Override
public boolean test(Point point) {
Expand Down
Loading

0 comments on commit 1da5dfa

Please sign in to comment.