package maps.convert.osm2gml;
import java.awt.Color;
import java.util.Set;
import java.util.HashSet;
import java.util.Collection;
import maps.convert.ConvertStep;
import rescuecore2.log.Logger;
/**
This step removes shapes that are duplicates or contained entirely inside another shape.
*/
public class RemoveShapesStep extends ConvertStep {
private TemporaryMap map;
/**
Construct a RemoveFacesStep.
@param map The TemporaryMap to use.
*/
public RemoveShapesStep(TemporaryMap map) {
super();
this.map = map;
}
@Override
public String getDescription() {
return "Removing extraneous shapes";
}
@Override
protected void step() {
debug.setBackground(ConvertTools.getAllDebugShapes(map));
debug.setAutozoomEnabled(false);
Collection<TemporaryObject> allObjects = map.getAllObjects();
setProgressLimit(allObjects.size() * 2);
Set<TemporaryObject> removed = new HashSet<TemporaryObject>();
setStatus("Removing duplicate shapes");
int duplicateCount = 0;
int interiorCount = 0;
Logger.debug("Removing building duplicates");
duplicateCount += removeDuplicates(map.getBuildings(), removed, allObjects);
Logger.debug("Removing intersection duplicates");
duplicateCount += removeDuplicates(map.getIntersections(), removed, allObjects);
Logger.debug("Removing road duplicates");
duplicateCount += removeDuplicates(map.getRoads(), removed, allObjects);
Logger.debug("Removing interior faces");
setStatus("Removing interior faces");
interiorCount += removeInterior(map.getRoads(), removed, allObjects);
interiorCount += removeInterior(map.getIntersections(), removed, allObjects);
interiorCount += removeInterior(map.getBuildings(), removed, allObjects);
setStatus("Removed " + removed.size() + " faces: " + duplicateCount + " duplicates and " + interiorCount + " interior");
debug.clearBackground();
debug.activate();
debug.show("Result", ConvertTools.getAllDebugShapes(map));
}
/**
Remove all shapes that are duplicates of a test set.
@param test The set of objects to test against.
@param removed The set of removed objects.
@param toCheck The set of shapes to check.
@return The number of objects removed.
*/
private int removeDuplicates(Collection<? extends TemporaryObject> test, Set<TemporaryObject> removed, Collection<TemporaryObject> toCheck) {
int count = 0;
Logger.debug(test.size() + " test objects, " + toCheck.size() + " to check, " + removed.size() + " already removed");
for (TemporaryObject first : test) {
bumpProgress();
if (removed.contains(first)) {
continue;
}
Logger.debug("Next test object: " + first);
for (TemporaryObject second : toCheck) {
if (removed.contains(second)) {
continue;
}
if (first == second) {
continue;
}
Logger.debug("Next check object: " + second);
if (first.isDuplicate(second)) {
map.removeTemporaryObject(second);
removed.add(second);
++count;
Logger.debug("Removed duplicate object: " + second + " is same as " + first);
}
debug.show("Checking for duplicates",
new TemporaryObjectInfo(first, "First", Color.WHITE, Constants.TRANSPARENT_LIME),
new TemporaryObjectInfo(second, "Second", Color.WHITE, Constants.TRANSPARENT_BLUE));
}
}
return count;
}
/**
Remove any shapes that are entirely inside another shapes.
@param toCheck The set of objects to check.
@param removed The set of removed objects.
@param allObjects All objects.
@return The number of removed objects.
*/
private int removeInterior(Collection<? extends TemporaryObject> toCheck, Set<TemporaryObject> removed, Collection<TemporaryObject> allObjects) {
int count = 0;
for (TemporaryObject first : toCheck) {
bumpProgress();
if (removed.contains(first)) {
continue;
}
for (TemporaryObject second : allObjects) {
if (removed.contains(second)) {
continue;
}
if (first == second) {
continue;
}
if (first.isEntirelyInside(second)) {
map.removeTemporaryObject(first);
removed.add(first);
++count;
}
}
}
return count;
}
}