public static double interpolateIDW()

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;
  }