public double calculateElevationBasedOnPointList(double lat, double lon, PointList pointList) {
        // See http://math.stackexchange.com/a/1930758/140512 for the
        // explanation
        final int size = pointList.size();
        if (size == 0) {
            throw new IllegalArgumentException("At least one point is required in the pointList.");
        } else if (size == 1) {
            return pointList.getEle(0);
        } else if (size == 2) {
            return calculateElevationBasedOnTwoPoints(lat, lon, pointList.getLat(0),
                    pointList.getLon(0), pointList.getEle(0), pointList.getLat(1),
                    pointList.getLon(1), pointList.getEle(1));
        } else if (size == 3) {
            return calculateElevationBasedOnThreePoints(lat, lon, pointList.getLat(0),
                    pointList.getLon(0), pointList.getEle(0), pointList.getLat(1),
                    pointList.getLon(1), pointList.getEle(1), pointList.getLat(2),
                    pointList.getLon(2), pointList.getEle(2));
        } else {
            double[] vs = new double[size];
            double[] eles = new double[size];
            double v = 0;
            for (int index = 0; index < size; index++) {
                double lati = pointList.getLat(index);
                double loni = pointList.getLon(index);
                double dlati = lati - lat;
                double dloni = loni - lon;
                double l2 = (dlati * dlati + dloni * dloni);
                eles[index] = pointList.getEle(index);
                if (l2 < EPSILON2) {
                    return eles[index];
                }
                vs[index] = 1 / l2;
                v += vs[index];
            }

            double ele = 0;
            for (int index = 0; index < size; index++) {
                ele += eles[index] * vs[index] / v;
            }
            return round2(ele);
        }
    }
@Test
    public void calculatesElevationOnNPoints() {
        assertEquals(0, elevationInterpolator.calculateElevationBasedOnPointList(5, 5,
                Helper.createPointList3D(0, 0, 0, 10, 0, 0, 10, 10, 0, 0, 10, 0)),
                PRECISION);
        assertEquals(10, elevationInterpolator.calculateElevationBasedOnPointList(5, 5,
                Helper.createPointList3D(0, 0, 0, 10, 0, 10, 10, 10, 20, 0, 10, 10)),
                PRECISION);
        assertEquals(5, elevationInterpolator.calculateElevationBasedOnPointList(5, 5,
                Helper.createPointList3D(0, 0, 0, 10, 0, 10, 10, 10, 0, 0, 10, 10)),
                PRECISION);
        assertEquals(2.65, elevationInterpolator.calculateElevationBasedOnPointList(2.5,
                2.5, Helper.createPointList3D(0, 0, 0, 10, 0, 10, 10, 10, 0, 0, 10, 10)),
                PRECISION);
        assertEquals(0, elevationInterpolator.calculateElevationBasedOnPointList(0.1,
                0.1, Helper.createPointList3D(0, 0, 0, 10, 0, 10, 10, 10, 0, 0, 10, 10)),
                PRECISION);
        assertEquals(0, elevationInterpolator.calculateElevationBasedOnPointList(
                ElevationInterpolator.EPSILON / 2, ElevationInterpolator.EPSILON / 2,
                Helper.createPointList3D(0, 0, 0, 10, 0, 10, 10, 10, 0, 0, 10, 10)),
                PRECISION);
        assertEquals(0, elevationInterpolator.calculateElevationBasedOnPointList(5, 0,
                Helper.createPointList3D(0, 0, 0, 10, 1, 10, 10, -1, -10, 20, 0, 0)),
                PRECISION);
    }