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
Taylor Smock 2019-10-03 16:40:02 -06:00
rodzic 2fd298a24c
commit 89cc8fe53c
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 625F6A74A3E4311A
10 zmienionych plików z 130 dodań i 34 usunięć

Wyświetl plik

@ -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();

Wyświetl plik

@ -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;
}
}

Wyświetl plik

@ -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);
}

Wyświetl plik

@ -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);

Wyświetl plik

@ -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;
}

Wyświetl plik

@ -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()));
}
}
}

Wyświetl plik

@ -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) {

Wyświetl plik

@ -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());
}

Wyświetl plik

@ -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;
}
}

Wyświetl plik

@ -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());