kopia lustrzana https://github.com/JOSM/MapWithAI
Now allow cropping of data from MapWithAI[1]
* Also add method to get arbitrary data from RapiD * Decrease size of bboxes sent to server (originally maxed at 10km, now 1km due to some issues, and that is roughly what RapiD uses (zoom level 16 tiles)) [1] The server backend requires that the crop area have connecting ways (for roads, not needed for buildings) Signed-off-by: Taylor Smock <taylor.smock@kaart.com>pull/1/head
rodzic
2fd298a24c
commit
89cc8fe53c
|
@ -1,8 +1,13 @@
|
|||
// License: GPL. For details, see LICENSE file.
|
||||
package org.openstreetmap.josm.plugins.rapid;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.swing.JMenu;
|
||||
|
||||
import org.openstreetmap.josm.actions.JosmAction;
|
||||
import org.openstreetmap.josm.gui.MainApplication;
|
||||
import org.openstreetmap.josm.gui.MainMenu;
|
||||
import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
|
||||
|
@ -12,6 +17,7 @@ import org.openstreetmap.josm.plugins.rapid.backend.RapiDAction;
|
|||
import org.openstreetmap.josm.plugins.rapid.backend.RapiDArbitraryAction;
|
||||
import org.openstreetmap.josm.plugins.rapid.backend.RapiDDataUtils;
|
||||
import org.openstreetmap.josm.plugins.rapid.backend.RapiDMoveAction;
|
||||
import org.openstreetmap.josm.tools.Logging;
|
||||
|
||||
public final class RapiDPlugin extends Plugin {
|
||||
/** The name of the plugin */
|
||||
|
@ -20,15 +26,35 @@ public final class RapiDPlugin extends Plugin {
|
|||
|
||||
private final PreferenceSetting preferenceSetting;
|
||||
|
||||
private static final LinkedHashMap<Class<? extends JosmAction>, Boolean> MENU_ENTRIES = new LinkedHashMap<>();
|
||||
static {
|
||||
MENU_ENTRIES.put(RapiDAction.class, false);
|
||||
MENU_ENTRIES.put(RapiDMoveAction.class, false);
|
||||
MENU_ENTRIES.put(RapiDArbitraryAction.class, true);
|
||||
}
|
||||
|
||||
public RapiDPlugin(PluginInformation info) {
|
||||
super(info);
|
||||
|
||||
preferenceSetting = new RapiDPreferences();
|
||||
|
||||
final JMenu dataMenu = MainApplication.getMenu().dataMenu;
|
||||
MainMenu.add(dataMenu, new RapiDAction(), false);
|
||||
MainMenu.add(dataMenu, new RapiDMoveAction(), false);
|
||||
MainMenu.add(dataMenu, new RapiDArbitraryAction(), true);
|
||||
for (Entry<Class<? extends JosmAction>, Boolean> entry : MENU_ENTRIES.entrySet()) {
|
||||
boolean alreadyAdded = false;
|
||||
for (Component component : dataMenu.getMenuComponents()) {
|
||||
if (entry.getKey().equals(component.getClass())) {
|
||||
alreadyAdded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!alreadyAdded) {
|
||||
try {
|
||||
MainMenu.add(dataMenu, entry.getKey().newInstance(), entry.getValue());
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
Logging.debug(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RapiDDataUtils.addRapiDPaintStyles();
|
||||
|
||||
|
|
|
@ -1,25 +1,34 @@
|
|||
// License: GPL. For details, see LICENSE file.
|
||||
package org.openstreetmap.josm.plugins.rapid.backend;
|
||||
|
||||
import static org.openstreetmap.josm.tools.I18n.tr;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.openstreetmap.josm.data.Bounds;
|
||||
import org.openstreetmap.josm.data.coor.LatLon;
|
||||
import org.openstreetmap.josm.data.gpx.GpxData;
|
||||
import org.openstreetmap.josm.data.gpx.GpxRoute;
|
||||
import org.openstreetmap.josm.data.gpx.WayPoint;
|
||||
import org.openstreetmap.josm.data.osm.BBox;
|
||||
import org.openstreetmap.josm.gui.MainApplication;
|
||||
import org.openstreetmap.josm.gui.layer.GpxLayer;
|
||||
import org.openstreetmap.josm.gui.layer.Layer;
|
||||
import org.openstreetmap.josm.plugins.rapid.RapiDPlugin;
|
||||
|
||||
/**
|
||||
* @author Taylor Smock
|
||||
*
|
||||
*/
|
||||
public class DetectTaskingManager {
|
||||
public static final String RAPID_CROP_AREA = tr("{0}: Crop Area", RapiDPlugin.NAME);
|
||||
public static final List<Pattern> patterns = new ArrayList<>();
|
||||
static {
|
||||
patterns.add(Pattern.compile("^Task Boundaries.*$"));
|
||||
patterns.add(Pattern.compile("^" + RAPID_CROP_AREA + "$"));
|
||||
}
|
||||
|
||||
private DetectTaskingManager() {
|
||||
|
@ -66,4 +75,17 @@ public class DetectTaskingManager {
|
|||
}
|
||||
return returnBBox;
|
||||
}
|
||||
|
||||
public static GpxData createTaskingManagerGpxData(BBox bbox) {
|
||||
final GpxData data = new GpxData();
|
||||
GpxRoute route = new GpxRoute();
|
||||
route.routePoints.add(new WayPoint(bbox.getBottomRight()));
|
||||
route.routePoints.add(new WayPoint(new LatLon(bbox.getBottomRightLat(), bbox.getTopLeftLon())));
|
||||
route.routePoints.add(new WayPoint(bbox.getTopLeft()));
|
||||
route.routePoints.add(new WayPoint(new LatLon(bbox.getTopLeftLat(), bbox.getBottomRightLon())));
|
||||
route.routePoints.add(route.routePoints.iterator().next());
|
||||
route.routePoints.forEach(waypoint -> waypoint.setTime(0));
|
||||
data.addRoute(route);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ public class RapiDAction extends JosmAction {
|
|||
private static final Object LAYER_LOCK = new Object();
|
||||
|
||||
public RapiDAction() {
|
||||
super(RapiDPlugin.NAME, null, tr("Get data from RapiD"),
|
||||
super(tr("{0}: Download data", RapiDPlugin.NAME), null, tr("Get data from RapiD"),
|
||||
Shortcut.registerShortcut("data:rapid", tr("Data: {0}", tr("RapiD")), KeyEvent.VK_R, Shortcut.SHIFT),
|
||||
true);
|
||||
}
|
||||
|
|
|
@ -48,9 +48,10 @@ public class RapiDArbitraryAction extends JosmAction {
|
|||
private final JCheckBox checkbox = new JCheckBox();
|
||||
|
||||
public RapiDArbitraryAction() {
|
||||
super(RapiDPlugin.NAME, null, tr("Get arbitrary data from RapiD"), Shortcut.registerShortcut("data:rapid",
|
||||
tr("Data: Arbitrary {0} Data", tr("Get arbitrary data from RapiD")), KeyEvent.VK_R,
|
||||
Shortcut.ALT_CTRL_SHIFT), true);
|
||||
super(tr("{0}: Download arbitrary data", RapiDPlugin.NAME), null, tr("Get arbitrary data from RapiD"),
|
||||
Shortcut.registerShortcut("data:arbitraryrapid",
|
||||
tr("Data: Arbitrary {0} Data", tr("Get arbitrary data from RapiD")), KeyEvent.VK_R,
|
||||
Shortcut.ALT_CTRL_SHIFT), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -123,10 +124,8 @@ public class RapiDArbitraryAction extends JosmAction {
|
|||
}
|
||||
|
||||
if (checkbox.isSelected()) {
|
||||
final GpxData data = new GpxData();
|
||||
data.addWaypoint(new WayPoint(bbox.getBottomRight()));
|
||||
data.addWaypoint(new WayPoint(bbox.getTopLeft()));
|
||||
MainApplication.getLayerManager().addLayer(new GpxLayer(data, tr("{0}: Crop Area", RapiDPlugin.NAME)));
|
||||
MainApplication.getLayerManager().addLayer(new GpxLayer(
|
||||
DetectTaskingManager.createTaskingManagerGpxData(bbox), DetectTaskingManager.RAPID_CROP_AREA));
|
||||
}
|
||||
|
||||
final DataSet data = RapiDDataUtils.getData(bbox);
|
||||
|
|
|
@ -41,8 +41,7 @@ import org.openstreetmap.josm.tools.Logging;
|
|||
*/
|
||||
public final class RapiDDataUtils {
|
||||
public static final String DEFAULT_RAPID_API = "https://www.facebook.com/maps/ml_roads?conflate_with_osm=true&theme=ml_road_vector&collaborator=josm&token=ASb3N5o9HbX8QWn8G_NtHIRQaYv3nuG2r7_f3vnGld3KhZNCxg57IsaQyssIaEw5rfRNsPpMwg4TsnrSJtIJms5m&hash=ASawRla3rBcwEjY4HIY&result_type=road_building_vector_xml&bbox={bbox}";
|
||||
// TODO add &crop_bbox={bbox} if there are bounds from a HOT Tasking Manager
|
||||
public static final int MAXIMUM_SIDE_DIMENSIONS = 10000; // 10 km
|
||||
public static final int MAXIMUM_SIDE_DIMENSIONS = 1000; // 1 km
|
||||
|
||||
private RapiDDataUtils() {
|
||||
// Hide the constructor
|
||||
|
@ -72,6 +71,9 @@ public final class RapiDDataUtils {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Microsoft buildings don't have a source, so we add one */
|
||||
RapiDDataUtils.addSourceTags(dataSet, "building", "Microsoft");
|
||||
return dataSet;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ import java.util.stream.Collectors;
|
|||
|
||||
import org.openstreetmap.josm.actions.JosmAction;
|
||||
import org.openstreetmap.josm.data.UndoRedoHandler;
|
||||
import org.openstreetmap.josm.data.osm.DataSet;
|
||||
import org.openstreetmap.josm.data.osm.OsmPrimitive;
|
||||
import org.openstreetmap.josm.gui.MainApplication;
|
||||
import org.openstreetmap.josm.gui.layer.Layer;
|
||||
|
@ -24,7 +23,8 @@ public class RapiDMoveAction extends JosmAction {
|
|||
private static final long serialVersionUID = 319374598;
|
||||
|
||||
public RapiDMoveAction() {
|
||||
super(tr("Add from ".concat(RapiDPlugin.NAME)), null, tr("Add data from RapiD"), Shortcut.registerShortcut(
|
||||
super(tr("{0}: Add selected data", RapiDPlugin.NAME), null, tr("Add data from RapiD"),
|
||||
Shortcut.registerShortcut(
|
||||
"data:rapidadd", tr("Rapid: {0}", tr("Add selected data")), KeyEvent.VK_A, Shortcut.SHIFT), true);
|
||||
}
|
||||
|
||||
|
@ -52,9 +52,6 @@ public class RapiDMoveAction extends JosmAction {
|
|||
UndoRedoHandler.getInstance().add(command);
|
||||
if (RapiDDataUtils.isSwitchLayers()) {
|
||||
MainApplication.getLayerManager().setActiveLayer(editLayer);
|
||||
final DataSet editable = editLayer.getDataSet();
|
||||
editable.setSelected(
|
||||
editable.getSelected().stream().filter(OsmPrimitive::isTagged).collect(Collectors.toSet()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import static org.openstreetmap.josm.tools.I18n.tr;
|
|||
|
||||
import java.awt.EventQueue;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.openstreetmap.josm.command.Command;
|
||||
import org.openstreetmap.josm.command.SequenceCommand;
|
||||
|
@ -13,7 +12,6 @@ import org.openstreetmap.josm.data.osm.DataSet;
|
|||
import org.openstreetmap.josm.data.osm.OsmPrimitive;
|
||||
import org.openstreetmap.josm.gui.layer.OsmDataLayer;
|
||||
import org.openstreetmap.josm.plugins.rapid.RapiDPlugin;
|
||||
import org.openstreetmap.josm.plugins.rapid.backend.RapiDDataUtils;
|
||||
import org.openstreetmap.josm.plugins.rapid.backend.RapiDLayer;
|
||||
import org.openstreetmap.josm.tools.Logging;
|
||||
|
||||
|
@ -66,8 +64,6 @@ public class RapiDAddCommand extends Command implements Runnable {
|
|||
rapid, editable);
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
primitives = new HashSet<>(primitives);
|
||||
RapiDDataUtils.addPrimitivesToCollection(/* collection= */ primitives, /* primitives= */ primitives);
|
||||
synchronized (this) {
|
||||
final boolean locked = rapid.isLocked();
|
||||
if (locked) {
|
||||
|
|
|
@ -56,7 +56,7 @@ public class RapiDPluginTest {
|
|||
final int originalPaintStyles = MapPaintPrefHelper.INSTANCE.get().size();
|
||||
final int dataMenuSize = dataMenu.getMenuComponentCount();
|
||||
plugin = new RapiDPlugin(info);
|
||||
Assert.assertEquals(dataMenuSize + 2, dataMenu.getMenuComponentCount());
|
||||
Assert.assertEquals(dataMenuSize + 3, dataMenu.getMenuComponentCount());
|
||||
Assert.assertEquals(originalPaintStyles + 1, MapPaintPrefHelper.INSTANCE.get().size());
|
||||
}
|
||||
|
||||
|
|
|
@ -48,13 +48,16 @@ public class RapiDDataUtilsTest {
|
|||
public void testGetDataCropped() {
|
||||
final BBox testBBox = getTestBBox();
|
||||
GpxData gpxData = new GpxData();
|
||||
gpxData.addWaypoint(new WayPoint(new LatLon(39.0738798, -108.5709922)));
|
||||
gpxData.addWaypoint(new WayPoint(new LatLon(39.0732914, -108.5707436)));
|
||||
GpxLayer gpx = new GpxLayer(gpxData);
|
||||
gpxData.addWaypoint(new WayPoint(new LatLon(39.0735205, -108.5711561)));
|
||||
gpxData.addWaypoint(new WayPoint(new LatLon(39.0736682, -108.5708568)));
|
||||
GpxLayer gpx = new GpxLayer(gpxData, DetectTaskingManager.RAPID_CROP_AREA);
|
||||
final DataSet originalData = RapiDDataUtils.getData(testBBox);
|
||||
MainApplication.getLayerManager().addLayer(gpx);
|
||||
final DataSet ds = new DataSet(RapiDDataUtils.getData(testBBox));
|
||||
final DataSet ds = RapiDDataUtils.getData(testBBox);
|
||||
Assert.assertEquals(1, ds.getWays().size());
|
||||
Assert.assertEquals(2, ds.getNodes().size());
|
||||
Assert.assertEquals(3, ds.getNodes().size());
|
||||
Assert.assertEquals(1, originalData.getWays().size());
|
||||
Assert.assertEquals(4, originalData.getNodes().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -146,18 +149,15 @@ public class RapiDDataUtilsTest {
|
|||
|
||||
bbox.add(0.01, 0.01);
|
||||
bboxes = RapiDDataUtils.reduceBBoxSize(bbox);
|
||||
Assert.assertEquals(1, bboxes.size());
|
||||
Assert.assertEquals(4, bboxes.size());
|
||||
checkInBBox(bbox, bboxes);
|
||||
checkBBoxesConnect(bbox, bboxes);
|
||||
|
||||
bbox.add(0.1, 0.1);
|
||||
bboxes = RapiDDataUtils.reduceBBoxSize(bbox);
|
||||
Assert.assertEquals(4, bboxes.size());
|
||||
checkInBBox(bbox, bboxes);
|
||||
|
||||
bbox.add(1, 1);
|
||||
bboxes = RapiDDataUtils.reduceBBoxSize(bbox);
|
||||
Assert.assertEquals(144, bboxes.size());
|
||||
checkInBBox(bbox, bboxes);
|
||||
checkBBoxesConnect(bbox, bboxes);
|
||||
}
|
||||
|
||||
private static void checkInBBox(BBox bbox, Collection<BBox> bboxes) {
|
||||
|
@ -165,4 +165,43 @@ public class RapiDDataUtilsTest {
|
|||
Assert.assertTrue(bbox.bounds(tBBox));
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkBBoxesConnect(BBox originalBBox, Collection<BBox> bboxes) {
|
||||
for (BBox bbox1 : bboxes) {
|
||||
boolean bboxFoundConnections = false;
|
||||
for (BBox bbox2 : bboxes) {
|
||||
if (!bbox1.equals(bbox2)) {
|
||||
bboxFoundConnections = bboxCheckConnections(bbox1, bbox2);
|
||||
if (bboxFoundConnections) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!bboxFoundConnections) {
|
||||
bboxFoundConnections = bboxCheckConnections(bbox1, originalBBox);
|
||||
}
|
||||
Assert.assertTrue(bboxFoundConnections);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean bboxCheckConnections(BBox bbox1, BBox bbox2) {
|
||||
int shared = 0;
|
||||
for (LatLon bbox1Corner : getBBoxCorners(bbox1)) {
|
||||
for (LatLon bbox2Corner : getBBoxCorners(bbox2)) {
|
||||
if (bbox1Corner.equalsEpsilon(bbox2Corner)) {
|
||||
shared++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return shared >= 2;
|
||||
}
|
||||
|
||||
private static LatLon[] getBBoxCorners(BBox bbox) {
|
||||
LatLon[] returnLatLons = new LatLon[4];
|
||||
returnLatLons[0] = bbox.getTopLeft();
|
||||
returnLatLons[1] = new LatLon(bbox.getTopLeftLat(), bbox.getBottomRightLon());
|
||||
returnLatLons[2] = bbox.getBottomRight();
|
||||
returnLatLons[3] = new LatLon(bbox.getBottomRightLat(), bbox.getTopLeftLon());
|
||||
return returnLatLons;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,6 +108,21 @@ public class AddPrimitivesCommandTest {
|
|||
Assert.assertNull(way1.getDataSet());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelection() {
|
||||
final DataSet dataSet = new DataSet();
|
||||
final Way way1 = TestUtils.newWay("highway=secondary", new Node(new LatLon(0.1, 0)),
|
||||
new Node(new LatLon(0.1, -0.1)));
|
||||
AddPrimitivesCommand command = new AddPrimitivesCommand(dataSet, Collections.singleton(way1),
|
||||
Collections.singleton(way1));
|
||||
final Collection<OsmPrimitive> selection = dataSet.getAllSelected();
|
||||
Assert.assertNull(way1.getDataSet());
|
||||
|
||||
command.executeCommand();
|
||||
Assert.assertNotEquals(new TreeSet<>(selection), new TreeSet<>(dataSet.getAllSelected()));
|
||||
Assert.assertEquals(new TreeSet<>(Collections.singleton(way1)), dataSet.getAllSelected());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDescription() {
|
||||
Assert.assertNotNull(new AddPrimitivesCommand(new DataSet(), null, null).getDescriptionText());
|
||||
|
|
Ładowanie…
Reference in New Issue