/** * Angle between line AB and CD * * @param a Point A. * @param b Point B. * @param c Point C. * @param d Point D. * @return Angle in degrees. */ public static double angleOfLines(LatLon a, LatLon b, LatLon c, LatLon d) { return (Math.abs( Math.atan2(a.lat() - b.lat(), a.lon() - b.lon()) - Math.atan2(c.lat() - d.lat(), c.lon() - d.lon())) / Math.PI * 180) % 360; }
/** * Determines if the given point {@code ll} is within these bounds. * * @param ll The lat/lon to check * @return {@code true} if {@code ll} is within these bounds, {@code false} otherwise */ public boolean contains(LatLon ll) { if (ll.lat() < minLat || ll.lat() > maxLat) return false; if (crosses180thMeridian()) { if (ll.lon() > maxLon && ll.lon() < minLon) return false; } else { if (ll.lon() < minLon || ll.lon() > maxLon) return false; } return true; }
public void selectFeatures(int x, int y) { int pixelDelta = 2; LatLon clickUL = Main.map.mapView.getLatLon(x - pixelDelta, y - pixelDelta); LatLon clickLR = Main.map.mapView.getLatLon(x + pixelDelta, y + pixelDelta); Envelope envelope = new Envelope( Math.min(clickUL.lon(), clickLR.lon()), Math.max(clickUL.lon(), clickLR.lon()), Math.min(clickUL.lat(), clickLR.lat()), Math.max(clickUL.lat(), clickLR.lat())); ReferencedEnvelope mapArea = new ReferencedEnvelope(envelope, crsOSMI); Intersects filter = ff.intersects(ff.property("msGeometry"), ff.literal(mapArea)); // // Select features in all layers // content.layers().clear(); // Iterate through features and build a list that intersects the above // envelope for (int idx = 0; idx < arrFeatures.size(); ++idx) { OSMIFeatureTracker tracker = arrFeatures.get(idx); FeatureCollection<SimpleFeatureType, SimpleFeature> features = tracker.getFeatures(); SimpleFeatureSource tempfs = DataUtilities.source(features); FeatureCollection<SimpleFeatureType, SimpleFeature> selectedFeatures; try { selectedFeatures = tempfs.getFeatures(filter); Set<FeatureId> IDs = new HashSet<>(); try (FeatureIterator<SimpleFeature> iter = selectedFeatures.features()) { Main.info("Selected features " + selectedFeatures.size()); while (iter.hasNext()) { SimpleFeature feature = iter.next(); IDs.add(feature.getIdentifier()); } } geometryType = selectGeomType.get(idx + layerOffset); Style style = createDefaultStyle(idx + layerOffset, IDs); content.addLayer(new FeatureLayer(features, style)); } catch (IOException e) { Main.error(e); } } bIsChanged = true; }
@Test public void b_eastNorth2latlon_test() { { EastNorth en = new EastNorth(533111.69, 152227.85); LatLon ll = Main.getProjection().eastNorth2latlon(en); if (debug) { System.out.println(ll); } assertTrue("Lausanne", Math.abs(ll.lat() - 46.518) < 0.00001); assertTrue("Lausanne", Math.abs(ll.lon() - 6.567) < 0.00001); } { EastNorth en = new EastNorth(685544.16, 292782.91); LatLon ll = Main.getProjection().eastNorth2latlon(en); if (debug) { System.out.println(ll); } assertTrue("Schafouse", Math.abs(ll.lat() - 47.78) < 0.00001); assertTrue("Schafouse", Math.abs(ll.lon() - 8.58) < 0.00001); } { EastNorth en = new EastNorth(833068.04, 163265.39); LatLon ll = Main.getProjection().eastNorth2latlon(en); if (debug) { System.out.println(ll); } assertTrue("Grinson", Math.abs(ll.lat() - 46.58) < 0.00001); assertTrue("Grinson", Math.abs(ll.lon() - 10.48) < 0.00001); } { EastNorth en = new EastNorth(600000.0, 200000.0); LatLon ll = Main.getProjection().eastNorth2latlon(en); if (debug) { System.out.println(ll); } assertTrue("Berne", Math.abs(ll.lat() - (46.0 + 57.0 / 60 + 3.89813884505 / 3600)) < 0.00001); assertTrue( "Berne", Math.abs(ll.lon() - (7.0 + 26.0 / 60 + 19.076595154147 / 3600)) < 0.00001); } { EastNorth en = new EastNorth(700000.0, 100000.0); LatLon ll = Main.getProjection().eastNorth2latlon(en); if (debug) { System.out.println(ll); } assertTrue("Ref", Math.abs(ll.lat() - (46.0 + 2.0 / 60 + 38.87 / 3600)) < 0.00001); assertTrue("Ref", Math.abs(ll.lon() - (8.0 + 43.0 / 60 + 49.79 / 3600)) < 0.00001); } }
/** * Returns the heading, in radians, that you have to use to get from this lat/lon to another. * * @param other the "destination" position * @return heading */ public double heading(LatLon other) { double rv; if (other.lat() == lat()) { rv = (other.lon() > lon() ? Math.PI / 2 : Math.PI * 3 / 2); } else { rv = Math.atan((other.lon() - lon()) / (other.lat() - lat())); if (rv < 0) { rv += Math.PI; } if (other.lon() < lon()) { rv += Math.PI; } } return rv; }
/** output a point */ private void wayPoint(WayPoint pnt, int mode) { String type; switch (mode) { case WAY_POINT: type = "wpt"; break; case ROUTE_POINT: type = "rtept"; break; case TRACK_POINT: type = "trkpt"; break; default: throw new RuntimeException(tr("Unknown mode {0}.", mode)); } if (pnt != null) { LatLon c = pnt.getCoor(); String coordAttr = "lat=\"" + c.lat() + "\" lon=\"" + c.lon() + '\"'; if (pnt.attr.isEmpty()) { inline(type, coordAttr); } else { openAtt(type, coordAttr); writeAttr(pnt, WPT_KEYS); closeln(type); } } }
/** * Creates new bounds around a coordinate pair <code>center</code>. The new bounds shall have an * extension in latitude direction of <code>latExtent</code>, and in longitude direction of <code> * lonExtent</code>. * * @param center the center coordinate pair. Must not be null. * @param latExtent the latitude extent. > 0 required. * @param lonExtent the longitude extent. > 0 required. * @throws IllegalArgumentException if center is null * @throws IllegalArgumentException if latExtent <= 0 * @throws IllegalArgumentException if lonExtent <= 0 */ public Bounds(LatLon center, double latExtent, double lonExtent) { CheckParameterUtil.ensureParameterNotNull(center, "center"); if (latExtent <= 0.0) throw new IllegalArgumentException( MessageFormat.format( "Parameter ''{0}'' > 0.0 expected, got {1}", "latExtent", latExtent)); if (lonExtent <= 0.0) throw new IllegalArgumentException( MessageFormat.format( "Parameter ''{0}'' > 0.0 expected, got {1}", "lonExtent", lonExtent)); this.minLat = LatLon.roundToOsmPrecision(LatLon.toIntervalLat(center.lat() - latExtent / 2)); this.minLon = LatLon.roundToOsmPrecision(LatLon.toIntervalLon(center.lon() - lonExtent / 2)); this.maxLat = LatLon.roundToOsmPrecision(LatLon.toIntervalLat(center.lat() + latExtent / 2)); this.maxLon = LatLon.roundToOsmPrecision(LatLon.toIntervalLon(center.lon() + lonExtent / 2)); }
private void testProj(Projection p) { double maxErrLat = 0, maxErrLon = 0; Bounds b = p.getWorldBoundsLatLon(); text += String.format("*** %s %s\n", p.toString(), p.toCode()); for (int num = 0; num < 1000; ++num) { double lat = rand.nextDouble() * (b.getMax().lat() - b.getMin().lat()) + b.getMin().lat(); double lon = rand.nextDouble() * (b.getMax().lon() - b.getMin().lon()) + b.getMin().lon(); LatLon ll = new LatLon(lat, lon); for (int i = 0; i < 10; ++i) { EastNorth en = p.latlon2eastNorth(ll); ll = p.eastNorth2latlon(en); } maxErrLat = Math.max(maxErrLat, Math.abs(lat - ll.lat())); maxErrLon = Math.max(maxErrLon, Math.abs(lon - ll.lon())); } String mark = ""; if (maxErrLat + maxErrLon > 1e-5) { mark = "--FAILED-- "; error = true; } text += String.format("%s errorLat: %s errorLon: %s\n", mark, maxErrLat, maxErrLon); }
/** * Determines whether a way is oriented clockwise. * * <p>Internals: Assuming a closed non-looping way, compute twice the area of the polygon using * the formula {@code 2 * area = sum (X[n] * Y[n+1] - X[n+1] * Y[n])}. If the area is negative the * way is ordered in a clockwise direction. * * <p>See http://paulbourke.net/geometry/polyarea/ * * @param w the way to be checked. * @return true if and only if way is oriented clockwise. * @throws IllegalArgumentException if way is not closed (see {@link Way#isClosed}). */ public static boolean isClockwise(Way w) { if (!w.isClosed()) { throw new IllegalArgumentException("Way must be closed to check orientation."); } double area2 = 0.; int nodesCount = w.getNodesCount(); for (int node = 1; node <= /*sic! consider last-first as well*/ nodesCount; node++) { LatLon coorPrev = w.getNode(node - 1).getCoor(); LatLon coorCurr = w.getNode(node % nodesCount).getCoor(); area2 += coorPrev.lon() * coorCurr.lat(); area2 -= coorCurr.lon() * coorPrev.lat(); } return area2 < 0; }
@Override public void paint(Graphics2D g, MapView mv, Bounds box) { LatLon min = box.getMin(); LatLon max = box.getMax(); Envelope envelope2 = new Envelope( Math.min(min.lat(), max.lat()), Math.max(min.lat(), max.lat()), Math.min(min.lon(), max.lon()), Math.max(min.lon(), max.lon())); ReferencedEnvelope mapArea = new ReferencedEnvelope(envelope2, crsOSMI); renderer.setInteractive(false); renderer.paint(g, mv.getBounds(), mapArea); bIsChanged = false; }
public static String getURL(LatLon pos, int zoom) { // Truncate lat and lon to something more sensible int decimals = (int) Math.pow(10, (zoom / 3)); double lat = (Math.round(pos.lat() * decimals)); lat /= decimals; double lon = (Math.round(pos.lon() * decimals)); lon /= decimals; return "http://www.openstreetmap.org/?lat=" + lat + "&lon=" + lon + "&zoom=" + zoom; }
@Override public void run() { if (!active) return; LatLon min = bbox.getMin(); LatLon max = bbox.getMax(); // Extend the area to download beond the view double t = Main.pref.getDouble("plugin.continuos_download.extra_download", 0.1); double dLat = Math.abs(max.lat() - min.lat()) * t; double dLon = Math.abs(max.lon() - min.lon()) * t; Bounds newBbox = new Bounds(min.lat() - dLat, min.lon() - dLon, max.lat() + dLat, max.lon() + dLon); // Do not try to download an area if the user have zoomed far out if (newBbox.getArea() < Main.pref.getDouble("plugin.continuos_download.max_area", 0.25)) getStrat().fetch(newBbox); }
@Override public void actionPerformed(GpsActionEvent event) { LatLon coordinates = event.getCoordinates(); System.out.println( getClass().getSimpleName() + " KOORD: " + coordinates.lat() + ", " + coordinates.lon() + " params: " + getParameters()); }
private void infoSync(LatLon pos, ProgressMonitor progressMonitor) { progressMonitor.beginTask(null, 3); try { mRuian.prepareData(pos); htmlText = mRuian.getHtml(); coordinatesText = PointInfoUtils.formatCoordinates(pos.lat(), pos.lon()); } finally { progressMonitor.finishTask(); } progressMonitor.invalidate(); if (htmlText.length() == 0) { GuiHelper.runInEDTAndWait( () -> PointInfoUtils.showNotification( tr("Data not available.") + "\n(" + pos.toDisplayString() + ")", "warning")); return; } }
public void update(Camera camera, Perspective3D perspective3d) { Point3d cameraPoint = camera.getPoint(); Vector3d cameraRotation = camera.getAngle(); Perspective3D perspective = perspective3d; EastNorth eastNorth = perspective.toEastNorth(cameraPoint.x, -cameraPoint.z); Projection proj = Main.getProjection(); LatLon latLon = proj.eastNorth2latlon(eastNorth); // XXX update cache this.photo.setLat(latLon.lat()); this.photo.setLon(latLon.lon()); this.photo.setHeight(cameraPoint.y); this.photo.setRotate(cameraRotation.x, cameraRotation.y, cameraRotation.z); }
/** * Computes the distance between this lat/lon and another point on the earth. Uses Haversine * formular. * * @param other the other point. * @return distance in metres. */ public double greatCircleDistance(LatLon other) { double R = 6378135; double sinHalfLat = sin(toRadians(other.lat() - this.lat()) / 2); double sinHalfLon = sin(toRadians(other.lon() - this.lon()) / 2); double d = 2 * R * asin( sqrt( sinHalfLat * sinHalfLat + cos(toRadians(this.lat())) * cos(toRadians(other.lat())) * sinHalfLon * sinHalfLon)); // For points opposite to each other on the sphere, // rounding errors could make the argument of asin greater than 1 // (This should almost never happen.) if (java.lang.Double.isNaN(d)) { System.err.println("Error: NaN in greatCircleDistance"); d = PI * R; } return d; }
public LatLon interpolate(LatLon ll2, double proportion) { return new LatLon( this.lat() + proportion * (ll2.lat() - this.lat()), this.lon() + proportion * (ll2.lon() - this.lon())); }
/** * @return <code>true</code> if the other point has almost the same lat/lon values, only differing * by no more than 1 / {@link #MAX_SERVER_PRECISION MAX_SERVER_PRECISION}. */ public boolean equalsEpsilon(LatLon other) { double p = MAX_SERVER_PRECISION / 2; return Math.abs(lat() - other.lat()) <= p && Math.abs(lon() - other.lon()) <= p; }
/** Construct bounds out of two points. Coords will be rounded. */ public Bounds(LatLon min, LatLon max) { this(min.lat(), min.lon(), max.lat(), max.lon()); }
/** * Single point Bounds defined by lat/lon {@code b}. Coordinates will be rounded to osm precision * if {@code roundToOsmPrecision} is true. * * @param b lat/lon of given point. * @param roundToOsmPrecision defines if lat/lon will be rounded. */ public Bounds(LatLon b, boolean roundToOsmPrecision) { this(b.lat(), b.lon(), roundToOsmPrecision); }
public Bounds(LatLon min, LatLon max, boolean roundToOsmPrecision) { this(min.lat(), min.lon(), max.lat(), max.lon(), roundToOsmPrecision); }
/** * Extend the bounds if necessary to include the given point. * * @param ll The point to include into these bounds */ public void extend(LatLon ll) { extend(ll.lat(), ll.lon()); }
protected static final boolean isNullLatLon(LatLon ll) { return ll.lat() == 0.0 && ll.lon() == 0.0; }
public LatLon getCenter(LatLon ll2) { return new LatLon((this.lat() + ll2.lat()) / 2.0, (this.lon() + ll2.lon()) / 2.0); }
public LatLon(LatLon coor) { super(coor.lon(), coor.lat()); }