Interpolación bicúbica de matriz 2D Java

Recientemente he estado jugando con Bicubic Interpolation, ya que quiero generar la tierra, basada en mapas de altura reales dentro de Minecraft. La razón por la que estoy usando la interpolación es porque me gustaría que el mundo tuviera más detalles. Después de mucha investigación y mucha prueba y error, decidí venir a preguntar aquí. :)

Debido a la memoria limitada, no puedo escalar la imagen al inicio, y mantener eso cargado, tengo que hacer la interpolación sobre la marcha.

Parece que he conseguido que la Interpolación cúbica funcione, como se ve aquí: Visualización de la interpolación Sin embargo, no puedo hacer que la Interpolación bicúbica funcione. Para fines de prueba, estoy usando una imagen pequeña y la escalo a 4. Esto es lo que hace el código: Entrada -> Salida

Este es mi código actual:

 public static double cubicInterpolate(double[] points, double x, double scale)
{
    x /= scale;

    double inBetweenPoint = x;
    int xInHeightmap = (int) x;
    inBetweenPoint -= xInHeightmap;

    double beforePoint1 = safe(points, xInHeightmap - 1);
    double point1 = safe(points, xInHeightmap);
    double point2 = safe(points, xInHeightmap + 1);
    double afterPoint2 = safe(points, xInHeightmap + 2);

    double p = (afterPoint2 - point2) - (beforePoint1 - point1);
    double q = (beforePoint1 - point1) - p;
    double r = point2 - beforePoint1;
    double s = point1;

    return (p * Math.pow(inBetweenPoint, 3)) + (q * Math.pow(inBetweenPoint, 2)) + (r * inBetweenPoint) + s;
}

public static double bicubicInterpolate(double[][] points, double x, double y, double scale)
{
    x /= scale;

    double inBetweenPoint = x;
    int xInHeightmap = (int) x;
    inBetweenPoint -= xInHeightmap;

    double beforePoint1 = cubicInterpolate(safe(points, xInHeightmap - 1), y, scale);
    double point1 = cubicInterpolate(safe(points, xInHeightmap), y, scale);
    double point2 = cubicInterpolate(safe(points, xInHeightmap + 1), y, scale);
    double afterPoint2 = cubicInterpolate(safe(points, xInHeightmap + 2), y, scale);

    return cubicInterpolate(new double[]{beforePoint1, point1, point2, afterPoint2}, inBetweenPoint + 1, scale);
}

public static double[] safe(double[][] p, int i)
{
    return p[Math.max(0, Math.min(i, p.length - 1))];
}

public static double safe(double[] p, int i)
{
    return p[Math.max(0, Math.min(i, p.length - 1))];
}

Gracias por tu ayuda :)

Respuesta 1

Según tengo entendido, su implementación trata lo dado xy las ycoordenadas de una manera totalmente diferente, lo que no conduce al resultado deseado. Básicamente deberías hacer lo siguiente.

Primero, debe identificar los cuatro puntos (pares de coordenadas) en la cuadrícula que formarán la base de la interpolación, así como las distancias en ambas direcciones desde la cuadrícula hasta la interpolación. Esto puede hacerse de la siguiente manera.

int xfloor = (int)x;
int yfloor = (int)y;
int xdelta = x - (double)xfloor;
int ydelta = y - (double)yfloor;

Los pares de coordenadas deseados son entonces (dependiendo de la orientación de los ejes)

P1 = (xfloor,     yfloor    ) // left upper corner
P2 = (xfloor,     yfloor + 1) // left lower corner
P3 = (xfloor + 1 ,yfloor + 1) // right lower corner
P4 = (xfloor + 1, yfloor    ) // left upper corner

y finalmente se interpolaría primero a lo largo de ejes paralelos y luego en el medio, lo que se puede hacer de la siguiente manera utilizando valores intermedios.

val1 = cubic(value(P1), value(P2), deltay) // interpolate cubically on the left edge
val2 = cubic(value(P4), value(P3), deltay) // interpolate cubically on the right edge
val = cubic (val1, val2, deltax) // interpolate cubically between the intermediates

Los métodos de interpolación también se discuten aquí .

Respuesta: 2

Estoy usando Ubuntu 10.10 amd64, Sun JDK 6.0.24 y el paquete ghostscript predeterminado. Ahora, estoy tratando de que funcione la muestra "Renderizar un documento PDF usando SimpleRenderer" de la página Ghost4J. Mientras ...

Como ejercicio de aprendizaje personal, escribí esta expresión regular para dividir una cadena unaria en partes cuya longitud aumenta los poderes de dos (ver también en ideone.com): for (String s: new String (new ...

Conocí en nuestro proyecto el siguiente código: MyInterface var = MyClass :: new; ¿Hay alguna diferencia con MyInterface var = new MyClass (); ¿Perezoso?

Me di cuenta de que dentro de la carpeta C: \ Archivos de programa \ Java, está el JRE público que instaló el JDK, sé que esto es normal. Pero luego está la carpeta jdk1.x \ jre \ bin \ con java.exe, javaw, etc.