Nueva orientación absoluta serializada como una cadena Well Known Text

Tal y como te explico en el post Novedades en el cálculo de orientaciones absolutas en el blog de novedades de Digi3D.NET, ahora el programa realiza el cálculo de las orientaciones absolutas en un sistema intermedio.

La decisión de en qué sistema se calcula la orientación explicada en el enlace anterior. Lo que te voy a explicar aquí es cómo se almacenan en el archivo .abs.xml las operaciones matemáticas necesarias para transformar un punto Terreno a Local y de Local a Modelo.

Una opción hubiera sido no almacenar en el archivo .abs.xml ninguna transformación, sino haber almacenado simplemente una cadena WKT con la definición del sistema de coordenadas de referencia de los puntos de apoyo por un lado y del sistema intermedio por otro y que luego la orientación absoluta al cargarse en memoria crease las transformaciones necesarias en función de esos datos, pero esa solución no es válida, pues no existen sistemas de coordenadas de referencia topocéntricos. Puedes crear un sistema topocéntrico en cualquier sitio, con origen en cualquier coordenada, de modo que hay infinitos sistemas topocéntricos y lógicamente no aparece ninguna en la base de datos EPSG.

De modo que la solución no es almacenar en el archivo de orientación el sistema de coordenadas de referencia intermedio, sino almacenar la serie de operaciones necesarias para transformar del sistema de coordenadas de referencia de los puntos de apoyo (que siempre será conocido, aunque sea local, pero es conocido) al sistema intemedio, que puede ser o no uno estándar, nos da igual, porque no nos interesa almacenar el sistema, sino las operaciones para llegar a él, y lo mismo del sistema intermedio al sistema modelo.

Podríamos haber almacenado estas transformaciones en un formato inventado, pero Digi3D.NET implementa el estándar Coordinate Transformation Services del Open Geospatial Consortium y eso significa que Digi3D.NET puede crear una cadena de texto Well Known Text a partir de una serie de transformaciones y al revés, puede crear en memoria una serie de transformaciones a partir de la información de una cadena Well Known Text.

Las operaciones matemáticas definidas en el estándar Coordinate Transformation Services son muy restrictivas, y todas ellas cumplen una serie de propiedades:

  1. Las operaciones que trabajan con coordenadas geográficas, siempre esperan recibir primero una longitud y luego la latitud, nunca al revés.
  2. Las operaciones que trabajan con coordenadas geográficas, siempre reciben las coordenadas en grados sexagesimales, y devuelves sexagesimales. Nunca reciben ni radianes ni centesimales.
  3. Cada operación informa del número coordenadas que recibe y del número de coordenadas que devuelve.

    Hay operaciones que reciben una coordenada y devuelven otra, como por ejemplo la operación vertical_offset que recibe una coordenada Z y devuelve otra coordenada Z, hay otras operaciones que reciben tres coordenadas y devuelven una, como por ejemplo la operación Geographic3DToGravityRelatedHeightEGM, que recibe una longitud/latitud/altitud y que devuelven una coordenada Z ortométrica, y así sucesivamente.

No se pueden pasar tres coordenadas a una operación que espera recibir dos, pues se lanzará una excepción. Digi3D.NET tiene en cuenta todos estos factores, y eso se ve reflejado en la cadena que aparece en el archivo .abs.xml>.

El estándar Coordinate Transformation Services da nombres a las distintas operaciones, ya hemos visto alguna, como vertical_offset o Geographic3DToGravityRelatedHeightEGM. Hay muchas, algunas para realizar operaciones de proyecciones de coordenadas, como transverse_mercator, cassini_soldner, … y existen dos en particular que utiliza mucho Digi3D.NET para resolver el problema de llamar a una función que recibe dos coordenadas cuando tengo tres por ejemplo.

Affine

Esta operación básicamente crea una transformación afín a partir de una matriz. Si el número de dimensiones de entrada es M y el número de dimensiones de salida es N, entonces la matriz tendrá un tamaño de [N+1][M+1]. El +1 en las dimensiones de la matriz permiten a la matriz realizar un desplazamiento además de una rotación.

Podemos utilizar una afín para mover una coordenada de posición. Digi3D.NET en ocasiones decide que tiene que cambiar el orden de la coordenada Z de X,Y,Z a Z,X,Y. Para ello utiliza la siguiente matriz:

0 0 1 0
1 0 0 0
0 1 0 0
0 0 0 1

Y al revés, transformar de Z,X,Y a X,Y,Z utilizando la siguiente matriz:

0 1 0 0
0 0 1 0
1 0 0 0
0 0 0 1

La orientación afín nos permite cambiar de dimensiones, de manera que si queremos una matriz que transforme las coordenadas X,Y,Z en X,Y, es decir, eliminar una dimensión, podemos aplicar la siguiente afín:

1 0 0 0
0 1 0 0
0 0 0 1

o justo lo contrario, en ocasiones, Digi3D.NET tiene que duplicar alguna coordenada, como por ejemplo pasar de X,Y,Z a X,Y,X,Y,Z mediante la siguiente matriz:

1 0 0 0
0 1 0 0
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1

Passthrough

Esta operación permite ejecutar una operación matemática sobre un subconjunto de coordenadas de entre las que recibe como parámetros.

Esta operación matemática recibe dos parámetros:

  1. El número de coordenadas a saltar de entre las coordenadas recibidas para hacer la transformación.
  2. Una operación matemática a realizar con el resto de coordenadas recibidas para hacer la transformación.

Con un ejemplo lo vas a entender mejor:

Supongamos que tenemos las coordenadas X,Y,Z y queremos llamar a la operación matemática lambert_to_elipsoid (que debe recibir únicamente las coordenadas X,Y y devuelve lontigud, latitud.

No podemos llamar a lambert_to_elipsoid y pasarle nuestras coordenadas X,Y,Z, pues esta operación matemática lanzará una excepción si le pasamos tres parámetros. Recibe 2 y devuelve 2. No es posible saltarse esta restricción.

Si Digi3D.NET se encuentra con este caso realizará las siguientes operaciones:

  1. Convertir la coordenada X,Y,Z en Z,X,Y (mediante una afín de las que hemos visto en el punto anterior).
  2. Llamar a la operación PASSTHROUGH(1, lambert_to_elipsoid). Esto devolverá Z,longitud,latitud.
  3. Convertir la coordenada Z,longitud,latitud en longitud,latitud,Z (mediante una afín de las que hemos visto en el punto anterior).

En ocasiones hay que transformar la coordenada Z (por ejemplo transformarla de elipsoidal a ortométrica). Existen dos tipos de operaciones matemáticas en lo referente a la coordenada Z:

  1. Las que reciben una coordenada Z y devuelven una coordenada Z’
  2. Las que reciben tres coordenadas X,Y,Z y devuelven una coordenada Z’.

El primer caso es trivial: si tenemos X,Y,Z y queremos X,Y,Z’, tan solo tenemos que llamar a la operación matemática que transforma la coordenada Z en Z’ mediante un PASSTHROUGH(2, operación_matemática), pero el otro caso requiere duplicar las coordenadas XY mediante el siguiente algoritmo:

  1. Convertimos X,Y,Z en X,Y,X,Y,Z mediante una operación afín.
  2. Llamamos a la operación que convierte de X,Y,Z a Z’ mediante un PASSTHROUGH(2, operación matemática)

A continuación tienes el contenido de una orientación absoluta hipotética de un sensor satelital en el que las coordenadas de los puntos de apoyo están en el sistema de coordenadas de referencia Merchich / Sud Maroc + EGM2008 geoid height y las coordenadas del sensor obviamente en WGS 84 3D.

<?xml version='1.0' encoding='ISO-8859-1'?>
<absolute xmlns='http://schemas.digi21.net/Digi3D/AbsoluteOrientation/v1.0' translationX='14013454.46506193800000000000' translationY='-1477144.60782388760000000000' translationZ='9031256.06252797320000000000' controlPointCoordinateSystem='COMPD_CS["Merchich / Sud Maroc + EGM2008 geoid height",PROJCS["Merchich / Sud Maroc",GEOGCS["Merchich",DATUM["Merchich",SPHEROID["Clarke 1880 (IGN)",6378249.2,293.4660212936269,AUTHORITY["EPSG","7011"]],AUTHORITY["EPSG","6261"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["°",0.01745329251994328,AUTHORITY["EPSG","9122"]],AXIS["Lat",North],AXIS["Long",East],AUTHORITY["EPSG","4261"]],PROJECTION["Lambert_Conformal_Conic_1SP"],PARAMETER["latitude_of_origin",29.69999999999997],PARAMETER["central_meridian",-5.399999999999994],PARAMETER["scale_factor",0.9996155960000001],PARAMETER["false_easting",500000],PARAMETER["false_northing",300000],PARAMETER["semi_major",6378249.2],PARAMETER["semi_minor",6356515],UNIT["metros",1,AUTHORITY["EPSG","9001"]],AXIS["X",East],AXIS["Y",North],AUTHORITY["EPSG","26192"]],VERT_CS["EGM2008 geoid height",VERT_DATUM["EGM2008 geoid",2005,AUTHORITY["EPSG","1027"]],UNIT["metros",1,AUTHORITY["EPSG","9001"]],AXIS["H",Up],AUTHORITY["EPSG","3855"]]]' mathTransformGroundToLocal='CONCAT_MT[PARAM_MT["Affine", PARAMETER["num_row",4], PARAMETER["num_col", 4],PARAMETER["elt_0_0", 0],PARAMETER["elt_0_1", 0],PARAMETER["elt_0_2", 1],PARAMETER["elt_0_3", 0],PARAMETER["elt_1_0", 1],PARAMETER["elt_1_1", 0],PARAMETER["elt_1_2", 0],PARAMETER["elt_1_3", 0],PARAMETER["elt_2_0", 0],PARAMETER["elt_2_1", 1],PARAMETER["elt_2_2", 0],PARAMETER["elt_2_3", 0],PARAMETER["elt_3_0", 0],PARAMETER["elt_3_1", 0],PARAMETER["elt_3_2", 0],PARAMETER["elt_3_3", 1]],PASSTHROUGH_MT[1,CONCAT_MT[INVERSE_MT[PARAM_MT["Lambert_Conformal_Conic_1SP",PARAMETER["latitude_of_origin",29.69999999999997],PARAMETER["central_meridian",-5.399999999999994],PARAMETER["scale_factor",0.9996155960000001],PARAMETER["false_easting",500000],PARAMETER["false_northing",300000],PARAMETER["semi_major",6378249.2],PARAMETER["semi_minor",6356515]]],PARAM_MT["Affine", PARAMETER["num_row",3], PARAMETER["num_col", 3],PARAMETER["elt_0_0", 0],PARAMETER["elt_0_1", 1],PARAMETER["elt_0_2", 0],PARAMETER["elt_1_0", 1],PARAMETER["elt_1_1", 0],PARAMETER["elt_1_2", 0],PARAMETER["elt_2_0", 0],PARAMETER["elt_2_1", 0],PARAMETER["elt_2_2", 1]]]],PARAM_MT["Affine", PARAMETER["num_row",4], PARAMETER["num_col", 4],PARAMETER["elt_0_0", 0],PARAMETER["elt_0_1", 1],PARAMETER["elt_0_2", 0],PARAMETER["elt_0_3", 0],PARAMETER["elt_1_0", 0],PARAMETER["elt_1_1", 0],PARAMETER["elt_1_2", 1],PARAMETER["elt_1_3", 0],PARAMETER["elt_2_0", 1],PARAMETER["elt_2_1", 0],PARAMETER["elt_2_2", 0],PARAMETER["elt_2_3", 0],PARAMETER["elt_3_0", 0],PARAMETER["elt_3_1", 0],PARAMETER["elt_3_2", 0],PARAMETER["elt_3_3", 1]],PARAM_MT["Affine", PARAMETER["num_row",4], PARAMETER["num_col", 4],PARAMETER["elt_0_0", 0],PARAMETER["elt_0_1", 1],PARAMETER["elt_0_2", 0],PARAMETER["elt_0_3", 0],PARAMETER["elt_1_0", 1],PARAMETER["elt_1_1", 0],PARAMETER["elt_1_2", 0],PARAMETER["elt_1_3", 0],PARAMETER["elt_2_0", 0],PARAMETER["elt_2_1", 0],PARAMETER["elt_2_2", 1],PARAMETER["elt_2_3", 0],PARAMETER["elt_3_0", 0],PARAMETER["elt_3_1", 0],PARAMETER["elt_3_2", 0],PARAMETER["elt_3_3", 1]],PASSTHROUGH_MT[2,INVERSE_MT[PARAM_MT["vertical_offset", PARAMETER["vertical_offset",0.000000]]]],PARAM_MT["Ellipsoid_To_Geocentric", PARAMETER["semi_major",6378249.2], PARAMETER["semi_minor", 6356515]]]' mathTransformLocalToGround='CONCAT_MT[PARAM_MT["Geocentric_To_Ellipsoid", PARAMETER["semi_major",6378249.2], PARAMETER["semi_minor", 6356515]],PASSTHROUGH_MT[2,PARAM_MT["vertical_offset", PARAMETER["vertical_offset",0.000000]]],PARAM_MT["Affine", PARAMETER["num_row",4], PARAMETER["num_col", 4],PARAMETER["elt_0_0", 0],PARAMETER["elt_0_1", 1],PARAMETER["elt_0_2", 0],PARAMETER["elt_0_3", 0],PARAMETER["elt_1_0", 1],PARAMETER["elt_1_1", 0],PARAMETER["elt_1_2", 0],PARAMETER["elt_1_3", 0],PARAMETER["elt_2_0", 0],PARAMETER["elt_2_1", 0],PARAMETER["elt_2_2", 1],PARAMETER["elt_2_3", 0],PARAMETER["elt_3_0", 0],PARAMETER["elt_3_1", 0],PARAMETER["elt_3_2", 0],PARAMETER["elt_3_3", 1]],PARAM_MT["Affine", PARAMETER["num_row",4], PARAMETER["num_col", 4],PARAMETER["elt_0_0", 0],PARAMETER["elt_0_1", 0],PARAMETER["elt_0_2", 1],PARAMETER["elt_0_3", 0],PARAMETER["elt_1_0", 1],PARAMETER["elt_1_1", 0],PARAMETER["elt_1_2", 0],PARAMETER["elt_1_3", 0],PARAMETER["elt_2_0", 0],PARAMETER["elt_2_1", 1],PARAMETER["elt_2_2", 0],PARAMETER["elt_2_3", 0],PARAMETER["elt_3_0", 0],PARAMETER["elt_3_1", 0],PARAMETER["elt_3_2", 0],PARAMETER["elt_3_3", 1]],PASSTHROUGH_MT[1,CONCAT_MT[PARAM_MT["Affine", PARAMETER["num_row",3], PARAMETER["num_col", 3],PARAMETER["elt_0_0", 0],PARAMETER["elt_0_1", 1],PARAMETER["elt_0_2", 0],PARAMETER["elt_1_0", 1],PARAMETER["elt_1_1", 0],PARAMETER["elt_1_2", 0],PARAMETER["elt_2_0", 0],PARAMETER["elt_2_1", 0],PARAMETER["elt_2_2", 1]],PARAM_MT["Lambert_Conformal_Conic_1SP",PARAMETER["latitude_of_origin",29.69999999999997],PARAMETER["central_meridian",-5.399999999999994],PARAMETER["scale_factor",0.9996155960000001],PARAMETER["false_easting",500000],PARAMETER["false_northing",300000],PARAMETER["semi_major",6378249.2],PARAMETER["semi_minor",6356515]]]],PARAM_MT["Affine", PARAMETER["num_row",4], PARAMETER["num_col", 4],PARAMETER["elt_0_0", 0],PARAMETER["elt_0_1", 1],PARAMETER["elt_0_2", 0],PARAMETER["elt_0_3", 0],PARAMETER["elt_1_0", 0],PARAMETER["elt_1_1", 0],PARAMETER["elt_1_2", 1],PARAMETER["elt_1_3", 0],PARAMETER["elt_2_0", 1],PARAMETER["elt_2_1", 0],PARAMETER["elt_2_2", 0],PARAMETER["elt_2_3", 0],PARAMETER["elt_3_0", 0],PARAMETER["elt_3_1", 0],PARAMETER["elt_3_2", 0],PARAMETER["elt_3_3", 1]]]' mathTransformModelToLocal='CONCAT_MT[PARAM_MT["Affine", PARAMETER["num_row",4], PARAMETER["num_col", 4],PARAMETER["elt_0_0", 0],PARAMETER["elt_0_1", 1],PARAMETER["elt_0_2", 0],PARAMETER["elt_0_3", 0],PARAMETER["elt_1_0", 1],PARAMETER["elt_1_1", 0],PARAMETER["elt_1_2", 0],PARAMETER["elt_1_3", 0],PARAMETER["elt_2_0", 0],PARAMETER["elt_2_1", 0],PARAMETER["elt_2_2", 1],PARAMETER["elt_2_3", 0],PARAMETER["elt_3_0", 0],PARAMETER["elt_3_1", 0],PARAMETER["elt_3_2", 0],PARAMETER["elt_3_3", 1]],PARAM_MT["Affine", PARAMETER["num_row",4], PARAMETER["num_col", 4],PARAMETER["elt_0_0", 1],PARAMETER["elt_0_1", 0],PARAMETER["elt_0_2", 0],PARAMETER["elt_0_3", 0],PARAMETER["elt_1_0", 0],PARAMETER["elt_1_1", 1],PARAMETER["elt_1_2", 0],PARAMETER["elt_1_3", 0],PARAMETER["elt_2_0", 0],PARAMETER["elt_2_1", 0],PARAMETER["elt_2_2", 1],PARAMETER["elt_2_3", 0],PARAMETER["elt_3_0", 0],PARAMETER["elt_3_1", 0],PARAMETER["elt_3_2", 0],PARAMETER["elt_3_3", 1]],PARAM_MT["Ellipsoid_To_Geocentric", PARAMETER["semi_major",6378137], PARAMETER["semi_minor", 6356752.314245179]]]' mathTransformLocalToModel='CONCAT_MT[PARAM_MT["Geocentric_To_Ellipsoid", PARAMETER["semi_major",6378137], PARAMETER["semi_minor", 6356752.314245179]],PARAM_MT["Affine", PARAMETER["num_row",4], PARAMETER["num_col", 4],PARAMETER["elt_0_0", 1],PARAMETER["elt_0_1", 0],PARAMETER["elt_0_2", 0],PARAMETER["elt_0_3", 0],PARAMETER["elt_1_0", 0],PARAMETER["elt_1_1", 1],PARAMETER["elt_1_2", 0],PARAMETER["elt_1_3", 0],PARAMETER["elt_2_0", 0],PARAMETER["elt_2_1", 0],PARAMETER["elt_2_2", 1],PARAMETER["elt_2_3", 0],PARAMETER["elt_3_0", 0],PARAMETER["elt_3_1", 0],PARAMETER["elt_3_2", 0],PARAMETER["elt_3_3", 1]],PARAM_MT["Affine", PARAMETER["num_row",4], PARAMETER["num_col", 4],PARAMETER["elt_0_0", 0],PARAMETER["elt_0_1", 1],PARAMETER["elt_0_2", 0],PARAMETER["elt_0_3", 0],PARAMETER["elt_1_0", 1],PARAMETER["elt_1_1", 0],PARAMETER["elt_1_2", 0],PARAMETER["elt_1_3", 0],PARAMETER["elt_2_0", 0],PARAMETER["elt_2_1", 0],PARAMETER["elt_2_2", 1],PARAMETER["elt_2_3", 0],PARAMETER["elt_3_0", 0],PARAMETER["elt_3_1", 0],PARAMETER["elt_3_2", 0],PARAMETER["elt_3_3", 1]]]'>
    <matrix omega='3.56928506875955740000' phi='-6.94752310306991740000' kappa='-156.36142599315596000000' scale='1.62608831756480400000'>
        <m row='0' col='0'>-0.76951445000824426000</m>
        <m row='0' col='1'>-0.62731999435274888000</m>
        <m row='0' col='2'>-0.11965423483427851000</m>
        <m row='1' col='0'>0.62927342674164544000</m>
        <m row='1' col='1'>-0.77676685562447978000</m>
        <m row='1' col='2'>0.02545989788050484500</m>
        <m row='2' col='0'>-0.10891494674899546000</m>
        <m row='2' col='1'>-0.05570347106353324600</m>
        <m row='2' col='2'>0.99248912220040875000</m>
    </matrix>
    <points mp='122.183975'>
        <point id='PC101' useXY='1' useZ='1'>
            <ground>
                <x>460320.184000</x>
                <y>626570.439000</y>
                <z>10.627000</z>
            </ground>
            <model>
                <x>-25.93169811989125200000</x>
                <y>32.57041742280095800000</y>
                <z>107.54832105804235000000</z>
            </model>
            <residual>
                <x>-164.295424</x>
                <y>52.099229</y>
                <z>-0.240689</z>
            </residual>
        </point>
        <point id='PC102' useXY='1' useZ='1'>
            <ground>
                <x>457916.886000</x>
                <y>624247.954000</y>
                <z>12.069000</z>
            </ground>
            <model>
                <x>-25.94416234828861400000</x>
                <y>32.58570876952164500000</y>
                <z>107.54832105804235000000</z>
            </model>
            <residual>
                <x>-28.990795</x>
                <y>-74.345370</y>
                <z>0.679271</z>
            </residual>
        </point>
        <point id='PC103' useXY='1' useZ='1'>
            <ground>
                <x>459179.334000</x>
                <y>623462.274000</y>
                <z>20.536000</z>
            </ground>
            <model>
                <x>-25.94941176839595100000</x>
                <y>32.57867438360941700000</y>
                <z>107.54837954837430000000</z>
            </model>
            <residual>
                <x>106.274481</x>
                <y>109.752252</y>
                <z>-0.886566</z>
            </residual>
        </point>
        <point id='PC104' useXY='1' useZ='1'>
            <ground>
                <x>463822.512000</x>
                <y>626685.132000</y>
                <z>10.102000</z>
            </ground>
            <model>
                <x>-25.92991593921098900000</x>
                <y>32.55051554021122200000</y>
                <z>117.54652568697929000000</z>
            </model>
            <residual>
                <x>87.007349</x>
                <y>-87.509945</y>
                <z>0.453673</z>
            </residual>
        </point>
    </points>
</absolute>

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google photo

Estás comentando usando tu cuenta de Google. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s