diff --git a/src/main/java/org/openstreetmap/josm/plugins/plbuildings/BuildingsAction.java b/src/main/java/org/openstreetmap/josm/plugins/plbuildings/BuildingsAction.java index 4dcfaae..fedd82b 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/plbuildings/BuildingsAction.java +++ b/src/main/java/org/openstreetmap/josm/plugins/plbuildings/BuildingsAction.java @@ -35,10 +35,10 @@ public BuildingsAction() { null, DESCRIPTION, Shortcut.registerShortcut( - "download:building", - tr("Download building"), - KeyEvent.VK_1, - Shortcut.CTRL_SHIFT + "download:building", + tr("Download building"), + KeyEvent.VK_1, + Shortcut.CTRL_SHIFT ), true ); @@ -75,129 +75,135 @@ public static boolean isCloseNode(Node node1, Node node2, double maxOffset) { public static DataSet getBuildingsAtCurrentLocation(){ LatLon latLonPoint = MainApplication.getMap().mapView.getLatLon( - MainApplication.getMap().mapView.getMousePosition().getX(), - MainApplication.getMap().mapView.getMousePosition().getY() + MainApplication.getMap().mapView.getMousePosition().getX(), + MainApplication.getMap().mapView.getMousePosition().getY() ); return BuildingsDownloader.downloadBuildings(latLonPoint, "bdot"); } public static void performBuildingImport(DataSet currentDataSet) { - try { - DataSet importedBuildingsDataSet = getBuildingsAtCurrentLocation(); + DataSet importedBuildingsDataSet = getBuildingsAtCurrentLocation(); + if (importedBuildingsDataSet == null){ + Logging.warn("Connection error: Cannot import building!"); + return; + } + if (importedBuildingsDataSet.isEmpty()) { + Logging.info("Imported empty dataset."); + return; + } - if (importedBuildingsDataSet == null || importedBuildingsDataSet.isEmpty()) { - return; - } + List importedBuildingsCollection = importedBuildingsDataSet.getWays() + .stream() + .filter(way -> way.hasKey("building")) + .collect(Collectors.toList()); - // just get first building - Way importedBuilding = (Way) importedBuildingsDataSet.getWays().toArray()[0]; - - List newNodes = importedBuilding.getNodes().stream() - .map(node -> new Node(node, true)) - .collect(Collectors.toList()); - - // last node is wrongly duplicated after cloning operation, so remove it now - // and add first node to the way below to get it as closed line (area) - newNodes.remove(newNodes.size() - 1); - - Way newBuilding = new Way(); - newBuilding.cloneFrom(importedBuilding, false); - importedBuildingsDataSet.clear(); - - // Check if any building's node is very close to existing node – almost/same lat lon and replace it - BBox bbox = getBBox(newNodes, BuildingsSettings.BBOX_OFFSET.get()); - - List closeNodes = currentDataSet.searchNodes(bbox).stream() - .filter(n -> !n.isDeleted()) - .collect(Collectors.toList()); - List buildingNodes = new ArrayList<>(); - List nodesToAddToDataSet = new ArrayList<>(); - - AtomicInteger sameNodeCounter = new AtomicInteger(); - newNodes.forEach(newNode -> { - Node sameNode = closeNodes.stream() - .filter(closeNode -> isCloseNode(closeNode, newNode, BuildingsSettings.BBOX_OFFSET.get())) - .findFirst().orElse(null); - - if (sameNode != null) { - buildingNodes.add(sameNode); - sameNodeCounter.getAndIncrement(); - } else { - buildingNodes.add(newNode); - nodesToAddToDataSet.add(newNode); - } - }); - - // Whole building is a duplicate – contains the same nodes - if (sameNodeCounter.get() == buildingNodes.size()) { - return; - } - newBuilding.setNodes(buildingNodes); - newBuilding.addNode(buildingNodes.get(0)); - - List commands = new ArrayList<>(); - - nodesToAddToDataSet.forEach(node -> commands.add(new AddCommand(currentDataSet, node))); - commands.add(new AddCommand(currentDataSet, newBuilding)); - - Collection selected = currentDataSet.getSelected() - .stream() - .filter(osmPrimitive -> osmPrimitive.getType() == OsmPrimitiveType.WAY) - .collect(Collectors.toList()); - - // TODO maybe semidetached/terrace auto-change building tag - SequenceCommand importBuildingSequenceCommand = new SequenceCommand(tr("Import building"), commands); - UndoRedoHandler.getInstance().add(importBuildingSequenceCommand); - Logging.debug("Imported new building {0}", newBuilding.getId()); - - if (selected.size() == 1) { - Way selectedBuilding = (Way) selected.toArray()[0]; - try { - ReplaceUpdateBuildingCommand replaceUpdateBuildingCommand = new ReplaceUpdateBuildingCommand( - currentDataSet, - selectedBuilding, - newBuilding - ); - UndoRedoHandler.getInstance().add(replaceUpdateBuildingCommand); - Logging.debug("Updated building {0} with new data", selectedBuilding.getId()); - - } catch (IllegalArgumentException ignored) { - // If user cancel conflict window do nothing - Notification note = new Notification(tr("Canceled merging buildings.")); - note.setIcon(JOptionPane.WARNING_MESSAGE); - note.setDuration(Notification.TIME_SHORT); - note.show(); - - UndoRedoUtils.undoUntil(UndoRedoHandler.getInstance(), importBuildingSequenceCommand, true); - Logging.debug( - "No building (id: {0}) update, caused: Cancel conflict dialog by user", - selectedBuilding.getId() - ); - } catch (ReplaceGeometryException ignore) { - // If selected building cannot be merged (e.g. connected ways/relation) - Notification note = new Notification(tr( - "Cannot merge buildings!" + - " Old building may be connected with some ways/relations" + - " or not whole area is downloaded." - )); - note.setIcon(JOptionPane.ERROR_MESSAGE); - note.setDuration(Notification.TIME_SHORT); - note.show(); - - UndoRedoUtils.undoUntil(UndoRedoHandler.getInstance(), importBuildingSequenceCommand, true); - Logging.debug( - "No building update (id: {0}), caused: Replacing Geometry from UtilPlugins2 error", - selectedBuilding.getId() - ); - } - - currentDataSet.clearSelection(); + if (importedBuildingsCollection.isEmpty()){ + Logging.warn("Imported dataset with some data, but without buildings!"); + return; + } + // just get first building + Way importedBuilding = importedBuildingsCollection.get(0); + + List newNodes = importedBuilding.getNodes().stream() + .map(node -> new Node(node, true)) + .collect(Collectors.toList()); + + // last node is wrongly duplicated after cloning operation, so remove it now + // and add first node to the way below to get it as closed line (area) + newNodes.remove(newNodes.size() - 1); + + Way newBuilding = new Way(); + newBuilding.cloneFrom(importedBuilding, false); + importedBuildingsDataSet.clear(); + + // Check if any building's node is very close to existing node – almost/same lat lon and replace it + BBox bbox = getBBox(newNodes, BuildingsSettings.BBOX_OFFSET.get()); + + List closeNodes = currentDataSet.searchNodes(bbox).stream() + .filter(n -> !n.isDeleted()) + .collect(Collectors.toList()); + List buildingNodes = new ArrayList<>(); + List nodesToAddToDataSet = new ArrayList<>(); + + AtomicInteger sameNodeCounter = new AtomicInteger(); + newNodes.forEach(newNode -> { + Node sameNode = closeNodes.stream() + .filter(closeNode -> isCloseNode(closeNode, newNode, BuildingsSettings.BBOX_OFFSET.get())) + .findFirst().orElse(null); + + if (sameNode != null) { + buildingNodes.add(sameNode); + sameNodeCounter.getAndIncrement(); + } else { + buildingNodes.add(newNode); + nodesToAddToDataSet.add(newNode); } + }); + // Whole building is a duplicate – contains the same nodes + if (sameNodeCounter.get() == buildingNodes.size()) { + return; + } + newBuilding.setNodes(buildingNodes); + newBuilding.addNode(buildingNodes.get(0)); + + List commands = new ArrayList<>(); + + nodesToAddToDataSet.forEach(node -> commands.add(new AddCommand(currentDataSet, node))); + commands.add(new AddCommand(currentDataSet, newBuilding)); + + Collection selected = currentDataSet.getSelected() + .stream() + .filter(osmPrimitive -> osmPrimitive.getType() == OsmPrimitiveType.WAY) + .collect(Collectors.toList()); + + SequenceCommand importBuildingSequenceCommand = new SequenceCommand(tr("Import building"), commands); + UndoRedoHandler.getInstance().add(importBuildingSequenceCommand); + Logging.debug("Imported new building {0}", newBuilding.getId()); + + if (selected.size() == 1) { + Way selectedBuilding = (Way) selected.toArray()[0]; + try { + ReplaceUpdateBuildingCommand replaceUpdateBuildingCommand = new ReplaceUpdateBuildingCommand( + currentDataSet, + selectedBuilding, + newBuilding + ); + UndoRedoHandler.getInstance().add(replaceUpdateBuildingCommand); + Logging.debug("Updated building {0} with new data", selectedBuilding.getId()); + + } catch (IllegalArgumentException ignored) { + // If user cancel conflict window do nothing + Notification note = new Notification(tr("Canceled merging buildings.")); + note.setIcon(JOptionPane.WARNING_MESSAGE); + note.setDuration(Notification.TIME_SHORT); + note.show(); + + UndoRedoUtils.undoUntil(UndoRedoHandler.getInstance(), importBuildingSequenceCommand, true); + Logging.debug( + "No building (id: {0}) update, caused: Cancel conflict dialog by user", + selectedBuilding.getId() + ); + } catch (ReplaceGeometryException ignore) { + // If selected building cannot be merged (e.g. connected ways/relation) + Notification note = new Notification(tr( + "Cannot merge buildings!" + + " Old building may be connected with some ways/relations" + + " or not whole area is downloaded." + )); + note.setIcon(JOptionPane.ERROR_MESSAGE); + note.setDuration(Notification.TIME_SHORT); + note.show(); + + UndoRedoUtils.undoUntil(UndoRedoHandler.getInstance(), importBuildingSequenceCommand, true); + Logging.debug( + "No building update (id: {0}), caused: Replacing Geometry from UtilPlugins2 error", + selectedBuilding.getId() + ); + } - } catch (NullPointerException ignored) { - // TODO log it + currentDataSet.clearSelection(); } }