use of org.openstreetmap.atlas.geography.atlas.items.Edge in project atlas-checks by osmlab.
the class SinkIslandCheck method flag.
@Override
protected Optional<CheckFlag> flag(final AtlasObject object) {
// Flag to keep track of whether we found an issue or not
boolean emptyFlag = false;
// The current edge to be explored
Edge candidate = (Edge) object;
// A set of all edges that we have already explored
final Set<AtlasObject> explored = new HashSet<>(this.storeSize, LOAD_FACTOR);
// A set of all edges that we explore that have no outgoing edges
final Set<AtlasObject> terminal = new HashSet<>();
// Current queue of candidates that we can draw from
final Queue<Edge> candidates = new ArrayDeque<>(this.storeSize);
// Start edge always explored
explored.add(candidate);
// Keep looping while we still have a valid candidate to explore
while (candidate != null) {
// process
if (this.isFlagged(candidate.getIdentifier())) {
emptyFlag = true;
break;
}
// Retrieve all the valid outgoing edges to explore
final Set<Edge> outEdges = candidate.outEdges().stream().filter(this::validEdge).collect(Collectors.toSet());
if (outEdges.isEmpty()) {
// Sink edge. Don't mark the edge explored until we know how big the tree is
terminal.add(candidate);
} else {
// Add the current candidate to the set of already explored edges
explored.add(candidate);
// From the list of outgoing edges from the current candidate filter out any edges
// that have already been explored and add all the rest to the queue of possible
// candidates
outEdges.stream().filter(outEdge -> !explored.contains(outEdge)).forEach(candidates::add);
// loop and assume that this is not a SinkIsland
if (candidates.size() + explored.size() > this.treeSize) {
emptyFlag = true;
break;
}
}
// Get the next candidate
candidate = candidates.poll();
}
// flag.
if (!emptyFlag) {
// Include all touched edges
explored.addAll(terminal);
}
// Set every explored edge as flagged for any other processes to know that we have already
// process all those edges
explored.forEach(marked -> this.markAsFlagged(marked.getIdentifier()));
// Create the flag if and only if the empty flag value is not set to false
return emptyFlag ? Optional.empty() : Optional.of(createFlag(explored, this.getLocalizedInstruction(0)));
}
use of org.openstreetmap.atlas.geography.atlas.items.Edge in project atlas-checks by osmlab.
the class RoundaboutValenceCheck method getAllRoundaboutEdges.
/**
* This method gets all edges in a roundabout given one edge in that roundabout
*
* @param edge
* An Edge object known to be a roundabout edge
* @return A set of edges in the roundabout
*/
private Set<Edge> getAllRoundaboutEdges(final Edge edge) {
final Set<Edge> roundaboutEdges = new HashSet<>();
// Initialize a queue to add yet to be processed connected edges to
final Queue<Edge> queue = new LinkedList<>();
// Mark the current Edge as visited and enqueue it
this.markAsFlagged(edge.getIdentifier());
queue.add(edge);
// As long as the queue is not empty
while (!queue.isEmpty()) {
// Dequeue a connected edge and add it to the roundaboutEdges
final Edge currentEdge = queue.poll();
roundaboutEdges.add(currentEdge);
// Get the edges connected to the edge e as an iterator
final Set<Edge> connectedEdges = currentEdge.connectedEdges();
for (final Edge connectedEdge : connectedEdges) {
final Long edgeId = connectedEdge.getIdentifier();
if (JunctionTag.isRoundabout(connectedEdge) && !roundaboutEdges.contains(connectedEdge)) {
this.markAsFlagged(edgeId);
queue.add(connectedEdge);
}
}
}
return roundaboutEdges;
}
use of org.openstreetmap.atlas.geography.atlas.items.Edge in project atlas-checks by osmlab.
the class SignPostCheck method findFirstRampEdge.
/**
* Given a final {@link Edge}, hops back and finds the first edge that was forming the ramp.
*
* @param finalEdge
* {@link Edge} that is the last/final piece of the ramp
* @return {@link Edge} that possibly is the first {@link Edge} forming the ramp
*/
private Edge findFirstRampEdge(final Edge finalEdge) {
int count = 0;
// Go back and collect edges
Edge nextEdge = finalEdge;
while (count < MAX_EDGE_COUNT_FOR_RAMP) {
count++;
// Break if edge has no heading
final Optional<Heading> initialHeading = nextEdge.asPolyLine().initialHeading();
if (!initialHeading.isPresent()) {
break;
}
// Collect in edges and make sure there is not more than one
final Set<Edge> inEdges = nextEdge.inEdges();
if (inEdges.isEmpty() || inEdges.size() > 1) {
break;
}
// Find the edge that precedes nextEdge
final HighwayTag highwayTag = nextEdge.highwayTag();
final Edge precedingEdge = inEdges.iterator().next();
// Ignore if edge has a different classification
if (!highwayTag.isIdenticalClassification(precedingEdge.highwayTag())) {
break;
}
// Break if given edge has no heading
final Optional<Heading> finalHeading = precedingEdge.asPolyLine().finalHeading();
if (!finalHeading.isPresent() || initialHeading.get().asPositiveAngle().difference(finalHeading.get().asPositiveAngle()).isGreaterThan(this.rampAngleDifference)) {
break;
}
nextEdge = precedingEdge;
}
return nextEdge;
}
use of org.openstreetmap.atlas.geography.atlas.items.Edge 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.atlas.items.Edge in project atlas-checks by osmlab.
the class RoundaboutValenceCheck method flag.
/**
* This is the actual function that will check to see whether the object needs to be flagged.
*
* @param object
* the atlas object supplied by the Atlas-Checks framework for evaluation
* @return an optional {@link CheckFlag} object that
*/
@Override
protected Optional<CheckFlag> flag(final AtlasObject object) {
final Edge edge = (Edge) object;
// Get all edges in the roundabout
final Set<Edge> roundaboutEdges = getAllRoundaboutEdges(edge);
final Set<Edge> connectedEdges = roundaboutEdges.stream().flatMap(roundaboutEdge -> roundaboutEdge.connectedEdges().stream()).filter(HighwayTag::isCarNavigableHighway).filter(Edge::isMasterEdge).filter(currentEdge -> !JunctionTag.isRoundabout(currentEdge)).filter(currentEdge -> !roundaboutEdges.contains(currentEdge)).collect(Collectors.toSet());
final int totalRoundaboutValence = connectedEdges.size();
// or greater than or equal to the maximum configured number of connections
if (totalRoundaboutValence < this.minimumValence || totalRoundaboutValence > this.maximumValence) {
this.markAsFlagged(object.getIdentifier());
// If the roundabout valence is 1, this should be labelled as a turning loop instead
if (totalRoundaboutValence == 1) {
return Optional.of(this.createFlag(roundaboutEdges, this.getLocalizedInstruction(1, edge.getOsmIdentifier())));
}
// Otherwise, we want to flag and given information about identifier and valence
return Optional.of(this.createFlag(roundaboutEdges, this.getLocalizedInstruction(0, edge.getOsmIdentifier(), totalRoundaboutValence)));
} else // If the totalRoundaboutValence is not unusual, we don't flag the object
{
return Optional.empty();
}
}
Aggregations