kopia lustrzana https://github.com/JOSM/MapWithAI
Add a check and cleanup for overnoded ways
Also switch layers to the appropriate data layer (for UI) for OverNodedWays/MissingConnectionTags. Signed-off-by: Taylor Smock <taylor.smock@kaart.com>pull/1/head
rodzic
3d43ee1434
commit
779c862cea
|
@ -30,6 +30,8 @@ import org.openstreetmap.josm.data.validation.tests.CrossingWays;
|
||||||
import org.openstreetmap.josm.data.validation.tests.DuplicateNode;
|
import org.openstreetmap.josm.data.validation.tests.DuplicateNode;
|
||||||
import org.openstreetmap.josm.gui.ConditionalOptionPaneUtil;
|
import org.openstreetmap.josm.gui.ConditionalOptionPaneUtil;
|
||||||
import org.openstreetmap.josm.gui.MainApplication;
|
import org.openstreetmap.josm.gui.MainApplication;
|
||||||
|
import org.openstreetmap.josm.gui.layer.AbstractOsmDataLayer;
|
||||||
|
import org.openstreetmap.josm.gui.layer.Layer;
|
||||||
import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
|
import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
|
||||||
import org.openstreetmap.josm.gui.util.GuiHelper;
|
import org.openstreetmap.josm.gui.util.GuiHelper;
|
||||||
import org.openstreetmap.josm.plugins.mapwithai.backend.commands.conflation.AbstractConflationCommand;
|
import org.openstreetmap.josm.plugins.mapwithai.backend.commands.conflation.AbstractConflationCommand;
|
||||||
|
@ -45,7 +47,8 @@ import org.openstreetmap.josm.tools.Utils;
|
||||||
* @author Taylor Smock
|
* @author Taylor Smock
|
||||||
*/
|
*/
|
||||||
public class MissingConnectionTags extends AbstractConflationCommand {
|
public class MissingConnectionTags extends AbstractConflationCommand {
|
||||||
private double precision = Config.getPref().getDouble("validator.duplicatenodes.precision", 0.);
|
private double precision;
|
||||||
|
private static final String HIGHWAY = "highway";
|
||||||
|
|
||||||
public MissingConnectionTags(DataSet data) {
|
public MissingConnectionTags(DataSet data) {
|
||||||
super(data);
|
super(data);
|
||||||
|
@ -64,11 +67,22 @@ public class MissingConnectionTags extends AbstractConflationCommand {
|
||||||
@Override
|
@Override
|
||||||
public String getKey() {
|
public String getKey() {
|
||||||
// For now, we assume that only highways are at issue.
|
// For now, we assume that only highways are at issue.
|
||||||
return "highway";
|
return HIGHWAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Command getRealCommand() {
|
public Command getRealCommand() {
|
||||||
|
precision = Config.getPref().getDouble("validator.duplicatenodes.precision", 0.);
|
||||||
|
Layer current = MainApplication.getLayerManager().getActiveLayer();
|
||||||
|
Collection<Way> ways = Utils.filteredCollection(possiblyAffectedPrimitives, Way.class);
|
||||||
|
if (!ways.isEmpty()) {
|
||||||
|
DataSet ds = this.getAffectedDataSet();
|
||||||
|
Layer toSwitch = MainApplication.getLayerManager().getLayersOfType(AbstractOsmDataLayer.class).stream()
|
||||||
|
.filter(d -> ds.equals(d.getDataSet())).findAny().orElse(null);
|
||||||
|
if (toSwitch != null) {
|
||||||
|
MainApplication.getLayerManager().setActiveLayer(toSwitch);
|
||||||
|
}
|
||||||
|
}
|
||||||
// precision is in meters
|
// precision is in meters
|
||||||
precision = precision == 0 ? 1 : precision;
|
precision = precision == 0 ? 1 : precision;
|
||||||
String prefKey = "mapwithai.conflation.missingconflationtags";
|
String prefKey = "mapwithai.conflation.missingconflationtags";
|
||||||
|
@ -79,6 +93,9 @@ public class MissingConnectionTags extends AbstractConflationCommand {
|
||||||
fixErrors(prefKey, commands, findDuplicateNodes(possiblyAffectedPrimitives));
|
fixErrors(prefKey, commands, findDuplicateNodes(possiblyAffectedPrimitives));
|
||||||
fixErrors(prefKey, commands, findCrossingWaysAtNodes(possiblyAffectedPrimitives));
|
fixErrors(prefKey, commands, findCrossingWaysAtNodes(possiblyAffectedPrimitives));
|
||||||
ConditionalOptionPaneUtil.endBulkOperation(prefKey);
|
ConditionalOptionPaneUtil.endBulkOperation(prefKey);
|
||||||
|
if (current != null) {
|
||||||
|
MainApplication.getLayerManager().setActiveLayer(current);
|
||||||
|
}
|
||||||
GuiHelper.runInEDT(() -> getAffectedDataSet().setSelected(selection));
|
GuiHelper.runInEDT(() -> getAffectedDataSet().setSelected(selection));
|
||||||
commands.forEach(Command::undoCommand);
|
commands.forEach(Command::undoCommand);
|
||||||
return commands.isEmpty() ? null : new SequenceCommand(tr("Perform missing conflation steps"), commands);
|
return commands.isEmpty() ? null : new SequenceCommand(tr("Perform missing conflation steps"), commands);
|
||||||
|
@ -149,7 +166,9 @@ public class MissingConnectionTags extends AbstractConflationCommand {
|
||||||
way.getDataSet().searchWays(way.getBBox()).forEach(crossingWays::visit);
|
way.getDataSet().searchWays(way.getBBox()).forEach(crossingWays::visit);
|
||||||
crossingWays.endTest();
|
crossingWays.endTest();
|
||||||
for (TestError error : crossingWays.getErrors()) {
|
for (TestError error : crossingWays.getErrors()) {
|
||||||
if (seenFix.containsAll(error.getPrimitives())) {
|
if (seenFix.containsAll(error.getPrimitives())
|
||||||
|
|| error.getPrimitives().stream().filter(Way.class::isInstance).map(Way.class::cast)
|
||||||
|
.filter(w -> w.hasKey(HIGHWAY)).count() == 0L) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
TestError.Builder fixError = TestError.builder(error.getTester(), error.getSeverity(), error.getCode())
|
TestError.Builder fixError = TestError.builder(error.getTester(), error.getSeverity(), error.getCode())
|
||||||
|
@ -164,11 +183,9 @@ public class MissingConnectionTags extends AbstractConflationCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Supplier<Command> createIntersectionCommandSupplier(TestError error, Way way) {
|
private Supplier<Command> createIntersectionCommandSupplier(TestError error, Way way) {
|
||||||
Collection<Node> nodes = Geometry
|
Collection<Node> nodes = Geometry.addIntersections(error.getPrimitives().stream().filter(Way.class::isInstance)
|
||||||
.addIntersections(
|
.map(Way.class::cast).filter(w -> w.hasKey(HIGHWAY)).collect(Collectors.toList()), false,
|
||||||
error.getPrimitives().stream().filter(Way.class::isInstance).map(Way.class::cast)
|
new ArrayList<>());
|
||||||
.filter(w -> w.hasKey("highway")).collect(Collectors.toList()),
|
|
||||||
false, new ArrayList<>());
|
|
||||||
if (nodes.stream().anyMatch(n -> way.getNodes().stream().filter(MissingConnectionTags::noConflationKey)
|
if (nodes.stream().anyMatch(n -> way.getNodes().stream().filter(MissingConnectionTags::noConflationKey)
|
||||||
.anyMatch(wn -> n.getCoor().greatCircleDistance(wn.getCoor()) < precision))) {
|
.anyMatch(wn -> n.getCoor().greatCircleDistance(wn.getCoor()) < precision))) {
|
||||||
return () -> createIntersectionCommand(way,
|
return () -> createIntersectionCommand(way,
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
// License: GPL. For details, see LICENSE file.
|
||||||
|
package org.openstreetmap.josm.plugins.mapwithai.backend.commands.conflation.cleanup;
|
||||||
|
|
||||||
|
import static org.openstreetmap.josm.tools.I18n.tr;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import org.openstreetmap.josm.actions.AutoScaleAction;
|
||||||
|
import org.openstreetmap.josm.actions.SimplifyWayAction;
|
||||||
|
import org.openstreetmap.josm.command.Command;
|
||||||
|
import org.openstreetmap.josm.command.SequenceCommand;
|
||||||
|
import org.openstreetmap.josm.data.osm.DataSet;
|
||||||
|
import org.openstreetmap.josm.data.osm.Node;
|
||||||
|
import org.openstreetmap.josm.data.osm.OsmPrimitive;
|
||||||
|
import org.openstreetmap.josm.data.osm.Way;
|
||||||
|
import org.openstreetmap.josm.gui.MainApplication;
|
||||||
|
import org.openstreetmap.josm.gui.layer.AbstractOsmDataLayer;
|
||||||
|
import org.openstreetmap.josm.gui.layer.Layer;
|
||||||
|
import org.openstreetmap.josm.plugins.mapwithai.backend.commands.conflation.AbstractConflationCommand;
|
||||||
|
import org.openstreetmap.josm.spi.preferences.Config;
|
||||||
|
import org.openstreetmap.josm.tools.Utils;
|
||||||
|
|
||||||
|
public class OverNodedWays extends AbstractConflationCommand {
|
||||||
|
|
||||||
|
private double threshold;
|
||||||
|
private int acceptableRemovalPercentage;
|
||||||
|
|
||||||
|
public OverNodedWays(DataSet data) {
|
||||||
|
super(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescriptionText() {
|
||||||
|
return tr("Fix overnoded ways");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<Class<? extends OsmPrimitive>> getInterestedTypes() {
|
||||||
|
return Collections.singleton(Way.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getKey() {
|
||||||
|
// Currently only interested in highways
|
||||||
|
return "highway";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Command getRealCommand() {
|
||||||
|
threshold = Config.getPref().getDouble("mapwithai.conflation.simplifyway", 0.5);
|
||||||
|
acceptableRemovalPercentage = Config.getPref().getInt("mapwithai.conflation.simplifywaynodepercentagerequired",
|
||||||
|
20);
|
||||||
|
Layer current = MainApplication.getLayerManager().getActiveLayer();
|
||||||
|
Collection<Way> ways = Utils.filteredCollection(possiblyAffectedPrimitives, Way.class);
|
||||||
|
if (!ways.isEmpty()) {
|
||||||
|
DataSet ds = this.getAffectedDataSet();
|
||||||
|
Layer toSwitch = MainApplication.getLayerManager().getLayersOfType(AbstractOsmDataLayer.class).stream()
|
||||||
|
.filter(d -> ds.equals(d.getDataSet())).findAny().orElse(null);
|
||||||
|
if (toSwitch != null) {
|
||||||
|
MainApplication.getLayerManager().setActiveLayer(toSwitch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Collection<Command> commands = new ArrayList<>();
|
||||||
|
for (Way way : ways) {
|
||||||
|
Command command = SimplifyWayAction.createSimplifyCommand(way, threshold);
|
||||||
|
if (command == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int count = Utils.filteredCollection(new ArrayList<>(command.getParticipatingPrimitives()), Node.class)
|
||||||
|
.size();
|
||||||
|
if ((count / (double) way.getNodesCount()) * 100 > this.acceptableRemovalPercentage) {
|
||||||
|
AutoScaleAction.zoomTo(Collections.singleton(way));
|
||||||
|
double length = SimplifyWayAction.askSimplifyWays(
|
||||||
|
tr("You are about to simplify {0} way with a total length of {1}.", 1, way.getLength()), true);
|
||||||
|
commands.add(SimplifyWayAction.createSimplifyCommand(way, length));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (current != null) {
|
||||||
|
MainApplication.getLayerManager().setActiveLayer(current);
|
||||||
|
}
|
||||||
|
if (commands.size() == 1) {
|
||||||
|
return commands.iterator().next();
|
||||||
|
} else if (!commands.isEmpty()) {
|
||||||
|
return new SequenceCommand(tr("Simplify ways"), commands);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean allowUndo() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean keyShouldNotExistInOSM() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -29,6 +29,7 @@ import org.openstreetmap.josm.plugins.mapwithai.backend.commands.conflation.Dupl
|
||||||
import org.openstreetmap.josm.plugins.mapwithai.backend.commands.conflation.MergeAddressBuildings;
|
import org.openstreetmap.josm.plugins.mapwithai.backend.commands.conflation.MergeAddressBuildings;
|
||||||
import org.openstreetmap.josm.plugins.mapwithai.backend.commands.conflation.MergeBuildingAddress;
|
import org.openstreetmap.josm.plugins.mapwithai.backend.commands.conflation.MergeBuildingAddress;
|
||||||
import org.openstreetmap.josm.plugins.mapwithai.backend.commands.conflation.cleanup.MissingConnectionTags;
|
import org.openstreetmap.josm.plugins.mapwithai.backend.commands.conflation.cleanup.MissingConnectionTags;
|
||||||
|
import org.openstreetmap.josm.plugins.mapwithai.backend.commands.conflation.cleanup.OverNodedWays;
|
||||||
import org.openstreetmap.josm.tools.Logging;
|
import org.openstreetmap.josm.tools.Logging;
|
||||||
import org.openstreetmap.josm.tools.Utils;
|
import org.openstreetmap.josm.tools.Utils;
|
||||||
|
|
||||||
|
@ -43,6 +44,7 @@ public class CreateConnectionsCommand extends Command {
|
||||||
CONFLATION_COMMANDS.add(MergeAddressBuildings.class);
|
CONFLATION_COMMANDS.add(MergeAddressBuildings.class);
|
||||||
CONFLATION_COMMANDS.add(MergeBuildingAddress.class);
|
CONFLATION_COMMANDS.add(MergeBuildingAddress.class);
|
||||||
CONFLATION_COMMANDS.add(MissingConnectionTags.class);
|
CONFLATION_COMMANDS.add(MissingConnectionTags.class);
|
||||||
|
CONFLATION_COMMANDS.add(OverNodedWays.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CreateConnectionsCommand(DataSet data, Collection<PrimitiveData> primitives) {
|
public CreateConnectionsCommand(DataSet data, Collection<PrimitiveData> primitives) {
|
||||||
|
|
Ładowanie…
Reference in New Issue