Ticket #17388: 17388.geometry_sqrt_cache.patch
File 17388.geometry_sqrt_cache.patch, 11.9 KB (added by , 5 years ago) |
---|
-
src/org/openstreetmap/josm/data/gpx/GpxDistance.java
1 1 // License: GPL. For details, see LICENSE file. 2 2 package org.openstreetmap.josm.data.gpx; 3 3 4 import org.openstreetmap.josm.data.osm.Node; 4 import java.util.OptionalDouble; 5 5 6 import org.openstreetmap.josm.data.osm.OsmPrimitive; 7 import org.openstreetmap.josm.data.projection.ProjectionRegistry; 6 8 import org.openstreetmap.josm.tools.Geometry; 7 9 8 10 /** … … 23 25 * @return The shortest distance 24 26 */ 25 27 public static double getLowestDistance(OsmPrimitive p, GpxData gpxData) { 26 return gpxData.getTrackPoints()27 .mapToDouble(tp -> Geometry.getDistance (p, new Node(tp.getCoor())))28 .filter(x -> x >= 0) 29 .min().orElse(Double.MAX_VALUE);28 OptionalDouble min = gpxData.getTrackPoints().map(waypoint -> waypoint.getEastNorth(ProjectionRegistry.getProjection())) 29 .mapToDouble(tp -> Geometry.getDistanceSq(p, tp)) 30 .filter(x -> x >= 0).min(); 31 return min.isPresent() ? Math.sqrt(min.getAsDouble()) : Double.MAX_VALUE; 30 32 } 31 33 } -
src/org/openstreetmap/josm/tools/Geometry.java
1303 1303 double lowestDistance = Double.MAX_VALUE; 1304 1304 TreeSet<T> closest = new TreeSet<>(); 1305 1305 for (T primitive : primitives) { 1306 double distance = getDistance (osm, primitive);1306 double distance = getDistanceSq(osm, primitive); 1307 1307 if (Double.isNaN(distance)) continue; 1308 1308 int comp = Double.compare(distance, lowestDistance); 1309 1309 if (comp < 0) { … … 1367 1367 double furthestDistance = Double.NEGATIVE_INFINITY; 1368 1368 TreeSet<T> furthest = new TreeSet<>(); 1369 1369 for (T primitive : primitives) { 1370 double distance = getDistance (osm, primitive);1370 double distance = getDistanceSq(osm, primitive); 1371 1371 if (Double.isNaN(distance)) continue; 1372 1372 int comp = Double.compare(distance, furthestDistance); 1373 1373 if (comp > 0) { … … 1394 1394 * @since 15035 1395 1395 */ 1396 1396 public static double getDistance(OsmPrimitive one, OsmPrimitive two) { 1397 double distance = getDistanceSq(one, two); 1398 return distance != Double.MAX_VALUE && !Double.isNaN(distance) ? Math.sqrt(distance) : Double.NaN; 1399 } 1400 1401 /** 1402 * Get the distance squared between different {@link OsmPrimitive}s 1403 * @param one The primitive to get the distance from 1404 * @param two The primitive to get the distance to 1405 * @return The distance squared between the primitives in meters 1406 * (or the unit of the current projection, see {@link Projection}). 1407 * May return {@link Double#NaN} if one of the primitives is incomplete. 1408 * 1409 * Note: The complexity is O(n*m), where (n,m) are the number of child 1410 * objects the {@link OsmPrimitive}s have. 1411 * @since xxx 1412 */ 1413 public static double getDistanceSq(OsmPrimitive one, OsmPrimitive two) { 1397 1414 double rValue = Double.MAX_VALUE; 1398 1415 if (one == null || two == null || one.isIncomplete() 1399 1416 || two.isIncomplete()) return Double.NaN; 1400 1417 if (one instanceof Node && two instanceof Node) { 1401 rValue = ((Node) one).getCoor().greatCircleDistance(((Node) two).getCoor());1418 rValue = Math.pow(((Node) one).getCoor().greatCircleDistance(((Node) two).getCoor()), 2); 1402 1419 } else if (one instanceof Node && two instanceof Way) { 1403 rValue = getDistanceWay Node((Way) two, (Node) one);1420 rValue = getDistanceWayEastNorthSq((Way) two, ((Node) one).getEastNorth()); 1404 1421 } else if (one instanceof Way && two instanceof Node) { 1405 rValue = getDistanceWay Node((Way) one, (Node) two);1422 rValue = getDistanceWayEastNorthSq((Way) one, ((Node) two).getEastNorth()); 1406 1423 } else if (one instanceof Way && two instanceof Way) { 1407 rValue = getDistanceWayWay ((Way) one, (Way) two);1424 rValue = getDistanceWayWaySq((Way) one, (Way) two); 1408 1425 } else if (one instanceof Relation && !(two instanceof Relation)) { 1409 1426 for (OsmPrimitive osmPrimitive: ((Relation) one).getMemberPrimitives()) { 1410 double currentDistance = getDistance (osmPrimitive, two);1427 double currentDistance = getDistanceSq(osmPrimitive, two); 1411 1428 if (currentDistance < rValue) rValue = currentDistance; 1412 1429 } 1413 1430 } else if (!(one instanceof Relation) && two instanceof Relation) { 1414 rValue = getDistance (two, one);1431 rValue = getDistanceSq(two, one); 1415 1432 } else if (one instanceof Relation && two instanceof Relation) { 1416 1433 for (OsmPrimitive osmPrimitive1 : ((Relation) one).getMemberPrimitives()) { 1417 1434 for (OsmPrimitive osmPrimitive2 : ((Relation) two).getMemberPrimitives()) { 1418 double currentDistance = getDistance (osmPrimitive1, osmPrimitive2);1435 double currentDistance = getDistanceSq(osmPrimitive1, osmPrimitive2); 1419 1436 if (currentDistance < rValue) rValue = currentDistance; 1420 1437 } 1421 1438 } … … 1424 1441 } 1425 1442 1426 1443 /** 1444 * Get the distance between a {@link OsmPrimitive} and a position 1445 * @param one The primitive to get the distance from 1446 * @param two The EastNorth to get the distance to 1447 * @return The distance between the objects in meters 1448 * (or the unit of the current projection, see {@link Projection}). 1449 * May return {@link Double#NaN} if one of the objects is incomplete. 1450 * 1451 * Note: The complexity is O(n*m), where (n,m) are the number of child 1452 * objects the {@link OsmPrimitive} have. 1453 * @since xxx 1454 */ 1455 public static double getDistanceSq(OsmPrimitive one, EastNorth two) { 1456 double rValue = Double.MAX_VALUE; 1457 if (one == null || two == null || one.isIncomplete() 1458 || !two.isValid()) return Double.NaN; 1459 if (one instanceof Node) { 1460 rValue = two.distanceSq(((Node) one).getEastNorth()); 1461 } else if (one instanceof Way) { 1462 rValue = getDistanceWayEastNorthSq((Way) one, two); 1463 } else if (one instanceof Relation) { 1464 for (OsmPrimitive osmPrimitive: ((Relation) one).getMemberPrimitives()) { 1465 double currentDistance = getDistanceSq(osmPrimitive, two); 1466 if (currentDistance < rValue) rValue = currentDistance; 1467 } 1468 } 1469 return rValue != Double.MAX_VALUE ? rValue : Double.NaN; 1470 } 1471 1472 /** 1427 1473 * Get the distance between a way and a node 1428 1474 * @param way The way to get the distance from 1429 1475 * @param node The node to get the distance to … … 1435 1481 public static double getDistanceWayNode(Way way, Node node) { 1436 1482 if (way == null || node == null || way.getNodesCount() < 2 || !node.isLatLonKnown()) 1437 1483 return Double.NaN; 1484 double distanceSq = getDistanceWayEastNorthSq(way, node.getEastNorth()); 1485 return distanceSq != Double.MAX_VALUE && !Double.isNaN(distanceSq) ? Math.sqrt(distanceSq) : distanceSq; 1486 } 1438 1487 1488 /** 1489 * Get the distance between a way and a node squared 1490 * @param way The way to get the distance from 1491 * @param eastNorth The EastNorth to get the distance to 1492 * @return The distance between the {@code way} and the {@code eastnorth} in 1493 * meters (or the unit of the current projection, see {@link Projection}). 1494 * May return {@link Double#NaN} if the primitives are incomplete. 1495 * @since xxx 1496 */ 1497 public static double getDistanceWayEastNorthSq(Way way, EastNorth eastNorth) { 1498 if (way == null || eastNorth == null || way.getNodesCount() < 2 || !eastNorth.isValid()) 1499 return Double.NaN; 1500 1439 1501 double smallest = Double.MAX_VALUE; 1440 EastNorth en0 = node.getEastNorth();1441 1502 // go through the nodes as if they were paired 1442 1503 Iterator<Node> iter = way.getNodes().iterator(); 1443 1504 EastNorth en1 = iter.next().getEastNorth(); 1444 1505 while (iter.hasNext()) { 1445 1506 EastNorth en2 = iter.next().getEastNorth(); 1446 double distance = getSegmentNodeDistSq(en1, en2, e n0);1507 double distance = getSegmentNodeDistSq(en1, en2, eastNorth); 1447 1508 if (distance < smallest) 1448 1509 smallest = distance; 1449 1510 en1 = en2; 1450 1511 } 1451 return smallest != Double.MAX_VALUE ? Math.sqrt(smallest): Double.NaN;1512 return smallest != Double.MAX_VALUE ? smallest : Double.NaN; 1452 1513 } 1453 1514 1454 1515 /** … … 1492 1553 * @since 15035 1493 1554 */ 1494 1555 public static double getDistanceWayWay(Way w1, Way w2) { 1556 double distance = getDistanceWayWaySq(w1, w2); 1557 return distance != Double.MAX_VALUE && !Double.isNaN(distance) ? Math.sqrt(distance) : Double.NaN; 1558 } 1559 /** 1560 * 1561 * Get the distance squared between different ways. Iterates over the nodes of the ways, complexity is O(n*m) 1562 * (n,m giving the number of nodes) 1563 * @param w1 The first {@link Way} 1564 * @param w2 The second {@link Way} 1565 * @return The shortest distance squared between the ways in meters 1566 * (or the unit of the current projection, see {@link Projection}). 1567 * May return {@link Double#NaN}. 1568 * @since xxx 1569 */ 1570 public static double getDistanceWayWaySq(Way w1, Way w2) { 1495 1571 if (w1 == null || w2 == null || w1.getNodesCount() < 2 || w2.getNodesCount() < 2) 1496 1572 return Double.NaN; 1497 1573 double rValue = Double.MAX_VALUE; … … 1503 1579 Node w2N1 = iter2.next(); 1504 1580 while (iter2.hasNext()) { 1505 1581 Node w2N2 = iter2.next(); 1506 double distance = getDistanceSegmentSegment (w1N1, w1N2, w2N1, w2N2);1582 double distance = getDistanceSegmentSegmentSq(w1N1, w1N2, w2N1, w2N2); 1507 1583 if (distance < rValue) 1508 1584 rValue = distance; 1509 1585 w2N1 = w2N2; … … 1538 1614 * @since 15035 1539 1615 */ 1540 1616 public static double getDistanceSegmentSegment(Node ws1Node1, Node ws1Node2, Node ws2Node1, Node ws2Node2) { 1617 double distance = getDistanceSegmentSegmentSq(ws1Node1, ws1Node2, ws2Node1, ws2Node2); 1618 return distance != Double.MAX_VALUE && !Double.isNaN(distance) ? Math.sqrt(distance) : Double.NaN; 1619 } 1620 /** 1621 * Get the distance squared between different {@link WaySegment}s 1622 * @param ws1Node1 The first node of the first WaySegment 1623 * @param ws1Node2 The second node of the second WaySegment 1624 * @param ws2Node1 The first node of the second WaySegment 1625 * @param ws2Node2 The second node of the second WaySegment 1626 * @return The distance squared between the two {@link WaySegment}s in meters 1627 * (or the unit of the current projection, see {@link Projection}). 1628 * May return {@link Double#NaN}. 1629 * @since xxx 1630 */ 1631 public static double getDistanceSegmentSegmentSq(Node ws1Node1, Node ws1Node2, Node ws2Node1, Node ws2Node2) { 1541 1632 EastNorth enWs1Node1 = ws1Node1.getEastNorth(); 1542 1633 EastNorth enWs1Node2 = ws1Node2.getEastNorth(); 1543 1634 EastNorth enWs2Node1 = ws2Node1.getEastNorth(); … … 1552 1643 double dist3sq = getSegmentNodeDistSq(enWs2Node1, enWs2Node2, enWs1Node1); 1553 1644 double dist4sq = getSegmentNodeDistSq(enWs2Node1, enWs2Node2, enWs1Node2); 1554 1645 double smallest = Math.min(Math.min(dist1sq, dist2sq), Math.min(dist3sq, dist4sq)); 1555 return smallest != Double.MAX_VALUE ? Math.sqrt(smallest): Double.NaN;1646 return smallest != Double.MAX_VALUE ? smallest : Double.NaN; 1556 1647 } 1557 1558 1648 /** 1559 1649 * Calculate closest distance between a line segment s1-s2 and a point p 1560 1650 * @param s1 start of segment