Archivo de la categoría: Digi3D

Implementando EGM08_REDNAP en Digi3D.NET

Introducción

Digi3D.NET se basa en la base de datos del EPSG para implementar todos sus cálculos geodésicos.

El problema de la base de datos EPSG es que no contempla ningún sistema de coordenadas vertical para la rejilla EGM08_REDNAP proporcionada por el Instituto Geográfico Nacional de España.

Aquí te voy a contar las modificaciones que he realizado en la base de datos para añadir el sistema de coordenadas vertical EGM08_REDNAP a Digi3D.NET.

El instalador de Digi3D.NET instala una copia (transformada a formato .sdf) de la base de datos del EPSG en la carpeta %ProgramData%\Digi3D.NET\OpenGis.

Conectándonos a la base de datos

Podemos conectarnos a esta base de datos con herramientas como Microsoft Visual Studio, WebMatrix o Microsoft SQL Server Management Studio. Yo lo he hecho con Visual Studio 2010.

He seguido los siguientes pasos:

  1. En el panel Server Explorer he pulsado el botón Connect to database. Aparece el cuadro de diálogo Choose Data Source.
  2. Selecciono la opción Microsoft SQL Server Compact 3.5
  3. Pulso el botón Continue. Aparece el cuadro de diálogo Add Connection.
  4. Pulso el botón Browse… Aparece el cuadro de diálogo Select SQL Server Compact 3.5 Database File.
  5. Localizo la base de datos y acepto el cuadro de diálogo Select SQL Server Compact 3.5 Database File.
  6. Pulso Ok en el cuadro de diálogo Add Connection. Aparece la base de datos como una rama de Data Connections en el panel Server Explorer.
  7. Pulso con el botón derecho del ratón en el nombre de la base de datos y aparece un menú contextual. Selecciono la opción New Query para crear una nueva consulta en la base de datos. Se abre una ventana para introducir la consulta y aparece un cuadro de diálogo Add Table. Lo cancelo.
  8. A partir de ahora podemos hacer consultas tecleándolas en la tercera fila. Para ejecutarlas pulsamos Ctrl+R

Añadiendo los sistemas de coordenadas de referencia verticales

El objetivo es añadir dos sistemas de coordenadas de referencia verticales: Uno para península (que denominaremos EGM08_REDNAP Península) y otro para Canarias (que denominaremos EGM08_REDNAP Canarias) para que el usuario de Digi3D.NET pueda seleccionar ese sistema de coordenadas.

Los sistemas de coordenadas de referencia se extraen de la tabla Coordinate Reference System.
Hago la siguiente consulta para averiguar los parámetros que rellenan todos los sistemas de coordenadas de referencia verticales que aparecen en la base de datos:

SELECT *
FROM [Coordinate Reference System]
WHERE COORD_REF_SYS_KIND = 'vertical'

Y compruebo que todos ellos rellenan únicamente los siguientes campos: COORD_REF_SYS_CODE, COORD_REF_SYS_NAME, AREA_OF_USE_CODE, COORD_REF_SYS_KIND, COORD_REF_SYS_CODE, DATUM_CODE, CRS_SCOPE, algunos rellenan REMARKS, INFORMATION_SOURCE, DATA_SOURCE, REVISION_DATE, SHOW_CRS y por último DEPRECATED.

Vamos a averiguar qué valores poner en cada campo.

COORD_REF_SYS_CODE:

Aquí tenemos que poner un código único para nuestro sistema de coordenadas. En el documento G7-1 del EPSG Users who wish to augment the EPSG, en el tema 5.9.1, podemos leer el siguiente párrafo: data with their own information should utilise codes greater than 32767, por lo tanto vamos a localizar el sistema de coordenadas de referencia cuyo código sea mayor de entre los mayores de 32767 con la siguiente consulta:

SELECT MAX(COORD_REF_SYS_CODE) AS Expr1
FROM [Coordinate Reference System]
WHERE (COORD_REF_SYS_CODE > 32767)

Nos sale el número 69036405, de modo que voy a añadir un sistema nuevo cuyo código va a ser 69036406 para el sistema de coordenadas a aplicar en la península y 69036407 para el de Canarias.

COORD_REF_SYS_NAME:

Aquí vamos a poner EGM08_REDNAP Península para el caso de península y EGM08_REDNAP Canarias para el caso de Canarias.

AREA_OF_USE_CODE:

Si hacemos la siguiente consulta:

SELECT *
FROM Area
WHERE (AREA_NAME LIKE '%spain%')

Nos encontramos con que el código a utilizar para la península es: 2366 y el de Canarias: 3199

COORD_REF_SYS_KIND:

Aquí vamos a poner vertical

COORD_REF_SYS_CODE:

Si realizamos la siguiente consulta:

SELECT *
FROM [Coordinate System]
WHERE (COORD_SYS_TYPE = 'vertical')

Comprobamos rápidamente que tendremos que introducir el código 6499 (ya que mide alturas, con orientación hacia arriba y con metros como unidad de medida).

DATUM_CODE:

Si ejecutamos la siguiente consulta:

SELECT *
FROM Datum
WHERE (DATUM_NAME LIKE '%EGM2008%')

Comprobamos que el valor a introducir en este campo es 1027.

CRS_SCOPE:

Aquí vamos a basarnos en el de EGM2008, que si lo consultamos con la siguiente consulta:

SELECT *
FROM [Coordinate Reference System]
WHERE (COORD_REF_SYS_NAME LIKE '%egm2008%')

comprobamos que tenemos que almacenar el valor Geodesy.

REMARKS:

Aquí vamos a poner:

Height Surface resulting from the application of the EGM08_REDNAP geoid model to the WGS 84 ellipsoid. Replaces EGM2008 geoid height (CRS code 3855) in Spain mainland

para el sistema de coordenadas de referencia vertical para la península y:

Height Surface resulting from the application of the EGM08_REDNAP geoid model to the WGS 84 ellipsoid. Replaces EGM2008 geoid height (CRS code 3855) in Spain – Canary islands

para el de Canarias.

INFORMATION_SOURCE:

Aquí vamos a poner la url del Instituto Geográfico Nacional España: http://www.ign.es/ign/layoutIn/actividadesGeodesiaRedn.do

DATA_SOURCE:

Aquí si hacemos la siguiente consulta:

SELECT DISTINCT DATA_SOURCE
FROM [Coordinate Reference System]

Resulta que únicamente existe un Data Source oficial, que es OGP, así que vamos a poner OGP (podríamos poner IGN pero como desconozco el valor a poner...).

REVISION_DATE:

Aquí vamos a poner la fecha de hoy: 26/11/2013

SHOW_CRS

Aquí vamos a poner True

DEPRECATED:

Aquí vamos a poner False

De modo que las consultas que debemos añadir para nuestros dos sistemas de coordenadas de referencia verticales son a la base de datos EPSG son:

INSERT INTO [Coordinate Reference System] (COORD_REF_SYS_CODE, COORD_REF_SYS_NAME, AREA_OF_USE_CODE, COORD_REF_SYS_KIND, COORD_SYS_CODE, DATUM_CODE, CRS_SCOPE, REMARKS, INFORMATION_SOURCE, DATA_SOURCE, 
                         REVISION_DATE, SHOW_CRS, DEPRECATED)
VALUES (69036406, 'EGM08_REDNAP Península', 2366, 'vertical', 6499, 1027, 'Geodesy', 'Height Surface resulting from the application of the EGM08_REDNAP geoid model to the WGS 84 ellipsoid. Replaces EGM2008 geoid height (CRS code 3855) in Spain mainland', 'http://www.ign.es/ign/layoutIn/actividadesGeodesiaRedn.do', 'OGP', GETDATE(), 1, 0)

y

INSERT INTO [Coordinate Reference System] (COORD_REF_SYS_CODE, COORD_REF_SYS_NAME, AREA_OF_USE_CODE, COORD_REF_SYS_KIND, COORD_SYS_CODE, DATUM_CODE, CRS_SCOPE, REMARKS, INFORMATION_SOURCE, DATA_SOURCE, REVISION_DATE, SHOW_CRS, DEPRECATED)
VALUES (69036407, 'EGM08_REDNAP Canarias', 3199, 'vertical', 6499, 1027, 'Geodesy', 'Height Surface resulting from the application of the EGM08_REDNAP geoid model to the WGS 84 ellipsoid. Replaces EGM2008 geoid height (CRS code 3855) in Spain - Canary islands', 'http://www.ign.es/ign/layoutIn/actividadesGeodesiaRedn.do', 'OGP', GETDATE(), 1, 0)

Con estos cambios ya podemos seleccionar el sistema de coordenadas de referencia vertical EGM08_REDNAP Península en Digi3D.NET tal y como se puede ver en la siguiente captura de pantalla:

Digi3D mostrando sistema vertical EGM08_REDNAP Península

A continuación la cadena Well Known Text generada automáticamente por Digi3D.NET al seleccionar el sistema de coordenadas de referencia que hemos creado para la península:

VERT_CS["EGM08_REDNAP Península",VERT_DATUM["EGM2008 geoid",2005,AUTHORITY["EPSG","1027"]],UNIT["metros",1,AUTHORITY["EPSG","9001"]],AXIS["H",Up],AUTHORITY["EPSG","69036406"]]

y a continuación el de Baleares:

VERT_CS["EGM08_REDNAP Baleares",VERT_DATUM["EGM2008 geoid",2005,AUTHORITY["EPSG","1027"]],UNIT["metros",1,AUTHORITY["EPSG","9001"]],AXIS["H",Up],AUTHORITY["EPSG","69036407"]]

Ahora nos quedan añadir entradas a la base de datos para indicar a Digi3D.NET la operación matemática a realizar para transformar coordenadas elipsoidales WGS 84 a ortométricas EGM08_REDNAP.

Para ello vamos a basarnos en la información que aparece en la base de datos EPGS para el sistema de coordenadas de referencia vertical EGM2008, pues EGM08_REDNAP no es más que una especialización de EGM2008:

Si realizamos la siguiente consulta:

SELECT *
FROM Coordinate_Operation
WHERE (SOURCE_CRS_CODE=4979 AND TARGET_CRS_CODE = 3855)

Comprobamos que hay dos variantes de la misma transformación. Vamos a introducir pues en esta tabla dos transformaciones, una cuyo destino será el sistema de coordenada de referencia 69036406 y otra el 69036407 y el resto de valores vamos a copiarlos de la consulta anterior.

Los números de operaciones serán también números mayores que 32767, así que vamos a averiguar primero el número mayor de entre los mayores de 32767 en esta tabla:

SELECT MAX(COORD_OP_CODE) AS Expr1
FROM Coordinate_Operation
WHERE (COORD_OP_CODE > 32767)

La respuesta es 32769, de modo que utilizaremos 32770 y 32771:

INSERT INTO Coordinate_Operation (COORD_OP_CODE, COORD_OP_NAME, COORD_OP_TYPE, SOURCE_CRS_CODE, TARGET_CRS_CODE, COORD_TFM_VERSION, COORD_OP_VARIANT, AREA_OF_USE_CODE, COORD_OP_SCOPE, COORD_OP_ACCURACY, COORD_OP_METHOD_CODE, REMARKS, DATA_SOURCE, REVISION_DATE, SHOW_OPERATION, DEPRECATED)
VALUES (32770, 'WGS 84 to EGM08_REDNAP Península Geoid height', 'transformation', 4979, 69036406, 'IGN-Spain mainland', 1, 2366, 'Derivation of gravity-related heights from GPS observations.', 0.5, 1025, 'Replaces WGS 84 to EGM2008 geoid height (2) (tfm code 3859) in Spain - mainland. This tfm uses a grid with node spacing of 1 arc-minute.', 'OGP', GETDATE(), 1, 0)

y este otro:

INSERT INTO Coordinate_Operation (COORD_OP_CODE, COORD_OP_NAME, COORD_OP_TYPE, SOURCE_CRS_CODE, TARGET_CRS_CODE, COORD_TFM_VERSION, COORD_OP_VARIANT, AREA_OF_USE_CODE, COORD_OP_SCOPE, COORD_OP_ACCURACY, COORD_OP_METHOD_CODE, REMARKS, DATA_SOURCE, REVISION_DATE, SHOW_OPERATION, DEPRECATED)
VALUES (32771, 'WGS 84 to EGM08_REDNAP Canary islands geoid height', 'transformation', 4979, 69036407, 'IGN-Spain Balearic', 1, 3199, 'Derivation of gravity-related heights from GPS observations.', 0.5, 1025, 'Replaces WGS 84 to EGM2008 geoid height (2) (tfm code 3859) in Spain - Balearic islands. This tfm uses a grid with node spacing of 1 arc-minute.', 'OGP', GETDATE(), 1, 0)

Añadiendo los parámetros a las transformaciones

Por último sólo nos queda por añadir los parámetros de nuestras transformaciones (que básicamente consisten en indicar el nombre del archivo a cargar).
Los parámetros de las transformaciones se almacenan en la tabla Coordinate_Operation Parameter Value.

Podemos ver los parámetros de la transformación EGM2008:

SELECT *
FROM [Coordinate_Operation Parameter Value]
WHERE (COORD_OP_CODE = 3858)

Comprobamos que únicamente tendremos que añadir dos entradas a esta tabla: una con el COORD_OP_CODE 32769, con el COORD_OP_METHOD_CODE 1025, con el PARAMETER_CODE 8666 y con PARAM_VALUE_FILE_REF EGM08_REDNAP.txt para península y COORD_OP_CODE 32770, con el COORD_OP_METHOD_CODE 1025, con el PARAMETER_CODE 8666 y con PARAM_VALUE_FILE_REF EGM08_REDNAP_Canarias.txt para Canarias:

INSERT INTO [Coordinate_Operation Parameter Value] (COORD_OP_CODE, COORD_OP_METHOD_CODE, PARAMETER_CODE, PARAM_VALUE_FILE_REF)
VALUES (32770, 1025, 8666, 'EGM08_REDNAP.txt')

y

INSERT INTO [Coordinate_Operation Parameter Value] (COORD_OP_CODE, COORD_OP_METHOD_CODE, PARAMETER_CODE, PARAM_VALUE_FILE_REF)
VALUES (32771, 1025, 8666, 'EGM08_REDNAP_Canarias.txt')

Por último he tenido que modificar el algoritmo Geographic3DToGravityRelatedHeightEGM2008 para que pueda cargar archivos .txt en el formato en el que lo publica el IGN que no tiene nada que ver con el que se publica el EGM2008 y ya está, Digi3D.NET es compatible con estos sistemas de coordenadas de referencia verticales.

Fragments Shaders en Digi3D.NET

Digi3D.NET permite transformar los parámetros radiomátricos (brillo/color/contraste/gama/niveles/tonos de gris/positivo o negativo…) de visualización de las imágenes que muestra en la ventana fotogramétrica mediante los controles del panel Propiedades de la imagen de la ventana fotogramétrica.

Podemos configurar el programa para que esta transformación se realice o por software o por hardware, en la opción del menú Herramientas/Configuración/Estereoscopía/Método para Brillo y Contraste.

Disponemos de dos opciones:

  • Software
  • Fragment Shaders

Si instalamos Digi3D.NET por primera vez en un equipo la opción predeterminada será Fragment Shaders que es la implementación por hardware.

La opción ideal es hacer la transformación por hardware, pero no todas las tarjetas gráficas están preparadas para realizar operaciones por hardware. Las tarjetas gráficas que admiten esta operación son tarjetas que admiten el lenguaje de programación de Shaders.

Si nuestra tarjeta gráfica no admite shaders, si tenemos seleccionada la opción Fragment Shaders comprobaremos que al desplazarnos por la imagen, esta dará tirones, en cuyo caso tendremos que seleccionar la opción Software.

Mi recomendación es que si tu tarjeta gráfica lo admite, selecciones la opción Fragment Shaders, por varios motivos:

  • Velocidad: ya que si la operación se realiza por software, cada vez que Digi3D.NET cargue una tesela de la imagen, tendrá que modificar pixel por pixel su valor en función de la configuración de brillo/contraste/color… seleccionada por el usuario.

    Además, me atrevería a asegurar que el 99% de los equipos cuya tarjeta gráfica no admite shaders son antiguos y lentos, lo que provocará que la carga de la tesela se relentice, provocando que el usuario visualice por uno o varios segundos esta tesela de color negro.

  • Carga del procesador: Si el procesador está ocupado cambiando el color de la imagen, el scroll de la imagen se puede ralentizar.

    Y tal y como expongo en el punto anterior, como el procesador seguro que tiene pocos núcleos (dos, no más) esto afectará al rendimiento de Digi3D.NET.

  • Modificación real de la imagen en memoria: Si nos disponemos a realizar alguna operación con la imagen cargada en memoria, como por ejemplo correlar un modelo, y esta ha sido alterada por software, los resultados variarán en función del los parámetros radiométricos de la imagen.

Digi3D.NET programa los shaders de radiometría mediante el lenguaje de programación GLSL que son las siglas de OpenGL Shading Language, y este lenguaje se programación se caracteriza porque los programas no se pueden almacenar compilados, sino que los compila la tarjeta gráfica (el Driver de OpenGL más bien) en el mismo instante en el que cargamos el programa en la tarjeta gráfica.

Puedes localizar el código fuente del Fragment Shader que gestiona los parámetros radiométricos de visualización de Digi3D.NET en la ruta:

Sistema operativo Versión de Digi3D.NET Ruta
32 bits 32 bits %ProgramFiles%Digi21.netDigi3D2011FragmentShader.glsl
64 bits 64 bits %ProgramFiles%Digi21.netDigi3D2011FragmentShader.glsl
64 bits 32 bits %ProgramFiles (x86)%Digi21.netDigi3D2011FragmentShader.glsl

Este archivo es un archivo de texto que puedes editar con cualquier editor como el bloc de notas. Está programado en el lenguaje CLSL que es muy parecido al lenguaje de programación C.

Lo que más te va a sorprender si no sabes de programación de shaders es que el programa se ejecuta una vez por cada pixel de pantalla, si has leido bien, si nuestro monitor tiene 1920×1080 píxeles, cada vez que movamos la ventana de Digi3D.NET un único píxel, se ejecutará este programa 2073600 veces!!!!! y en tiempo real, seguro que si nuestra tarjeta no es muy lenta podremos llegar a los 140 frames por segundo sin ningún problema.

No es mi intención enseñarte a programar shaders, lo que si que puedo es recomendarte un libro, como es OpenGL Shading Language, pero si te puedo explicar un poquito el contenido del código y cómo modificarlo para hacer una broma o para investigar.

El código del shader es el siguiente:

// Fragment Shader para las transformaciones de color en Digi3D 2011-2012
// Desarrollado por José Ángel Martínez Torres - Dreaming With Objects S.L.
// www.digi21.net/digi3d
//

// Indica realizar una transformación por tabla de color. Si es verdadero no se ajustarán ni brillo, 
// ni contraste ni gamma, sino que se transformará el color de entrada
// en un color de salida.
// Lo activa por ejemplo la casilla de Niveles Automáticos. Si el usuario activa esta casilla, se 
// calcula una tabla de transformación de colores mediante el algoritmo
// indicado en http://en.wikipedia.org/wiki/Histogram_equalization
uniform bool aplicarTablaColor;
uniform vec3 tablaColor[256];

// En la variable brillo se almacena el desplazamiento a realizar en el brillo. Se admiten valores entre [-1,+1]
uniform float brillo;

// En la variable brillo se almacena el desplazamiento de contraste a aplicar. Se admiten valores entre [-1,+1]
uniform float contraste;

// La variable transformarTonoGris controla si se debe transformar la imagen a tonos de gris.
uniform bool transformarTonosGris;

// La variable negativo controla si se debe mostrar la imagen en negativo.
uniform bool negativo;

// El valor escalaColor indica el factor (que será potencia de 2) por el cual se debe escalar el color.
uniform float escalaColor;

// Indica si el usuario ha desplazado el control de Gamma.
// Documentación de Gamma en http://www.ivl.disco.unimib.it/Teaching/AIC-2010-specialistica/proof_paper_JEI.pdf
uniform float gamma;


// Fórmula del brillo contraste de The Gimp tal y como aparece en el artículo de la wikipedia
// http://en.wikipedia.org/wiki/Image_editing#Contrast_change_and_brightening
// Modificada para no calcular la tangente por cada componente
float CalculaValorBrilloContrasteRapido(float value, float brightness, float tangentePiCeroCinco)
{
    if (brightness < 0.0)
        value = value * ( 1.0 + brightness);
    else
        value = value + ((1.0 - value) * brightness);

    value = (value - 0.5) * tangentePiCeroCinco + 0.5;
    return value;
}

void main(void)
{
    vec4 colorTransformado = gl_Color;

    if( aplicarTablaColor ) {
        colorTransformado.r = tablaColor[int(gl_Color.r*255.0)].r;
        colorTransformado.g = tablaColor[int(gl_Color.g*255.0)].g;
        colorTransformado.b = tablaColor[int(gl_Color.b*255.0)].b;
    } else {
        if( brillo != 0.0 || contraste != 0.0) {
            float tangentePiCeroCinco = tan((contraste + 1.0) * 3.14159265358979323/4.0);
            colorTransformado.r = CalculaValorBrilloContrasteRapido(gl_Color.r, brillo, tangentePiCeroCinco);
            colorTransformado.g = CalculaValorBrilloContrasteRapido(gl_Color.g, brillo, tangentePiCeroCinco);
            colorTransformado.b = CalculaValorBrilloContrasteRapido(gl_Color.b, brillo, tangentePiCeroCinco);
        }

        if( 1.0 != escalaColor )
            colorTransformado *= vec4(escalaColor, escalaColor, escalaColor, 1.0);

        if( gamma != 1.0 )
            colorTransformado = pow(colorTransformado, vec4(1.0/gamma, 1.0/gamma, 1.0/gamma, 1.0));
    }

    if( negativo )
        colorTransformado = vec4(1.0, 1.0, 1.0, 0.0) - colorTransformado;

    if( transformarTonosGris ) {
        float iluminacion = colorTransformado.r * 0.299 + colorTransformado.g * 0.587 + colorTransformado.b * 0.114;
        colorTransformado = vec4(iluminacion, iluminacion, iluminacion, 1.0);
    }

    gl_FragColor = colorTransformado;
}

Como puedes comprobar, al principio se declaran una serie de variables (aplicarTablaColor, tablaColor, brillo, …) que son las que se modifican cuando el usuario interactua con los controles, y dentro de la función main tienes el código que realiza las correspondientes transformaciones.

Te recuerdo que este programa se ejecuta una vez por cada pixel a mostrar, y el objetivo de cualquier Fragment Shader es el de asignar la variable global gl_FragColor que es un tipo con cuatro componentes (rojo, verde, azul, alfa). El color original lo tenemos almacenado en la viable global gl_Color.

Vamos a modificar el Fragment Shader para que no se muestren colores ni verde ni azul, únicamente rojo, de esta manera conseguiremos ver el modelo de Bronchales (que es el que utilizo para la captura de pantalla del comienzo de la entrada) de color rojo. Para ello, voy a obtener el valor de iluminación (que como puedes ver en el código fuente original se obtiene multiplicando la componente roja del pixel por 0,299, la componente verde por 0,587 y la componente azul por 0,114, y vamos a indicar que este valor será el color a utilizar en la componente roja del color de salida.

A continuación el código fuente de nuestro Fragment Shader modificado…

void main(void)
{
    float iluminacion = gl_Color.r * 0.299 + gl_Color.g * 0.587 + gl_Color.b * 0.114;
    gl_FragColor = vec4(iluminacion, 0.0, 0.0, 1.0);
}

Digi3D 2011 ahora es Digi3D.NET

Debido al enfoque orientado al alquiler que estamos dando a nuestros productos, no tiene sentido el poner un número de versión al nombre de la aplicación, ya que los usuarios que alquilen un producto, tendrán siempre acceso a la versión con las últimas novedades. Por ello, y en el caso de Digi3D debido a la gran vinculación que tiene con .NET al ser completamente programable, hemos decidido cambiar el nombre de la aplicación que a partir de ahora pasa a llamarse Digi3D.NET. El módulo de CAD de la aplicación pasa a llamarse DigiNG.NET

Imágenes TIFF comprimidas con JPEG de 12 bits

La semana pasada estuvimos en una empresa en Portugal que trabajan con imágenes TIFF comprimidas con compresión JPEG y con una profundidad de color de 12 bits (el estándar JPEG permite compresiones de 8 y de 12 bits).

Digi3D 2011 utiliza para la lectura de archivos JPEG la librería LibJPEG, y para la lectura de archivos TIFF la librería LibTIFF. La librería LibTIFF se basa en la LibJPEG si se encuentra con un archivo TIFF comprimido con compresión JPEG.

La librería LibJPEG se puede compilar para trabajar con profundidades de color de 8 y de 12 bits, para seguir el estándar de JPEG, pero tiene un pequeño problema: no se puede compilar para 8 y 12 bits simultáneamente. Esto quiere decir que o tenemos una librería LibJPEG (y por lo tanto una LibTIFF) que puede descomprimir archivos JPEG de 8 bits o de 12, pero nunca simultáneamente. Esto hace que sea muy complicado desarrollar una aplicación que soporte simultáneamente JPEG de 8 y de 12 bits.

Por esta razón, Digi3D no puede cargar imágenes TIFF con JPEG de 12 bits. Si intentamos cargar una imagen TIFF comprimida en JPEG de 12 bits, Digi3D mostrará un cuadro de diálogo indicando que no se puede cargar la imagen porque no se soportan imágenes TIFF con compresión JPEG de 12 bits.

Actualizando la base de datos Epsg v7.9 para añadir transformaciones de cambio de datum ED50 -> ETRS89 y ED50 -> WGS84

Este post es avanzado, y supone que acabas de descargar una versión nueva de la base de datos EPSG y la has exportado al formato Microsoft SQL Server Compact tal y como se explica en el post Cómo se ha creado la base de datos geográfica EPSG en formato SQL Server Compact que se instala con Digi3D 2011.

La última versión de los archivos de rejilla de mínima curvatura NTv2 suministrados por el Instituto Geográfico Nacional data del 2009, sin embargo no existe ninguna transformación en la base de datos EPSG v7.9 (la mas moderna a día de hoy 17/04/2012) que utilice este archivo de mínima curvatura.

En este post te explico cómo modificar la base de datos para añadir una transformación que utilice el archivo de mínima curvatura actualizado.

La base de datos EPSG define 12 transformaciones para transformar entre los sistemas de coordenadas geográficos ED50 y ETRS89 y 40 transformaciones para transformar entre ED50 y WGS 84.

Puedes comprobarlo mediante las siguientes consultas SQL:

SELECT COUNT(*)
FROM Coordinate_Operation
WHERE SOURCE_CRS_CODE=4230 and TARGET_CRS_CODE=4258 and COORD_OP_TYPE='transformation';

SELECT COUNT(*)
FROM [Coordinate_Operation]
WHERE SOURCE_CRS_CODE=4230 and TARGET_CRS_CODE=4326 AND COORD_OP_TYPE='transformation';

Muchas de ellas consisten simplemente en desplazamientos geográficos (es decir, transformar de coordenadas geográficas a geocéntricas y realizar un desplazamiento en geocéntricas para luego volver a transformar a geográficas), por lo que tienen poca precisión.

De entre todos los algoritmos para transformar entre sistemas geográficos, el más preciso es el método interpolación mediante una rejilla de mínima curvatura. Esta rejilla le indica al programa: “Para este par de coordenadas latitud, longitud en el sistema de coordenadas de referencia ED50, le corresponde este otro par de coordenadas latitud, longitud en el sistema de coordenadas de referencia ETRS89”. Luego el programa tan solo tiene que interpolar mediante una interpolación bilineal. El resultado es muy preciso (20 cm para el caso de España).

Es responsabilidad de cada país/organismo crear su archivo de rejilla y de publicarlo. Cualquiera podría inventarse su propio formato de rejilla (lo que obligaría a que los desarrolladores de programas de cartografía y sistemas de información geográfica tuvieran que implementar un importador específico para cada formato de rejilla) pero existe uno estandarizado denominado NTv2.

En el caso de España, el organismo encargado de crear y actualizar ese archivo de rejilla es el Instituto Geográfico Nacional que publica este archivo a través de su página en internet: www.ign.es.

Descarga los archivos de rejilla entrando en www.ign.es: en el menú Herramientas de la página web, puedes seleccionar la opción: Rejilla para cambio de Datum entre ED50 y ETRS89 (en formato NTV2). Verás que puedes descargar dos rejillas: una para Península y otra para Baleares. Descarga el archivo Península, comprobarás que el nombre del archivo descargado es PENR2009.gsb.

Como la creación y mantenimiento de los archivos NTv2 depende del centro geográfico nacional de cada país, la base de datos EPSG no distribuye estos datos, sin embargo, Digi3D 2011 incorpora una copia de estos archivos en la carpeta %ProgramData%Digi3D 2011OpenGis, de modo que en ese directorio encontrarás el archivo PENR2009.gsb.

El único inconveniente es que la base de datos original EPSG (la que acabas de descargar de http://www.epsg.org/Geodetic.html no dispone de ninguna transformación que utilice este archivo, únicamente tiene transformaciones que utilizan versiones anteriores de ese archivo.

Vamos a comprobarlo:

La base de datos EPSG dispone de una tabla denominada ‘Coordinate_Operation Method’ que registra los códigos, nombres y descripciones de las distintas transformaciones.

Consultemos el código asociado al algoritmo NTv2 mediante la siguiente consulta SQL:

SELECT * FROM [Coordinate_Operation Method]
WHERE COORD_OP_METHOD_NAME='NTv2';

Puedes comprobar que el algoritmo NTv2 tiene asociado el código 9615.

Podemos consultar también los parámetros que recibe un determinado algoritmo. Comprobemos los parámetros que recibe el algoritmo 9615:

La base de datos EPSG dispone de una tabla ‘Coordinate_Operation Parameter Usage’ que nos indica los parámetros de cada algoritmo. Estos parámetros (como todo en la base de datos EPSG) tienen asignado un código. Disponemos de otra tabla ‘Coordinate_Operation Parameter’ que nos muestra una descripción de cada tipo de parámetro.

Para averiguar los parámetros que recibe la transformación con código 9615 podemos ejecutar la siguiente consulta SQL:

SELECT *
FROM [Coordinate_Operation Parameter Usage]
WHERE COORD_OP_METHOD_CODE=9615;

Eso nos devolverá un único registro indicando que el único parámetro que recibe el algoritmo 9615 es el parámetro cuyo código es el 8656.

Podemos consultar el significado de ese parámetro con la siguiente consulta SQL:

SELECT *
FROM [Coordinate_Operation Parameter]
WHERE PARAMETER_CODE=8656;

Por último, si quieres hacerlo bien, puedes hacerlo con una consulta JOIN de la siguiente manera:

SELECT *
FROM [Coordinate_Operation Parameter Usage] AS A
JOIN [Coordinate_Operation Parameter] AS B
ON A.PARAMETER_CODE = B.PARAMETER_CODE
WHERE A.COORD_OP_METHOD_CODE=9615;

De entre todas las posibles transformaciones (te recuerdo que había 12) entre ED50 y ETRS89 que define la base de datos EPSG, únicamente hay dos que utilicen el algoritmo 9615: La transformación 15895: ED50 to ETRS89 (11) y la operación 15932: ED50 to ETRS89 (12).

Puedes comprobarlo mediante la siguiente consulta SQL:

SELECT *
FROM Coordinate_Operation
WHERE SOURCE_CRS_CODE=4230 and TARGET_CRS_CODE=4258 and COORD_OP_TYPE='transformation' AND COORD_OP_METHOD_CODE=9615;

Si nos leemos los comentarios de estas dos transformaciones, rápidamente averiguamos que la transformación 15895 ha sido sustituida por la 15932, de modo que la que nos interesará utilizar es la 15932, pero tal y como vamos a comprobar muy pronto, esta transformación no nos sirve, pues el archivo de rejilla a que utiliza esta transformación no es “PENR2009.gsb”.

Los parámetros de las transformaciones se almacenan en la tabla ‘Coordinate_Operation Parameter Value’.

Esta tabla almacena los parámetros de todos los algoritmos utilizados en todas las posibles transformaciones especificadas en la base de datos EPSG. Actualmente tiene 15743 registros.

Cada registro tiene varios campos:

COORD_OP_CODE COORD_OP_METHOD_CODE PARAMETER_CODE PARAMETER_VALUE PARAM_VALUE_FILE_REF UOM_CODE

Si comprobamos los registros de esta tabla para el código de operación 15932, comprobaremos que el nombre del archivo de rejilla asignado para esa operación es “SPED2ETV2.gsb”.

SELECT * FROM [Coordinate_Operation Parameter Value] WHERE COORD_OP_CODE=15932;

Por lo tanto esta operación no nos sirve. El archivo “SPED2ETV2.gsb” es el nombre que tenía la versión antigua de los archivos de rejilla, de hecho, la operación 15932 se añadió a la base de datos EPSG con fecha 27-03-2007, y el nombre de archivo “PENR2009” nos hace pensar que este archivo se creó en el año 2009.

Podrías pensar que una solución sería modificar este registro de la base de datos y cambiar la palabra “SPED2ETV2.gsb” por “PENR2009.gsb”, pero esto no se puede hacer porque la base de datos EPSG es inmutable. No se permiten cambios. Podemos añadir información, transformaciones, sistemas de coordenadas, pero nunca cambiar nada.

Así que no nos queda más remedio que crear una transformación nueva.

En la documentación de EPSG te indican que si quieres añadir información, utilices siempre códigos con valores superiores a 32767, por lo tanto vamos a crear una transformación con código 32768 que nos servirá para transformar entre los sistemas de coordenadas geográficos ED50 (4230) y ETRS89 (4326), para la zona de España con el algoritmo 9615 y utilizando como archivo de rejilla NTv2 el archivo “PENR2009.gsb”.

Para ello ejecutaremos la consulta:

INSERT INTO Coordinate_Operation (COORD_OP_CODE, COORD_OP_NAME, COORD_OP_TYPE, SOURCE_CRS_CODE, TARGET_CRS_CODE, COORD_TFM_VERSION, COORD_OP_VARIANT, AREA_OF_USE_CODE, COORD_OP_SCOPE, COORD_OP_ACCURACY, COORD_OP_METHOD_CODE, REMARKS, INFORMATION_SOURCE, DATA_SOURCE, REVISION_DATE, SHOW_OPERATION, DEPRECATED)
VALUES (32768, 'ED50 a ETRS89 (14)', 'transformation', 4230, 4258, 'IGN-Esp v3', 14, 3429, 'For applications to an accuracy of 10-15cm (95% confidence) for Spain mainland and about 4cm (95%) for Balearic Islands.',0.2,9615,'Reemplaza a ED50 to ETRS89(12)','Instituto Geográfico Nacional, www.ign.es', 'OGP', 2009-01-01, 1, 0);

Y ya puestos, y considerando que el sistema de coordenadas geográfico ETRS89 es idéntico al WGS84, vamos a crear una transformación para transformar entre los sistemas de coordenadas geográficos ED50 (4230) y WGS84 (4326), esta vez con código 32769 con la siguiente consulta:

INSERT INTO Coordinate_Operation (COORD_OP_CODE, COORD_OP_NAME, COORD_OP_TYPE, SOURCE_CRS_CODE, TARGET_CRS_CODE, COORD_TFM_VERSION, COORD_OP_VARIANT, AREA_OF_USE_CODE, COORD_OP_SCOPE, COORD_OP_ACCURACY, COORD_OP_METHOD_CODE, REMARKS, INFORMATION_SOURCE, DATA_SOURCE, REVISION_DATE, SHOW_OPERATION, DEPRECATED)
VALUES (32769, 'ED50 a WGS84 (43)', 'transformation', 4230, 4326, 'IGN-Esp v3', 43, 3429, 'For applications to an accuracy of 10-15cm (95% confidence) for Spain mainland and about 4cm (95%) for Balearic Islands.',0.2,9615,'Valor de los parámetros de la transformación ED50 a ETRS89 (14). Asume que ETRS89 y WGS 84 se consideran iguales dentro de la precisión de la transformación. Reemplaza ED50 to WGS 84 (41)','Instituto Geográfico Nacional, www.ign.es', 'OGP', 2009-01-01, 1, 0);

Tan solo nos queda añadir en la tabla ‘Coordinate_Operation Parameter Value’ los parámetros para estas dos transformaciones.

Para ello tan solo tenemos que ejecutar las consultas:

INSERT INTO [Coordinate_Operation Parameter Value]
VALUES (32768, 9615, 8656, NULL, 'PENR2009.gsb', NULL);

INSERT INTO [Coordinate_Operation Parameter Value]
VALUES (32769, 9615, 8656, NULL, 'PENR2009.gsb', NULL);

y ya lo tenemos. Ahora cuando Digi3D detecte que tiene que transformar entre los sistemas de coordenadas de referencia ED50 y ETRS89 o ED50 y WGS 84 nos mostrará esta transformacion en el cuadro de diálogo de posibles transformaciones.

Cómo se ha creado la base de datos geográfica EPSG en formato SQL Server Compact que se instala con Digi3D 2011

Estoy terminando de implementar los sistemas de cordenadas de referencia en Digi3D 2011, y me he encontrado con un problema inesperado: Las consultas SQL que debe ejecutar Digi3D 2011 para realizar determinadas consultas sobre la base de datos geográfica varían en función de si la base de datos está almacenada en un archivo .mdb (de Microsoft Access) o está alojada en una instancia de Microsoft SQL Server.

La base de datos geográfica en formato .mdb se puede utilizar en las versiones de 32 bits de Digi3D 2011 sin ningún problema. Las versiones de 64 bits no tienen esa suerte, ya que no es posible que un programa de 64 bits se conecte con un archivo en formato .mdb.

La única manera que tenían las versiones de 64 bits de conectarse con esa base de datos era creando una base de datos SQL Server y configurar el programa para que se conecte con esta base de datos en vez de con el archivo local .mdb. Tienes instrucciones de cómo realizar esa tarea en el post Base de datos EPSG en Digi3D 2011 edición de 64 Bits.

El problema ha surgido porque con la versión que liberaré esta semana (me imagino que el día 25 a 27 de enero de 2012) en ciertas consultas es necesario saber si el usuario ha marcado alguna operación como visible o no.

Si en un determinado momento Digi3D 2011 necesita transformar una coordenada de un sistema de coordenadas de referencia a otro, tiene que realizar una consulta SQL sobre la base de datos geográfica y ésta le indica de todas las operaciones (cada una con mejor o peor precisión) que existen para transformar coordenadas entre los dos sistemas.

Si se localiza más de una operación, Digi3D 2011 muestra un cuadro de diálogo al usuario indicando que se han localizado múltiples métodos, invitándole a que seleccione el más apropiado.

En ocasiones no queremos que Digi3D 2011 muestre todas las posibles opciones, como por ejemplo en el caso de transformar entre los sistemas de coordenadas de referencia ED50 y ETRS89: siempre nos interesará utilizar la operación que utiliza el algoritmo NTv2 y nunca las que utilizan desplazamientos geocéntricos.

La base de datos dispone de un campo denominado SHOW_OPERATION que en Access es de tipo booleano, pero que en SQL Server se convierte a campo de tipo bit.

Y el problema surgue aquí: Si queremos localizar todas las transformaciones entre los sistemas de coordenadas 4230 y 4258 que sean visibles, con SQL Server tenemos que ejecutar la siguiente consulta:

SELECT *
FROM Coordinate_Operation
WHERE SOURCE_CRS_CODE=4230
AND TARGET_CRS_CODE=4258
AND COORD_OP_TYPE='transformation'
AND SHOW_OPERATION=1

Sin embargo, si la base de datos no está ubicada en un SQL Server, sino que estamos conectados con el .mdb la consulta se realiza de esta otra forma:

SELECT *
FROM Coordinate_Operation
WHERE SOURCE_CRS_CODE=4230
AND TARGET_CRS_CODE=4258
AND COORD_OP_TYPE='transformation'
AND SHOW_OPERATION=True

Si te fijas hay una pequeña diferencia: en SQL Server utilizamos un 1 para filtrar los registros que tienen el campo SHOW_OPERATION a activo, sin embargo con Access tenemos que utilizar un True.

La solución más obvia es olvidarme del archivo .mdb que está desfasado (fíjate cómo de desfasado está que los señores de Microsoft directamente no te dejan conectarte con él en las versiones de 64 bits), pero eso obligaría a instalar un SQL Server Express junto con cada Digi3D 2011. Hasta ahora, así ha sido para las versiones de 64 bits de Digi3D 2011: había que instalar un SQL Server Express (o mejor) en el equipo o en la red de la empresa para que Digi3D 2011 se pudiera conectar con la base de datos geográfica.

Como no quiero forzar a instalar un SQL Server en cada equipo donde se instale Digi3D 2011 (porque habrá entornos en los que sencillamente no se puede, como centros geográficos nacionales con mucha seguridad), no queda más remedio que probar una tercera opción: Convertir la base de datos EPSG a formato Microsoft SQL Server Compact Edition, que es digámoslo así el sustituto de los obsoletos .mdb.

Este formato es un SQL Server en un archivo (con extensión .sdf) y está pensado para mono usuario y tiene la ventaja de que no hay que instalar un servidor, con copiar un par de DLLs junto con la instalación de Digi3D 2011 sobra.

El problema es que no existe ningún asistente, importador o exportador en Microsoft SQL Server Management Studio que convierta o un .mdb o una base de datos .mdf (las de Microsoft SQL Server) en un archivo .sdf.

Se me ocurren tres soluciones:

  1. Crear un guión (pulsando con el botón derecho del ratón en la base de datos EPSG en el panel Object Explorer de Microsoft SQL Server Management Studio, y seleccionando la opción Tasks/Generate scripts… del menú contextual. Crear una nueva base de datos en formato Microsoft SQL Server Compact y ejecutar sobre esta nueva base de datos el guión.
  2. Localizar alguna herramienta por Internet que convierta una base de datos .mdf (la extensión que tienen las bases de datos Microsoft SQL Server) en una con extensión .sdf.
  3. Programar una utilidad que realice la tarea.

La primera solución es compleja, pues el SQL que se genera en el guión no es compatible con SQL Server Compact y habría que corregirlo: añadir por puntos y comas al final de cada entrada, eliminar las cláusulas GO, el comando print que aparece en el guión cada X líneas, …).

La segunda opción es mucho más sencilla siempre y cuando exista alguna utilidad por internet.

La tercera es la última opción, pues debe de existir alguna utilidad por internet, ¡y la hay!, si buscas en Google localizarás un programa denominado SDF Viewer que nos va a solucionar la papeleta. Esta herramienta es de pago, pero permite que la utilicemos 15 días (tiempo más que de sobra para realizar esta práctica).

Vamos a ver cómo he construido la base de datos con extensión .sdf que se copia junto con la instalación de Digi3D 2011 (en la carpeta %ProgramData%Digi3D 2011epsg.sdf).

  1. Descárga e instala la aplicación SDF Viewer.
  2. Ejecuta la aplicación SDF Viewer.
  3. Aparecerá un cuadro de diálogo indicando que quedan X días de prueba. Pulsa la opción Ask Later.
  4. En Tools pulsa la opción From SQL Server.
  5. En el cuadro de diálogo Import From SQL Server, en el campo Server name: teclea la dirección de tu servidor Microsoft SQL Server en el cual tienes la base de datos EPSG (aquella que importaste si seguiste los pasos del post Base de datos EPSG en Digi3D 2011 edición de 64 Bits). Usualmente aquí tienes que poner .sqlexpress
  6. En Authentication: selecciona el método de autenticación de tu instancia de SQL Server. Por defecto es Windows Authentication.
  7. Pulsa el botón Connect.
  8. En Database selecciona la base de datos EPSG.
  9. En Tables pulsa el botón Select All.
  10. Ásegúrate de que está seleccionado el checkbox titulado Include Data.
  11. Pulsa el botón Script.
  12. En el cuadro de diálogo común Guardar Como indica la ubicación al archivo .sqlce que va a generar el programa SDF Viewer con el SQL necesario para crear las tablas y los datos.
  13. Cierra el programa SDF Viewer.

Bien, ahora vamos a crear una base de datos nueva en formato Microsoft SQL Server Compact y la rellenaremos con la información generara con el programa SDF Viewer.

  1. Ejecuta Microsoft SQL Server Management Studio.
  2. En el cuadro de diálogo Connect to Server, en el campo Server type, selecciona SQL Server Compact.
  3. En el campo Database file despliega la lista y selecciona <New database>.
  4. En el cuadro de diálogo Create New SQL Server Compact Database, selecciona la ruta donde crear la base de datos SQL Server Compact y pulsa OK.
  5. Aparecerá un cuadro de diálogo indicando que si estás seguro de crear la base de datos sin protección por contraseña. Confirma pulsando Yes.
  6. Ya está creada la base de datos, pero volverá a aparecer el cuadro de diálogo Create New SQL Server Compact Database. Pulsa Cancel.
  7. Ahora aparecerá el cuadro de diálogo Connect to Server con la ruta a la base de datos que acabas de crear. Pulsa el botón Connect para conectarte a ella.
  8. Arrastra y suelta el archivo .sqlce que creaste en la sección anterior.
  9. Pulsa el botón Execute.

Ya tienes creada la base de datos EPSG en formato Microsoft SQL Server Compact.

El instalador no solo copia esta base de datos en %ProgramData%Digi3D 2011EPSG, sino que además almacena en el registro la ubicación de esta base de datos.

En función de si la versión de Digi3D 2011 es de 32 o de 64 bits la ubicación de la ruta a la base de datos se almacenará en una u otra entradas del registo.
A continuación tienes una tabla que indica dónde se almacena en el registro la cadena de conexión a la base de datos geográfica.

Digi3D 2011 edición de 32 bits Digi3D 2011 edición de 64 bits
HKEY_LOCAL_MACHINESOFTWAREDigi21Digi3D2011AppConfigurationEPSGConnectionString HKEY_LOCAL_MACHINESOFTWAREWow6432NodeDigi21Digi3D2011AppConfigurationEPSGConnectionString

Solucionando problemas al instalar Digi3D 2011

Si al instalar Digi3D 2011 la instalación se queda bloqueada por mucho tiempo, aparecerá un mensaje de error indicando que se ha localizado el error número 1935 0x800736FD.

Este error es producido porque se ha agotado el espacio de almacenamiento en el registro de Windows.
Para solucionarlo, tendremos que incrementar el tamaño del registro de Windows siguiendo los siguientes pasos:

  1. Abrimos el editor de registro de Windows (Inicio/Ejecutar y tecleamos “regedit”.
  2. Seleccionamos la rama HKEY_LOCAL_MACHINESystemCurrentControlSetControl
  3. Comprobamos si existe en la parte derecha del editor del registro la clave RegistrySizeLimit. Si no existe, la creamos de tipo DWORD.
  4. Asignamos a esta clave el valor: FFFFFFFF en hexadecimal.
  5. Reiniciamos el ordenador.
  6. Ya podemos instalar Digi3D 2011.