![JAR search and dependency download from the Maven repository](/logo.png)
org.locationtech.spatial4j.distance.CartesianDistCalc Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of spatial4j Show documentation
Show all versions of spatial4j Show documentation
Spatial4j is a general purpose spatial / geospatial ASL licensed open-source Java library. It's
core capabilities are 3-fold: to provide common geospatially-aware shapes, to provide distance
calculations and other math, and to read shape formats like WKT and GeoJSON.
/*******************************************************************************
* Copyright (c) 2015 Voyager Search and MITRE
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Apache License, Version 2.0 which
* accompanies this distribution and is available at
* http://www.apache.org/licenses/LICENSE-2.0.txt
******************************************************************************/
package org.locationtech.spatial4j.distance;
import org.locationtech.spatial4j.context.SpatialContext;
import org.locationtech.spatial4j.shape.Circle;
import org.locationtech.spatial4j.shape.Point;
import org.locationtech.spatial4j.shape.Rectangle;
/**
* Calculates based on Euclidean / Cartesian 2d plane.
*/
public class CartesianDistCalc extends AbstractDistanceCalculator {
public static final CartesianDistCalc INSTANCE = new CartesianDistCalc();
public static final CartesianDistCalc INSTANCE_SQUARED = new CartesianDistCalc(true);
private final boolean squared;
public CartesianDistCalc() {
this.squared = false;
}
/**
* @param squared Set to true to have {@link #distance(org.locationtech.spatial4j.shape.Point, org.locationtech.spatial4j.shape.Point)}
* return the square of the correct answer. This is a
* performance optimization used when sorting in which the
* actual distance doesn't matter so long as the sort order is
* consistent.
*/
public CartesianDistCalc(boolean squared) {
this.squared = squared;
}
@Override
public double distance(Point from, double toX, double toY) {
double xSquaredPlusYSquared = distanceSquared(from.getX(), from.getY(), toX, toY);
if (squared)
return xSquaredPlusYSquared;
return Math.sqrt(xSquaredPlusYSquared);
}
private static double distanceSquared(double fromX, double fromY, double toX, double toY) {
double deltaX = fromX - toX;
double deltaY = fromY - toY;
return deltaX*deltaX + deltaY*deltaY;
}
/**
* Distance from point to a line segment formed between points 'v' and 'w'.
* It respects the "squared" option.
*/
// TODO add to generic DistanceCalculator and develop geo versions.
public double distanceToLineSegment(Point point, double vX, double vY, double wX, double wY) {
// Translated from: http://bl.ocks.org/mbostock/4218871
double d = distanceSquared(vX, vY, wX, wY);
double toX;
double toY;
if (d <= 0) {
toX = vX;
toY = vY;
} else {
// t = ((point[0] - v[0]) * (w[0] - v[0]) + (point[1] - v[1]) * (w[1] - v[1])) / d
double t = ((point.getX() - vX) * (wX - vX) + (point.getY() - vY) * (wY - vY)) / d;
if (t < 0) {
toX = vX;
toY = vY;
} else if (t > 1) {
toX = wX;
toY = wY;
} else {
toX = vX + t * (wX - vX);
toY = vY + t * (wY - vY);
}
}
return distance(point, toX, toY);
}
@Override
public boolean within(Point from, double toX, double toY, double distance) {
double deltaX = from.getX() - toX;
double deltaY = from.getY() - toY;
return deltaX*deltaX + deltaY*deltaY <= distance*distance;
}
@Override
public Point pointOnBearing(Point from, double distDEG, double bearingDEG, SpatialContext ctx, Point reuse) {
if (distDEG == 0) {
if (reuse == null)
return from;
reuse.reset(from.getX(), from.getY());
return reuse;
}
double bearingRAD = DistanceUtils.toRadians(bearingDEG);
double x = from.getX() + Math.sin(bearingRAD) * distDEG;
double y = from.getY() + Math.cos(bearingRAD) * distDEG;
if (reuse == null) {
return ctx.makePoint(x, y);
} else {
reuse.reset(x, y);
return reuse;
}
}
@Override
public Rectangle calcBoxByDistFromPt(Point from, double distDEG, SpatialContext ctx, Rectangle reuse) {
double minX = from.getX() - distDEG;
double maxX = from.getX() + distDEG;
double minY = from.getY() - distDEG;
double maxY = from.getY() + distDEG;
if (reuse == null) {
return ctx.makeRectangle(minX, maxX, minY, maxY);
} else {
reuse.reset(minX, maxX, minY, maxY);
return reuse;
}
}
@Override
public double calcBoxByDistFromPt_yHorizAxisDEG(Point from, double distDEG, SpatialContext ctx) {
return from.getY();
}
@Override
public double area(Rectangle rect) {
return rect.getArea(null);
}
@Override
public double area(Circle circle) {
return circle.getArea(null);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CartesianDistCalc that = (CartesianDistCalc) o;
if (squared != that.squared) return false;
return true;
}
@Override
public int hashCode() {
return (squared ? 1 : 0);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy