in common/src/main/java/org/apache/sedona/common/utils/RasterInterpolate.java [55:138]
public static double interpolateIDW(
int x,
int y,
STRtree strtree,
int width,
int height,
double power,
String mode,
Double numPointsOrRadius,
Double maxRadiusOrMinPoints) {
GeometryFactory geometryFactory = new GeometryFactory();
PriorityQueue<RasterPoint> minHeap =
new PriorityQueue<>(Comparator.comparingDouble(RasterPoint::getDistance));
if (mode.equalsIgnoreCase("variable")) {
Double numPoints =
(numPointsOrRadius == null) ? 12 : numPointsOrRadius; // Default no. of points -> 12
Double maxRadius =
(maxRadiusOrMinPoints == null)
? Math.sqrt((width * width) + (height * height))
: maxRadiusOrMinPoints; // Default max radius -> diagonal of raster
List<RasterPoint> queryResult =
strtree.query(new Envelope(x - maxRadius, x + maxRadius, y - maxRadius, y + maxRadius));
if (mode.equalsIgnoreCase("variable") && strtree.size() < numPointsOrRadius) {
throw new IllegalArgumentException(
"Parameter 'numPoints' defaulted to 12 which is larger than no. of valid pixels within the max search radius. Please choose an appropriate value");
}
for (RasterPoint rasterPoint : queryResult) {
if (numPoints <= 0) {
break;
}
Point point = rasterPoint.getPoint();
double distance = point.distance(geometryFactory.createPoint(new Coordinate(x, y)));
rasterPoint.setDistance(distance);
minHeap.add(rasterPoint);
numPoints--;
}
} else if (mode.equalsIgnoreCase("fixed")) {
Double radius =
(numPointsOrRadius == null)
? Math.sqrt((width * width) + (height * height))
: numPointsOrRadius; // Default radius -> diagonal of raster
Double minPoints =
(maxRadiusOrMinPoints == null)
? 0
: maxRadiusOrMinPoints; // Default min no. of points -> 0
List<RasterPoint> queryResult = new ArrayList<>();
do {
queryResult.clear();
Envelope searchEnvelope = new Envelope(x - radius, x + radius, y - radius, y + radius);
queryResult = strtree.query(searchEnvelope);
// If minimum points requirement met, break the loop
if (queryResult.size() >= minPoints) {
break;
}
radius *= 1.5; // Increase radius by 50%
} while (true);
for (RasterPoint rasterPoint : queryResult) {
Point point = rasterPoint.getPoint();
double distance = point.distance(geometryFactory.createPoint(new Coordinate(x, y)));
if (distance <= 0 || distance > radius) {
continue;
}
rasterPoint.setDistance(distance);
minHeap.add(rasterPoint);
}
}
double numerator = 0.0;
double denominator = 0.0;
while (!minHeap.isEmpty()) {
RasterPoint rasterPoint = minHeap.poll();
double value = rasterPoint.getValue();
double distance = rasterPoint.getDistance();
double weight = 1.0 / Math.pow(distance, power);
numerator += weight * value;
denominator += weight;
}
double interpolatedValue = (denominator > 0 ? numerator / denominator : Double.NaN);
return interpolatedValue;
}