package org.osm2world.core.map_data.data.overlaps;
import static java.util.Collections.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import org.osm2world.core.map_data.data.MapArea;
import org.osm2world.core.map_data.data.MapAreaSegment;
import org.osm2world.core.map_data.data.MapWaySegment;
import org.osm2world.core.math.LineSegmentXZ;
import org.osm2world.core.math.VectorXZ;
/**
* overlap between a {@link MapWaySegment} and a {@link MapArea} ("Way-Area").
* The way either intersects with the area
* or is completely contained within the area.
*/
public class MapOverlapWA extends MapOverlap<MapWaySegment, MapArea> {
//TODO maybe create a MapIntersection object for each of these?
private final List<VectorXZ> intersectionPositions;
private final List<MapAreaSegment> intersectingAreaSegments;
public MapOverlapWA(MapWaySegment waySegment, MapArea area,
MapOverlapType type, List<VectorXZ> intersectionPositions,
List<MapAreaSegment> intersectingAreaSegments) {
super(waySegment, area, type);
this.intersectionPositions = intersectionPositions;
this.intersectingAreaSegments = intersectingAreaSegments;
}
public MapArea getOther(MapWaySegment waySegment) {
return (MapArea) super.getOther(waySegment);
}
public MapWaySegment getOther(MapArea area) {
return (MapWaySegment) super.getOther(area);
}
/** same order as {@link #getIntersectingAreaSegments()} */
public List<VectorXZ> getIntersectionPositions() {
return intersectionPositions;
}
/** same order as {@link #getIntersectionPositions()} */
public List<MapAreaSegment> getIntersectingAreaSegments() {
return intersectingAreaSegments;
}
public Collection<LineSegmentXZ> getOverlappedSegments() {
if (type == MapOverlapType.CONTAIN) {
return singletonList(e1.getLineSegment());
} else if (type == MapOverlapType.INTERSECT) {
/* order intersections and start/end nodes
* by distance from the way segments' start node */
List<VectorXZ> positions = new ArrayList<VectorXZ>(getIntersectionPositions());
positions.add(e1.getStartNode().getPos());
positions.add(e1.getEndNode().getPos());
sort(positions, new Comparator<VectorXZ>() {
public int compare(VectorXZ v1, VectorXZ v2) {
return Double.compare(
VectorXZ.distance(v1, e1.getStartNode().getPos()),
VectorXZ.distance(v2, e1.getStartNode().getPos()));
}
});
/* check for each line segments between two positions
* whether it overlaps with the area */
List<LineSegmentXZ> result = new ArrayList<LineSegmentXZ>();
for (int i = 0; i+1 < positions.size(); i++) {
LineSegmentXZ segment =
new LineSegmentXZ(positions.get(i), positions.get(i+1));
if (e2.getPolygon().contains(segment.getCenter())) {
result.add(segment);
}
}
return result;
} else {
return emptyList();
}
}
public Collection<LineSegmentXZ> getSharedSegments() {
if (type == MapOverlapType.SHARE_SEGMENT) {
for (MapAreaSegment areaSegment : e2.getAreaSegments()) {
if (areaSegment.sharesBothNodes(e1)) {
return singletonList(areaSegment.getLineSegment());
}
}
throw new Error("no shared segment found");
} else {
return emptyList();
}
}
}