package maps.convert.osm2gml.buildings.row; import java.util.Set; import java.util.HashSet; import java.util.Random; import maps.gml.GMLDirectedEdge; import maps.gml.GMLShape; import maps.gml.GMLMap; /** A RowFiller that creates rectangular duplex units. */ public final class RectangularDuplexRowFiller implements RowFiller { private static final double WIDE_LOT_WIDTH_M = 25; private static final double WIDE_BUILDING_WIDTH_M = 21; private static final double WIDE_BUILDING_DEPTH_M = 7; private static final double WIDE_MIN_OFFSET_M = 2; private static final double WIDE_MAX_OFFSET_M = 10; private static final double LONG_LOT_WIDTH_M = 18; private static final double LONG_BUILDING_WIDTH_M = 15; private static final double LONG_BUILDING_DEPTH_M = 15; private static final double LONG_MIN_OFFSET_M = 1; private static final double LONG_MAX_OFFSET_M = 4; private static final int MIN_RUN_LENGTH = 1; private static final int MAX_RUN_LENGTH = 5; private final double lotWidth; private final double buildingWidth; private final double buildingDepth; private final double minOffset; private final double maxOffset; private final Random random; private RectangularDuplexRowFiller(double sizeOf1m, Random random, double lotWidth, double buildingWidth, double buildingDepth, double minOffset, double maxOffset) { this.lotWidth = lotWidth * sizeOf1m; this.buildingWidth = buildingWidth * sizeOf1m; this.buildingDepth = buildingDepth * sizeOf1m; this.minOffset = minOffset * sizeOf1m; this.maxOffset = maxOffset * sizeOf1m; this.random = random; } /** Create a filler that creates wide buildings. @param sizeOf1m The size of 1m in GML units. @param random The random number generator to use. @return A new RectangularDuplexRowFiller. */ public static RectangularDuplexRowFiller makeWideFiller(double sizeOf1m, Random random) { return new RectangularDuplexRowFiller(sizeOf1m, random, WIDE_LOT_WIDTH_M, WIDE_BUILDING_WIDTH_M, WIDE_BUILDING_DEPTH_M, WIDE_MIN_OFFSET_M, WIDE_MAX_OFFSET_M); } /** Create a filler that creates longer, narrower buildings. @param sizeOf1m The size of 1m in GML units. @param random The random number generator to use. @return A new RectangularDuplexRowFiller. */ public static RectangularDuplexRowFiller makeLongFiller(double sizeOf1m, Random random) { return new RectangularDuplexRowFiller(sizeOf1m, random, LONG_LOT_WIDTH_M, LONG_BUILDING_WIDTH_M, LONG_BUILDING_DEPTH_M, LONG_MIN_OFFSET_M, LONG_MAX_OFFSET_M); } @Override public Set<GMLShape> fillRow(GMLDirectedEdge edge, GMLMap map) { Set<GMLShape> result = new HashSet<GMLShape>(); /* Line2D edgeLine = ConvertTools.gmlDirectedEdgeToLine(edge); Vector2D normal = edgeLine.getDirection().getNormal().normalised(); // Create lots along the edge double edgeLength = edgeLine.getDirection().getLength(); int lots = (int)(edgeLength / LOT_WIDTH); double trueLotWidth = edgeLength / lots; System.out.println("Creating " + lots + " lots"); double offset = getRandomOffset(); int runLength = getRandomRunLength(); for (int i = 0; i < lots; ++i) { if (runLength-- == 0) { offset = getRandomOffset(); runLength = getRandomRunLength(); } double d1 = i; double d2 = i + 1; d1 /= lots; d2 /= lots; Point2D topRight = edgeLine.getPoint(d1); Point2D topLeft = edgeLine.getPoint(d2); Set<GMLFace> faces = createBuildingInLot(edgeLine, topRight, topLeft, normal, offset, map); result.addAll(faces); } */ return result; } /* private Set<GMLFace> createBuildingInLot(Line2D edgeLine, Point2D lotTopRight, Point2D lotTopLeft, Vector2D edgeNormal, double depthOffset, GMLMap map) { // Create the building by moving in from the sides of the lot boundary Line2D topLine = new Line2D(lotTopRight, lotTopLeft); double lotWidth = topLine.getDirection().getLength(); double widthSlack = ((lotWidth - BUILDING_WIDTH) / lotWidth) / 2; Point2D topRight = topLine.getPoint(widthSlack); Point2D topMiddle = topLine.getPoint(0.5); Point2D topLeft = topLine.getPoint(1.0 - widthSlack); // Offset from the top of the boundary topRight = topRight.plus(edgeNormal.scale(depthOffset)); topMiddle = topMiddle.plus(edgeNormal.scale(depthOffset)); topLeft = topLeft.plus(edgeNormal.scale(depthOffset)); // Find the other end of the building Point2D bottomRight = topRight.plus(edgeNormal.scale(BUILDING_DEPTH)); Point2D bottomMiddle = topMiddle.plus(edgeNormal.scale(BUILDING_DEPTH)); Point2D bottomLeft = topLeft.plus(edgeNormal.scale(BUILDING_DEPTH)); // Create new nodes and directed edges for the building GMLNode n1 = map.ensureNodeNear(topRight); GMLNode n2 = map.ensureNodeNear(topMiddle); GMLNode n3 = map.ensureNodeNear(topLeft); GMLNode n4 = map.ensureNodeNear(bottomLeft); GMLNode n5 = map.ensureNodeNear(bottomMiddle); GMLNode n6 = map.ensureNodeNear(bottomRight); // Create two new buildings List<GMLDirectedEdge> edges1 = new ArrayList<GMLDirectedEdge>(); // List<GMLDirectedEdge> edges2 = new ArrayList<GMLDirectedEdge>(); // edges1.add(map.ensureDirectedEdge(topRight, topMiddle)); // edges1.add(map.ensureDirectedEdge(topMiddle, bottomMiddle)); // edges1.add(map.ensureDirectedEdge(bottomMiddle, bottomRight)); // edges1.add(map.ensureDirectedEdge(bottomRight, topRight)); // edges2.add(map.ensureDirectedEdge(topMiddle, topLeft)); // edges2.add(map.ensureDirectedEdge(topLeft, bottomLeft)); // edges2.add(map.ensureDirectedEdge(bottomLeft, bottomMiddle)); // edges2.add(map.ensureDirectedEdge(bottomMiddle, topMiddle)); edges1.add(map.ensureDirectedEdge(topRight, topLeft)); edges1.add(map.ensureDirectedEdge(topLeft, bottomLeft)); edges1.add(map.ensureDirectedEdge(bottomLeft, bottomRight)); edges1.add(map.ensureDirectedEdge(bottomRight, topRight)); // TO DO: Make the entrance faces Set<GMLFace> result = new HashSet<GMLFace>(); result.add(map.createFace(edges1, FaceType.BUILDING)); // result.add(map.createFace(edges2, FaceType.BUILDING)); return result; } private double getRandomOffset() { double d = random.nextDouble(); double range = MAX_OFFSET - MIN_OFFSET; return MIN_OFFSET + (d * range); } private int getRandomRunLength() { return MIN_RUN_LENGTH + random.nextInt(MAX_RUN_LENGTH - MIN_RUN_LENGTH + 1); } */ }