kopia lustrzana https://github.com/JOSM/MapWithAI
Improve calculations for areas that have already been downloaded
Signed-off-by: Taylor Smock <tsmock@fb.com>pull/1/head
rodzic
0441c11d4a
commit
1ffa7fcad3
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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=")
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue