Problem: Geospatial Data Processing and IDW Interpolation

The problem aims to implement a set of C++ functions for spatial data processing and inverse distance weighted (IDW) interpolation, including reading point/raster data, computing distance matrices, finding center points, determining adaptive raster parameters, and performing IDW with adaptive power adjustment to support geographic data analysis.


Input/Output: The problem accepts input data including filepaths for point and raster data (strings), 2D point sets (std::vector<std::pair<double, double>>), optional weight vectors (std::vector<double>), spatial boundary values (xmin, ymin, xmax, ymax as doubles), initial raster resolution (double), interpolation coordinates (x, y as doubles), known value vectors (std::vector<double>), and a neighbor count (int). It generates outputs: a vector of 2D points from the point file (empty if invalid), a 2D vector for raster data (empty if invalid), a symmetric distance matrix (std::vector<std::vector<double>>), the index of the center point (int, -1 for empty points), raster parameters (std::vector<double> with bounds, resolution, rows, cols), and the IDW interpolation result (double). The workflow includes file validation, distance matrix computation, center point identification, adaptive raster parameter adjustment, and adaptive-power IDW interpolation.

Required dependencies:
#include <iostream>
#include <vector>
#include <string>
#include <io.h>
#include <cmath>
#include <limits>
#include <algorithm>
using namespace std;

Sub-steps:
step_number: 1
step_description_prompt: Please write a C++ function named readPointData that reads point data from a file and returns a vector of pairs of doubles (each pair represents a point's coordinates). The function has the following signature: std::vector<std::pair<double, double>> readPointData(const std::string& filepath);  

Algorithm flow:  
1. Define an internal lambda function fileExists that checks file existence using the _access function (from <io.h>).  
2. Check if the input filepath exists with fileExists.  
3. If the file does not exist, output the warning message "Warning: Point data file not found: " followed by the filepath.  
4. Return an empty vector (this is a simplified version; full implementation requires GDAL/OGR library to read actual data).  

Note: The _access function, required headers (<iostream>, <vector>, <string>, <io.h>, <cmath>, <limits>, <algorithm>), and standard library components (std::vector, std::pair, std::string, std::cout) are assumed to be available. The fileExists lambda is defined inside readPointData. The function includes file existence check and returns an empty vector (even if the file exists, as it skips actual data reading for simplification).
function_header: std::vector<std::pair<double, double>> readPointData(const std::string& filepath)
test_cases: int main() {
    // Comparison function for pairs
    auto isEqualPair = [](const std::pair<double, double>& a, const std::pair<double, double>& b, double tolerance = 1e-6) {
        return std::abs(a.first - b.first) <= tolerance && std::abs(a.second - b.second) <= tolerance;
    };
    
    // Comparison function for vector of pairs
    auto isEqualVec = [&isEqualPair](const std::vector<std::pair<double, double>>& a, const std::vector<std::pair<double, double>>& b, double tolerance = 1e-6) {
        if (a.size() != b.size()) return false;
        for (size_t i = 0; i < a.size(); ++i) {
            if (!isEqualPair(a[i], b[i], tolerance)) return false;
        }
        return true;
    };
    
    // Get relative path (from problems directory to data directory)
    auto getDataPath = [](const std::string& relativePath) -> std::string {
        return "../test_data/gisdata/" + relativePath;
    };
    
    // Helper function to read point data from CSV file
    auto readPointDataReal = [](const std::string& csvPath) -> std::vector<std::pair<double, double>> {
        std::vector<std::pair<double, double>> points;
        std::ifstream file(csvPath);
        if (!file.is_open()) {
            return points;
        }
        std::string line;
        bool firstLine = true;
        while (std::getline(file, line)) {
            if (firstLine) {
                firstLine = false;
                continue; // Skip header line
            }
            if (line.empty()) continue;
            std::istringstream iss(line);
            std::string xStr, yStr;
            if (std::getline(iss, xStr, ',') && std::getline(iss, yStr, ',')) {
                try {
                    double x = std::stod(xStr);
                    double y = std::stod(yStr);
                    points.push_back({x, y});
                } catch (...) {
                    // Skip invalid lines
                }
            }
        }
        file.close();
        return points;
    };
    
    std::cout << "Subproblem 6.0: Read point data from file" << std::endl;
    std::cout << "==========================================" << std::endl << std::endl;
    
    int correctCount = 0;
    
    // Test case 1: pm10_pts
    std::string path1 = getDataPath("pm10_pts_coordinates.csv");
    auto result1 = readPointDataReal(path1);
    std::vector<std::pair<double, double>> expected1 = {
        {1426980.6689179072, 3451415.2929588202},
        {1424200.6317453892, 3452856.7419655342},
        {1433833.9725806965, 3459364.7923419289},
        {1423469.6794857476, 3459561.4694037940},
        {1433202.1356232269, 3463506.2068246640}
    };
    bool passed1 = (result1.size() >= 5) && isEqualVec(
        std::vector<std::pair<double, double>>(result1.begin(), result1.begin() + 5),
        expected1, 0.01);
    std::cout << "Test case 1: " << (passed1 ? "correct" : "wrong") << std::endl;
    if (!passed1) {
        std::cout << "  Actual result size: " << result1.size() << std::endl;
        if (result1.size() > 0) {
            std::cout << "  Actual result (first " << std::min(result1.size(), size_t(5)) << " points): ";
            std::cout << std::fixed << std::setprecision(10);
            for (size_t i = 0; i < std::min(result1.size(), size_t(5)); ++i) {
                std::cout << "(" << result1[i].first << ", " << result1[i].second << ")";
                if (i < std::min(result1.size(), size_t(5)) - 1) std::cout << ", ";
            }
            std::cout << std::endl;
            std::cout.unsetf(std::ios_base::fixed);
        }
    }
    if (passed1) correctCount++;
    
    // Test case 2: capitals
    std::string path2 = getDataPath("capitals_coordinates.csv");
    auto result2 = readPointDataReal(path2);
    std::vector<std::pair<double, double>> expected2 = {
        {-134.1334075928, 58.3885917664},
        {-122.8937988281, 47.0419197083},
        {-100.7673034668, 46.8054695129},
        {-112.0204010010, 46.5965194702},
        {-93.1036834717, 44.9477386475}
    };
    bool passed2 = (result2.size() >= 5) && isEqualVec(
        std::vector<std::pair<double, double>>(result2.begin(), result2.begin() + 5),
        expected2, 0.01);
    std::cout << "Test case 2: " << (passed2 ? "correct" : "wrong") << std::endl;
    if (!passed2) {
        std::cout << "  Actual result size: " << result2.size() << std::endl;
        if (result2.size() > 0) {
            std::cout << "  Actual result (first " << std::min(result2.size(), size_t(5)) << " points): ";
            std::cout << std::fixed << std::setprecision(10);
            for (size_t i = 0; i < std::min(result2.size(), size_t(5)); ++i) {
                std::cout << "(" << result2[i].first << ", " << result2[i].second << ")";
                if (i < std::min(result2.size(), size_t(5)) - 1) std::cout << ", ";
            }
            std::cout << std::endl;
            std::cout.unsetf(std::ios_base::fixed);
        }
    }
    if (passed2) correctCount++;
    
    // Test case 3: Uscities_WGS
    std::string path3 = getDataPath("uscities_wgs_coordinates.csv");
    auto result3 = readPointDataReal(path3);
    std::vector<std::pair<double, double>> expected3 = {
        {-122.4681987127, 48.7438855091},
        {-109.6798679467, 48.5438252847},
        {-122.6307005487, 48.4922214881},
        {-122.3157828428, 48.4215629532},
        {-122.6289422452, 48.3079034221}
    };
    bool passed3 = (result3.size() >= 5) && isEqualVec(
        std::vector<std::pair<double, double>>(result3.begin(), result3.begin() + 5),
        expected3, 0.01);
    std::cout << "Test case 3: " << (passed3 ? "correct" : "wrong") << std::endl;
    if (!passed3) {
        std::cout << "  Actual result size: " << result3.size() << std::endl;
        if (result3.size() > 0) {
            std::cout << "  Actual result (first " << std::min(result3.size(), size_t(5)) << " points): ";
            std::cout << std::fixed << std::setprecision(10);
            for (size_t i = 0; i < std::min(result3.size(), size_t(5)); ++i) {
                std::cout << "(" << result3[i].first << ", " << result3[i].second << ")";
                if (i < std::min(result3.size(), size_t(5)) - 1) std::cout << ", ";
            }
            std::cout << std::endl;
            std::cout.unsetf(std::ios_base::fixed);
        }
    }
    if (passed3) correctCount++;
    
    if (correctCount == 3) {
        std::cout << "Subproblem 6.0: Completely correct!" << std::endl;
    }
    
    return 0;
}

step_number: 2
step_description_prompt: Please write a C++ function named readRasterData that reads raster data from a file (simplified version). The function has the signature std::vector<std::vector<double>> readRasterData(const std::string& filepath). Algorithm flow: 1. Use the pre-defined lambda function fileExists (which checks file existence via _access) to verify if the input file exists. 2. If the file does not exist, print "Warning: Raster data file not found: " followed by the filepath and return an empty vector. 3. If the file exists, return an empty vector (this is a simplified version; full implementation requires GDAL library to read actual raster data). The lambda function fileExists is already defined and does not need redefinition. This function involves file existence checking for raster data reading.
function_header: std::vector<std::vector<double>> readRasterData(const std::string& filepath)
test_cases: int main() {
    // Get relative path (from problems directory to data directory)
    auto getDataPath = [](const std::string& relativePath) -> std::string {
        return "../test_data/gisdata/" + relativePath;
    };
    
    std::cout << "Subproblem 6.2: Read raster data from file" << std::endl;
    std::cout << "===========================================" << std::endl << std::endl;
    
    int correctCount = 0;
    
    // Test case 1: Check if function returns empty vector (simplified version)
    std::string path1 = getDataPath("landsat/20180523.img");
    auto result1 = readRasterData(path1);
    std::vector<std::vector<double>> expected1;  // Expected: empty vector
    bool passed1 = (result1.size() == expected1.size() && result1 == expected1);
    std::cout << "Test case 1: " << (passed1 ? "correct" : "wrong") << std::endl;
    if (passed1) correctCount++;
    
    // Test case 2: Check if function returns empty vector for different path
    std::string path2 = getDataPath("mask/mask.shp");
    auto result2 = readRasterData(path2);
    std::vector<std::vector<double>> expected2;  // Expected: empty vector
    bool passed2 = (result2.size() == expected2.size() && result2 == expected2);
    std::cout << "Test case 2: " << (passed2 ? "correct" : "wrong") << std::endl;
    if (passed2) correctCount++;
    
    // Test case 3: Check if function returns empty vector for another path
    std::string path3 = getDataPath("city/city.shp");
    auto result3 = readRasterData(path3);
    std::vector<std::vector<double>> expected3;  // Expected: empty vector
    bool passed3 = (result3.size() == expected3.size() && result3 == expected3);
    std::cout << "Test case 3: " << (passed3 ? "correct" : "wrong") << std::endl;
    if (passed3) correctCount++;
    
    if (correctCount == 3) {
        std::cout << "Subproblem 6.2: Completely correct!" << std::endl;
    }
    
    return 0;
}

step_number: 3
step_description_prompt: Please write a C++ function named computeDistanceMatrix that computes a symmetric distance matrix for a given list of 2D points. The function takes a const std::vector<std::pair<double, double>>& points as input and returns a std::vector<std::vector<double>>.

Initialize an n×n matrix (n is points.size()) filled with 0.0. Use symmetry optimization: iterate i from 0 to n-1, j from i+1 to n-1. For each (i,j), compute dx = points[i].first - points[j].first, dy = points[i].second - points[j].second. Calculate Euclidean distance as std::sqrt(dx*dx + dy*dy), then assign this distance to matrix[i][j] and matrix[j][i]. Other used functions are pre-defined.
function_header: std::vector<std::vector<double>> computeDistanceMatrix( const std::vector<std::pair<double, double>>& points )
test_cases: int main() {
    // Comparison function
    auto isEqual = [](double a, double b, double tolerance = 1e-6) {
        return std::abs(a - b) <= tolerance;
    };
    
    std::cout << "Subproblem 6.3: Compute distance matrix (symmetric optimization)" << std::endl;
    std::cout << "=================================================================" << std::endl << std::endl;
    
    int correctCount = 0;
    
    // Test case 1: Three points
    std::vector<std::pair<double, double>> points1 = {{0, 0}, {1, 1}, {2, 2}};
    auto result1 = computeDistanceMatrix(points1);
    bool passed1 = (result1.size() == 3) && 
                   isEqual(result1[0][0], 0.0, 0.01) &&
                   isEqual(result1[1][1], 0.0, 0.01) &&
                   isEqual(result1[2][2], 0.0, 0.01) &&
                   isEqual(result1[0][1], result1[1][0], 0.01);
    std::cout << "Test case 1: " << (passed1 ? "correct" : "wrong") << std::endl;
    if (passed1) correctCount++;
    
    // Test case 2: Square pattern
    std::vector<std::pair<double, double>> points2 = {{0, 0}, {1, 0}, {0, 1}, {1, 1}};
    auto result2 = computeDistanceMatrix(points2);
    bool passed2 = (result2.size() == 4) && 
                   isEqual(result2[0][0], 0.0, 0.01) &&
                   isEqual(result2[0][1], result2[1][0], 0.01);
    std::cout << "Test case 2: " << (passed2 ? "correct" : "wrong") << std::endl;
    if (passed2) correctCount++;
    
    // Test case 3: Five points
    std::vector<std::pair<double, double>> points3 = {{0, 0}, {1, 0}, {0, 1}, {1, 1}, {0.5, 0.5}};
    auto result3 = computeDistanceMatrix(points3);
    bool passed3 = (result3.size() == 5) && 
                   isEqual(result3[0][0], 0.0, 0.01) &&
                   isEqual(result3[4][4], 0.0, 0.01);
    std::cout << "Test case 3: " << (passed3 ? "correct" : "wrong") << std::endl;
    if (passed3) correctCount++;
    
    if (correctCount == 3) {
        std::cout << "Subproblem 6.3: Completely correct!" << std::endl;
    }
    
    return 0;
}


step_number: 4
step_description_prompt: Please write a C++ function named findCenterPoint that solves the weighted or unweighted Fermat-Weber problem to find the index of the center point (the point with the minimum sum of weighted or unweighted Euclidean distances to all other points) in a 2D point set.
The function is defined as: int findCenterPoint(const std::vector<std::pair<double, double>>& points, const std::vector<double>& weights = std::vector<double>()).
Algorithm steps: 1. Return -1 if points is empty. 2. Compute a symmetric distance matrix where each element (i,j) is the Euclidean distance between point i and point j. 3. Check if weights are valid (non-empty and size matches points.size()). 4. For each point i, calculate the sum of distances from i to all points (use weights[j] to multiply each distance if weights are valid, else use unweighted sum). 5. Return the index of the point with the smallest sum.
Helper functions or operations used (assumed to be defined): std::sqrt, std::numeric_limits<double>::max, static_cast<int>, and standard vector operations.
function_header: int findCenterPoint( const std::vector<std::pair<double, double>>& points, const std::vector<double>& weights = std::vector<double>()
test_cases: int main() {
    std::cout << "Subproblem 6.4: Find center point (weighted Fermat-Weber)" << std::endl;
    std::cout << "=========================================================" << std::endl << std::endl;
    
    int correctCount = 0;
    
    // Test case 1: Center point in square (unweighted)
    std::vector<std::pair<double, double>> points1 = {{0, 0}, {1, 0}, {0, 1}, {1, 1}, {0.5, 0.5}};
    int result1 = findCenterPoint(points1);
    bool passed1 = (result1 == 4);
    std::cout << "Test case 1: " << (passed1 ? "correct" : "wrong") << std::endl;
    if (passed1) correctCount++;
    
    // Test case 2: Weighted center
    std::vector<std::pair<double, double>> points2 = {{0, 0}, {1, 1}, {2, 2}};
    std::vector<double> weights1 = {1.0, 2.0, 1.0};  // Middle point has larger weight
    int result2 = findCenterPoint(points2, weights1);
    bool passed2 = (result2 == 1);  // Middle point should be center
    std::cout << "Test case 2: " << (passed2 ? "correct" : "wrong") << std::endl;
    if (passed2) correctCount++;
    
    // Test case 3: Five points
    std::vector<std::pair<double, double>> points3 = {{0, 0}, {2, 0}, {1, 2}, {0, 2}, {2, 2}};
    int result3 = findCenterPoint(points3);
    bool passed3 = (result3 == 2);
    std::cout << "Test case 3: " << (passed3 ? "correct" : "wrong") << std::endl;
    if (passed3) correctCount++;
    
    if (correctCount == 3) {
        std::cout << "Subproblem 6.4: Completely correct!" << std::endl;
    }
    
    return 0;
}


step_number: 5
step_description_prompt: Please write a C++ function named determineRasterParams that calculates raster parameters including adaptive resolution adjustment based on input boundaries, initial resolution, and optional data points. Function definition: std::vector<double> determineRasterParams(double xmin, double ymin, double xmax, double ymax, double resolution, const std::vector<std::pair<double, double>>& dataPoints = std::vector<std::pair<double, double>>()). Algorithm flow: 1. Initialize a RasterParams struct (defined inside the function with members xmin, ymin, xmax, ymax, xResolution, yResolution, nRows, nCols and a default constructor) with input xmin, ymin, xmax, ymax. 2. If dataPoints is not empty, calculate data density as dataPoints.size() divided by the area ((xmax - xmin) * (ymax - ymin)). Adjust resolution: if density > 0.01, multiply by 0.8; if density < 0.001, multiply by 1.2; else use original resolution. Set xResolution and yResolution to the adjusted or original value. 3. Calculate nCols as static_cast<int>((xmax - xmin) / xResolution) + 1, nRows as static_cast<int>((ymax - ymin) / yResolution) + 1. 4. Return a std::vector<double> containing xmin, ymin, xmax, ymax, xResolution, yResolution, static_cast<double>(nRows), static_cast<double>(nCols) in this order.
function_header: std::vector<double> determineRasterParams( double xmin, double ymin, double xmax, double ymax, double resolution, const std::vector<std::pair<double, double>>& dataPoints = std::vector<std::pair<double, double>>()
test_cases: int main() {
    // Comparison function
    auto isEqual = [](double a, double b, double tolerance = 1e-6) {
        return std::abs(a - b) <= tolerance;
    };
    
    std::cout << "Subproblem 6.5: IDW interpolation preparation (adaptive resolution)" << std::endl;
    std::cout << "=====================================================================" << std::endl << std::endl;
    
    int correctCount = 0;
    
    // Test case 1: Standard
    auto result1 = determineRasterParams(0.0, 0.0, 100.0, 100.0, 10.0);
    bool passed1 = (static_cast<int>(result1[6]) == 11) && (static_cast<int>(result1[7]) == 11) &&
                   isEqual(result1[4], 10.0, 0.01) &&
                   isEqual(result1[5], 10.0, 0.01);
    std::cout << "Test case 1: " << (passed1 ? "correct" : "wrong") << std::endl;
    if (passed1) correctCount++;
    
    // Test case 2: With data points (adaptive)
    std::vector<std::pair<double, double>> densePoints(100);
    for (int i = 0; i < 100; ++i) {
        densePoints[i] = {i % 10, i / 10};
    }
    auto result2 = determineRasterParams(0.0, 0.0, 500.0, 500.0, 50.0, densePoints);
    // Actual values: nRows=9, nCols=9 (adaptive resolution changes to 60.0, so 500/60+1=9.33->9)
    bool passed2 = (static_cast<int>(result2[6]) == 9) && (static_cast<int>(result2[7]) == 9);
    std::cout << "Test case 2: " << (passed2 ? "correct" : "wrong") << std::endl;
    if (passed2) correctCount++;
    
    // Test case 3: Low density
    std::vector<std::pair<double, double>> sparsePoints = {{0, 0}, {100, 100}};
    auto result3 = determineRasterParams(0.0, 0.0, 1000.0, 1000.0, 100.0, sparsePoints);
    // Actual values: nRows=9, nCols=9 (adaptive resolution changes to 120.0, so 1000/120+1=9.33->9)
    bool passed3 = (static_cast<int>(result3[6]) == 9) && (static_cast<int>(result3[7]) == 9);
    std::cout << "Test case 3: " << (passed3 ? "correct" : "wrong") << std::endl;
    if (passed3) correctCount++;
    
    if (correctCount == 3) {
        std::cout << "Subproblem 6.5: Completely correct!" << std::endl;
    }
    
    return 0;
}


step_number: 6
step_description_prompt: Please write a C++ function named idwInterpolation that implements inverse distance weighted (IDW) interpolation with adaptive power adjustment. The function definition is: double idwInterpolation(double x, double y, const std::vector<std::pair<double, double>>& knownPoints, const std::vector<double>& knownValues, int nNeighbors); 

The algorithm flow is: 
1. Calculate squared distances from (x, y) to each point in knownPoints and store in a vector distSq. 
2. Create a vector of pairs (distSq[i], i) for all i, sort the vector in ascending order. 
3. Set n as the minimum of nNeighbors and the size of the pairs vector to select the nearest n points. 
4. Compute adaptive power: get minDist (sqrt of pairs[0].first) and maxDist (sqrt of pairs[n-1].first). If both >0, compute distRatio = maxDist / minDist; set power to 3.0 if distRatio >10.0, 1.5 if <2.0, else 2.0. 
5. Compute weights: for each of the n points, if pairs[i].first <1e-10, return knownValues[pairs[i].second] immediately. Weight is 1.0 / pow(sqrt(pairs[i].first), power). Sum all weights. 
6. Calculate weighted average: sum (weights[i]/sum * knownValues[pairs[i].second]) for all n points, then return the result. 

Assume all used standard library functions (e.g., std::sort, std::pow) are already defined.</think>Please write a C++ function named idwInterpolation that implements inverse distance weighted (IDW) interpolation with adaptive power adjustment. The function definition is: double idwInterpolation(double x, double y, const std::vector<std::pair<double, double>>& knownPoints, const std::vector<double>& knownValues, int nNeighbors); 

The algorithm flow is: 
1. Calculate squared distances from (x,y) to each point in knownPoints and store in a vector distSq. 
2. Create pairs of (distSq[i], i), sort the pairs in ascending order. 
3. Set n as the minimum of nNeighbors and pairs.size() to get the number of nearest points. 
4. Compute adaptive power: get minDist (sqrt of pairs[0].first) and maxDist (sqrt of pairs[n-1].first). If both maxDist and minDist are greater than 0, calculate distRatio = maxDist / minDist; adjust power to 3.0 if distRatio >10.0, 1.5 if distRatio <2.0, else keep 2.0. 
5. Compute weights for the n points: if pairs[i].first <1e-10, return knownValues[pairs[i].second] immediately. Weight is 1.0 / pow(sqrt(pairs[i].first), power). Sum all weights. 
6. Calculate weighted average: sum (weights[i]/sum * knownValues[pairs[i].second]) for the n points, return the result. 

Assume all used standard library functions (e.g., std::sort, std::pow) are predefined.
function_header: double idwInterpolation( double x, double y, const std::vector<std::pair<double, double>>& knownPoints, const std::vector<double>& knownValues, int nNeighbors )
test_cases: int main() {
    // Comparison function
    auto isEqual = [](double a, double b, double tolerance = 1e-6) {
        return std::abs(a - b) <= tolerance;
    };
    
    std::cout << "Subproblem 6.6: IDW interpolation calculation and result validation" << std::endl;
    std::cout << "===================================================================" << std::endl << std::endl;
    
    int correctCount = 0;
    
    // Test case 1: IDW interpolation calculation
    std::vector<std::pair<double, double>> points1 = {{0, 0}, {50, 50}, {150, 150}};
    std::vector<double> values1 = {10.0, 20.0, 30.0};
    double result1 = idwInterpolation(100.0, 100.0, points1, values1, 3);
    // Actual value: 23.3333 (using adaptive power IDW)
    bool passed1 = isEqual(result1, 23.3333, 0.1);
    std::cout << "Test case 1: " << (passed1 ? "correct" : "wrong") << std::endl;
    if (passed1) correctCount++;
    
    // Test case 2: IDW interpolation calculation
    std::vector<std::pair<double, double>> points2 = {{0, 0}, {100, 0}, {0, 100}, {100, 100}};
    std::vector<double> values2 = {1.0, 2.0, 3.0, 4.0};
    double result2 = idwInterpolation(50.0, 50.0, points2, values2, 4);
    bool passed2 = isEqual(result2, 2.5, 0.1);
    std::cout << "Test case 2: " << (passed2 ? "correct" : "wrong") << std::endl;
    if (passed2) correctCount++;
    
    // Test case 3: IDW interpolation calculation
    std::vector<std::pair<double, double>> points3 = {{0, 0}, {1, 1}, {2, 2}};
    std::vector<double> values3 = {5.0, 10.0, 15.0};
    double result3 = idwInterpolation(0.0, 0.0, points3, values3, 2);
    bool passed3 = isEqual(result3, 5.0, 0.01);
    std::cout << "Test case 3: " << (passed3 ? "correct" : "wrong") << std::endl;
    if (passed3) correctCount++;
    
    if (correctCount == 3) {
        std::cout << "Subproblem 6.6: Completely correct!" << std::endl;
    }
    
    return 0;
}


General solution:

General tests: