private void distribute(AddressNodeGroup group) { List<AddressNode> nodes = group.getAddressNodes(); Collections.sort(nodes, addressNodeComparator); Coordinate start = group.getGeometry().getCoordinate(); // center of the building Coordinate center = group.getBuilding().getGeometry().getCentroid().getCoordinate(); double dx; double dy; if (start.equals(center)) { // if the nodes are at the center of the building, use an angle of 45 degrees dx = SQRT2 * DISTANCE; dy = SQRT2 * DISTANCE; } else { double angle = new LineSegment(start, center).angle(); dx = Math.cos(angle) * DISTANCE; dy = Math.sin(angle) * DISTANCE; } double x = group.getGeometry().getX(); double y = group.getGeometry().getY(); // List<Command> cmds = new LinkedList<>(); for (AddressNode node : nodes) { Point point = geoUtil.toPoint(new Coordinate(x, y)); node.setGeometry(point); // Command cmd = node.updateGeometry(point); // if (cmd != null) { // cmds.add(cmd); // } x = x + dx; y = y + dy; } // if (!nodes.isEmpty()) { // final SequenceCommand sequenceCommand = new SequenceCommand( // I18n.tr("Distribute {0} address nodes.", cmds.size()), cmds); // Main.main.undoRedo.add(sequenceCommand); // } }
/** * This analyzer finds overlapping nodes in the data and distibutes them, so they are no longer * overlapping. The AddressToBuildingMatcher analyzer must run before this class, so when can * distribute over the line pointing to the center of the building. * * @author Gertjan Idema <*****@*****.**> */ public class AddressNodeDistributor implements Analyzer { private static GeoUtil geoUtil = GeoUtil.getInstance(); private static double SQRT2 = Math.sqrt(2.0); private static AddressNodeComparator addressNodeComparator = new AddressNodeComparator(); private double DISTANCE = 2e-7; // Distance between nodes public AddressNodeDistributor() { super(); } @Override public void analyze(DataLayer dataLayer, EntitySet newEntities) { EntitySet entities = newEntities; if (entities == null) { entities = dataLayer.getEntitySet(); } BuiltEnvironment environment = new BuiltEnvironment(entities); Iterator<Building> it = environment.getBuildings().iterator(); while (it.hasNext()) { Building building = it.next(); for (AddressNodeGroup group : buildGroups(building).values()) { if (group.getAddressNodes().size() > 1) { distribute(group); } } } } /** * Analyze all new address nodes and group them by Geometry (Point) * * @param newEntities */ private Map<Point, AddressNodeGroup> buildGroups(Building building) { Map<Point, AddressNodeGroup> groups = new HashMap<>(); Iterator<? extends AddressNode> it = building.getAddressNodes().iterator(); while (it.hasNext()) { AddressNode addressNode = it.next(); AddressNodeGroup group = groups.get(addressNode.getGeometry()); if (group == null) { group = new AddressNodeGroup(addressNode); groups.put(addressNode.getGeometry(), group); } else { group.addAddressNode(addressNode); } } return groups; } private void distribute(AddressNodeGroup group) { List<AddressNode> nodes = group.getAddressNodes(); Collections.sort(nodes, addressNodeComparator); Coordinate start = group.getGeometry().getCoordinate(); // center of the building Coordinate center = group.getBuilding().getGeometry().getCentroid().getCoordinate(); double dx; double dy; if (start.equals(center)) { // if the nodes are at the center of the building, use an angle of 45 degrees dx = SQRT2 * DISTANCE; dy = SQRT2 * DISTANCE; } else { double angle = new LineSegment(start, center).angle(); dx = Math.cos(angle) * DISTANCE; dy = Math.sin(angle) * DISTANCE; } double x = group.getGeometry().getX(); double y = group.getGeometry().getY(); // List<Command> cmds = new LinkedList<>(); for (AddressNode node : nodes) { Point point = geoUtil.toPoint(new Coordinate(x, y)); node.setGeometry(point); // Command cmd = node.updateGeometry(point); // if (cmd != null) { // cmds.add(cmd); // } x = x + dx; y = y + dy; } // if (!nodes.isEmpty()) { // final SequenceCommand sequenceCommand = new SequenceCommand( // I18n.tr("Distribute {0} address nodes.", cmds.size()), cmds); // Main.main.undoRedo.add(sequenceCommand); // } } static class AddressNodeComparator implements Comparator<AddressNode> { @Override public int compare(AddressNode an1, AddressNode an2) { Address a1 = an1.getAddress(); Address a2 = an2.getAddress(); int result = ObjectUtils.compare(a1.getCityName(), a2.getCityName()); if (result == 0) { result = ObjectUtils.compare(a1.getPostcode(), a2.getPostcode()); } ; if (result == 0) { result = ObjectUtils.compare(a1.getStreetName(), a2.getStreetName()); } ; if (result == 0) { result = ObjectUtils.compare(a1.getHouseNumber(), a2.getHouseNumber()); } ; return result; } } }