use of org.openstreetmap.atlas.geography.Polygon in project atlas-checks by osmlab.
the class SelfIntersectingPolylineCheck method flag.
@Override
protected Optional<CheckFlag> flag(final AtlasObject object) {
final Optional<CheckFlag> response;
final int localizedInstructionIndex;
final PolyLine polyline;
if (object instanceof Edge) {
polyline = ((Edge) object).asPolyLine();
// Send building instructions if building tag exists
localizedInstructionIndex = (TagPredicates.IS_BUILDING.test(object)) ? 2 : 0;
} else if (object instanceof Line) {
polyline = ((Line) object).asPolyLine();
// Send building instructions if building tag exists
localizedInstructionIndex = (TagPredicates.IS_BUILDING.test(object)) ? 2 : 0;
} else if (object instanceof Area) {
polyline = ((Area) object).asPolygon();
// Send duplicate Edge instructions if duplicate Edges exist
localizedInstructionIndex = hasDuplicateSegments(polyline) ? THREE : 1;
} else {
throw new CoreException("Invalid item type {}", object.getClass().toString());
}
// First, find shape point intersections
final Set<Location> selfIntersections = polyline.selfIntersections();
if (selfIntersections.size() > 0) {
final CheckFlag flag = new CheckFlag(Long.toString(object.getIdentifier()));
flag.addObject(object);
flag.addInstruction(this.getLocalizedInstruction(localizedInstructionIndex, object.getOsmIdentifier(), selfIntersections.toString()));
selfIntersections.forEach(flag::addPoint);
response = Optional.of(flag);
} else {
// Next, find intersections occurring at non-shape points using JTS verification
boolean isJtsValid = true;
try {
if (object instanceof Area) {
isJtsValid = GeometryValidator.isValidPolygon((Polygon) polyline);
} else {
isJtsValid = GeometryValidator.isValidPolyLine(polyline);
}
} catch (final IllegalArgumentException e) {
// Invalid geometry found when converting the PolyLine/Polygon.
// This can be a number of cases. For example, a LineString expects exactly 0 or >=2
// points or a Polygon expects 0 or >= 4 points. This isn't self-intersecting
// geometry, but rather inconsistent geometry, according to JTS.
logger.error("Encountered invalid geometry for feature {}", object.getOsmIdentifier(), e);
}
if (!isJtsValid) {
response = Optional.of(createFlag(object, this.getLocalizedInstruction(localizedInstructionIndex)));
} else {
response = Optional.empty();
}
}
return response;
}
use of org.openstreetmap.atlas.geography.Polygon in project atlas-checks by osmlab.
the class IntersectingBuildingsCheck method findIntersectionType.
/**
* Find {@link IntersectionType} for given {@link Polygon}s. There are some edge cases where
* there are minor boundary intersections. So we do additional area check to filter off the
* false positives.
*
* @param polygon
* {@link Polygon} to check for intersection
* @param otherPolygon
* Another {@link Polygon} to check against for intersection
* @param areaSizeToCheck
* Area size to decide if intersection area is big enough for overlap
* @return {@link IntersectionType} between given {@link Polygon}s
*/
private IntersectionType findIntersectionType(final Polygon polygon, final Polygon otherPolygon) {
Clip clip = null;
try {
clip = polygon.clip(otherPolygon, ClipType.AND);
} catch (final TopologyException e) {
logger.warn(String.format("Skipping intersection check. Error clipping [%s] and [%s].", polygon, otherPolygon), e);
}
// Skip if nothing is returned
if (clip == null) {
return IntersectionType.NONE;
}
// Sum intersection area
long intersectionArea = 0;
for (final PolyLine polyline : clip.getClip()) {
if (polyline != null && polyline instanceof Polygon) {
final Polygon clippedPolygon = (Polygon) polyline;
intersectionArea += clippedPolygon.surface().asDm7Squared();
}
}
// Avoid division by zero
if (intersectionArea == 0) {
return IntersectionType.NONE;
}
// Pick the smaller building's area as baseline
final long baselineArea = Math.min(polygon.surface().asDm7Squared(), otherPolygon.surface().asDm7Squared());
final double proportion = (double) intersectionArea / baselineArea;
if (proportion >= this.overlapLowerLimit) {
return IntersectionType.OVERLAP;
} else if (proportion >= this.intersectionLowerLimit) {
return IntersectionType.INTERSECT;
}
return IntersectionType.NONE;
}
use of org.openstreetmap.atlas.geography.Polygon in project atlas-checks by osmlab.
the class IntersectingBuildingsCheck method flag.
@Override
protected Optional<CheckFlag> flag(final AtlasObject object) {
final Area building = (Area) object;
// Fetch building's area as polygon and make sure it has at least 3 points
final Polygon buildingPolygon = building.asPolygon();
if (buildingPolygon.size() < MINIMUM_POINT_COUNT_FOR_POLYGON) {
return Optional.empty();
}
// Fetch possibly intersecting buildings
final Iterable<Area> possiblyIntersectingBuildings = object.getAtlas().areasIntersecting(building.bounds(), area -> BuildingTag.isBuilding(area) && building.getIdentifier() != area.getIdentifier() && area.intersects(buildingPolygon));
// Assuming that we'd find intersections/overlaps below, create a flag
final CheckFlag flag = new CheckFlag(this.getTaskIdentifier(object));
flag.addObject(object);
boolean hadIntersection = false;
// Go over possible intersections
for (final Area otherBuilding : possiblyIntersectingBuildings) {
// Fetch other building's area as polygon and make sure it has at least 3 points
final Polygon otherBuildingsPolygon = otherBuilding.asPolygon();
if (otherBuildingsPolygon.size() < MINIMUM_POINT_COUNT_FOR_POLYGON) {
continue;
}
// Create a unique identifier for building tuple to avoid processing same buildings more
// than once
final String uniqueIdentifier = getIdentifierTuple(building, otherBuilding);
if (this.isFlagged(getIdentifierTuple(building, otherBuilding))) {
continue;
}
// Find intersection type
final IntersectionType resultType = this.findIntersectionType(buildingPolygon, otherBuildingsPolygon);
// Flag based on intersection type
if (resultType == IntersectionType.OVERLAP) {
flag.addObject(otherBuilding, this.getLocalizedInstruction(0, object.getOsmIdentifier(), otherBuilding.getOsmIdentifier()));
this.markAsFlagged(uniqueIdentifier);
hadIntersection = true;
} else if (resultType == IntersectionType.INTERSECT) {
flag.addObject(otherBuilding, this.getLocalizedInstruction(1, object.getOsmIdentifier(), otherBuilding.getOsmIdentifier()));
this.markAsFlagged(uniqueIdentifier);
hadIntersection = true;
}
}
if (hadIntersection) {
return Optional.of(flag);
}
return Optional.empty();
}
Aggregations