%&luaplainJA.fmt
\input Manual-lib_macros.tex

\null\kern-\baselineskip\kern0.25\vsize
\ftitle
\centerline{La librería de Aerotri}
\kern1em
\fsubsection
\centerline{Manual para el programador}
\vfill
\break
\null\vfill
\break
}

\chapter{Contenidos}
\input indice.tex

\newwrite\indice
\openout\indice indice.tex

\chapter{General}

\section{Introducción}

Para usar la librería de Aerotri ha de incluirse el fichero \fichero{aerotri_trabajos.h}:

\byte{\#include}{\str{aerotri_trabajos.h}}

\noindent y en el momento de enlazar hacer referencia a \fichero{ATcrt.lib}, \fichero{aerotri_trabajos.lib} y \fichero{relativa.lib}.

La comunicación con la librería se realiza a través del llamado {\it trabajo de Aerotri;\/} en concreto, mediante la estructura en memoria de tipo \estructura{TrabajoAerotri} que representa un trabajo de Aerotri. Dicho trabajo puede almacenarse en un fichero de texto, normalmente con extensión .art.

Un trabajo de Aerotri contiene toda la información necesaria para el cálculo. Un usuario que tenga instalado Aerotri en su ordenador puede hacer doble click sobre un fichero de trabajo de Aerotri, por ejemplo {\it ejemplo.art,\/} con lo que dicho fichero se abrirá con Aerotri, e inmediatamente pulsar el botón de calcular, y se realiza el cálculo. De modo análogo, un programador que quiera emplear la librería de Aerotri para el cálculo puede simplemente 1$^\circ$) llamar a la función que lee y carga en memoria un fichero de trabajo de Aerotri y 2$^\circ$) llamar a la función que calcula, pasando la estructura de tipo \estructura{TrabajoAerotri} creada al leer el fichero. Se muestra un ejemplo de código que hace esto en \fichero{maintest.c}.

El proceder anterior exige crear primero el fichero de trabajo, que incluye multitud de opciones de configuración. Más sencillo resulta pedir a la librería una estructura \estructura{TrabajoAerotri} con valores por defecto y modificar solamente lo que se quiera. Una vez hecho esto se puede llamar a la función que calcula así como a la que escribe el fichero de texto a partir de la estructura \estructura{TrabajoAerotri} en memoria. Dicho fichero podrá leerse posteriormente. El formato de los ficheros de trabajo de Aerotri no está documentado explicitamente, pero se corresponde casi exactamente punto por punto con la estructura \estructura{TrabajoAerotri} en memoria, que se documenta aquí. Además, al ser un fichero de texto es muy fácil de interpretar. Por último, es de mucha ayuda modificar parámetros en la interfaz gráfica de Aerotri y analizar las variaciones en el fichero .art correspondiente. Aerotri genera ese fichero cada vez que se pulsa el botón «Calcular».
Así pues, la manera más sencilla de emplear la librería sería como sigue:

{\code
\bb[int] nret;
\bb[char16_t] mensaje\[512\];
\bb[TrabajoAerotri] *tr=get_trabajo_aerotri();
tr->ficheros.fotos=\ustr[estatua.ftm];
tr->ficheros.apoyo=\ustr[puntos_apoyo.xyz];
nret=calcula_trabajo_aerotri(\NULL,0,tr,mensaje,\macro[ATIDIOMA_Esp]);
ATtrabajos_free(tr);	\%This is the same as free(tr), except that the code is
\null\kern11em \%executed in the aerotri_trabajos.dll module
\par]

\vskip-\baselineskip
El programador puede crear él mismo una estructura \estructura{TrabajoAerotri} sin más que declarar un objeto de ese tipo:

{\code\bb[TrabajoAerotri] trabajo;\par]

\noindent rellenarlo y pasar punteros a ese objeto a las funciones de la librería. Véase la sección {\it Asignar valores por defecto\/} del siguiente capítulo.

Esta estructura, a su vez, contiene punteros a memoria que se reserva; por ejemplo, para los nombres de los ficheros de entrada. Si es el programador el que maneja esos punteros NO debe llamar a la función \funcion{libera_trabajoAT,} mientras que si es la librería la que ha reservado memoria para los mismos, lo que solamente sucede si la estructura se rellena mediante una llamada a \funcion{lee_trabajoAT,} ha de llamar a dicha función para liberarlos:

{\code
\bb[TrabajoAerotri] \tt trabajo;
\* Here the programmer must set all pointers within trabajo to NULL, viz:
\null\quad\quad trabajo.ficheros.fotos=NULL;
\null\quad\quad \[...\]
\null\quad\quad trabajo.configsalida.fich_Imaster.rutaf=NULL;
\null\quad The next chapter lists all those pointers.
*/
lee_trabajoAT(\ustr[ejemplo.art],&trabajo);
\*
...
*/
libera_trabajoAT(&trabajo);\par]

Si el programador rellena él mismo la estructura \estructura{TrabajoAerotri} el modo de trabajar será algo así como

{\code
\bb[int] nret;
\bb[char16_t] mensaje\[512\];
\bb[TrabajoAerotri] trabajo;

RellenaMiTrabajo(&trabajo);	\%rellena la estructura con la información
															\%para el cálculo
nret=calcula_trabajo_aerotri(\NULL,0,tr,mensaje,\macro[ATIDIOMA_Esp]);
if(nret==\macro[AT_ESC]){	\%The user escaped
\null\quad\*...*/
}else{
\null\quad\*... analizar los otros valores de nret
\null\quad if(...){
\null\quad}else if(...){
\null\quad}...
\null\quad*/
}
LiberaMiTrabajo(&trabajo);\par]

Las funciones \funcion{RellenaMiTrabajo} y \funcion{LiberaMiTrabajo} son nombres inventados en cuyo lugar ha de ir la función o funciones que el usuario de la librería haya programado.


\section{Cálculo en dos fases}

En lugar de \funcion{calcula_trabajo_aerotri} tal vez prefiera un cálculo separado de los valores aproximados y el ajuste del bloque:

{\code
\bb[int] nret;
\bb[struct strRelativaParams] *rparams;
\bb[struct strAbsolutaCallData] *aparams;
\bb[TrabajoAerotri] trabajo;
\* ... */

rparams=get_relativa_params();
aparams=get_absoluta_calldata();
if(rparams==\NULL[] || aparams==\NULL){
\null	ATtrabajos_free(aparams);	\%frees if not NULL
	ATtrabajos_free(rparams);	\%ditto
	\* El programa se ha quedado sin memoria. Mostrar mensaje de error */
}

RellenaMiTrabajo(&trabajo);
nret=prepara_trabajo_relativa(&trabajo, &rparams);
if(nret!=0){
\null	\*Mostrar mensaje de error según nret*/
}
nret=calcula_relativa(\* ... */);
if(nret!=0){
\null	\*Mostrar mensaje de error según nret*/
}
trabajo.ficheros.aproximadas=\* ... */	\%indicar el fichero de valores aproxima-
						\%dos generado en el cálculo anterior; es decir, en calcula_relativa().

nret=prepara_trabajo_absoluta(&trabajo, &aparams);
if(nret!=0){
\null	\*Mostrar mensaje de error según nret*/
}
nret=calcula_absoluta(\* ... */);
if(nret==\macro[AT_ESC]){
\null	\*No hacer nada*/
}else if(nret!=0){
\null	\*Mostrar mensaje de error según nret*/
}else{
\null	\*Mostrar mensaje de que el cálculo ha terminado
\null	bien y realizar otras tareas*/
}

ATtrabajos_free(aparams);
ATtrabajos_free(rparams);\par]

\section{Las funciones de la librería}

Con lo explicado en las secciones anteriores y los comentarios en \fichero{aerotri_trabajos.h} es casi suficiente. Solamente falta aclarar el comportamiento de las funciones \funcion{lee_trabajoAT} y \funcion{change_absparams} y las estructuras devueltas por \funcion{calcula_relativa} y \funcion{calcula_absoluta} en punteros pasados como parámetros, que se explican más adelante en capítulo a parte.

\subsection{lee_trabajoAT}

Lo primero que hace esta función es liberar los punteros de la estructura en caso de que no sean \NULL. De esta manera, si se deja que sea la librería la que cree la estructura, mediante \funcion{get_trabajo_aerotri,} se rellena y modifica solamente mediante \funcion{lee_trabajoAT,} y por último se libera su contenido mediante \funcion{libera_trabajoAT} y la propia estructura mediante \funcion{ATtrabajos_free,} el programador no tiene que preocuparse en ningún momento de dichos punteros. En cambio, si es el programador el asigna valores a esos puntoeros, o bien crea un objeto de ese tipo, antes de cualquier llamada a \funcion{lee_trabajoAT} ha de poner a \NULL{} todos los punteros:

{\code
\bb[TrabajoAerotri] trabajo;
\bb[int] err_code;

setNULL(&trabajo); \* Poner a NULL los punteros que contiene la estructura */
err_code=lee_trabajoAT(\str[ejemplo.art],&trabajo);%
\par]

\funcion{setNULL} es un nombre inventado. Se trataría de una función del programador que pone los punteros a \NULL. En el siguiente capítulo se enumeran todos los punteros a memoria que tiene la estructura.

La función \funcion{lee_trabajoAT} efectúa las siguientes acciones en el orden indicado:

{\narrower\parindent=0pt \def\nodot{\hbox to 0pt{.\hss}}
${1\nodot}^\circ$ Liberar todos los punteros de la estructura que no sean \NULL\par
${2\nodot}^\circ$ Rellenar toda la estructura con valores por defecto\par
${3\nodot}^\circ$ Abrir y leer el fichero\par}

Este orden de acciones permite emplear esta función para asignar valores por defecto a una estructura \estructura{TrabajoAerotri} sin más que llamarla pasando dicha estructura y un nombre de fichero inexistente.

\subsection{change_absparams}

Esta función permite modificar una estructura de tipo \estructura{struct strAbsolutaCallData}. Antes de continuar leyendo tenga en cuenta que es posible que nunca necesite lo que aquí se explica.

De momento esta función solamente puede modificar un campo de la estructura \estructura{str\-AbsolutaCallData.} La razón de proporcionar esta función para modificar ese campo en particular es que dicho campo siempre adquiere el valor cero cuando la estructura se crea a partir de un \estructura{TrabajoAerotri} mediante la llamada a \funcion{prepara_trabajo_absoluta,} que es la única manera de rellenar la estructura (la librería de Aerotri la decalara pero no proporciona su definición). Por tanto la única manera de poner el susodicho campo a uno es mediante esta función. Así que las dos únicas maneras de llamar a la función y que esta haga algo~son

{\code
change_absparams(params,\macro[APARAMS_flags0_Semilibre],1);
change_absparams(params,\macro[APARAMS_flags0_Semilibre],0);\par]

\noindent en donde {\tt params} es de tipo \estructura{struct strAbsolutaCallData*}.

Establecer la bandera \macro{APARAMS_flags0_Semilibre} a uno indica a la función de ajuste del bloque que continúe con el ajuste aunque los puntos de control y de GPS, cuando se indica alguno de estos dos ficheros o ambos, no sean suficientes para llevar el bloque a su sistema de coordenadas~3D (es decir, que no haya puntos comunes suficientes entre estos ficheros y el bloque que se ajusta). En caso de que no se incluya ni uno ni otro fichero no es necesario establecer esta bandera; el ajuste continúa sin más en un sistema arbitrario. Si la bandera está a cero, se indica un fichero de apoyo o GPS, y los puntos en esos ficheros son insuficientes, la función \funcion{calcula_trabajo_absoluta} devolverá~12 según se explica en \fichero{clases_mainabsoluta.h.}

Cuando la bandera no está activa (es el comportamiento por defecto) y la función devuelve el valor~12, normalmente será señal de un error en el fichero de puntos de apoyo o GPS, como que el fichero indicado es el correspondiente a otro trabajo o que los puntos o centros de toma no se llaman igual en estos ficheros y en el fichero de fotogramas, como por ejemplo 1034 frente a 001034, además de que cuando se indican esos ficheros obviamente se quiere que el bloque quede calculado en el sistema de coordenadas de los mismos. Por lo tanto un valor devuelto de~12 realmente refleja un error, por lo que seguramente nunca deba preocuparse por esta bandera.

\chapter{La estructura TrabajoAerotri}

\section{Introducción}

La estructura \estructura{TrabajoAerotri} representa completamente un trabajo de Aerotri y es todo lo que se necesita para interactuar con las funciones de la librería Aerotri-lib. El fichero \fichero{ClaseTrabajo.h} y los ficheros por este incluidos tienen algunos comentarios aclaratorios, pero que no bastan para entender todos los campos de la estructura. Este capítulo se dedica a su descripción completa.

Un trabajo de Aerotri guarda más informacion de la necesaria para un cálculo. La razón es que tiene que almacenar completamente el estado de todos los controles, incluídos los desactivados y aquellos que no van a intervenir en el ajuste. Por ejemplo, si no se indica fichero de GPS/INS todas las opciones relativas al GPS se pueden igornar para el cálculo, pero el trabajo de Aerotri las guardará igual. Otro ejemplo: si se selecciona como sistema de coordenadas \symbolic{Conforme Genérico} todas las opciones del sistema UTM no intervienen, pero el \estructura{TrabajoAerotri} ha de almacenarlas igual, de modo que si el usuario selecciona UTM los parámetros de esta proyección no cambien desde la última vez que lo seleccionó, etc. Si se usa la estructura para pasarla a las funciones de la librería que calculan no es necesario asignar los valores que serán ignorados.

\section{Asignar valores por defecto}

Puesto que la estructura y sus sub-estructuras contienen en total muchos campos puede ser pesado asignar valores por defecto a todos ellos, así como difícil de hacer correctamente para el que lo aborde por primera vez. La librería de Aerotri no proporciona una función cuya finalidad sea explícitamente iniciar una estructura con valores por defecto, pero se puede conseguir el mismo objetivo llamando a \funcion{lee_trabajoAT} indicando un nombre de fichero que no exista, o simplemente mediante una llamada a \funcion{get_trabajo_aerotri}:

{\code
\bb[TrabajoAerotri] trabajo;
\*Set all pointers to NULL. Code for that omitted*/
lee_trabajoAT(L\str[],&trabajo);	\%Ignore the returned value

\*O bien*/
\bb[TrabajoAerotri] *trabajo;
trabajo=get_trabajo_aerotri();	\%Rellena con los valores por defecto
\par]

La primera manera requiere que el programador ponga a \NULL{} todos los punteros, ya que lo primero que hace la función \funcion{lee_trabajoAT} es liberar dichos punteros si no son \NULL. En la segunda manera es la propia función \funcion{get_trabajo_aerotri} la que inicializa los punteros.

\section{Punteros NULL}

Se ha hecho mención varias veces a los punteros de la estructura, que si no son \NULL{} son liberados por las funciones \funcion{lee_trabajoAT} y \funcion{libera_trabajoAT} (la primera de estas funciones llama a la segunda para liberar la estructura que se le pasa). Pues bien, dichos punteros son los que se muestran a continuación, mediante un ejemplo que los pone todos a \NULL:

{\code
\bb[TrabajoAerotri] trabajo;

trabajo.ficheros.fotos=\NULL;
trabajo.ficheros.aproximadas=\NULL;
trabajo.ficheros.apoyo=\NULL;
trabajo.ficheros.gpsins=\NULL;
trabajo.ficheros.interna=\NULL;
trabajo.configsalida.fich_Digi.rutarel=\NULL;
trabajo.configsalida.fich_Digi.rutaf=\NULL;
trabajo.configsalida.fich_Imaster.rutarel=\NULL;
trabajo.configsalida.fich_Imaster.rutaf=\NULL;\par]

El programador atento habrá observado que si inicializa la estructura llamando a la función \funcion{lee_trabajoAT} pasando un nombre de fichero inexistente, los punteros de {\tt fich_Digi} y {\tt fich_Imaster} no se establecen a \NULL{} sino que apuntan a rutas por defecto, como por ejemplo {\tt\str{.\char`\\\char`\\}}. Estas cadenas son posiciones de memoria estáticas dentro de la librería de Aerotri, por lo que se trata en cualquier caso de memoria que no se ha reservado y que la función \funcion{libera_trabajoAT} no va a liberar. El programador no tiene que preocuparse en absoluto de esto.

\section{Tipos básicos}

Si se incluye el fichero \str{aerotri_trabajos.h} este a su vez incluye los ficheros de cabecera de la librería \fichero{ATcrt} que definen ciertos tipos. En la práctica el programador puede suponer las siguientes definiciones:

{\code
\bb[typedef unsigned char] uint8m, bool8;
\bb[typedef signed char] int8m;
\bb[typedef uint16_t] uint16m;
\bb[typedef int16_t] sint16m;
\bb[typedef uint32_t] bint, u8int, u16int, uint;
\bb[typedef int32_t] s8int, s16int, ssint;
\bb[typedef double] Double;\par]

\section{TrabajoAerotri}

{\elemento
	\byte{uint8m}{sensor;}
	\byte{Trabajo_Modos}{modos;}
	\byte{Trabajo_Ficheros}{ficheros;}
	\byte{Trabajo_TipoFicheros}{tiposf;}
	\byte{Trabajo_DatosGPS}{datosgps;}
	\byte{EstimacionConjuntas}{conjuntas;}
	\byte{Trabajo_AutoCalib}{autocalib;}
	\byte{ValoresAproximados}{valoresaproximados;}
	\byte{Precisiones}{apriori;}
	\byte{Trabajo_Opciones}{opciones;}
	\byte{Trabajo_Sistema}{sistema;}
	\byte{AjbloqueConfigSalida}{configsalida;}
	\byte{Trabajo_Salida}{salidatrabajo;}
}
\endelemento{TrabajoAerotri}

{\explicacion
\byte{sensor}{0, cónico; 1, modelo local (usar siempre 0)}
}

\section{Trabajo_Modos}

{\elemento
	\byte{uint8m}{modo_ajuste;}
	\byte{uint8m}{modo_toma;}
	\byte{uint8m}{modo_medida;}
}
\endelemento{Trabajo_Modos}

{\defines \macrovalwidth=20pt
\byte{ATMODOTOMA_Unknown}{0}{}
\byte{ATMODOTOMA_Plano}{1}{}
\byte{ATMODOTOMA_Generico}{2}{}
\byte{ATMODOMEDIDA_Unknown}{0}{}
\byte{ATMODOMEDIDA_Manual}{1}{}
\byte{ATMODOMEDIDA_Automatico}{2}{\%Puede incluir puntos manuales también}
\byte{ATMODOAJUSTE_Completo}{0}{\%Un ajuste normal}
\byte{ATMODOAJUSTE_vvap}{1}{\%Solamente valores aproximados}
\byte{ATMODOAJUSTE_Outputfile}{2}{\%Sólo ficheros de salida. (No es necesario que los valores aproximados incluyan puntos)}
\byte{ATMODOAJUSTE_Residuos}{3}{\%Además calcular residuos. (Hace falta que haya puntos en los valores aproximados)}
\byte{ATMODOAJUSTE_Simulacion}{4}{\%Se toman los valores aproximados como los valores ajustados y se calcula todo (residuos, precisiones, etc.).}
}

{\explicacion
\byte{modo_ajuste}{Indica qué se quiere hacer en el ajuste. Lo más común es un ajuste normal: \macro{ATMODOAJUSTE_Completo}}
\byte{modo_toma}{Indica el modo en que fueron tomadas las fotografías. Se emplea solamente en el cálculo de valores aproximados y no tiene mucha influencia.}
\byte{modo_medida}{Aún no se emplea, pero versiones futuras de la librería seguramente lo empleen para calcular de una u otra manera según la medida sea manual o automática, especialmente en el ajuste robusto.}
}

{\tt modo_medida} ha quedado obsoleto como medio para indicar a las funciones de cálculo cómo se han medido los puntos de aerotriangulación, ya que esto lo detecta la función sin más que analizar el número de puntos dados por fotograma, que es muy alto en el caso de medidas automática y bajo en el caso de medidas manuales. Puede servir para forzar a la función de cálculo a calcular de una u otra manera, impidiendo que haga este análisis para deducir el modo de toma.

La variable {\tt modo_toma} se emplea en el cálculo de valores aproximados. El modo\break \symbolic{Unknown} equivale esencialmente al modo \symbolic{Generico}. En el caso de que las fotografías estén tomadas en paralelo y aproximadamente en el mismo plano, como habitualmente sucede en fotogrametría aérea, el indicar \macro{ATMODOTOMA_Plano} favorece que no se produzcan errores en el cálculo de valores aproximados. No obstante estos errores son consecuencia de que el tratamiento de los casos no contemplados en \macro{ATMODOTOMA_Plano} así como la eliminación de observaciones erróneas no está programado del todo. Cuando esto se haga el modo
\macro{ATMODOTOMA_Plano} supondrá solamente un menor tiempo de cálculo, probablemente sin relevancia, y el parámetro {\tt modo_toma} quedará obsoleto.

\section{Trabajo_Ficheros}

{\elemento
	\lbyte{char16_t}{*fotos,}{\%Puntero al fichero de fotogramas}
	\lbyte{\phantom{char16_t}}{*aproximadas,}{\%Puntero al fichero de valores aproximados}
	\lbyte{\phantom{char16_t}}{*apoyo,}{\%Puntero al fichero de apoyo}
	\lbyte{\phantom{char16_t}}{*gpsins,}{\%Puntero al fichero de gps/ins}
	\lbyte{\phantom{char16_t}}{*interna;}{\%Puntero al fichero de orientación interna (fichero de cámara)}
	\byte{uint8m}{generar;}
}
\endelemento{Trabajo_Ficheros}

Esta estructura contiene punteros a los nombres de los ficheros de entrada más la variable {\tt generar}. Algunos ficheros pueden no existir. En ese caso los punteros correspondientes deben estar a \NULL.

El fichero {\tt fotos} es obligatorio siempre. {\tt aproximadas} es obligatorio para el ajuste del bloque. Si no existe, la función \funcion{calcula_trabajo_aerotri} lo calculará automáticamente, por lo que se puede pasar \NULL{} en ese parámetro a esa función. La presencia de los parámetros obligatorios se comprueba en las funciones \funcion{prepara_trabajo_relativa,} \funcion{prepara_trabajo_absoluta} y \funcion{calcula_trabajo_aerotri}.

La reducción al punto principal y corrección de la distorsión indicadas en el fichero {\tt interna} se aplicarán a las coordenadas del fichero de fotocoordenadas. Por tanto el fichero {\tt interna} no se ha de indicar si las coordenadas del fichero de fotogramas ya están refinadas, esto es, respecto al punto principal y con la distorsión corregida. Se recomienda que las fotocoordenadas se indiquen en coordenadas píxel brutas, respecto a la esquina superior izquierda de la foto, y se indique en {\tt interna} la orientación interna de la cámara. De esta manera, si en el ajuste de la aerotriangulación se calculan parámetros de autocalibración, Aerotri podrá combinar el fichero de interna indicado con los parámetros calculados para generar un fichero de interna nuevo.

Si el fichero de fotogramas es de formato Aerotri o PATB para cada fotograma se indica un valor de la focal. Si se especifica un fichero de interna el valor de la focal en este tiene preferencia sobre los valores indicados en el fichero de fotogramas.

Si no se indica ni fichero de puntos de apoyo ni fichero de gps/ins el cálculo se hace en un sistema arbitrario. Si se indica al menos uno de estos ficheros pero no hay puntos suficientes para el cálculo el cálculo no se realiza y se devuelve un código de error. La razón es que cuando esto sucede normalmente es porque los ficheros indicados no son los correctos. Para cambiar este comportamiento y que la librería continúe con el cálculo a pesar de esta circunstancia véase cómo hacerlo en la sección {\it change_absparams\/} del capítulo anterior.

{\tt generar} es una variable cuyos bytes inferiores son flags, que si están a~1 indican si se ha de generar un fichero con formato de Aerotri de un cierto tipo (por ejemplo, de gps/ins) en caso de que el correspondiente fichero de entrada no sea de Aerotri. El programa Aerotri pasa~5 en esta variable, que es {\tt 00101} binario, lo que significa que se generen ficheros de Aerotri de fotogramas y apoyo. La mayoría de los formatos de ficheros de fotogramas no indican ningún valor para la focal de las fotografías, ya que entienden que esa información estará en un fichero de interna. En estos casos en el fichero de formato Aerotri generado el valor de la focal para todos los fotogramas será de 1.0. Según lo indicado dos párrafos más arriba esto no importa porque el valor de la focal se tomará del fichero de interna.

\section{Trabajo_TipoFicheros}

{\elemento
	\byte{uint8m}{tfot,tapr,tapy,tgps,tint,}
	\byte{\phantom{uint8m}}{tdapr;}
}
\endelemento{Trabajo_TipoFicheros}

Esta estructura indica el formato de cada fichero de entrada, más la variable {\tt tdapr}. Los posibles valores para cada una de las variables son

{\explicacion
\byte{tfot}{(0,)1: Aerotri, 2: PatB, 3: Image Master, 4: Enso Mosaic}
\byte{tapr}{(0,)1(,2): Aerotri}
\byte{tapy}{(0,)1: Aerotri, 2: XYZ}
\byte{tgps}{2: Aerotri, 4: AeroOffice, 5: TopoSys EO-file}
\byte{tint}{0: Aerotri, 1: ini, 2: Image Master, 3: RapidCal}
}

Si un fichero de entrada no existe su correspondiente variable en esta estructura será ignorado. Los valores para los formatos Aerotri son resultado de la historia del programa y la compatibilidad de versiones nuevas con ficheros de trabajo antiguos. Los valores entre paréntesis no se han de emplear y no los generará nunca la GUI de Aerotri. Los distintos formatos de cada clase de ficheros se encuentran descritos en el manual de Aerotri.

{\explicacion
\byte{tdapr}{Tipo de valores aproximados. 0: Unos cualesquiera; 2: Los valores ajustados de un ajuste anterior}
}

El valor~1 para {\tt tdapr} lo emplea internamente Aerotri. Si se pasa~2 en {\tt tdapr} pero Aerotri ve que algunas opciones del ajuste no coinciden con las del ajuste anterior según el fichero de valores aproximados (que si {\tt tdapr} es~2 tiene que ser el de valores ajustados del ajuste anterior), como por ejemplo el sistema de coordenadas o los parámetros de autocalibración, lo «degrada» a~1.

\section{Trabajo_DatosGPS}
{\elemento
	\byte{uint8m}{tdgps,tdins;}
	\byte{bool8}{signoins;}
}
\endelemento{Trabajo_DatosGPS}

{\defines
\byte{GrupoGPSINS_TDGPS_Offset}{255}{Error constante global}
\byte{ATTrabajo_TDGPS_Offset}{GrupoGPSINS_TDGPS_Offset}{}
\byte{ATTrabajo_TDGPS_NoError}{0}{}
\byte{ATTrabajo_TDGPS_Constant}{1}{}
\byte{ATTrabajo_TDGPS_Linear}{2}{}
}

{\explicacion
\byte{tdgps,tdins}{Tipo de errores sistemáticos presentes en los datos gps e ins. 0, sin error; 1, error constante; 2, error linear; 255, offset}
\byte{signoins}{0: el criterio interno de Aerotri; 1: el criterio más habitual en los ficheros de ins}
}

Las componentes de error sistemático son independientes para cada pasada; es decir, se calcula un juego de parámetros para cada pasada. El tipo de error \symbolic{offset} significa un error constante e igual para todas las pasadas, y solamente se aplica a los datos~INS. En principio el tipo de errores esperable es 1/0, es decir, constante para el GPS y sin error para el~INS, o bien 2/0 si el cálculo de los datos GPS no tiene mucha calidad. Para el INS el error puede ser \symbolic{offset} si no está bien calibrada la posición relativa (alineación) del sistema inercial con los ejes de la cámara, y \symbolic{constante} si el programa que ha generado el fichero INS no ha transformado bien los giros. En caso de no querer preguntar al usuario lo más seguro es pasar 2/1, si bien 1/\symbolic{offset} será prácticamente siempre suficiente. Aerotri por defecto asigna valores 1/1.

El valor de \macro{ATTrabajo_TDGPS_Offset} es arbitrario, y si queremos \symbolic{offset} hemos de pasar la macro, no {\tt 255} literalmente. Para los demás se puede emplear las macros o bien los números $0$, $1$, $2$, ya que no van a cambiar pues tienen un significado que permite emplearlos en operaciones aritméticas, y el código interno de Aerotri lo hace. El valor es igual al número de grados de libertad del error sistemático para cada coordenada.

Para {\tt signoins} se ha de pasar~1. Un~0 indica un sentido de giros positivos que no es el empleado en fotogrametría, si bien es más habitual en matemáticas y es el que emplea internamente Aerotri.

\section{EstimacionConjuntas}

{\elemento
	\byte{uint8m}{xy;}
	\byte{uint8m}{XY;}
	\byte{uint8m}{planiZ;}
}
\endelemento{EstimacionConjuntas}

Estos parámetros tienen significado en un ajuste robusto y se ignoran si el ajuste es mímimo cuadrático. Indican si un error muy grande en una coordenada de un punto significa que también se ha de eliminar la otra coordenada; es decir, indica un tratamiento conjunto o individual de las coordenadas de los puntos de cara a la estimación robusta.

{\tt xy} se refiere a las fotocoordenadas $x$ e~$y$, {\tt XY} a las coordenadas planimétricas de los puntos de apoyo y {\tt planiZ} a las coordenadas planimétricas por un lado frente a la coordenada~$Z$ por el otro. Lo habitual es que los valores correctos sean 1/1/0; es decir, que los errores en las fotocoordenadas $x$ e~$y$ no son independientes; tampoco los errores en $X$ e~$Y$ de los puntos de apoyo, pero el error en $Z$ de los puntos de apoyo sí es independiente del error en planimetría.

\section{Trabajo_Autocalib}

{\elemento
	\lbyte{bool8}{existe;}{\%Si se ha seleccionado Autocalibración para el cálculo}
	\byte{struct}{\{}{\narrower\edef\oldparindent{\the\parindent} \parindent 0pt
		\byte{bool8}{f;}
		\byte{bool8}{pp;}
		\byte{bool8}{distorsion;}
		\byte{struct}{\{}{\advance\leftskip-\oldparindent \advance\leftskip-\oldparindent
			\byte{bool8}{radsim;}
			\byte{bool8}{tansim;}
			\byte{bool8}{asimetricas;}
		}\byte{}{\} componentes;}
	}\byte{}{\} selected;}
	\byte{Config_distorsion}{config_dist;}
}
\endelemento{Trabajo_AutoCalib}

Si la variable {\tt existe} está a \false{} el resto de la estructura ya no se lee en las funciones que calculan, pero obviamente sí en la función \funcion{escribe_trabajoAT.} Las variables dentro de la estructura {\tt selected} indican si unos u otros parámetros se han seleccionado o no para el cálculo:

{\explicacion
\lbyte{bool8}{f;}{Longitud focal}
\lbyte{bool8}{pp;}{Punto principal}
\lbyte{bool8}{distorsion;}{Parámetros de distorsión}
}

Si {\tt distorsion} está a \false{} no se incluyen componentes de distorsión en el cálculo. Además de la distorsión la autocalibración puede incluir el cálculo de la longitud focal y el punto principal. Si {\tt distorsion} está a \true, la estructura {\tt componentes} indica para cada uno de los tres juegos de componentes si ha sido seleccionado:

{\explicacion
\byte{radsim}{Distorsión radial simétrica}
\byte{tansim}{Distorsión tangencial simétrica}
\byte{asimetricas}{Distorsiones asimétricas}
}

El detalle de cada componente se incluye en {\tt config_dist}. Por ejemplo, ciertos bits dentro de {\tt config_dist} indicarán si cada una de las componentes $a_2$... $a_5$ de la distorsión radial simétrica se ha seleccionado para su cálculo, para lo cual es necesario además que {\tt radsim} sea \true.

\subsection{Config_distorsion}

{\elemento
	\lbyte{float}{semidiag;}{\%Semidiagonal del fotograma, e.d., $r_{\rm máx.}$}
	\lbyte{uint8m}{modelo_poli;}{\%modelo polínomico.}
	\lbyte{uint8m}{modelo_asim;}{\%modelo de distorsiones asimétricas.}
	\lbyte{uint8m}{condicion_radsim;}{\%condición para la definición del término lineal de la Drs}
	\byte{float}{r1;}
	\lbyte{uint}{param_radsim;}{\%flags que indican los parámetros que se calculan de la Drs. $a_1$, $a_2$, $a_3$... empezando en el bit más bajo.}
	\lbyte{uint}{param_tansim;}{\%Idem para la distorsión tangencial simétrica.}
	\lbyte{uint}{param_asim1;}{\%Idem para la primera serie de componentes asimétricas.}
	\lbyte{uint}{param_asim2;}{\%Idem para la segunda serie de componentes asimétricas.}
}
\endelemento{Config_distorsion}

{\defines \macrovalwidth=20pt
\byte{CAL_MODPOL_IMPAR}{1}{}
\byte{CAL_MODPOL_COMPLETO}{2}{}
\byte{CAL_MODASIM_RADTAN}{1}{\%radial/tangencial}
\byte{CAL_MODASIM_VECTOR}{2}{\%vector giratorio}
\byte{CAL_CONDICIONR_ORTO}{0}{\%que la distorsión radial sea ortogonal a la focal ($a_1=0$)}
\byte{CAL_CONDICIONR_R1}{1}{\%ajustar $a_1$ para que Drs(r1)=0}
\byte{CAL_CONDICIONR_MM}{2}{\%ajustar a1 para que |Drs mín|=|Drs máx|}
}

{\explicacion
\byte{semidiag}{Por lo general se deja que el programa deduzca el valor adecuado de $r_{\rm máx.}$. Buscará el valor máximo de~$r$ y tomará un valor redondo que se ajuste a ese valor. Para ello se ha de pasar infinito o NaN, lo cual se puede hacer con las macros de \fichero{system.h}. En concreto, el código {\tt NAN_F(semidiag)} asigna a semidiag un NaN.}
\byte{modelo_poli}{Por compatibilidad con otros modelos de distorsión se recomienda emplear siempre \macro{CAL_MODPOL_IMPAR}.}
\byte{modelo_asim}{Salvo que haya alguna razón para lo contrario se ha de pasar \macro{CAL_MODASIM_RADTAN}.}
\byte{condicion_radsim}{Se recomienda emplear siempre \macro{CAL_CONDICIONR_ORTO}.}
\byte{r1}{Si {\tt condicion_radsim} es \macro{CAL_CONDICIONR_R1} este es el valor para el que se quiere Drs(r1)=0. En particular, si  {\tt condicion_radsim} es \macro{CAL_CONDICIONR_ORTO} este valor es ignorado.}
\byte{param_radsim}{En caso de que se calculen parámetros de distorsión radial simétrica este parámetro indican qué componentes se calculan. Si el bit más bajo está a~1 indica que se ha de calcular $a_1$, si el segundo bit más bajo está a~1 indica que se ha de calcular $a_2$, etc., así hasta las componentes que haya programadas. En estos momentos hay hasta~$a_5$.}
}

Los parámetros {\tt param_tansim}, {\tt param_asim1} y {\tt param_asim2} son los análogos a {\tt param_radsim} para las componentes tangencial simétrica y para las dos series de las componentes asimétricas, que en el modelo \symbolic{radial/tangencial} son las componentes radiales asimétricas ($c_1$, $c_2$,... ) y las tangenciales asimétricas ($d_1$, $d_2$,... ). El número de componentes asimétricas programado es de 12 para cada serie.

Un elemento \estructura{Config_distorsion} generado mediante la interfaz de Aerotri siempre tendrá a cero los bits correspondientes a las componentes $a_1$, $b_1$, $c_1$ y~$c_2$, ya que no deben existir sea cual sea la distorsión de la cámara, y el propio concepto de su cálculo junto con los parámetros de orientación de las fotografías no tiene sentido. Para entender por qué esto es así véase el manual de Calibracion que se incluye en el instalador de Aerotri.

Además, la interfaz de Aerotri no pregunta por el modelo polinómico o por el modelo de distorsiones asimétricas. Siempre pasará \symbolic{impar} y \symbolic{radial/tagencial.} Tampoco pregunta por la variable {\tt condicion_radsim}, y siempre emplea \symbolic{ortogonal}. En consecuencia tampoco pregunta por {\tt r1}, ya que para \symbolic{ortogonal} no es de aplicación.

La estructura \estructura{Trabajo_Autocalib} guarda todo el estado de todos los controles relativos a autocalibración. Por lo tanto para que se calculen unas ciertas componentes de distorsión no es suficiente con que los respectivos bits en {\tt param_radsim},... {\tt param_asim2} estén a~1. Es necesario además que estén a~1 las variables {\tt autocalib.existe}, {\tt autocalib.selected.distorsion} y la correspondiente dentro de {\tt autocalib.selected.componentes}; es decir, {\tt autocalib.marcados.radsim}, {\tt autocalib.marcados.tansim} o {\tt autocalib.marcados.asimetricas}. Además {\tt modelo_poli} tiene que ser un modelo reconocido (\macro{CAL_MODPOL_IMPAR} o \macro{CAL_MODPOL_COMPLETO}) así como {\tt modelo_asim} (\macro{CAL_MODASIM_RADTAN} o \macro{CAL_MODASIM_VECTOR}).

Si el resultado de la autocalibración se va a almacenar en un fichero de un formato que incluye como parámetros de distorsión K1, K2, K3, P1 y P2 (llamémosle formato~$X$), en el cálculo de autocalibración mediante Aerotri solamente se pueden incluir las componentes $a_2$, $a_3$, $a_4$, $d_1$ y~$d_2$. Si el formato~$X$ no permite~K3 entonces no se puede incluir~$a_4$. Además, si se han calculado $d_1$ y~$d_2$ y el resultado se almacena en el fichero de formato~$X$ (el resultado de combinar la interna original con los parámetros calculados en la autocalibración), este fichero se ha de indicar como fichero de interna en nuevo ajuste, y se debe realizar esta operación hasta que el resultado no varíe. Para una explicación detallada de esto véase la sección «Autocalibración» del manual de Aerotri y dentro de esta los apartados {\it Parámetros seguros para ficheros de interna no de Aerotri\/} y {\it Cálculos iterativos\/}.

\section{Valores aproximados}

{\elemento
	\lbyte{uint8m}{usa_gps;}{\%0: no; 1: sí (de momento se trata igual que 2); 2: Emplear sólo si están todos}
	\lbyte{bool8}{force_mmcc;}{\%0: fuerza un ajuste mm.cc., !=0: deja que el programa ajuste como quiera}
	\byte{u16int}{hacha;}
	\lbyte{u16int}{maximof;}{\%máximo número de fotos para el ajuste riguroso de todo el modelo}
	\byte{u16int}{mult_contra;}
}
\endelemento{ValoresAproximados}

Esta estructura contiene las opciones para el cálculo de valores aproximados, que son muy pocas. Si hay coordenadas gps/ins de los centros de proyección el cálculo es muy sencillo. En ese caso, además del fichero de fotogramas se indicará un fichero de GPS/INS. Además en el parámetro {\tt usa_gps} se pasará~1 para que dichos datos se empleen. Se puede pasar siempre 1, aunque no haya fichero de GPS, ya que si este fichero no existe el parámetro {\tt usa_gps} es ignorado.

El parámetro {\tt force_mmcc} indica, si está a~0, que el ajuste sea puramente mínimo cuadrático. La librería todavía no lo emplea y cálculo es esencialmente mínimo cuadrático siempre.

Los siguietes parámetros se emplean solamente si no hay datos gps/ins para todas las fotos:

{\explicacion
\byte{hacha}{Este parámetro ha de ser el número de puntos en común de un par de fotografías consecutivas tipo. Lo más cómodo es dejar que el programa lo deduzca. Para ello pasar 0.}
\byte{maximof}{El ajuste de valores aproximados no tiene que ser un proceso riguroso, por lo que cuando Aerotri tiene que realizar ajustes de modelos grandes dentro de este proceso no lo hace de modo riguroso para ahorrar tiempo. Si se pasa~0 Aerotri tomará un valor por defecto. Dicho valor es en estos momentos~12.}
\byte{mult_contra}{Pasar 0.}
}

En resumen, se pueden pasar simpre los mismos valores para esta estructura:

{\code {1,1,0,0,0}\par]

\section{Precisiones}

{\elemento
	\lbyte{float}{im;}{\%Coordenadas imagen}
	\lbyte{float}{pXY, pZ;}{\%Puntos de apoyo}
	\lbyte{float}{gpsXY, gpsZ;}{\%Coord. gps de los centros de proyección}
	\lbyte{float}{insΩΦ, insK;}{\%Giros de los centros de proyección}
}
\endelemento{Precisiones}

Esta estructura se corresponde exactamente con los datos pedidos en el recuadro «Precisiones» de la interfaz de Aerotri. Si alguno de los valores no existe se ha de pasar NaN o infinito, lo que se puede conseguir mediante la macro {\tt NAN_F}. Por ejemplo, {\tt NAN_F(apriori.insΩΦ)}. En ese caso serán las funciones de cálculo de la librería las que decidan qué valor de precisión emplear.

\section{Trabajo_Opciones}

{\elemento
	\byte{uint8m}{unigiros}
	\byte{bool8}{reescribe_cpp;}
	\byte{uint8m}{estimador;}
	\byte{bool8}{bgirok;}
	\lbyte{bool8}{fijas;}{\%Apoyo variable}
	\lbyte{bool8}{completo;}{\%Pasar 1}
	\lbyte{uint8m}{interp_gps;}{\%0, no; 1, sólo interpolar; 2, también extrapolar}
	\byte{bool8}{interp_resgps;}
	\byte{uint8m}{escalaresiduos;}
	\byte{float}{residuos_escala[20];}
}
\endelemento{Trabajo_Opciones}

{\defines
\byte{ATUNIGIROS_Rad}{0}{}
\byte{ATUNIGIROS_Gon}{1}{}
\byte{ATUNIGIROS_Sex}{2}{}
{ }
\byte{ESTIMADOR_MMCC}{0}{}
\byte{ESTIMADOR_AEROTRI_2006}{3}{}
{}
\byte{ATTrabajo_GiroINS180_Camara}{0}{}
\byte{ATTrabajo_GiroINS180_Fichero}{1}{}
}

Esta estructura incluye varios parámetros heterogéneos que no entran dentro de ninguna otra estructura.

{\explicacion
\byte{unigiros}{\symbolic{radianes}, grados \symbolic{centesimales} (gon) y grados \symbolic{sexagesimales}. Las unidades de los giros en los ficheros de entrada, que será las que se empleen también para los ficheros de salida. Antes solía emplearse grados centesimales, pero desde que se inlcuyen datos inerciales, que vienen siempre en grados sexagesimales, se emplea siempre estos últimos. Pasar por tanto \macro{ATUNIGIROS_Sex}.}

\byte{reescribe_cpp}{Indica si el fichero de valores aproximados se ha de reescribir trasformando los puntos aproximadamente al sistema de coordenadas del apoyo y GPS. Cuando se calculan valores aproximados sin ayuda de un fichero de GPS/INS el sistema de coordenadas de los valores aproximados es totalmente arbitratio, con el cero coincidiendo, o casi, con un centro de proyección y la escala de manera que las coordenadas~$Z$ de los puntos están en torno a~$-1$. Si se pasa~1 en este parámetro, cuando el cálculo del bloque haya transformado los valores aproximados al sistema del apoyo reescribirá el fichero de valores aproximados, que normalmente tendrá extensión .prm. Aerotri pasa~0  en este parámetro, ya que si el cálculo termina correctamente se genera un fichero .ajs de valores ajustados que está obviamente en el sistema de coordenadas de los puntos de apoyo y reemplaza al .prm de valores aproximados para cálculos futuros.}

\byte{estimador}{Ha de ser un número que selecciona un estimador entre varios predefinidos. De momento solamente hay dos posibles: \symbolic{mm.cc.} y \symbolic{Aerotri 2006}.}

\byte{bgirok}{indica la manera de interpretar una diferencia de un múltiplo de 90$^\circ$ (normalmente 180$^\circ$) entre la orientación que tiene la fotografía y el valor del giro ins recogido en el fichero. Una posibilidad es interpretar que la cámara está girada en el avión respecto al sistema inercial; la otra consiste en suponer que la fotografía fue girada a posteriori en el ordenador. Para lo primero se pasa \macro{ATTrabajo_GiroINS180_Camara} y para lo segundo \macro{ATTrabajo_GiroINS180_Fichero}. Se recomienda no hacer esto último, y por ello el valor por defecto en Aerotri es~0. Para una explicación detallada de la diferencia entre ambas interpretaciones véase la sección correspondiente en el manual de Aerotri.}

\byte{fijas}{Está a~1 si los puntos de apoyo se tratan como observaciones que pueden tener un cierto error o a~0 si se obliga a que sean fijos. Se recomienda pasar~1. En caso de que se obligue a que sean fijos los valores de precisión indicados para el apoyo se ignoran.}

\byte{completo}{Obsoleto hace mucho. Se ha de pasar~1, si bien si se pasa~0 el ajuste del bloque lo primero que hará será ponerlo a~1.}
}

Los parámetros {\tt interp_gps} e {\tt interp_resgps} se refieren a lo mismo. En una pasada puede haber centros de proyección presentes en el fichero GPS/INS pero que no se encuentran en el fichero de fotogramas; es decir, que no fueron medidos. Aerotri puede aplicar el error sistemático calculado para las coordenadas gps e ins de esa pasada a esos cc.pp. y generar unas coordenadas ajustadas, que se pueden incluir en los ficheros de salida de coordenadas de los cc.pp. Esto es útil por ejemplo cuando se vuela con un 80\char`\%\ de solape con el objetivo de mejorar la calidad de la ortofoto (o por lo que sea). Con este solape se pueden omitir una de cada dos fotos y formar modelos con fotografías alternas, que tienen un 60\char`\%\ de solape. Esto ahorra mucho trabajo ya que hay que medir la mitad de los modelos. Se introduce en el cálculo el fichero de fotogramas con solamente la mitad de las fotografías del vuelo, y Aerori generará coordenadas ajustadas para todas, sin más que aplicar a las coordenadas en el fichero de GPS/INS de las fotografías que no fueron medidas la corrección debida al error sistemático de dichas coordenadas que Aerotri calcula para cada pasada.

{\explicacion

\byte{interp_gps}{0: No incluir cc.pp. gps/ins intermedios; 1: Incluirlos en los ficheros de salida; 2: Incluir además los cc.pp. anteriores al primero medido de la pasada y los posteriores al último.}

\byte{interp_resgps}{Si está a~1 se corregirá además la coordenada del fichero GPS/INS de un residuo que se calcula como el intermedio entre el residuo de las coordenadas gps/ins del cc.pp. anterior y del siguiente. La idea de este parámetro es corregir errores sistemáticos más complejos que lineales, que se ponen de manifiesto en un cierto sistematismo en los residuos, en lugar de una completa aleatoriedad. Si existe un sistematismo en los residuos (por ejemplo que sean positivos hacial el principio y el final de la pasada, más en los extremos, y negativos en el centro), tiene sentido estimar el residuo que tendría un coordenada GPS promediando los de los puntos anterior y siguiente. Si no existe tal sistematimo la corrección de un suspuesto residuo calculado como el promedio de los residuos de los cc.pp. anterior y siguiente solamente añade ruido. Por defecto Aerotri pasa~0; es decir, no corregir de residuo interpolado.}

\byte{escalaresiduos}{Es un parámetro para los ficheros de salida. Refleja lo seleccionado en «Escala para las marcas de los residuos» (véase el manual de Aerotri). Si {\tt 0${}\leq{}$escalaresiduos${}\leq{}$3} se trata de una de las series predefinidas en {\it predefined_limites,\/} definido justo antes de la estructura \estructura{Trabajo_Opciones.} Si es {\tt ((uint8m)$-1$)} es otra cualquiera. En cualquier caso los valores límite para cada marca han de estar en {\tt residuos_escala}}

\byte{residuos_escala}{Serie de números positivos crecientes, cuyo final se indica mediante un {\tt NAN_F}. Por ejemplo, cuando la función \funcion{lee_trabajoAT} lee un trabajo, si el valor indicado para este parámetros es $n$, con $0\leq n\leq 3$, se ejecuta el siguiente código:}
}

\bgroup\code
trabajo->opciones.escalaresiduos=n;
memcpy_float(trabajo->opciones.residuos_escala,predefined_limites\[n\],10)\kern-2pt;
NAN_F(trabajo->opciones.residuos_escala\[10\]);\par]

En realidad, el único punto de la librería en el que se {\it emplea\/} el valor de {\tt escalaresiduos} es en \funcion{escribe_trabajoAT,} que escribirá dicho valor y solamente escribirá a continuación los valores de {\tt residuos_escala} si {\tt escalaresiduos} está fuera del rango de valores reconocidos (e.d., fuera del rango 0-3). Por lo tanto, para pasar a las funciones de la librería de cara al cálculo, los valores límites para las marcas han de estar siempre en {\tt residuos_escala}, cerrados por un {\tt NAN_F}.

\section{Trabajo_Sistema}

{\elemento
	\lbyte{uint}{nsistema;}{\%SIS_Rectangular... SIS_Geograficas}
	\lbyte{uint8m}{elipsoide;}{\%0: Esfera, 1: otro, 2-6: predefinido en ElipsoidesValores}
	\byte{float}{ondulacion;}
	\byte{struct\thinspace\{\thinspace Double}{a,ee;\bb{\}} elipsoideotro;}
	\byte{TSistema_Tierra}{tierra;}
	\byte{TSistema_ValoresProy}{valoressistemas;}
}
\endelemento{Trabajo_Sistema}

{\elemento
	\byte{Double}{N,rho,conv,k;}
}
\endelemento{TSistema_Tierra}

{\elemento
	\byte{Double}{kUTM, kLambert;}
	\byte{Double}{XUTM,YUTM, XLambert,YLambert;}
	\lbyte{ssint}{Phi0Lambert;}{\%El valor en milésismas de segundo}
	\lbyte{bool8}{LatLong;}{\%0 si el orden es φ,λ; 1 si es λ,φ}
}
\endelemento{TSistema_ValoresProy}

{\defines
\byte{SIS_Geograficas_{\rm φλ}}{0}{}
\byte{SIS_Geograficas_{\rm λφ}}{1}{}
}

Esta estructura guarda el sistema de coordenadas seleccionado y los valores indicados para todos los sistemas de coordenadas que Aerotri ofrece. Si la estructura \estructura{TrabajoAerotri} en la que se incluye tiene por objeto ser pasada a una de las funciones de cálculo solamente será necesario completar los valores que sean de aplicación al sistema de coordenadas seleccionado. Por ejemplo, si {\tt nsistema} es \macro{SIS_Rectangular} no hace falta asignar ningún valor más en la estructura.

Lo más importante es que se calcule la aerotriangulación en el mismo sistema de coordenadas que después vaya a emplear el software de restitución, generación de ortofotos, etc. Si dicho software no tiene en cuenta ningún sistema de coordenadas y simplemente trata las coordenadas como rectangulares se ha de calcular indicando \macro{SIS_Rectangular} o \macro{SIS_Conforme} con $\hbox{\tt tierra.k}=1$.

{\explicacion
\byte{nsistema}{Uno de los valores definidos en \fichero{ClaseSistema.h}.}
\byte{elipsoide}{Si es 0 se trata de una esfera y el radio se toma como {\tt (tierra.N + tierra.rho)/2}. Si es~1 se trata de un elipsoide cualquiera cuyos valores de $a$ y $e^2$ se toman de {\tt elipsoideotro}. Si es ≥2 sus dimensiones se toman de {\tt ElipsoidesValores[elipsoide-2]}, definido en \fichero{ClaseSistema.h}.}
\byte{ondulacion}{Ondulación del geoide en la zona. Exactamente, altura sobre la superficie de referencia (elipsode) de los puntos con $Z$ cero.}
}

Si el sistema de coordenadas es \macro{SIS_Rectangular} no hace falta ningún parámetro más. Cualquier otro sistema empleará en primer lugar el valor de {\tt ondulacion}. Se debe pasar cero en este parámetro salvo que el software que llama a la librería también tenga en cuenta la ondulación del geoide cada vez que trabaje con coordenadas terreno. Este parámetro se eliminó de la interfaz de Aerotri porque los usuarios se preocupaban de buscar el valor de ondulación del geoide en la zona cuando en realidad debían indicar cero, ya que los distintos software de restitución nunca tenía en cuenta este valor.

El elipsoide indicado en {\tt elipsoide} será de aplicación si {\tt nsistema} es distinto de\hfil\break \macro{SIS_Conforme}. Para este último sus parámetros se toman de {\tt tierra}:

{\explicacion
\byte{N}{Radio de curvatura mayor; esto es, según la dirección E-O.}
\byte{rho}{Radio de curvatura menor; esto es, según la dirección N-S.}
\byte{conv}{Ángulo que forma el eje~$Y$ con la dirección de curvatura menor; es decir, con el Norte. Positivo si hacia el Este.}
\byte{k}{Factor de escala de la proyección en la zona. <1 si la distancia de dos puntos sobre la proyección es menor que sobre el elipsoide.}
}

El sistema \macro{SIS_Conforme} es un sistema genérico que permite imitar localmente un sistema conforme cualquiera con precisión suficiente para una aerotriangulación salvo para grandes extensiones de terreno. Lo más importante es indicar correctamente el valor de~{\tt k}. Si el software de resitución no va a tener en cuenta el sistema de coordenadas se puede calcular la aerotriangulación indicando \macro{SIS_Conforme} para que al menos se tenga en cuenta la esfericidad de la Tierra, acordándose de pasar {\tt k=1}.

Los valores de {\tt N} y {\tt rho} no tienen mucha importancia. {\tt conv} sólo importa si $\hbox{\tt N}\neq\hbox{\tt rho}$. La mayoría de las veces es suficiente
$\hbox{\tt N}=\hbox{\tt rho}=6376000$.

Para extensiones de miles de quilómetros cuadrados la simulación de un sistema conforme cualquiera que permite \macro{SIS_Conforme} puede no ser suficiente. No obstante, para extensiones tan grandes la tendencia debería ser a que los ficheros estén directamente en coordenadas geográficas.

\subsection{TSistema_ValoresProy}

Guarda los valores seleccionados para todas las proyecciones que soporta la librería de Aerotri. En breve se añadirá la estereográfica oblicua y probablemente ya no se añada ninguna más.

{\explicacion
	\byte{kUTM, kLambert}{Factor de escala en el meridiano o paralelo central.}
	\byte{XUTM,YUTM, XLambert,YLambert}{Coordenadas del punto central de la proyección. Para la proyección UTM la coordenada {\tt YUTM} es la de los puntos del Ecuador.}
	\byte{Phi0Lambert}{Para la proyección Lambert. La latitud del paralelo central en milésismas de segundo.}
	\byte{LatLong}{Para geográficas. 0 si el orden en los ficheros es φ,λ; 1 si es λ,φ. Es mejor emplear las macros \macro{SIS_Geograficas_{\rm φλ}} y \macro{SIS_Geograficas_{\rm λφ}}.}
}

\section{AjbloqueConfigSalida}

Esta es una estructura bastante grande que se corresponde con el contenido de la pestaña «Ficheros de salida» de Aerotri, salvo por la escala para las marcas de los residuos que se incluye en \estructura{Trabajo_Opciones.} Por ello no se hará una descripción detallada de cada campo sino que se dirá con qué control de la GUI se corresponde y si acaso se hará una referencia al manual de Aerotri.

{\elemento
\def\omited{\lbyte{}{}{\kern-80pt/* ... */}}
	\struct
		\omited
	\byte{\}}{ficheros;}
	\struct
		\omited
	\byte{\}}{general;}
	\struct
		\omited
	\byte{\}}{pares_pasadas;}
	\struct
		\omited
	\byte{\}}{fich_Digi;}
	\struct
		\omited
	\byte{\}}{fich_Imaster;}
	\struct
		\omited
	\byte{\}}{fich_inf;}
	\struct
		\omited
	\byte{\}}{fich_std;}
	\struct
		\omited
	\byte{\}}{fich_pdf;}
	\struct
		\omited
	\byte{\}}{fich_dibujo;}
}
\endelemento{AjbloqueConfigSalida}

La estructura {\tt ficheros} consta de campos de un solo bit, según puede verse en \fichero{clases_mainabsoluta.h}, que se corresponden con cada uno de los {\it check box\/} que permiten seleccionar un fichero o un grupo de ficheros. Los dos primeros bits: {\tt res} e {\tt inc} no se corresponden con ningún check box porque son ficheros que ya no se generan; los generaban las primeras versiones de Aerotri.

La estructura {\tt general} se corresponde con el recuadro «Opciones generales», y junto con los los comentarios en el fichero .h no hace falta más explicación. Nótese que si bien la interfaz de Aerotri, en la elección del número de decimales a mostrar para los residuos, si se quere un número fijo de cifras significativas solamente da la opción de dos cifras significativas, la estructura \bb{AjbloqueDecimales} {\tt decres}, que es donde se pasan esos valores, permite cualesquiera otros valores.

La estructura {\tt pares_pasadas} se corresponde con «Pares» dentro de «Opciones generales». Se explica en la sección «Configuración de la salida$\rightarrow$ Pares» en el manual de Aerotri. {\tt brev} se corresponde con «Orientar las pasadas en el mismo sentido» y significa que si, por ejmeplo, el avión voló en dirección E-O en una pasada y O-E en la siguiente, los pares se generarán de manera que la fotografía izquierda sea siempre la del Este, o siempre la del Oeste, de manera que al abrir un par el Norte quede siempre hacia arriba o siempre hacia abajo, igual en ambas pasadas.

{\tt fich_Digi} y {\tt fich_Imaster} se corresponden con las opciones para los grupos de ficheros de salida de Digi e Image Master. En ambos casos {\tt files} son flags que indican los ficheros que se han de generar, según se indica en el comentario al mismo en \fichero{clases_mainabsoluta.h}. Las rutas {\tt rutarel} y {\tt rutaf} son las dos rutas por las que se pregunta en el cuadro de diálogo, en el mismo orden en que se piden. Los valores {\tt px,py} de {\tt fich_Digi} son las coordenadas del punto principal para escribir en los ficheros .rel. Son simplemente informativas y la interfaz de Aerotri no los pide y pasa siempre $(0,0)$.

{\tt fich_dibujo} pasa opciones para el gráfico del conjunto y el gráfico de los residuos y distorsiones. De momento los campos {\tt hwnd} y {\tt ConfigDibujo} se ignoran, mientras que los arrays de nombres de ficheros {\tt configs_main} y {\tt configs_residuos}, que han de estar cada uno terminados por un puntero \NULL, se establecen siempre a unos valores fijos en la interfaz de Aerotri, correpondientes a nombres de ficheros que se instalan con el programa, sin que el usuario pueda seleccionar otros, si bien se mira primero si existe una versión de ese fichero en la carpeta de datos del programa específica del usuario, por lo que si no el nombre, sí el contenido se puede modificar en esa copia local. {\tt configs_main} y {\tt configs_residuos} pueden ser \NULL. Excepcionalmente, estos arrays de nombres de ficheros no se guardan en el fichero de trabajo.

\subsection{fich_inf y fich_std}

{\elementocorto
	\byte{unsigned}{infR:16;}
	\byte{unsigned}{infP:16;}
}
\endelemento{fich_inf}

{\defines
\byte{AJ_INFR_Fotogramas}{1}{}
{\bf ...\/}\par%\byte{}{...}{}
\byte{AJ_INFR_Elevados}{0x20}{}
\byte{AJ_INFP_ParCentros}{1}{}
{\bf ...\/}\par%\byte{}{...}{}
\byte{AJ_INFP_PrecPuntosTodos}{0x100}{}
}

Se corresponde esta estructura con los checkbox de la ventana que se muestra al pulsar el botón a la derecha de «Texto (.inf)» y «Html (.html)».
Los bits de {\tt infR} e {\tt infP} inidican si uno u otro bloque de información ha de incluirse en dichos ficheros. {\tt infR} para los residuos e {\tt infP} para los valores ajustados y las precisiones. Las definiciones de macros que comienzan por \macro{AJ_INFR_} permiten discernir el significado de cada bit de {\tt infR}, mientras que las que comienzan por \macro{AJ_INFP_} se corresponden con los bits de {\tt infP}. En esta última las macros correspondientes a valores ajustados contienen la abreviatura {\tt Par} (de parámetros) mientras que las correspondientes a precisiones contienen en su nombre {\tt Prec}.

\macro{AJ_INFP_PrecCentros} indica si se han de mostrar las precisiones de los centros de proyección, mientras que \macro{AJ_INFP_PrecCentrosTodos} indica si se ha de mostrar solamente una muestra o todos. Análogamente para los puntos. Las macros terminadas en \macro{Grupo} hacen referencia a los parámetros de desviación (error sistemático) de los grupos (normalmente las pasadas) gps/ins.

{\elementocorto
	\byte{unsigned}{stdR:16;}
	\byte{unsigned}{stdP:16;}
}
\endelemento{fich_std}

{\defines
\byte{AJ_STDR_Distribucion}{1}{}
{\bf ...\/}\par%\byte{}{...}{}
\byte{AJ_STDR_GpsIns}{8}{}
\byte{AJ_STDP_PrecCentros}{1}{}
{\bf ...\/}\par%\byte{}{...}{}
\byte{AJ_STDP_CorrCentrosTodos}{0x80}{}
}

Análogamente al fichero de información esta estructura contiene dos variables cuyos bits indican si tal o cual información se incluye en el fichero de estadísticas. La macro \macro{AJ_STDR_Distribucion} hace referencia a la distribución de los residuos, mientras que el resto de las macros \macro{AJ_STDR_} hacen referencia a las redundancias parciales de cada conjunto de observaciones. La escritura de estas últimas aún no está programada por lo que los correspondientes bits todavía no tienen efecto.

El bit \macro{AJ_STDP_CorrCentrosTodos} quiere decir que se muestren las correlaciones de los parámetros de orientación entre centros de proyección con puntos comunes. Tampoco está programado todavía.

\section{Trabajo_Salida}

{\elemento
	\lbyte{bool8}{log_ajuste;}{\%Fichero de log para el ajuste}
	\lbyte{bool8}{log_pdfs;}{\%Mantener los logs de generación de los pdfs (de TeX)}
	\lbyte{u16int}{log_level;}{\%Nivel de log para ajbloque y relativa}
	\lbyte{bool8}{muestra_html;}{\%Mostrar html tras el cálculo}
}
\endelemento{Trabajo_Salida}

Esta estructura contiene unas pocas variables relativas a los ficheros de salida que no se incluyen en AjbloqueConfigSalida. Las variables {\tt log_pdfs} y {\tt muestra_html} no se usan en las funciones de cálculo de la librería de Aerotri ya que corresponden a acciones a llevar a cabo por la GUI. En la GUI de Aerotri, si {\tt log_pdfs} está a~1 se omite la eliminación de ciertos ficheros .log intermedios.

{\tt log_ajuste} indica si la GUI de Aerotri creará un fichero de log para pasar a la función \funcion{calcula_absoluta} para que lo escriba con los pasos que el ajuste del bloque va siguiendo. Puesto que dicho fichero es un parámetro que se pasa a \funcion{calcula_absoluta,} y si no se quiere lo que hay que hacer es pasar \NULL, la variable {\tt log_ajuste} no interviene en las funciones de cálculo de la librería (el trabajo la guarda como una indicación de lo que ha de hacer la GUI). {\tt log_level} indica el nivel de información mostrado en el log. Para \funcion{calcula_relativa} la infomación a glosar se incluye en el fichero .pro de proceso, que se genera siempre.


\chapter{Funciones de cáculo}

{\code \parindent-20pt \leftskip20pt
\bb[int] calcula_trabajoAT([\blue Handler] hwnd_main, [\blue int] log_code, [\blue TrabajoAerotri] *tr,
	[\blue bint] allow_empty, [\blue char16_t]* mensaje, [\blue u8int] idioma);\par
\bb[int] calcula_relativa([\blue Handler] hwnd_main, [\blue int] log_code,
	[\blue const struct strRelativaParams] *params, [\blue InfoMalos] *pinfomalos,
	[\blue char16_t]* mensaje, [\blue u8int] idioma);\par
\bb[int] calcula_absoluta([\blue Handler] hwnd_main, [\blue int] log_code, [\blue Buffer_to] *log_file,
	[\blue const struct strAbsolutaCallData] *params, [\blue FicheroBnf] *pinfo,
	[\blue char16_t]* mensaje, [\blue u8int] idioma);%
\par]

Los parámetros {\tt hwnd_main}, {\tt log_code}, {\tt mensaje} e {\tt idioma}, comunes a las tres funciones, se explican en \fichero{aerotri_trabajos.h}, con motivo de la explicación de \funcion{calcula_trabajoAT.} El parámetro {\tt params} ha de ser el resultado de una llamda con éxito a \funcion{prepara_trabajo_relativa} o \funcion{prepara_trabajo_absoluta.}

El parámetro {\tt log_file} en \funcion{calcula_absoluta} es el fichero de log, si se quiere uno; en caso contrario se ha de pasar \NULL. La información de este fichero no tiene mucho interés y nadie cambia la opción por defecto que es pasar \NULL, por lo que no vamos a extendernos aquí en explicar la estructura \estructura{Buffer_to.} Si se pasa un puntero a dicha estructura el fichero ha de estar ya abierto, \funcion{calcula_absoluta} escribe en él y no lo cierra.

El parámetro {\tt log_file} en \funcion{calcula_trabajoAT} indica que se permite que no existan algunos o todos los valores de precisión: precisión de las coordenadas imagen, del apoyo, etc. Si se pasa \true{} en este parámetro, los valores de precisión que no existan serán completados en el ajuste del bloque con valores por defecto. Puesto que los valores en cuestión siempre forman parte de la estructura {\tt apriori} dentro del \estructura{TrabajoAerotri}, la manera de indicar que un valor determinado no existe es pasando un infinito o NaN en ese valor.

Falta por explicar los parámetros {\tt pinfomalos} y {\tt pinfo}. Ambos son punteros a estructuras declaradas en ficheros de cabecera incluidos por \fichero{aerotri_trabajos.h} que las funciones de cálculo han de rellenar. Si no se quiere esa información se ha de pasar \NULL{} en dichos punteros.

\section{InfoMalos}

Esta estructura se rellena por \funcion{calcula_relativa} en caso de que el valor devuelto sea 10 u~11, lo que indica un error en el cálculo. Véase \fichero{mainrelativa.h}. Si lo que se quiere es mostrar al usuario información acerca de posibles pares de fotos o puntos malos no es necesario emplear esta estructura. Esa información ya se presenta en el archivo .pro que se genera siempre en el cálculo de la relativa. Aerotri, por ejemplo, no emplea esta estructura y siempre pasa \NULL{} en este parámetro. La información devuelta en esta estructura sirve para un correlador, para eliminar puntos malos o volver a correlar puntos nuevos, y tras ello volver a llamar a la librería. De esta manera el proceso de remedida y recálculo es transparente para el usuario, que no es consciente de que en un primer momento el cálculo dio error.

Si relamente se pasa un puntero a una estructura (en lugar de pasar \NULL) \funcion{calcula_relativa} la rellenará con punteros a memoria reservada que han de liberarse mediante una llamada a \funcion{free_plist} como sigue:

{\code free_plist(informalos.plist);]

\noindent Este código puede ejecutarse aunque la estructura no se haya rellenado, por lo que lo más cómodo es ejecutarlo siempre tras una llamada a \funcion{calcula_relativa} con {\tt pinfomalos} distinto de \NULL, una vez que ya no vamos a emplear más la estructura.

{\elemento
	\byte{PLIST}{plist;}
	\byte{UnPaso}{paresmalos[10];}
	\byte{Ajuste_con_PuntoMalo*}{ajustesmalos;}
	\byte{char*}{nombresf;}
	\byte{char*}{nombresp;}
	\byte{uint*}{fotos;}
	\byte{uint*}{puntos;}
}
\endelemento{InfoMalos}

El proceso de cálculo de valores aproximados, en ausencia de datos gps/ins para los centros de proyección, consiste en la unión de fotogramas para formar modelos. Después estos modelos se van uniendo entre sí o con fotogramas que todavía queden sueltos para ir formando modelos cada vez mas grandes. Tras el último paso el resultado es un modelo que contiene todas las fotos del trabajo. Cada uno de estos pasos une dos elementos y da como resultado un elemento. Los elementos pueden ser fotogramas o modelos ya existentes. Es la información que se muestra en el fichero de proceso.

Por ejemplo, un paso puede consistir en la unión de las fotografías 002435 y 002437 para formar el modelo~23. Otro paso puede ser la unión del modelo~23 con la fotografía 002502, cuyo resultado es otra vez el modelo 23. Otro paso puede ser la unión de los modelos 65 y 23 para dar como resultado el modelo 65; es decir, el modelo 65 se ha {\it comido\/} al 23. La información de cada paso se codifica en una estructura de tipo \estructura{UnPaso:}

{\elemento
	\lbyte{uint}{elem_r;}{\%n de modelo resultado}
	\lbyte{uint}{elem1;}{\%Si <0 es \~fotograma, si>0 un modelo.}
	\byte{uint}{elem2;}
	\lbyte{uint}{npuntos;}{\%número de puntos en común}
	\lbyte{uint}{ncentros;}{\%número de fotos del modelo resultado}
	\byte{Resultado}{ajuste;}
}
\endelemento{UnPaso}

Tanto los modelos como las fotografías se identifican con un número. Los números de fotografías empiezan en~0 y los de modelos en~1 (no existe el modelo~0). {\tt elem_r} es el número del modelo del resultado, ya que el resultado de un paso siempre es un modelo. {\tt elem1} y {\tt elem2} son los dos elementos que se unen. Si el número de tipo \bb{uint} tiene el bit más alto a~0 se trata de un número de modelo; si tiene el bit más alto a~1 se trata de un número de fotograma, codificado en complemento a unos; es lo que en los comentarios se indica como <0. Se pueden emplear las macros {\tt ispos_uint} e {\tt isneg_uint} para distinguir unos de otros. La macro {\tt ispos_uint} también se evalúa a \true{} si el número es cero:

{\code
[\green /* paso is of type UnPaso* */]
\bb[if](ispos_uint(paso->elem1)){	[\green //Se trata de un modelo]
\null	uint m=paso->elem1;
\null	[\green /* ... */]
}\bb[else]{	[\green //se trata de una foto]
\null	uint f=\char`\~paso->elem1;
\null	[\green /* ... */]
}\par%
]

\noindent Cuando se unan un modelo y una fotografía simpre será {\tt elem1} el modelo y {\tt elem2} la fotografía.

Cuando un ajuste de valores aproximados da error hay al menos un paso que dio error. Estos pasos se almacenan en el array {\tt ajustesmalos} dentro de {\tt infomalos}. El primer elemento del array con {\tt .najuste=\macro{EOUIA}} indica el final. Véanse definiciones y comentarios en \fichero{mainrelativa.h}. El propio elemento con {\tt .najuste=\macro{EOUIA}} ya no contiene nada.

El contenido de \estructura{Ajuste_con_PuntoMalo} se define y explica en \fichero{mainrelativa.h}. Da información acerca del punto peor del ajuste, que es el posible punto malo. {\tt ajsute.p_peor} es el número del punto peor y {\tt nast} una variable que indica cómo de verosímil es que el punto realmente sea malo, mediante un número que va de cero a cuatro. Esto se corresponde exactamente con lo mostrado en el archivo de proceso para cada ajuste malo.

La estructura {\tt infomalos} también contiene un array de pares de fotos que se consideran que pueden ser malos. Un par con {\tt ajuste.vv=0} indica el final. Puesto que el array se define como \bb{UnPaso} {\tt paresmalos[10]}, este puede contener entre cero y nueve posibles pares malos. Cómo de probable es que el par sea malo depende de {\tt ajuste.prop_peor}, {\tt ajuste.vvmax} y {\tt npuntos}, y depende mucho del correlador empleado, de modo que unos valores pueden ser indicativos de un punto malo para medidas procedentes de un cierto algoritmo de correlación pero no para otros. Por otra parte debe recordarse que en pares con solamente seis puntos en común el punto malo no puede deducirse salvo que supongamos {\it a priori\/} una posición relativa aproximada para los fotogramas (por ejemplo, aproximadamente en caso normal). En pares con seis puntos en común el punto {\tt p_peor} muchas veces no es el punto malo.

\subsection{Identificación de fotografías y puntos}

Se ha visto que tanto las fotografías como los puntos se identifican mediante un número. Para asociar un número de foto o de punto a su nombre, la estructura \estructura{InfoMalos} contiene los arrays {\tt nombresf}, {\tt fotos}, {\tt nombresp} y {\tt puntos}, para cuya comprensión y empleo son suficientes los comentarios adyacentes a su definición en el fichero \fichero{mainrelativa.h}.

\section{FicheroBnf}

{\elemento
	\byte{PLIST}{plist;}
	\byte{NamedPointer*}{punteros;}
	\byte{Namedn*}{enes;}
	\byte{BnfVarios}{*varios;}
}
\endelemento{FicheroBnf}

La función \funcion{calcula_absoluta} recibe un puntero a esta estructura para rellenarlo con resultados del cálculo. Es la misma información que se escribe en el fichero bnf. Si no se quiere recibir esta información se ha de pasar \NULL{} en {\tt pinfo}. Si en lugar de esto se pasa un puntero a una estructura para que se rellene, posteriormente ha de liberarse la memoria reservada mediante

{\code free_plist(informalos.plist);]

\noindent al igual que para \bb{InfoMalos} {\tt *pinfomalos} en \funcion{calcula_relativa.} Esta llamada no hará nada si debido a un error en el ajuste la estructura no se llegó a rellenar.

\subsection{BnfVarios}

{\elemento
	\byte{}{\quad ...}
	\struct
		\byte{\quad uint}{ncp, npm, npy, ngruposgps,ngps, ngruposins,nins, ngruposcalib;}
	\byte{\}}{ncalc;}
	\lbyte{Precisiones}{apriori;}{\%Los valores para magnitudes angulares,}
	\lbyte{Precisiones}{aposteriori;}{\%INSΩΦ e INSK, están en radianes}
	\lbyte{float}{$\sigma$_aposteriori;}{/*En relación a los valores a priori*/}
	\struct
		\byte{\quad float}{foto, apoyo, gps, ins;}
	\byte{\}}{redun_parciales;}
	\byte{uint}{nobs;}
	\byte{uint}{nincog;}
	\byte{DecimalesAj}{decj;}
}
\endelemento{BnfVarios}

Esta es una estructura con información variada. Los elementos anteriores a {\tt ncalc}, que van de {\tt ficherof} a {\tt estimador}, no se muestran porque coinciden con campos de la estructura \estructura{TrabajoAerotri} que ya se han explicado.

{\tt ncalc} contiene el número de elementos calculados, para distintos elementos:

{\explicacion
\byte{ncp}{Centros de proyección (cc.pp.); e.d., fotografías}
\byte{npm}{Puntos, incluyendo los de apoyo}
\byte{npy}{Puntos de apoyo}
\byte{ngruposgps}{Conjuntos con datos gps}
\byte{ngps}{Número de observaciones de cc.pp. gps o ins. En la práctica son siempre de gps y pueden ser además de ins}
\byte{ngruposins}{Conjuntos con datos ins (giros)}
\byte{nins}{Número de cc.pp. ins}
\byte{ngruposcalib}{0 si no hay datos de calibración, 1 si hay}
}

{\tt apriori} también se corresponde con datos de entrada, y {\tt aposteiori} son las desviaciones típicas que Aerotri deduce para cada conjunto de datos a raíz del ajuste. {\tt $\sigma$_aposteriori} es un valor global que indica la precisión de los datos en relación a lo especificado {\tt a priori}. Si es menor que~1 es que del ajuste se infiere que la precisión es mejor que la indicada en los datos de entrada; si es mayor que~1, que es peor.

Las redundancias parciales permiten deducir si hay datos del tipo en cuestión: si el valor es~0 no hay datos de ese tipo. Nótese que la indicación de un fichero de entrada no implica que contenga datos que vayan a entrar en el cálculo. Por ejemplo, si por equivocación se indica un fichero de GPS/INS de otro trabajo, en el que ningún nombre de centro de proyección coincide con los nombres de las fotos medidas, no habrá datos gps en el cálculo.

{\explicacion
\byte{foto}{De las fotocoordenadas. Nunca puede ser cero}
\byte{apoyo}{De las coordenadas de los puntos de apoyo}
\byte{gps}{De las observaciones gps de los cc.pp.}
\byte{ins}{De las observaciones ins de los cc.pp.}
}

{\tt nobs} y {\tt nincog} son respectivamete el número total de observaciones y de incógnitas del ajuste. En un ajuste mínimo cuadrático la suma de las redundancias parciales tiene que ser igual a la resta de estos dos valores. En un ajuste robusto puede variar ligeramente.

La estructura \bb{DecimalesAj} {\tt decj} contiene el número de cifras decimales con que se han de mostrar los valores ajustados, deducidos a partir de las precisiones {\it a priori\/} proporcionadas. Los valores que contiene son siempre positivos o cero, indicando el número de decimales tras la coma (y no, por tanto, el número de cifras significativas).

\subsection{Namedn}

{\elemento
	\byte{const char*}{name;}
	\byte{uint}{n;}
}
\endelemento{Namedn}

Este es un simple array de pares de nombre/valor. En el fichero \fichero{clases_infobinario.h} el array constante {\tt bnf_nombres_enteros} contiene los posibles valores de {\tt name}.

{\explicacion
\def\sbyte#1{\byte{\str{#1}}}
\sbyte{n fotogramas}{Número de fotogramas en el fichero de fotogramas, sin contar los vacíos}
\sbyte{n CentrosProy}{Número de centros de proyección en el fichero de valores aproximados que se corresponden con fotogramas del fichero de fotogramas. Normalmente coindice con el número de cc.pp. calculados ({\tt varios->ncalc.ncp}), pero este puede ser menor debido a centros que se hayan eliminado del cálculo por no tener suficientes puntos.}
\sbyte{n PuntosM}{Número de puntos en el fichero de valores aproximados que se corresponden con puntos en el fichero de fotogramas. Suele coincidir con el número de puntos calculados pero este último puede ser menor por algún punto eliminado por no aparecer en al menos dos fotogramas.}
\sbyte{n puntosA}{Número de puntos de apoyo en el fichero de apoyo.}
\sbyte{n puntosC}{Número de puntos de control en el fichero de apoyo.}
\sbyte{n GruposNAV}{Número de grupos gps/ins}
\sbyte{n gpss}{Número de obervaciones gps de cc.pp.}
\sbyte{n ins}{Número de observaciones ins de los cc.pp.}
\sbyte{n observaciones}{Número de fotocoordenadas medidas que entran en el cálculo}
}

\subsection{NamedPointer}

{\elemento
	\byte{uint}{tipo;}
	\byte{const char*}{name;}
	\lbyte{uint}{n;}{\%Número de elementos}
	\byte{void*}{p;}
}
\endelemento{NamedPointer}

{\explicacion
\byte{p}{Puntero a la dirección de memoria que almacena el array de elementos de tipo {\tt tipo}.}
\byte{tipo}{Tipo de elementos del array {\tt p}. Los posibles tipos están declarados en el mismo fichero que la estructura.}
\byte{n}{Número de elementos del array.}
\byte{name}{Nombre que identifica el array almacenado.}
}

El tamaño de un elemento de cada {\tt tipo} está definido en {\tt NamedPointersSizeof}, de manera que es

{\code NamedPointersSizeof\[tipo\].]

\noindent y el tamaño total del array es el número anterior multiplicado por {\tt n}. Los posibles nombres son los que se listan en {\tt bnf_nombres_punteros}.

Aerotri usa la información devuelta en esta estructura para mostrar los residuos en un cuadro, ordenados de mayor a menor por defecto. Para hacer esto mismo el programador puede analizar la estructura y organizar una tabla como desee, o bien emplear las funciones declaradas en \fichero{infobinario.h}. También se puede emplear el visor de Aerotri sin más que ejecutar EditordeDatos.exe pasando como argumento el nombre del fichero con extensión .bnf generado en el cálculo. (El nombre EditordeDatos no es adecuado, ya que no se edita nada, pero ha quedado así por razones históricas).


\chapter{Infobinario}

Esta librería consta de los ficheros \fichero{infobinario.h}, \fichero{clases_infobinario.h} y algún fichero de cabecera más incluido por estos. Para compilar hay que incluir

\byte{\#include}{\str{infobinario.h}}

\noindent y hacer referencia a \fichero{infobinario.lib}, y la dll con el código ejecutable es \fichero{infobinario.dll}.

La librería declara la estructura \estructura{FicheroBnf} y proporciona una función que lee un fichero binario de Aerotri, de extensión .bnf, rellenando una estructura de tipo \estructura{FicheroBnf;} una función que escribe el fichero a partir de la estructura, y funciones que rellenan tablas de residuos a partir de la estructura.

La descripción de la estructura se encuentra al final de capítulo anterior.

\section{Extraer los residuos de las fotocoordenadas}

El número total de puntos medidos es el entero indicado en \str{n observaciones}; es decir, el campo {\tt .n} del elemento del array {\tt enes} cuyo campo {\tt .name} apunta a la cadena \str{n observaciones}. Los residuos se encuentran en el array de nombre \str{L puntosf}, de tipo float; es decir, {\tt tipo==\macro{TIPOBNF_F}} . Si llamamos~{\tt L} a este array los residuos de la observación~{\tt i} se encuentran en {\tt L[2*i]} y {\tt L[2*i+1]}. Son los residuos de la fotocoordenada~$x$ y la fotocoordenada~$y$ respectivamente. Para saber a qué fotograma y punto corresponde esa observación se ha de mirar el array \str{observaciones}, de tipo int4 (\macro{TIPOBNF_U4}). El elemento {\tt observaciones[i]} contendrá la siguiente información:

{\explicacion
\byte{n1}{Número de punto}
\byte{n2}{Número de punto de apoyo. \macro{AT_NODATA} si no es punto de apoyo}
\byte{n3}{Número de centro de proyección (fotograma)}
\byte{n4}{Número de punto dentro del fotograma}
}

El nombre del punto se puede extraer mediante {\tt PuntosModelo[n1].nom}.

El nombre del fotograma se puede extraer mediante {\tt CentrosProy[n3].nom}.

{\tt PuntosModelo} y {\tt CentrosProy} son los arrays homónimos; es decir, de nombre\hfil\break \hbox{\str{PuntosModelo}} y \str{CentrosProy} respectivamente.


\section{Extraer los residuos de los puntos de apoyo}

Hay el entero de nombre \str{n puntosA} puntos de apoyo. Sus residuos se encuentran en el array de nombre \str{L puntosA}. Si llamamos~{\tt L} a este array los residuos en X,Y y Z del punto de apoyo~{\tt i} se encuentran en {\tt L[3*i]}, {\tt L[3*i+1]} y {\tt L[3*i+2]}.

Algún punto de apoyo puede no haber entrado en el cálculo. Para ello se mira el array \str{puntosA_a_PuntosM}. Sea {\tt pApM} ese array. Si {\tt pApM[i]==}\macro{AT_NODATA} entonces el punto de apoyo no entró en el cálculo y se debe ignorar.

Sea {\tt puntosApoyo} el array homónimo. El nombre del punto de apoyo~{\tt i} es {\tt puntosApoyo[i].nom}.


\section{Extraer los residuos de los puntos de control}

Hay (el entero de nombre) \str{n puntosC} puntos de control. Sus residuos se encuentran en el array de nombre \str{L puntosC}, análogo al array \str{L puntosA} para los puntos de apoyo.

Algún punto de control puede no haber entrado en el cálculo. Para ello se mira el array \str{puntosC_a_PuntosM}. Sea {\tt pCpM} ese array. Si {\tt pCpM[i]==\macro{AT_NODATA}} entonces el punto de control no entró en el cálculo y se debe ignorar.

Sea {\tt puntosControl} el array homónimo. El nombre del punto de control~{\tt i} es {\tt puntosControl[i].nom}.


\section{Extraer los residuos de GPS e INS}

Hay un total de (el entero de nombre) \str{n gpss} observaciones de gps y/o ins de los centros de proyección. El array \str{gpss} contiene dichas observaciones.

{\explicacion
\byte{gpss[i].nom}{El nombre del centro de proyección de la observación~{\tt i}}
\byte{gpss[i].bg}{Si es \true{} hay observación de gps $(X,Y,Z)$; si es \false, no}
\byte{gpss[i].bi}{Si es \true{} hay observación de ins $(Ω,Φ,K)$; si es \false, no}
}

Sus residuos se encuentran en los arrays de nombre \str{L gpss} y \str{L inss}. Sean {\tt Lg} y {\tt Li} dichos arrays. Los residuos de la observación~$i$ estarán en {\tt Lg[3*i]}, {\tt Lg[3*i+1]}, {\tt Lg[3*i+2]}; {\tt Li[3*i]}, {\tt Li[3*i+1]} y {\tt Li[3*i+2]}.

La función \funcion{calcula_absoluta} de la libería de Aerotri pone a \false{} los campos {\tt bg} y {\tt bi} de las observaciones que no se corresponden con un fotograma que entre en el cálculo de la aerotriangulación.

\section{Residuos normalizados}

Para cada residuo se puede calcular el cociente entre su valor y lo que cabría esperar de él en el ajuste. Dichos cocientes se almacenan en los arrays \str{Lnorm puntosf}, \str{Lnorm puntosA}, etc. Los valores almacenados son positivos o negativos según sea el residuo original.

\section{Las funciones que rellenan tablas}

Son las siguientes:

{\code
\bb[int] rellena_res_porfotos([\blue BnfTabla_ResporFoto] *tabla, ...
\bb[int] rellena_res_porpuntos([\blue BnfTabla_ResporPunto] *tabla, ...
\bb[int] rellena_res_apoyo([\blue BnfTabla_ResApoyo] *tabla, ...
\bb[int] rellena_res_gpsins([\blue BnfTabla_ResGPS] *tabla, ...\par%
]

Como puede verse el primer argumento de todas ellas es una tabla. Dicha tabla es rellenada por la función, para lo cual ha de reservar memoria. Posteriormente las filas de la tabla han de liberarse mediante la función \funcion{free_filas.} La definición de las tablas se encuentra al final del fichero \fichero{clases_infobinario.h}:

{\code
\bb[typedef struct]{[\blue BnfFila_ResporFoto] *filas; [\blue uint] nfilas;} BnfTabla_ResporFoto;
\bb[typedef struct]{[\blue BnfFila_ResporPunto] *filas; [\blue uint] nfilas;} BnfTabla_ResporPunto;\kern-1pt\null
\bb[typedef struct]{[\blue BnfFila_ResApoyo] *filas; [\blue uint] nfilas;} BnfTabla_ResApoyo;
\bb[typedef struct]{[\blue BnfFila_ResGPS] *filas; [\blue uint] nfilas;} BnfTabla_ResGPS;]

Si hemos pasado a una de esas funciones un puntero a una tabla de nombre {\tt tabla} deberemos liberar las filas así:

{\code free_filas(tabla.filas);]

En las funciones \funcion{rellena_res_porfotos} / \funcion{rellena_res_porpuntos} hay un parámetro de nombre {\tt llena_nombres}. Si está a \false{} se rellenarán las filas como las muestra el visor de resultados binarios de Aerotri, dejando en blanco el primer elemento de la fila para las filas que no sean la cabecera de una foto / punto. Si está a \true{} se completará ese elemento con el nombre de la foto / punto. Lo mejor para entender estas funciones es llamarlas y observar las filas creadas en la tabla.

Los parámetros {\tt dec}, o bien {\tt decgps} y {\tt decins} indican el número de decimales con que se formaterán los residuos, según la explicación del propio fichero \fichero{infobinario.h}, justo encima de la declaración de las funciones. El valor {\tt fccpi} es el multiplicador que pasa de radianes a las unidades en que queremos que se muestren los valores angulares. Si por ejemplo queremos que se muestren en grados sexagesimales el valor a pasar en {\tt fccpi} será $180/\pi=57.29578$.

El parámetro {\tt fijas} es el del mismo nombre en la estrucutra Trabajo_Opciones. Si es \false{} los puntos de apoyo se han mantenido fijos y no hay por tanto residuos de los puntos de apoyo. Podrá haber residuos de los puntos de control, ya que esto último no tiene nada que ver con que los puntos de apoyo sean fijos o no.

Los demás parámetros son enteros o punteros de la estructura \estructura{FicheroBnf,} según se indica a continuación:

\tabskip=0pt plus 1 fil
Enteros:
$$
\halign to\displaywidth{&\tt #\hfil&\str{#}\hfil\cr
ncp& n PuntosM & npm& n PuntosM\cr
ntot& n observaciones & npy& n puntosA\cr
npc& n puntosC & ngrupos& n GruposNAV\cr
}
$$

Punteros a arrays:
$$
\halign to\displaywidth{&\tt #\hfil&\str{#}\hfil\cr
orden_cp&Orden CentrosProy & p_cp_acum&Acumulado CentrosProy\cr
mafp&observaciones & centros&CentrosProy\cr
puntosM&PuntosModelo & pm_ppios&Ppios PuntoM_en_CP\cr
puntosA&puntosApoyo & orden_pm&Orden PuntosM\cr
pA_a_pM&puntosA_a_PuntosM & puntosC&puntosControl\cr
pC_a_pM&puntosC_a_PuntosM & grupos&GruposNAV\cr
grupos_acum&Acumulado GruposNAV & gpss&gpss\cr\noalign{\vskip10pt}
L&L puntosf & L_norm&Lnorm puntosf\cr
Lp&L puntosA & Lp_norm&Lnorm puntosA\cr
Lpc&L puntosC & Lpc_norm&Lnorm puntosC\cr
Lgps&L gpss & Lgps_norm&Lnorm gpss\cr
Lins&L inss & Lins_norm&Lnorm inss\cr
}
$$

\section{Las estructuras fila}

Los nombres de los campos de estas estructuras dan cuenta de su significado de manera clara (v. el fichero \fichero{clases_infobinario.h}). Los que comienzan por {\tt v_} son columnas que el visor de ficheros bnf de Aerotri no muestra al usuario. Las columnas {\v_resx}, etc. son los valores de los residuos, como un número \bb{float}, mientras que {\tt f2_resx}, etc. es lo mismo formateado como texto. Las columnas cuyo nombre contiene {\tt res_norm} son residuos normalizados, en valor absoluto (es decir, siempre positivos).

Las columnas que comienzan por {\tt v_orden_} contienen enteros que sirven para ordenar las filas según esa columna, pudiendo ordenarse por el orden por defecto, por residuo de mayor a menor o por residuo normalizado.

En las filas que rellena la función \funcion{rellena_res_apoyo} se intercala una fila vacía entre los puntos de apoyo y los puntos de control. En las filas de las funciones \funcion{rellena_res_porfotos} y \funcion{rellena_res_porpuntos} hay una fila de cabecera para cada foto o punto respectivamente seguida de las filas con los residuos de los puntos de la foto / de ese punto en las distintas fotos. Para entender esto bien no hay más que llamar a estas funciones y observar las filas devueltas, o bien observar las filas mostradas por el visor de ficheros .bnf de Aerotri al abrir uno de ellos.

\chapter{Distorsión}

La librería distorsión permite la lectura y escritura de ficheros de interna de Aerotri y su aplicación a fotocoordenadas medidas, en uno y otro sentido. El fichero de cabecera es \fichero{distorsion.h}, la referencia para enlazar es \fichero{distorsion.lib} y la dll \fichero{distorsion.dll}. Si se incluye \fichero{distorsion.h} además de \fichero{aerotri_trabajos.h} o \fichero{infobinario.h} ha de hacerse después de estos ficheros. Los comentarios del fichero .h bastan para el uso de esta librería.

\section{Lectura y escritura de ficheros}

La librería reconoce los siguientes formatos. No todos se pueden leer ni todos se pueden escribir. Los que se pueden leer se indican con \%R, los que se pueden escribir con \%W, y con \%R/W los que la librería es capaz de leer y escribir.

{\defines%\macrowidth=130pt
\byte{CAMFORMAT_Aerotri}{0}{\%R/W}
\byte{CAMFORMAT_ini}{1}{\%R/W}
\byte{CAMFORMAT_cmr}{2}{\%R/W}
\byte{CAMFORMAT_RapidCal}{3}{\%R}
\byte{CAMFORMAT_Digi}{4}{\%W}
\byte{CAMFORMAT_Agisfot}{5}{\%W}
}

La lectura del fichero se hace a través de la función \funcion{lee_ficheroint}:

{\code
\bb[int] lee_ficheroint([\blue const char16_t] *ficheroint, [\blue u8int] inm,
\null										[\blue OrientacionInterna*] interna,
\null										[\blue char16_t*] mensaje, [\blue u8int] idioma);\par]

El parámetro {\tt interna} apunta a una estructura que se llenará si la lectura tiene éxito. Véase el fichero \fichero{distorsion.h} para los posiblees valores devueltos y la explicación de los parámetros de la función.

La escritura del fichero se hace mediante una función específica para cada tipo de fichero. Véase el fichero \fichero{distorsion.h} para las distintas posibilidades. La función que escribe el fichero en el formato de Aerotri recibe un parámetro de tipo \bb{const OrientacionInterna}{\bf~*}; las demás reciben \bb{const InternaKPB}{\bf~*}. Una estructura de tipo \estructura{OrientacionInterna} se puede transformar en \estructura{InternaKBP} y viceversa. Se explica más abajo.

Lo primero que hace la función \funcion{lee_ficheroint} es inicializar la estructura {\tt interna}, antes incluso de intentar abrir el fichero. Por tanto cualquier contenido que tenga se destruirá. El contenido de la estructura {\tt interna}, es decir, la memoria a la cual los punteros de dicha estructura apuntan, ha de liberarse posteriormente mediante \funcion{free_interna}, incluso aunque la función devuelva algún código de error, pues pudo haberse rellenado parcialmente. Si el fichero no se llega a abrir no es necesario; no obstante no hace daño llamar siempre a \funcion{free_interna} y es lo mas fácil y seguro.

\section{OrientacionInterna}

{\elemento
	\byte{KeyVal}{*info;}
	\byte{uint}{flags;}
	\byte{Lineal2D_fl}{afin_1;}
	\byte{Valores_Interna}{valI;}
	\byte{Distorsion}{distorsion;}
}
\endelemento{OrientacionInterna}

La estructura \estructura{OrientacionInterna} representa una orientación interna de Aerotri. El array de \bb{KeyVal} contiene información sobre la cámara o la calibración. De momento hay definidas las siguientes claves (valores de {\tt key}).

{\defines\macrowidth=130pt
\byte{CAL_KV_END}{0}{\%Final del array}
\byte{CAL_KV_EMPTY}{((uintptr_t)-1)}{\%Par clave/valor vacío}
\byte{CAL_KV_minx}{1}{}
\byte{CAL_KV_maxx}{2}{}
\byte{CAL_KV_miny}{3}{}
\byte{CAL_KV_maxy}{4}{}
}

\noindent Para estas claves el valor es \bb{float}; es decir, la unión {\tt val} contiene el float {\tt val.fl}. Si el valor de la clave es \macro{CAL_KV_EMPTY} el par clave/valor está vacío, se debe ignorar. El final del array se indica mediante la clave \macro{CAL_KV_END}.

{\explicacion
\byte{flags}{Cada bit de este entero indica si un cierto tipo de trasformación está presente o no. El significado de cada bit viene dado por las macros \macro{CAL_FLAG_...}}
}

{\tt afin_1} es lo que Aerotri llama una transformación previa. Típicamente se usa para pasar del sistema píxel original de la foto, con el origen en la esquina superior izquierda y el eje~$y$ hacia abajo, a un sistema con origen en el centro de la foto y el eje~$y$ hacia arriba, ya sea en píxeles o en milímetros. La manera más rápida de explicar {\tt afin_1} y el significado de algunos bits de {\tt flags} es mostranto el código de la función \funcion{medida_a_fotocoord} de la librería:

{\code
\bb[void] medida_a_fotocoord([\blue Puntoxy_Double] *ob,
\null												[\blue const OrientacionInterna] *interna){
\null	[\blue if](interna->flags & CAL_FLAG_Transf1){
\null		[\blue Double] aux;
\null		ob->x-= interna->afin_1.Tx;
\null		ob->y-= interna->afin_1.Ty;
\null		aux= interna->afin_1.a*ob->x + interna->afin_1.b*ob->y;
\null		ob->y= interna->afin_1.c*ob->x + interna->afin_1.d*ob->y;
\null		ob->x= aux;
\null	}
\null	[\blue if](interna->flags & CAL_FLAG_pp){
\null		ob->x-= interna->valI.x;
\null		ob->y-= interna->valI.y;
\null	}
\null	[\blue if](interna->flags & CAL_FLAG_Distorsiones){
\null		corrige_distorsion(ob,interna,0);
\null	}
}\par]

A su vez, para que se calcule cada tipo de distorsión: radial simétrica, etc. es necesario que el correspondiente bit en {\tt flags} esté a~1.

{\explicacion
\byte{valI}{Almacena la focal y el punto principal, cuyo significado exacto se deriva del código arriba mostrado.}
\byte{distorsion}{Contiene un elemento de tipo \estructura{ConfigDistorsion} cuya exposición se desarrolla al explicar la estructura \estructura{Trabajo_Autocalib.} Contiene también cuatro arrays de float que almacenan los valores de las componentes de las cuatro series: Radial simétrica, Tangencial simétrica, Asimétricas 1 y Asimétricas 2.}
}

El manual Calibracion.html que viene con el instalador de Aerotri explica detalladamente el modelo de distorsión de Aerotri.

\section{InternaKPB}

{\elemento
	\byte{uint8m}{inexacta;}
	\struct
		\lbyte{\quad Double}{cx, cy;}{\%center, in pixels with respect to top left corner}
		\byte{\quad float}{px, py;}
	\byte{\}}{pixels;}
	\byte{Double}{x,y;}
	\byte{Double}{f;}
	\lbyte{float}{k[5];}{\%k[0]: distorsión lineal}
	\lbyte{float}{p1,p2;}{\%Half of these could go away}
	\lbyte{float}{b1,b2;}{\%The appearance of b1 changes k[0]; b2 would change kappa}
}
\endelemento{InternaKPB}

Esta estructura almacena una interna en la que los parámetros de distorsión son los conocidos K1, K2, K3, P1 y P2. Además permite un K4 y un K0, representando este último una distorsión radial lineal, proporcional al radio. El comentario en las componentes {\tt p1,p2} da una idea de porqué este modelo se llamaba antes InternaMala, si bien es de largo es más usado.

{\explicacion
\byte{inexacta}{Flags que indican pérdidas en un paso de \estructura{OrientacionInterna} a \estructura{InternaKPB} o bien cambios que darían lugar a orientaciones externas distintas. Véase el fichero \fichero{clases_distorsion.h} para una explicación detallada.}
\byte{pixels}{{\tt cx,cy} son análogos a {\tt Tx,Ty} de {\tt afin_1} en la interna de Aerotri (véase el comentario). {\tt px,py} son los tamaños de píxel en $x$ e~$y$. Normalmente son iguales. Pueden ser iguales a~1, en cuyo caso las unidades del resto de la estructura son píxeles.}
\byte{x,y}{Posición del punto principal respecto al centro (cx, cy). Análogos a {\tt valI.x} y {\tt valI.y} de Aerotri.}
\byte{f}{La focal}
\byte{k[5], p1,p2}{Las componentes de distorsión. {\tt k[0]} se establece inicialmente a cero al crear esta estructura a partir de una \estructura{OrientacionInterna}.}
\byte{b1,b2;}{Otras componentes. La aparición de {\tt b1} cambia {\tt k[0]}. Por tanto {\tt k[0]} y {\tt b1} son ambos cero o ambos distintos de cero si se generan a partir de una \estructura{OrientacionInterna} mediante las funciones de esta librería; {\tt b2} cambiaría kappa.}
}

\section{Transformación entre OrientacionInterna InternaKPB}

La primera función transforma de KPB a Aerotri; la segunda en sentido contrario:

{\code
\bb[int] interna_Aerotri___kpb([\blue const InternaKPB] *kpb,
\null													[\blue OrientacionInterna] *interna,
\null													[\blue bint] bfocal, [\blue bint] bpp);

\bb[int] interna_kpb___Aerotri([\blue const OrientacionInterna] *interna,
\null													[\blue InternaKPB] *kpb, [\blue float] *despl);\par]

Estos nombres un tanto extraños se deben a que en el editor de código del autor la secuencia de caracteres {\tt ___} se muestra gracia a una ligadura de la fuente como {\tt «}, de modo que los nombres se ven como \funcion{interna_Aerotri«kpb} y \funcion{interna_kpb«Aerotri} respectivamente.

Véase el archivo de cabecera para el significado de {\tt bfocal} y {\tt bpp} y los valores recomendados así como para los posibles valores devueltos por ambas funciones. El puntero {\tt despl} puede ser \NULL. En caso contrario se almacena en {\tt *despl} lo que ha sido necesario desplazar el punto principal al transformar a \estructura{InernaKPB}. Si es mayor que $\diez{8}{-6}$ de la semidiagonal del fotograma se pone a~{\tt 1} el bit bajo de {\tt inexacta} en {\tt kpb}.

\section{CombinaInternas}

{\code
\bb[int] combina_internas([\blue const OrientacionInterna] *interna1,
\null										[\blue const OrientacionInterna] *interna2,
\null										[\blue OrientacionInterna] *combinada);\par]

Esta función recibe dos orientaciones internas y genera, en una orientación interna única, el resultado de aplicar primero una y después la otra. {\tt interna1} e {\tt interna2} apuntan a orientaciones internas. {\tt combinada} apunta a una orientación interna vacía, que la función rellena y que posteriormente ha de liberarse mediante {\tt free_interna.} Se usa normalmente para combinar la interna procedente del fichero de cámara con la que surge del cálculo de parámetros de autocalibración.

\section{Modificaciones en la interna}

Las funciones \funcion{elimina_a1, elimina_a1_semidiag} y \funcion{cambia_semidiag} modifican la orientación interna pero de manera que el resultado neto es el mismo. Esto es posible ya que los parámetros no son todos independientes, y variaciones de unos se pueden anular con variaciones de otros. Se emplean por otras funciones que manejan orientaciones internas: las que transforman una \estructura{OrientacionInterna} en una \estructura{InternaKPB} o viceversa y \funcion{combina_internas.} Si el programador entiende lo que hacen (es imposible explicarlo brevemente con precisión) puede emplearlas si las necesita.

\closeout\indice
\theend
