Improve calculations for areas that have already been downloaded

Signed-off-by: Taylor Smock <tsmock@fb.com>
pull/1/head
Taylor Smock 2020-09-21 16:42:35 -06:00
rodzic 0441c11d4a
commit 1ffa7fcad3
15 zmienionych plików z 213 dodań i 256 usunięć

Wyświetl plik

@ -3,8 +3,10 @@ package org.openstreetmap.josm.plugins.mapwithai.backend;
import static org.openstreetmap.josm.tools.I18n.tr;
import java.awt.geom.Area;
import java.io.InputStream;
import java.net.SocketTimeoutException;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.ExecutionException;
@ -72,7 +74,8 @@ public class BoundingBoxMapWithAIDownloader extends BoundingBoxDownloader {
return url.replace("{bbox}", Double.toString(lon1) + ',' + lat1 + ',' + lon2 + ',' + lat2)
.replace("{xmin}", Double.toString(lon1)).replace("{ymin}", Double.toString(lat1))
.replace("{xmax}", Double.toString(lon2)).replace("{ymax}", Double.toString(lat2))
+ (crop ? "&crop_bbox=" + DetectTaskingManagerUtils.getTaskingManagerBBox().toStringCSV(",") : "");
+ (crop ? "&crop_bbox=" + DetectTaskingManagerUtils.getTaskingManagerBounds().toBBox().toStringCSV(",")
: "");
}
@Override
@ -119,7 +122,7 @@ public class BoundingBoxMapWithAIDownloader extends BoundingBoxDownloader {
}
// Just in case something happens, try again...
DataSet ds = new DataSet();
GetDataRunnable runnable = new GetDataRunnable(downloadArea.toBBox(), ds, NullProgressMonitor.INSTANCE);
GetDataRunnable runnable = new GetDataRunnable(downloadArea, ds, NullProgressMonitor.INSTANCE);
runnable.setMapWithAIInfo(info);
MainApplication.worker.execute(() -> {
try {
@ -143,9 +146,9 @@ public class BoundingBoxMapWithAIDownloader extends BoundingBoxDownloader {
* @return The dataset to send to the server
*/
private static DataSet getConflationData(Bounds bound) {
List<OsmDataLayer> layers = MainApplication
.getLayerManager().getLayersOfType(OsmDataLayer.class).stream().filter(l -> l.getDataSet()
.getDataSourceBounds().stream().anyMatch(b -> b.toBBox().bounds(bound.toBBox())))
Area area = DataSource.getDataSourceArea(Collections.singleton(new DataSource(bound, "")));
List<OsmDataLayer> layers = MainApplication.getLayerManager().getLayersOfType(OsmDataLayer.class).stream()
.filter(l -> l.getDataSet().getDataSourceBounds().stream().anyMatch(b -> area.contains(bound.asRect())))
.collect(Collectors.toList());
return layers.stream().max(Comparator.comparingInt(l -> l.getDataSet().allPrimitives().size()))
.map(OsmDataLayer::getDataSet).orElse(null);

Wyświetl plik

@ -19,8 +19,8 @@ import javax.json.JsonObject;
import javax.json.JsonValue;
import javax.json.stream.JsonParser;
import org.openstreetmap.josm.data.Bounds;
import org.openstreetmap.josm.data.coor.LatLon;
import org.openstreetmap.josm.data.osm.BBox;
import org.openstreetmap.josm.io.CachedFile;
import org.openstreetmap.josm.plugins.mapwithai.data.mapwithai.MapWithAIInfo;
import org.openstreetmap.josm.plugins.mapwithai.data.mapwithai.MapWithAILayerInfo;
@ -151,11 +151,11 @@ public class DataAvailability {
* @return A string that doesn't have quotes at the beginning or end
*/
public static String stripQuotes(String string) {
return string.replaceAll("(^\"|\"$)", EMPTY_STRING);
return string.replaceAll("((^\")|(\"$))", EMPTY_STRING);
}
/**
* Get the global i nstance that should be used to check for data availability
* Get the global instance that should be used to check for data availability
*
* @return the unique instance
*/
@ -168,19 +168,19 @@ public class DataAvailability {
}
/**
* Check if a bbox may have data
* Check if a bounds may have data
*
* @param bbox An area that may have data
* @return True if one of the corners of the {@code bbox} is in a country with
* @param bounds An area that may have data
* @return True if one of the corners of the {@code bounds} is in a country with
* available data.
*/
public boolean hasData(BBox bbox) {
public boolean hasData(Bounds bounds) {
final List<LatLon> corners = new ArrayList<>();
corners.add(bbox.getBottomRight());
corners.add(new LatLon(bbox.getBottomRightLat(), bbox.getTopLeftLon()));
corners.add(bbox.getTopLeft());
corners.add(new LatLon(bbox.getTopLeftLat(), bbox.getBottomRightLon()));
corners.add(bbox.getCenter());
corners.add(bounds.getMin());
corners.add(new LatLon(bounds.getMinLat(), bounds.getMaxLon()));
corners.add(bounds.getMax());
corners.add(new LatLon(bounds.getMaxLat(), bounds.getMinLon()));
corners.add(bounds.getCenter());
return corners.parallelStream().anyMatch(this::hasData);
}

Wyświetl plik

@ -12,7 +12,6 @@ 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;
@ -58,35 +57,39 @@ final class DetectTaskingManagerUtils {
}
/**
* Get the bbox from the tasking manager layer
* Get the bounds from the tasking manager layer
*
* @return A {@link BBox} made from a tasking manager layer, or one that is not
* valid.
* @return A {@link Bounds} made from a tasking manager layer, or one that is
* not valid.
*/
public static BBox getTaskingManagerBBox() {
final BBox returnBBox = new BBox();
public static Bounds getTaskingManagerBounds() {
Bounds returnBounds = new Bounds(0, 0, 0, 0);
final Layer layer = getTaskingManagerLayer();
if (layer instanceof GpxLayer) {
final GpxLayer gpxLayer = (GpxLayer) layer;
final Bounds realBounds = gpxLayer.data.recalculateBounds();
returnBBox.add(realBounds.toBBox());
if (returnBounds.isCollapsed()) {
returnBounds = realBounds;
} else {
returnBounds.extend(realBounds);
}
}
return returnBBox;
return returnBounds;
}
/**
* Create a GpxData that can be used to define a crop area
*
* @param bbox A bbox to crop data to
* @param bounds A bounds to crop data to
* @return A gpx layer that can be used to crop data from MapWithAI
*/
public static GpxData createTaskingManagerGpxData(BBox bbox) {
public static GpxData createTaskingManagerGpxData(Bounds bounds) {
final GpxData data = new GpxData();
final 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(new WayPoint(bounds.getMin()));
route.routePoints.add(new WayPoint(new LatLon(bounds.getMaxLat(), bounds.getMinLon())));
route.routePoints.add(new WayPoint(bounds.getMax()));
route.routePoints.add(new WayPoint(new LatLon(bounds.getMinLat(), bounds.getMaxLon())));
route.routePoints.add(route.routePoints.iterator().next());
route.routePoints.forEach(waypoint -> waypoint.setTime(0));
data.addRoute(route);

Wyświetl plik

@ -6,7 +6,6 @@ import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import org.openstreetmap.josm.data.Bounds;
import org.openstreetmap.josm.data.DataSource;
@ -44,11 +43,11 @@ public final class DownloadListener implements DataSourceListener, Destroyable {
return;
}
if (layer.downloadContinuous()) {
MapWithAIDataUtils.getMapWithAIData(layer, event.getAdded().stream().map(ev -> ev.bounds)
.map(Bounds::toBBox).collect(Collectors.toList()));
List<Bounds> bounds = DataSource.getDataSourceBounds(event.getSource().getDataSources());
bounds.removeIf(a -> layer.getDataSet().getDataSourceBounds().stream().map(Bounds::toBBox)
.anyMatch(b -> b.bboxIsFunctionallyEqual(a.toBBox(), BBOX_SIMILARITY_DEGREES)));
MapWithAIDataUtils.getMapWithAIData(layer, bounds);
}
}
}

Wyświetl plik

@ -53,7 +53,7 @@ import org.openstreetmap.josm.tools.Pair;
*/
public class GetDataRunnable extends RecursiveTask<DataSet> {
private static final long serialVersionUID = 258423685658089715L;
private final transient List<BBox> bbox;
private final transient List<Bounds> runnableBounds;
private final transient DataSet dataSet;
private final transient ProgressMonitor monitor;
private static final float DEGREE_BUFFER = 0.001f;
@ -88,7 +88,7 @@ public class GetDataRunnable extends RecursiveTask<DataSet> {
* @param dataSet The dataset to add the data to
* @param monitor A monitor to keep track of progress
*/
public GetDataRunnable(BBox bbox, DataSet dataSet, ProgressMonitor monitor) {
public GetDataRunnable(Bounds bbox, DataSet dataSet, ProgressMonitor monitor) {
this(Arrays.asList(bbox), dataSet, monitor);
}
@ -98,9 +98,9 @@ public class GetDataRunnable extends RecursiveTask<DataSet> {
* @param dataSet The dataset to add the data to
* @param monitor A monitor to keep track of progress
*/
public GetDataRunnable(List<BBox> bbox, DataSet dataSet, ProgressMonitor monitor) {
public GetDataRunnable(List<Bounds> bbox, DataSet dataSet, ProgressMonitor monitor) {
super();
this.bbox = bbox.stream().distinct().collect(Collectors.toList());
this.runnableBounds = bbox.stream().distinct().collect(Collectors.toList());
this.dataSet = dataSet;
this.monitor = Optional.ofNullable(monitor).orElse(NullProgressMonitor.INSTANCE);
}
@ -116,19 +116,19 @@ public class GetDataRunnable extends RecursiveTask<DataSet> {
@Override
public DataSet compute() {
final List<BBox> bboxes = maximumDimensions == null ? MapWithAIDataUtils.reduceBBoxSize(bbox)
: MapWithAIDataUtils.reduceBBoxSize(bbox, maximumDimensions);
monitor.beginTask(tr("Downloading {0} data ({1} total downloads)", MapWithAIPlugin.NAME, bboxes.size()),
bboxes.size() - 1);
final List<Bounds> bounds = maximumDimensions == null ? MapWithAIDataUtils.reduceBoundSize(runnableBounds)
: MapWithAIDataUtils.reduceBoundSize(runnableBounds, maximumDimensions);
monitor.beginTask(tr("Downloading {0} data ({1} total downloads)", MapWithAIPlugin.NAME, bounds.size()),
bounds.size() - 1);
if (!monitor.isCanceled()) {
if (bboxes.size() == MAX_NUMBER_OF_BBOXES_TO_PROCESS) {
final DataSet temporaryDataSet = getDataReal(bboxes.get(0), monitor);
if (bounds.size() == MAX_NUMBER_OF_BBOXES_TO_PROCESS) {
final DataSet temporaryDataSet = getDataReal(bounds.get(0), monitor);
synchronized (GetDataRunnable.class) {
dataSet.mergeFrom(temporaryDataSet);
}
} else {
final Collection<GetDataRunnable> tasks = bboxes.parallelStream()
.map(tBbox -> new GetDataRunnable(tBbox, dataSet, monitor.createSubTaskMonitor(0, true)))
final Collection<GetDataRunnable> tasks = bounds.parallelStream()
.map(bound -> new GetDataRunnable(bound, dataSet, monitor.createSubTaskMonitor(0, true)))
.collect(Collectors.toList());
tasks.forEach(GetDataRunnable::fork);
tasks.parallelStream().forEach(runnable -> {
@ -139,8 +139,8 @@ public class GetDataRunnable extends RecursiveTask<DataSet> {
}
// This can technically be included in the above block, but it is here so that
// cancellation is a little faster
if (!monitor.isCanceled() && !bboxes.isEmpty()) {
cleanup(dataSet, new Bounds(bboxes.get(0).getBottomRight(), bboxes.get(0).getTopLeft()), info);
if (!monitor.isCanceled() && !bounds.isEmpty()) {
cleanup(dataSet, bounds.get(0), info);
}
monitor.finishTask();
return dataSet;
@ -391,8 +391,7 @@ public class GetDataRunnable extends RecursiveTask<DataSet> {
}
private static boolean distanceCheck(Node nearNode, Node node, Double distance) {
return nearNode == null || node == null ? false
: nearNode.getCoor().greatCircleDistance(node.getCoor()) < distance;
return !(nearNode == null || node == null) && nearNode.getCoor().greatCircleDistance(node.getCoor()) < distance;
}
private static boolean keyCheck(Node nearNode, Node node) {
@ -516,19 +515,17 @@ public class GetDataRunnable extends RecursiveTask<DataSet> {
/**
* Actually get the data
*
* @param bbox The bbox to get the data from
* @param bounds The bounds to get the data from
* @param monitor Use to determine if the operation has been cancelled
* @return A dataset with the data from the bbox
* @return A dataset with the data from the bounds
*/
private static DataSet getDataReal(BBox bbox, ProgressMonitor monitor) {
private static DataSet getDataReal(Bounds bounds, ProgressMonitor monitor) {
final DataSet dataSet = new DataSet();
dataSet.setUploadPolicy(UploadPolicy.DISCOURAGED);
new ArrayList<>(MapWithAILayerInfo.getInstance().getLayers()).parallelStream().forEach(map -> {
try {
Bounds bound = new Bounds(bbox.getBottomRight());
bound.extend(bbox.getTopLeft());
BoundingBoxMapWithAIDownloader downloader = new BoundingBoxMapWithAIDownloader(bound, map,
BoundingBoxMapWithAIDownloader downloader = new BoundingBoxMapWithAIDownloader(bounds, map,
DetectTaskingManagerUtils.hasTaskingManagerLayer());
dataSet.mergeFrom(downloader.parseOsm(monitor));
} catch (OsmTransferException e1) {

Wyświetl plik

@ -4,6 +4,7 @@ package org.openstreetmap.josm.plugins.mapwithai.backend;
import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
import static org.openstreetmap.josm.tools.I18n.tr;
import java.awt.geom.Area;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@ -19,7 +20,6 @@ import javax.swing.JOptionPane;
import org.openstreetmap.josm.data.Bounds;
import org.openstreetmap.josm.data.UndoRedoHandler;
import org.openstreetmap.josm.data.coor.LatLon;
import org.openstreetmap.josm.data.osm.BBox;
import org.openstreetmap.josm.data.osm.DataSet;
import org.openstreetmap.josm.data.osm.Node;
import org.openstreetmap.josm.data.osm.OsmPrimitive;
@ -92,54 +92,53 @@ public final class MapWithAIDataUtils {
}
/**
* Get a dataset from the API servers using a bbox
* Get a dataset from the API servers using a bounds
*
* @param bbox The bbox from which to get data
* @return A DataSet with data inside the bbox
* @param bounds The bounds from which to get data
* @return A DataSet with data inside the bounds
*/
public static DataSet getData(BBox bbox) {
return getData(Arrays.asList(bbox), MAXIMUM_SIDE_DIMENSIONS);
public static DataSet getData(Bounds bounds) {
return getData(Arrays.asList(bounds), MAXIMUM_SIDE_DIMENSIONS);
}
/**
* Get a dataset from the API servers using a bbox
* Get a dataset from the API servers using a bounds
*
* @param bbox The bbox from which to get data
* @param bounds The bounds from which to get data
* @param maximumDimensions The maximum dimensions to try to download at any one
* time
* @return A DataSet with data inside the bbox
* @return A DataSet with data inside the bounds
*/
public static DataSet getData(BBox bbox, int maximumDimensions) {
return getData(Arrays.asList(bbox), maximumDimensions);
public static DataSet getData(Bounds bounds, int maximumDimensions) {
return getData(Arrays.asList(bounds), maximumDimensions);
}
/**
*
* Get a dataset from the API servers using a list bboxes
* Get a dataset from the API servers using a list of bounds
*
* @param bbox The bboxes from which to get data
* @return A DataSet with data inside the bboxes
* @param bounds The bounds from which to get data
* @return A DataSet with data inside the bounds
*/
public static DataSet getData(List<BBox> bbox) {
return getData(bbox, MAXIMUM_SIDE_DIMENSIONS);
public static DataSet getData(List<Bounds> bounds) {
return getData(bounds, MAXIMUM_SIDE_DIMENSIONS);
}
/**
* Get a dataset from the API servers using a list bboxes
* Get a dataset from the API servers using a list bounds
*
* @param bbox The bboxes from which to get data
* @param bounds The bounds from which to get data
* @param maximumDimensions The maximum dimensions to try to download at any one
* time
* @return A DataSet with data inside the bboxes
* @return A DataSet with data inside the bounds
*/
public static DataSet getData(List<BBox> bbox, int maximumDimensions) {
public static DataSet getData(List<Bounds> bounds, int maximumDimensions) {
final DataSet dataSet = new DataSet();
final List<BBox> realBBoxes = bbox.stream().filter(BBox::isValid).distinct().collect(Collectors.toList());
final List<Bounds> realBounds = realBBoxes.stream()
.flatMap(tBBox -> MapWithAIDataUtils.reduceBBoxSize(tBBox, maximumDimensions).stream())
.map(MapWithAIDataUtils::bboxToBounds).collect(Collectors.toList());
final List<Bounds> realBounds = bounds.stream().filter(b -> !b.isOutOfTheWorld()).distinct()
.flatMap(bound -> MapWithAIDataUtils.reduceBoundSize(bound, maximumDimensions).stream())
.collect(Collectors.toList());
if (!MapWithAIPreferenceHelper.getMapWithAIUrl().isEmpty()) {
if ((realBBoxes.size() < TOO_MANY_BBOXES) || confirmBigDownload(realBBoxes)) {
if ((bounds.size() < TOO_MANY_BBOXES) || confirmBigDownload(realBounds)) {
final PleaseWaitProgressMonitor monitor = new PleaseWaitProgressMonitor();
monitor.beginTask(tr("Downloading {0} Data", MapWithAIPlugin.NAME), realBounds.size());
realBounds.parallelStream()
@ -155,7 +154,7 @@ public final class MapWithAIDataUtils {
} catch (OsmTransferException e) {
Logging.error(e);
if (maximumDimensions > MAXIMUM_SIDE_DIMENSIONS / 10) {
dataSet.mergeFrom(getData(bound.toBBox(), maximumDimensions / 2));
dataSet.mergeFrom(getData(bound, maximumDimensions / 2));
}
}
}));
@ -180,18 +179,18 @@ public final class MapWithAIDataUtils {
return dataSet;
}
private static boolean confirmBigDownload(List<BBox> realBBoxes) {
ConfirmBigDownload confirmation = new ConfirmBigDownload(realBBoxes);
private static boolean confirmBigDownload(List<Bounds> realBounds) {
ConfirmBigDownload confirmation = new ConfirmBigDownload(realBounds);
GuiHelper.runInEDTAndWait(confirmation);
return confirmation.confirmed();
}
private static class ConfirmBigDownload implements Runnable {
Boolean bool;
List<BBox> realBBoxes;
List<?> realBounds;
public ConfirmBigDownload(List<BBox> realBBoxes) {
this.realBBoxes = realBBoxes;
public ConfirmBigDownload(List<?> realBounds) {
this.realBounds = realBounds;
}
@Override
@ -199,7 +198,7 @@ public final class MapWithAIDataUtils {
bool = ConditionalOptionPaneUtil.showConfirmationDialog(MapWithAIPlugin.NAME.concat(".alwaysdownload"),
null,
tr("You are going to make {0} requests to the MapWithAI server. This may take some time. <br /> Continue?",
realBBoxes.size()),
realBounds.size()),
null, JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE, JOptionPane.YES_OPTION);
}
@ -208,12 +207,6 @@ public final class MapWithAIDataUtils {
}
}
private static Bounds bboxToBounds(BBox bbox) {
Bounds bound = new Bounds(bbox.getBottomRight());
bound.extend(bbox.getTopLeft());
return bound;
}
/**
* Get a ForkJoinPool that is safe for use in Webstart
*
@ -228,18 +221,18 @@ public final class MapWithAIDataUtils {
}
/**
* Get the height of a bbox
* Get the height of a bounds
*
* @param bbox The bbox with lat/lon information
* @param bounds The bounds with lat/lon information
* @return The height in meters (see {@link LatLon#greatCircleDistance})
*/
public static double getHeight(BBox bbox) {
final LatLon bottomRight = bbox.getBottomRight();
final LatLon topLeft = bbox.getTopLeft();
final double minx = topLeft.getX();
final double miny = bottomRight.getY();
final LatLon bottomLeft = new LatLon(miny, minx);
return topLeft.greatCircleDistance(bottomLeft);
public static double getHeight(Bounds bounds) {
final LatLon topRight = bounds.getMax();
final LatLon bottomLeft = bounds.getMin();
final double minx = bottomLeft.getX();
final double maxY = topRight.getY();
final LatLon topLeft = new LatLon(maxY, minx);
return bottomLeft.greatCircleDistance(topLeft);
}
/**
@ -295,36 +288,33 @@ public final class MapWithAIDataUtils {
* @return true if data was downloaded
*/
public static boolean getMapWithAIData(MapWithAILayer layer, OsmDataLayer osmLayer) {
return getMapWithAIData(layer,
osmLayer.getDataSet().getDataSourceBounds().stream().map(Bounds::toBBox).collect(Collectors.toList()));
return getMapWithAIData(layer, osmLayer.getDataSet().getDataSourceBounds());
}
/**
* Get the data for MapWithAI
*
* @param layer A pre-existing {@link MapWithAILayer}
* @param bboxes The bboxes to get the data in
* @param bounds The bounds to get the data in
* @return true if data was downloaded
*/
public static boolean getMapWithAIData(MapWithAILayer layer, BBox... bboxes) {
return getMapWithAIData(layer, Arrays.asList(bboxes));
public static boolean getMapWithAIData(MapWithAILayer layer, Bounds... bounds) {
return getMapWithAIData(layer, Arrays.asList(bounds));
}
/**
* Get the data for MapWithAI
*
* @param layer A pre-existing {@link MapWithAILayer}
* @param bboxes The bboxes to get the data in
* @param bounds The bounds to get the data in
* @return true if data was downloaded
*/
public static boolean getMapWithAIData(MapWithAILayer layer, Collection<BBox> bboxes) {
public static boolean getMapWithAIData(MapWithAILayer layer, Collection<Bounds> bounds) {
final DataSet mapWithAISet = layer.getDataSet();
final List<BBox> mapWithAIBounds = mapWithAISet.getDataSourceBounds().stream().map(Bounds::toBBox)
.collect(Collectors.toList());
final List<BBox> editSetBBoxes = bboxes.stream()
.filter(bbox -> mapWithAIBounds.stream().noneMatch(tBBox -> tBBox.bounds(bbox)))
.collect(Collectors.toList());
final List<BBox> toDownload = reduceBBox(mapWithAIBounds, editSetBBoxes);
Area area = mapWithAISet.getDataSourceArea();
final List<Bounds> toDownload = area == null ? new ArrayList<>(bounds)
: bounds.stream().filter(Objects::nonNull).filter(tBounds -> !area.contains(tBounds.asRect()))
.collect(Collectors.toList());
if (!toDownload.isEmpty()) {
getForkJoinPool().execute(() -> {
final DataSet newData = getData(toDownload);
@ -336,134 +326,87 @@ public final class MapWithAIDataUtils {
} finally {
lock.unlock();
}
toDownload.stream().map(MapWithAIDataUtils::bboxToBounds).forEach(layer::onPostDownloadFromServer);
toDownload.stream().forEach(layer::onPostDownloadFromServer);
});
}
return !toDownload.isEmpty();
}
private static List<BBox> reduceBBox(List<BBox> alreadyDownloaded, List<BBox> wantToDownload) {
final List<BBox> alreadyDownloadedReduced = new ArrayList<>(alreadyDownloaded);
int aDRSize = -1;
do {
aDRSize = alreadyDownloadedReduced.size();
for (int i = 0; i < alreadyDownloadedReduced.size(); i++) {
final BBox bbox1 = alreadyDownloadedReduced.get(i);
for (int j = 0; j < alreadyDownloadedReduced.size(); j++) {
final BBox bbox2 = alreadyDownloadedReduced.get(j);
if (!bbox1.bboxIsFunctionallyEqual(bbox2, null) && bboxesShareSide(bbox1, bbox2)) {
bbox1.add(bbox2);
alreadyDownloadedReduced.remove(bbox2);
}
}
}
} while (aDRSize != alreadyDownloadedReduced.size());
return removeDuplicateBBoxes(wantToDownload, alreadyDownloadedReduced);
}
private static List<BBox> removeDuplicateBBoxes(List<BBox> wantToDownload, List<BBox> alreadyDownloaded) {
for (final BBox bbox : wantToDownload) {
for (final BBox downloaded : alreadyDownloaded) {
if (downloaded.bboxIsFunctionallyEqual(downloaded, null)) {
Logging.debug("{0}: It looks like we already downloaded {1}", MapWithAIPlugin.NAME,
bbox.toStringCSV(","));
}
}
}
return wantToDownload.parallelStream()
.filter(bbox1 -> alreadyDownloaded.parallelStream()
.noneMatch(bbox2 -> bbox2.bboxIsFunctionallyEqual(bbox1, 0.000_02)))
.collect(Collectors.toList());
}
private static boolean bboxesShareSide(BBox bbox1, BBox bbox2) {
final List<Double> bbox1Lons = Arrays.asList(bbox1.getTopLeftLon(), bbox1.getBottomRightLon());
final List<Double> bbox1Lats = Arrays.asList(bbox1.getTopLeftLat(), bbox1.getBottomRightLat());
final List<Double> bbox2Lons = Arrays.asList(bbox2.getTopLeftLon(), bbox2.getBottomRightLon());
final List<Double> bbox2Lats = Arrays.asList(bbox2.getTopLeftLat(), bbox2.getBottomRightLat());
final Long lonDupeCount = bbox1Lons.parallelStream()
.filter(lon -> bbox2Lons.parallelStream().anyMatch(lon2 -> Double.compare(lon, lon2) == 0)).count();
final Long latDupeCount = bbox1Lats.parallelStream()
.filter(lat -> bbox2Lats.parallelStream().anyMatch(lat2 -> Double.compare(lat, lat2) == 0)).count();
return (lonDupeCount + latDupeCount) > 1;
}
/**
* Get the width of a bbox
* Get the width of a bounds
*
* @param bbox The bbox to get the width of
* @param bounds The bounds to get the width of
* @return See {@link LatLon#greatCircleDistance}
*/
public static double getWidth(BBox bbox) {
public static double getWidth(Bounds bounds) {
// Lat is y, Lon is x
final LatLon bottomRight = bbox.getBottomRight();
final LatLon topLeft = bbox.getTopLeft();
final double maxx = bottomRight.getX();
final double minx = topLeft.getX();
final double miny = bottomRight.getY();
final double maxy = topLeft.getY();
final LatLon bottomLeft = new LatLon(miny, minx);
final LatLon topRight = new LatLon(maxy, maxx);
return Math.max(bottomRight.greatCircleDistance(bottomLeft), topRight.greatCircleDistance(topLeft));
final LatLon bottomLeft = bounds.getMin();
final LatLon topRight = bounds.getMax();
final double minx = bottomLeft.getX();
final double maxx = topRight.getX();
final double miny = bottomLeft.getY();
final double maxy = topRight.getY();
final LatLon bottomRight = new LatLon(miny, maxx);
final LatLon topLeft = new LatLon(maxy, minx);
return Math.max(bottomLeft.greatCircleDistance(bottomRight), topLeft.greatCircleDistance(topRight));
}
/**
* Reduce a bbox to the specified dimensions, returning a list of bboxes.
* Reduce a bound to the specified dimensions, returning a list of bounds.
*
* @param bbox The bbox to reduce to a set maximum dimension
* @param maximumDimensions The maximum side dimensions of the bbox
* @return A list of BBoxes that have a dimension no more than
* @param bound The bound to reduce to a set maximum dimension
* @param maximumDimensions The maximum side dimensions of the bound
* @return A list of Bounds that have a dimension no more than
* {@code maximumDimensions}
*/
public static List<BBox> reduceBBoxSize(BBox bbox, int maximumDimensions) {
final List<BBox> returnBounds = new ArrayList<>();
final double width = getWidth(bbox);
final double height = getHeight(bbox);
public static List<Bounds> reduceBoundSize(Bounds bound, int maximumDimensions) {
final List<Bounds> returnBounds = new ArrayList<>();
final double width = getWidth(bound);
final double height = getHeight(bound);
final Double widthDivisions = width / maximumDimensions;
final Double heightDivisions = height / maximumDimensions;
final int widthSplits = widthDivisions.intValue() + ((widthDivisions - widthDivisions.intValue()) > 0 ? 1 : 0);
final int heightSplits = heightDivisions.intValue()
+ ((heightDivisions - heightDivisions.intValue()) > 0 ? 1 : 0);
final double newMinWidths = Math.abs(bbox.getTopLeftLon() - bbox.getBottomRightLon()) / widthSplits;
final double newMinHeights = Math.abs(bbox.getBottomRightLat() - bbox.getTopLeftLat()) / heightSplits;
final double newMinWidths = Math.abs(bound.getMaxLon() - bound.getMinLon()) / widthSplits;
final double newMinHeights = Math.abs(bound.getMaxLat() - bound.getMinLat()) / heightSplits;
final double minx = bbox.getTopLeftLon();
final double miny = bbox.getBottomRightLat();
final double minx = bound.getMinLon();
final double miny = bound.getMinLat();
for (int x = 1; x <= widthSplits; x++) {
for (int y = 1; y <= heightSplits; y++) {
final LatLon lowerLeft = new LatLon(miny + (newMinHeights * (y - 1)), minx + (newMinWidths * (x - 1)));
final LatLon upperRight = new LatLon(miny + (newMinHeights * y), minx + (newMinWidths * x));
returnBounds.add(new BBox(lowerLeft, upperRight));
returnBounds.add(new Bounds(lowerLeft, upperRight));
}
}
return returnBounds.stream().distinct().collect(Collectors.toList());
}
/**
* Reduce a list of bboxes to {@link MapWithAIDataUtils#MAXIMUM_SIDE_DIMENSIONS}
* Reduce a list of bounds to {@link MapWithAIDataUtils#MAXIMUM_SIDE_DIMENSIONS}
*
* @param bboxes The bboxes to reduce to a set maximum dimension
* @return A list of BBoxes that have a dimension no more than
* @param bounds The bounds to reduce to a set maximum dimension
* @return A list of Bounds that have a dimension no more than
* {@link MapWithAIDataUtils#MAXIMUM_SIDE_DIMENSIONS}
*/
public static List<BBox> reduceBBoxSize(List<BBox> bboxes) {
return reduceBBoxSize(bboxes, MAXIMUM_SIDE_DIMENSIONS);
public static List<Bounds> reduceBoundSize(List<Bounds> bounds) {
return reduceBoundSize(bounds, MAXIMUM_SIDE_DIMENSIONS);
}
/**
* Reduce a list of bboxes to a specified size
* Reduce a list of bounds to a specified size
*
* @param bboxes The bboxes to reduce to a set maximum dimension
* @param bounds The bounds to reduce to a set maximum dimension
* @param maximumDimensions The maximum width/height dimensions
* @return A list of BBoxes that have a dimension no more than the
* @return A list of Bounds that have a dimension no more than the
* {@code maximumDimensions}
*/
public static List<BBox> reduceBBoxSize(List<BBox> bboxes, int maximumDimensions) {
final List<BBox> returnBBoxes = new ArrayList<>();
bboxes.forEach(bbox -> returnBBoxes.addAll(reduceBBoxSize(bbox, maximumDimensions)));
return returnBBoxes.stream().distinct().collect(Collectors.toList());
public static List<Bounds> reduceBoundSize(List<Bounds> bounds, int maximumDimensions) {
final List<Bounds> returnBounds = new ArrayList<>();
bounds.forEach(bound -> returnBounds.addAll(reduceBoundSize(bound, maximumDimensions)));
return returnBounds.stream().distinct().collect(Collectors.toList());
}
/**

Wyświetl plik

@ -5,8 +5,9 @@ import static org.openstreetmap.josm.tools.I18n.tr;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.stream.Stream;
import org.openstreetmap.josm.data.osm.BBox;
import org.openstreetmap.josm.data.Bounds;
import org.openstreetmap.josm.gui.MainApplication;
import org.openstreetmap.josm.gui.layer.GpxLayer;
import org.openstreetmap.josm.gui.layer.OsmDataLayer;
@ -20,8 +21,8 @@ public class MapWithAIRemoteControl extends RequestHandler.RawURLParseRequestHan
private static final PermissionPrefWithDefault PERMISSION_PREF_WITH_DEFAULT = new PermissionPrefWithDefault(
MapWithAIPlugin.NAME.concat(".remote_control"), true, tr("MapWithAI"));
private BBox download;
private BBox crop;
private Bounds download;
private Bounds crop;
private Integer maxObj;
private Boolean switchLayer;
private String url;
@ -43,10 +44,10 @@ public class MapWithAIRemoteControl extends RequestHandler.RawURLParseRequestHan
if (args != null) {
try {
if (args.containsKey(BBOX)) {
download = parseBBox(args.get(BBOX));
download = parseBounds(args.get(BBOX));
}
if (args.containsKey(CROP_BBOX)) {
crop = parseBBox(args.get(CROP_BBOX));
crop = parseBounds(args.get(CROP_BBOX));
}
if (args.containsKey(MAX_OBJ)) {
maxObj = Integer.parseInt(args.get(MAX_OBJ));
@ -70,24 +71,32 @@ public class MapWithAIRemoteControl extends RequestHandler.RawURLParseRequestHan
}
}
private static BBox parseBBox(String coordinates) throws RequestHandlerBadRequestException {
final String[] coords = coordinates.split(",", -1);
final BBox tBBox = new BBox();
if (coords.length >= 4 && coords.length % 2 == 0) {
for (int i = 0; i < coords.length / 2; i++) {
tBBox.add(Double.parseDouble(coords[2 * i]), Double.parseDouble(coords[2 * i + 1]));
}
}
if (!tBBox.isInWorld()) {
/**
* Parse a string of coordinates into bounds
*
* @param coordinates The coordinates to parse
* @return The new Bounds
* @throws RequestHandlerBadRequestException If there was something wrong with
* the coordinates
*/
private static Bounds parseBounds(String coordinates) throws RequestHandlerBadRequestException {
final Double[] coords = Stream.of(coordinates.split(",", -1)).map(Double::parseDouble).toArray(Double[]::new);
// min lat, min lon, max lat, max lon
final double minLat = Math.min(coords[1], coords[3]);
final double maxLat = Math.max(coords[1], coords[3]);
final double maxLon = Math.max(coords[0], coords[2]);
final double minLon = Math.min(coords[0], coords[2]);
final Bounds tBounds = new Bounds(minLat, minLon, maxLat, maxLon);
if (tBounds.isOutOfTheWorld() || tBounds.isCollapsed()) {
throw new RequestHandlerBadRequestException(
tr("Bad bbox: {0} (converted to {1})", coordinates, tBBox.toString()));
tr("Bad bbox: {0} (converted to {1})", coordinates, tBounds.toString()));
}
return tBBox;
return tBounds;
}
@Override
protected void handleRequest() throws RequestHandlerErrorException, RequestHandlerBadRequestException {
if (crop != null && crop.isInWorld()) {
if (crop != null && crop.toBBox().isInWorld()) {
MainApplication.getLayerManager()
.addLayer(new GpxLayer(DetectTaskingManagerUtils.createTaskingManagerGpxData(crop),
DetectTaskingManagerUtils.MAPWITHAI_CROP_AREA));
@ -108,12 +117,12 @@ public class MapWithAIRemoteControl extends RequestHandler.RawURLParseRequestHan
layer.setSwitchLayers(switchLayer);
}
if (download != null && download.isInWorld()) {
if (download != null && download.toBBox().isInWorld()) {
MapWithAIDataUtils.getMapWithAIData(layer, download);
} else if (MainApplication.getLayerManager().getLayersOfType(OsmDataLayer.class).stream()
.anyMatch(tLayer -> !(tLayer instanceof MapWithAILayer))) {
MapWithAIDataUtils.getMapWithAIData(layer);
} else if (crop != null && crop.isInWorld()) {
} else if (crop != null && crop.toBBox().isInWorld()) {
MapWithAIDataUtils.getMapWithAIData(layer, crop);
}
}
@ -129,10 +138,10 @@ public class MapWithAIRemoteControl extends RequestHandler.RawURLParseRequestHan
}
sb.append(tr("automatically switch layers.")).append(br);
if (download != null) {
sb.append(tr("We will download data in ")).append(download.toStringCSV(",")).append(br);
sb.append(tr("We will download data in ")).append(download.toBBox().toStringCSV(",")).append(br);
}
if (crop != null) {
sb.append(tr("We will crop the data to ")).append(crop.toStringCSV(",")).append(br);
sb.append(tr("We will crop the data to ")).append(crop.toBBox().toStringCSV(",")).append(br);
}
sb.append(tr("There is a maximum addition of {0} objects at one time", maxObj));
return sb.toString();

Wyświetl plik

@ -35,7 +35,8 @@ public class MapWithAIUploadHook implements UploadHook, Destroyable {
sb.append(";maxadd=").append(MapWithAIPreferenceHelper.getMaximumAddition());
}
if (DetectTaskingManagerUtils.hasTaskingManagerLayer()) {
sb.append(";task=").append(DetectTaskingManagerUtils.getTaskingManagerBBox().toStringCSV(","));
sb.append(";task=")
.append(DetectTaskingManagerUtils.getTaskingManagerBounds().toBBox().toStringCSV(","));
}
if (!MapWithAIPreferenceHelper.getMapWithAIUrl().isEmpty()) {
sb.append(";url_ids=")

Wyświetl plik

@ -9,6 +9,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.Rule;
import org.junit.Test;
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.WayPoint;
@ -49,18 +50,18 @@ public class DetectTaskingManagerUtilsTest {
@Test
public void testGetTaskingManagerBounds() {
assertFalse(DetectTaskingManagerUtils.getTaskingManagerBBox().isInWorld(), "No TM layer exists yet");
assertTrue(DetectTaskingManagerUtils.getTaskingManagerBounds().isCollapsed(), "No TM layer exists yet");
final GpxLayer layer = new GpxLayer(new GpxData(), LAYER_NAME);
layer.data.addWaypoint(new WayPoint(new LatLon(0, 0)));
MainApplication.getLayerManager().addLayer(layer);
assertEquals(0, DetectTaskingManagerUtils.getTaskingManagerBBox().height(), 0.000001,
assertEquals(0, DetectTaskingManagerUtils.getTaskingManagerBounds().toBBox().height(), 0.000001,
"The TM layer only has one point");
assertEquals(0, DetectTaskingManagerUtils.getTaskingManagerBBox().width(), 0.000001,
assertEquals(0, DetectTaskingManagerUtils.getTaskingManagerBounds().toBBox().width(), 0.000001,
"The TM layer only has one point");
layer.data.addWaypoint(new WayPoint(new LatLon(1, 1)));
final BBox bbox = DetectTaskingManagerUtils.getTaskingManagerBBox();
final BBox bbox = DetectTaskingManagerUtils.getTaskingManagerBounds().toBBox();
assertTrue(bbox.isInWorld(), "A TM layer exists");
assertTrue(bbox.getBottomRight().equalsEpsilon(new LatLon(0, 1)), "The bottom right should be at (0, 1)");
assertTrue(bbox.getTopLeft().equalsEpsilon(new LatLon(1, 0)), "The top left should be at (1, 0)");
@ -70,12 +71,13 @@ public class DetectTaskingManagerUtilsTest {
public void testCreateTaskingManagerGpxBounds() {
assertFalse(DetectTaskingManagerUtils.hasTaskingManagerLayer(), "No TM layer exists yet");
final BBox bbox = new BBox(0, 0, 1, 1);
final Bounds bounds = new Bounds(0, 0, 1, 1);
MainApplication.getLayerManager()
.addLayer(new GpxLayer(DetectTaskingManagerUtils.createTaskingManagerGpxData(bbox),
.addLayer(new GpxLayer(DetectTaskingManagerUtils.createTaskingManagerGpxData(bounds),
DetectTaskingManagerUtils.MAPWITHAI_CROP_AREA));
assertTrue(DetectTaskingManagerUtils.hasTaskingManagerLayer(), "A TM layer exists");
assertTrue(DetectTaskingManagerUtils.getTaskingManagerBBox().bounds(bbox), "The TM layer should bound itself");
assertTrue(DetectTaskingManagerUtils.getTaskingManagerBounds().toBBox().bounds(bounds.toBBox()),
"The TM layer should bound itself");
}
}

Wyświetl plik

@ -18,8 +18,8 @@ import java.util.Map;
import org.junit.Rule;
import org.junit.Test;
import org.openstreetmap.josm.TestUtils;
import org.openstreetmap.josm.data.Bounds;
import org.openstreetmap.josm.data.coor.LatLon;
import org.openstreetmap.josm.data.osm.BBox;
import org.openstreetmap.josm.data.osm.DataSet;
import org.openstreetmap.josm.data.osm.Node;
import org.openstreetmap.josm.data.osm.Way;
@ -103,7 +103,7 @@ public class GetDataRunnableTest {
public void testRegressionTicket46() {
DataSet ds = new DataSet();
GetDataRunnable getData = new GetDataRunnable(
Arrays.asList(new BBox(-5.7400005, 34.4524384, -5.6686014, 34.5513153)), ds, null);
Arrays.asList(new Bounds(34.4524384, -5.7400005, 34.5513153, -5.6686014)), ds, null);
getData.setMaximumDimensions(5_000);
getData.fork().join();
assertNotNull(ds);

Wyświetl plik

@ -13,8 +13,8 @@ import org.awaitility.Durations;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.openstreetmap.josm.data.Bounds;
import org.openstreetmap.josm.data.coor.LatLon;
import org.openstreetmap.josm.data.osm.BBox;
import org.openstreetmap.josm.plugins.mapwithai.data.mapwithai.MapWithAILayerInfo;
import org.openstreetmap.josm.plugins.mapwithai.testutils.MapWithAITestRules;
import org.openstreetmap.josm.testutils.JOSMTestRules;
@ -38,8 +38,8 @@ public class MapWithAIAvailabilityTest {
@Test
public void testHasDataBBox() {
assertFalse(instance.hasData(new BBox(0, 0, 0.1, 0.1)), "There shouldn't be data in the ocean");
assertTrue(instance.hasData(new BBox(-99.9, 39.9, 100.1, 40.1)), "There should be data in the US");
assertFalse(instance.hasData(new Bounds(0, 0, 0.1, 0.1)), "There shouldn't be data in the ocean");
assertTrue(instance.hasData(new Bounds(39.9, -99.9, 40.1, 100.1)), "There should be data in the US");
}
@Test

Wyświetl plik

@ -50,7 +50,7 @@ public class MapWithAIDataUtilsTest {
*/
@Test
public void testGetData() {
final BBox testBBox = getTestBBox();
final Bounds testBBox = getTestBounds();
final DataSet ds = new DataSet(MapWithAIDataUtils.getData(testBBox));
assertEquals(1, ds.getWays().size(), "There should only be one way in the testBBox");
}
@ -60,9 +60,9 @@ public class MapWithAIDataUtilsTest {
*/
@Test
public void testGetDataMultiple() {
final BBox testBBox = getTestBBox();
final BBox testBBox2 = new BBox(-108.4495519, 39.095376, -108.4422314, 39.0987811);
final DataSet ds = new DataSet(MapWithAIDataUtils.getData(Arrays.asList(testBBox, testBBox2)));
final Bounds testBounds1 = getTestBounds();
final Bounds testBounds2 = new Bounds(39.095376, -108.4495519, 39.0987811, -108.4422314);
final DataSet ds = new DataSet(MapWithAIDataUtils.getData(Arrays.asList(testBounds1, testBounds2)));
int expectedBounds = 2;
assertEquals(expectedBounds, ds.getDataSourceBounds().size(), "There should be two data sources");
}
@ -73,14 +73,14 @@ public class MapWithAIDataUtilsTest {
*/
@Test
public void testGetDataCropped() {
final BBox testBBox = getTestBBox();
final Bounds testBounds = getTestBounds();
final GpxData gpxData = new GpxData();
gpxData.addWaypoint(new WayPoint(new LatLon(39.0735205, -108.5711561)));
gpxData.addWaypoint(new WayPoint(new LatLon(39.0736682, -108.5708568)));
final GpxLayer gpx = new GpxLayer(gpxData, DetectTaskingManagerUtils.MAPWITHAI_CROP_AREA);
final DataSet originalData = MapWithAIDataUtils.getData(testBBox);
final DataSet originalData = MapWithAIDataUtils.getData(testBounds);
MainApplication.getLayerManager().addLayer(gpx);
final DataSet ds = MapWithAIDataUtils.getData(testBBox);
final DataSet ds = MapWithAIDataUtils.getData(testBounds);
assertEquals(1, ds.getWays().size(), "There should only be one way in the cropped testBBox");
assertEquals(3, ds.getNodes().size(), "There should be three nodes in the cropped testBBox");
assertEquals(1, originalData.getWays().size(), "There should be one way in the testBBox");
@ -153,14 +153,15 @@ public class MapWithAIDataUtilsTest {
@Test
public void testSplitBounds() {
final BBox bbox = new BBox(0, 0, 0.0001, 0.0001);
final Bounds bounds = new Bounds(0, 0, 0.0001, 0.0001);
for (Double i : Arrays.asList(0.0001, 0.001, 0.01, 0.1)) {
bbox.add(i, i);
List<BBox> bboxes = MapWithAIDataUtils.reduceBBoxSize(bbox, 5_000);
assertEquals(getExpectedNumberOfBBoxes(bbox, 5_000), bboxes.size(),
bounds.extend(i, i);
List<BBox> bboxes = MapWithAIDataUtils.reduceBoundSize(bounds, 5_000).stream().map(Bounds::toBBox)
.collect(Collectors.toList());
assertEquals(getExpectedNumberOfBBoxes(bounds, 5_000), bboxes.size(),
"The bbox should be appropriately reduced");
checkInBBox(bbox, bboxes);
checkBBoxesConnect(bbox, bboxes);
checkInBBox(bounds.toBBox(), bboxes);
checkBBoxesConnect(bounds.toBBox(), bboxes);
}
}
@ -176,7 +177,7 @@ public class MapWithAIDataUtilsTest {
.collect(Collectors.toList()).isEmpty());
}
private static int getExpectedNumberOfBBoxes(BBox bbox, int maximumDimensions) {
private static int getExpectedNumberOfBBoxes(Bounds bbox, int maximumDimensions) {
double width = MapWithAIDataUtils.getWidth(bbox);
double height = MapWithAIDataUtils.getHeight(bbox);
int widthDivisions = (int) Math.ceil(width / maximumDimensions);

Wyświetl plik

@ -30,7 +30,6 @@ import org.openstreetmap.josm.data.Bounds;
import org.openstreetmap.josm.data.DataSource;
import org.openstreetmap.josm.data.UndoRedoHandler;
import org.openstreetmap.josm.data.coor.LatLon;
import org.openstreetmap.josm.data.osm.BBox;
import org.openstreetmap.josm.data.osm.DataSet;
import org.openstreetmap.josm.data.osm.Node;
import org.openstreetmap.josm.data.osm.OsmPrimitive;
@ -143,7 +142,7 @@ public class MapWithAILayerTest {
MapWithAILayer mapWithAILayer = MapWithAIDataUtils.getLayer(true);
DataSet ds = mapWithAILayer.getDataSet();
GetDataRunnable getData = new GetDataRunnable(
Arrays.asList(new BBox(-5.7400005, 34.4524384, -5.6686014, 34.5513153)), ds, null);
Arrays.asList(new Bounds(34.4524384, -5.7400005, 34.5513153, -5.6686014)), ds, null);
getData.setMaximumDimensions(5_000);
getData.fork().join();
assertTrue(ds.getSelected().isEmpty());

Wyświetl plik

@ -139,7 +139,7 @@ public class MapWithAIRemoteControlTest {
"http://127.0.0.1:8111/mapwithai?bbox={bbox}".replace("{bbox}", temp2.toStringCSV(",")))
.handle());
assertEquals(
"Bad bbox: 39.0621223,-108.4625421,39.0633059,-108.4594728 (converted to [ x: 39.0621223 -> 39.0633059, y: -108.4625421 -> -108.4594728 ])",
"Bad bbox: 39.0621223,-108.4625421,39.0633059,-108.4594728 (converted to Bounds[-108.4625421,39.0621223,-108.4594728,39.0633059])",
exception.getMessage());
}

Wyświetl plik

@ -18,8 +18,8 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.openstreetmap.josm.TestUtils;
import org.openstreetmap.josm.data.Bounds;
import org.openstreetmap.josm.data.coor.LatLon;
import org.openstreetmap.josm.data.osm.BBox;
import org.openstreetmap.josm.data.osm.DataSet;
import org.openstreetmap.josm.data.osm.Node;
import org.openstreetmap.josm.data.osm.Way;
@ -119,9 +119,9 @@ public class MapWithAIUploadHookTest {
assertTrue(split.contains("url_ids=false-url"), "The false-url should be shown in the changeset tag");
assertTrue(split.contains("maxadd=20"), "The maxadd should be 20");
BBox tBBox = new BBox(1, 0, 0, 1);
Bounds tBounds = new Bounds(0, 1, 1, 0);
MainApplication.getLayerManager()
.addLayer(new GpxLayer(DetectTaskingManagerUtils.createTaskingManagerGpxData(tBBox),
.addLayer(new GpxLayer(DetectTaskingManagerUtils.createTaskingManagerGpxData(tBounds),
DetectTaskingManagerUtils.MAPWITHAI_CROP_AREA));
tags.clear();
@ -131,7 +131,7 @@ public class MapWithAIUploadHookTest {
assertTrue(split.contains("version=".concat(info.localversion)), "The version should match the local version");
assertTrue(split.contains("url_ids=false-url"), "The false-url should be shown in the changeset tag");
assertTrue(split.contains("maxadd=20"), "The maxadd should be 20");
assertTrue(split.contains("task=".concat(tBBox.toStringCSV(","))),
assertTrue(split.contains("task=".concat(tBounds.toBBox().toStringCSV(","))),
"There should be a task in the mapwithai:options");
}