package maps.convert.osm2gml;
import java.util.List;
import java.util.ArrayList;
import java.util.Set;
import java.util.HashSet;
import java.util.Collection;
import maps.convert.ConvertStep;
import rescuecore2.log.Logger;
/**
This step splits any shapes that overlap.
*/
public class SplitShapesStep extends ConvertStep {
private TemporaryMap map;
/**
Construct a SplitFacesStep.
@param map The map to use.
*/
public SplitShapesStep(TemporaryMap map) {
this.map = map;
}
@Override
public String getDescription() {
return "Splitting overlapping shapes";
}
@Override
protected void step() {
Collection<TemporaryObject> all = map.getAllObjects();
setProgressLimit(all.size());
int count = 0;
debug.setBackground(ConvertTools.getAllDebugShapes(map));
for (TemporaryObject shape : all) {
count += splitShapeIfRequired(shape);
bumpProgress();
}
setStatus("Added " + count + " new shapes");
}
private int splitShapeIfRequired(TemporaryObject shape) {
Set<DirectedEdge> edgesRemaining = new HashSet<DirectedEdge>(shape.getEdges());
boolean firstShape = true;
int newShapeCount = 0;
// debug.show("Splitting shapes", new TemporaryObjectInfo(shape, "Shape", Constants.BLACK, Constants.TRANSPARENT_ORANGE));
// Logger.debug("Splitting shape " + shape);
// Logger.debug("Edges: ");
// for (DirectedEdge e : edgesRemaining) {
// Logger.debug(" " + e);
// }
while (!edgesRemaining.isEmpty()) {
// Logger.debug(edgesRemaining.size() + " edges remaining");
DirectedEdge dEdge = edgesRemaining.iterator().next();
edgesRemaining.remove(dEdge);
Node start = dEdge.getStartNode();
Node end = dEdge.getEndNode();
List<DirectedEdge> result = new ArrayList<DirectedEdge>();
result.add(dEdge);
// Now walk around
Logger.debug("Starting walk from " + dEdge);
Logger.debug("Start: " + start);
Logger.debug("End: " + end);
while (!end.equals(start)) {
Set<Edge> candidates = map.getAttachedEdges(end);
// Logger.debug("From edge: " + dEdge);
// Logger.debug("Candidates: ");
// for (Edge e : candidates) {
// Logger.debug(" " + e);
// }
Edge turn = ConvertTools.findLeftTurn(dEdge, candidates);
Logger.debug("Best turn: " + turn);
DirectedEdge newDEdge = new DirectedEdge(turn, end);
// debug.show("Splitting shapes",
// new TemporaryObjectInfo(shape, "Shape", Constants.BLACK, Constants.TRANSPARENT_ORANGE),
// new ShapeDebugFrame.Line2DShapeInfo(dEdge.getLine(), "Edge", Constants.BLUE, true, true),
// new ShapeDebugFrame.Line2DShapeInfo(newDEdge.getLine(), "Turn", Constants.RED, true, true));
dEdge = newDEdge;
end = dEdge.getEndNode();
edgesRemaining.remove(dEdge);
result.add(dEdge);
Logger.debug("Added " + dEdge);
Logger.debug("New end: " + end);
}
if (!firstShape || !edgesRemaining.isEmpty()) {
// Didn't cover all edges so new shapes are needed.
if (firstShape) {
map.removeTemporaryObject(shape);
firstShape = false;
}
else {
++newShapeCount;
}
TemporaryObject newObject = null;
if (shape instanceof TemporaryRoad) {
newObject = new TemporaryRoad(result);
}
if (shape instanceof TemporaryIntersection) {
newObject = new TemporaryIntersection(result);
}
if (shape instanceof TemporaryBuilding) {
newObject = new TemporaryBuilding(result, ((TemporaryBuilding)shape).getBuildingID());
}
map.addTemporaryObject(newObject);
// debug.show("Splitting shapes",
// new TemporaryObjectInfo(shape, "Original shape", Constants.BLACK, null),
// new TemporaryObjectInfo(newObject, "New shape", Constants.RED, Constants.TRANSPARENT_RED));
}
}
return newShapeCount;
}
}