\uselanguage{USenglish}
\input Manual-lib_macros.tex

\null\kern-\baselineskip\kern0.25\vsize
\ftitle
\centerline{The Aerotri Library}
\kern1em
\fsubsection
\centerline{Programmer's Manual}
\vfill
\break
\null\vfill
\break
}

\chapter{Table of Contents}
\input indice_eng.tex

\newwrite\indice
\openout\indice indice_eng.tex

\chapter{General}

\section{Introduction}

In order to use the Aerotri library the file \fichero{aerotri_trabajos.h} has to be included.

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

\noindent and at the linking step add a reference to \fichero{ATcrt.lib}, \fichero{aerotri_trabajos.lib} and \fichero{relativa.lib}.

The communication with the library takes place through the {\it Aerotri work;\/} more precisely, by means of an in-memory structure of type \estructura{TrabajoAerotri}, which represents an Aerotri work. Such work can be stored in a text file, usually with extension .art.

An Aerotri work stores all the information needed for the adjustment. An user having Aerotri installed in his computer may double-click on an Aerotri work file, for example {\it ejemplo.art,\/} whereby the file will be opened by Aerotri, and right after press the “Compute” button, and the adjustment will start. Likewise, a programmer who wishes to use the Aerotri library for the adjustment may just 1$^{\rm st}$) call the function that reads and loads in memory an Aerotri work file and 2$^{\rm nd}$) call the function that computes, passing it the structure of type \estructura{TrabajoAerotri} which was created upon reading the file. There is an example of code doing this in \fichero{maintest.c}.

Doing as described in the previous paragraph requires the creation in the first place of the work file, in which a hoard of configuration options are included. It is easier to ask the library for a structure \estructura{TrabajoAerotri} full with default values and then modify only what is needed. Afterwards, the function which computes may be called as well as that writing the text file from the in-memory structure of type \estructura{TrabajoAerotri}. This file may be read later on. The format of Aerotri work files is not documented explicitly, but it matches almost point by point the structure \estructura{TrabajoAerotri}, which is documented here. Also, because it is a text file it is very easy to read and interpreted. It is also enlightening to modify parameters on the Aerotri graphic interface and study the corresponding changes in the .art file. Aerotri writes this file every time the user presses the “Compute”  button, even if there is no license of Aerotri present.

Therefore, the easiest way to use the library is as follows:

{\code
\bb[int] nret;
\bb[char16_t] mensaje\[512\];
\bb[TrabajoAerotri] *tr=get_trabajo_aerotri();
tr->ficheros.fotos=u\str[estatua.ftm];
tr->ficheros.apoyo=u\str[puntos_apoyo.xyz];
nret=calcula_trabajo_aerotri(\NULL,0,tr,mensaje,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
The programmer may create himself a \estructura{TrabajoAerotri} structure by just declaring an object of that type:

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

\noindent fill it and pass pointers to it to the library functions. See the section {\it Filling with default values\/} from next chapter.

This structure, in turn, includes pointers into reserved memory, such us the input file names. If the programmer himself manages those pointers he should NOT call the library function \funcion{libera_trabajoAT,} whereas if it was the library to reserve memory for the pointers, which can only happen if the structure is filled by a call to \funcion{lee_trabajoAT,} the former function should be called in order to free them:

{\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(L\str[ejemplo.art],&trabajo);
\*
...
*/
libera_trabajoAT(&trabajo);\par]

If it is the programmer who fills the \estructura{TrabajoAerotri} structure, the code for working with the same might be similar to

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

FillMyWork(&trabajo);	\%Fills the structure with the information
												\%for the adjustment
nret=calcula_trabajo_aerotri(\NULL,0,tr,mensaje,\macro{ATIDIOMA_Eng});
if(nret==\macro{AT_ESC}){	\%The user escaped
\null\quad\*...*/
}else{
\null\quad\*... analyze the different values of nret
\null\quad if(...){
\null\quad}else if(...){
\null\quad}...
\null\quad*/
}
FreeMyWork(&trabajo);\par]

The functions \funcion{FillMyWork} and \funcion{FreeMyWork} are placeholders for the actual names of the user's functions.


\section{Two step adjustment}

Instead of the function \funcion{calcula_trabajo_aerotri} the programmer may prefer an independent computation of approximate values and the block adjustment:

{\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
	\* The program has run out of memory. Display the error message */
}

FillMyWork(&trabajo);
nret=prepara_trabajo_relativa(&trabajo, &rparams);
if(nret!=0){
\null	\*Display an error message according to nret*/
}
nret=calcula_relativa(\* ... */);
if(nret!=0){
\null	\*Display an error message according to nret*/
}
trabajo.ficheros.aproximadas=\* ... */	\%write here the name of the approximate
				\%values file generated in the previous calculation; i. e., in calcula_relativa().

nret=prepara_trabajo_absoluta(&trabajo, &aparams);
if(nret!=0){
\null	\*Display an error message according to nret*/
}
nret=calcula_absoluta(\* ... */);
if(nret==\macro{AT_ESC}){
\null	\*Don't do anything*/
}else if(nret!=0){
\null	\*Display an error message according to nret*/
}else{
\null	\*Display the message of a successful adjustment
\null	accomplishment and do other tasks*/
}

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

\section{The library functions}

The explanations of the previous sections and the comments within the file \fichero{aerotri_trabajos.h} are almost enough. There only remains to detail the behaviour of the functions \funcion{lee_trabajoAT} and \funcion{change_absparams} as well as the structures returned by \funcion{calcula_relativa} and \funcion{calcula_absoluta} in pointers passed to them as parameters, which will be explained later in a chapter of their own.

\subsection{lee_trabajoAT}

The first thing this function does is freeing the pointers within the structure in case they are not \NULL. Therefore, if the structure is created by the library by a call to \funcion{get_trabajo_aerotri,} filled and modified only by \funcion{lee_trabajoAT,} and its contents eventually freed by \funcion{libera_trabajoAT} and the structure itself by \funcion{ATtrabajos_free,} the programmer need not care about these pointers at all. If on the other hand it is the programmer who assigns values to those pointers, or who creates an object of the type \estructura{TrabajoAerotri}, before a call to \funcion{lee_trabajoAT} he should (re)set all its pointers to \NULL{}:

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

setNULL(&trabajo); \* Set all pointers within the structure to NULL */
err_code=lee_trabajoAT(\str[ejemplo.art],&trabajo);%
\par]

\funcion{setNULL} is an invented name, a placeholder for a programmer's function which should set to \NULL all the pointers within the structure. The next chapter lists all pointers into memory from this structure.

The function \funcion{lee_trabajoAT} does the following tasks in the specified order:

{\narrower\parindent=0pt \def\nodot{\hbox to 0pt{.\hss}}
${1\nodot}^\circ$ Free all pointers within the structure which are not \NULL\par
${2\nodot}^\circ$ Fill the structure with default values\par
${3\nodot}^\circ$ Open and read the file\par}

This order of things allows the use of this function with the purpose of assigning default values to a structure \estructura{TrabajoAerotri} by just calling it with a pointer to the said structure and a name of a non-existent file.

\subsection{change_absparams}

The function change_absparams can modify a structure of type \estructura{struct strAbsolutaCallData.} Before
proceeding further reading this first note that you may never need it.

Currently, this function can only modify one field from \estructura{strAbsolutaCallData.} The reason for providing this function to modify that field is that that particular field always gets a value of zero when the structure is created from a TrabajoAerotri using prepara_trabajo_absoluta, and so there is no other way of setting that field equal to one other than calling this function. Therefore, the only two ways the function can currently be called meaningfully are

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

\noindent assuming {\tt params} is of type \estructura{struct strAbsolutaCallData*.}

Setting the flag \macro{APARAMS_flags0_Semilibre} to one instructs the block adjustment to proceed even if the points within the control point file and/or the GPS/INS file, when either or both of these files are provided, are not enough for fixing the block to a 3D~coordinate system. Note that if none of these files is provided there is no need to set this flag: the adjustment will proceed in an arbitrary system. If the flag is not set, either a control file or GPS/INS file or both are specified, and the data within those files does not suffice to fix the block to a coordinate system, the function \funcion{calcula_trabajo_absoluta} will return~12 as explained at \fichero{clases_mainabsoluta.h.}

Note that a return value of~12 when the flag is not set (the default) usually means an error in the control or GPS file, not to mention that if any of those files is specified it is because they must carry the block to their coordinate system, and so a returned value of~12 really means an error. So you may never need to worry about this flag.


\chapter{The structure TrabajoAerotri}

\section{Introduction}

The structure \estructura{TrabajoAerotri} completely represents an Aerotri work and constitutes all that is needed for communicating with the library functions. The header file \fichero{ClaseTrabajo.h} and the files included by this afford some explanatory comments, which are nonetheless not enough for the understanding of all the fields from this structure. The intent of this chapter is its description in full.

An Aerotri work stores more information than is needed for a single adjustment. The reason for this is that it must store completely the state of all the GUI controls, including those deactivated and those that will not take part in the adjustment. Thus, if for instance a GPS/INS file is not provided, all the options relative to GPS can be ignored for the adjustment; the Aerotri work must store them all nonetheless. Another example: if the selected coordinate system is \symbolic{Conforme Genérico} all the options relative to the UTM system will not be part of this adjustment, jet the \estructura{TrabajoAerotri} must store them, so that if the user selects the UTM projection, the parameters he will see are the same as the last time it had been selected, and so forth. If the \estructura{TrabajoAerotri} structure is passed to the library functions that carry out the computations it is not necessary to assign values to the fields that will be ignored.

\section{Filling with default values}

The structure and the substructures that compose it have in all many different fields, and it may be tedious to assign default values to them all, as well as difficult and error-prone for the one facing the task for the first time. The Aerotri library does not provide a specific function for doing so, but the same can be achieved calling the function \funcion{lee_trabajoAT} with an inexistent file name, or just by calling the function \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();	\%Fills with default values
\par]

The first option needs the programmer to set to \NULL{} all the pointers prior to the function call, for the first thing that the function \funcion{lee_trabajoAT} does is freeing those pointers in case they are not \NULL. The second alternative is easier, since the function \funcion{get_trabajo_aerotri} will take care of initializing all the pointers to \NULL.

\section{NULL pointers}

Several times up to now word has been said about the structure pointers, which if not \NULL{} will be freed by the functions \funcion{lee_trabajoAT} and \funcion{libera_trabajoAT} (the former call the latter for freeing the structure it is passed in). These pointers are shown here, in a piece of code that sets all of them to \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]

The attentive programmer will have noticed that in case the structure is initialized by a call to \funcion{lee_trabajoAT} passing an inexistent file name, the pointers from {\tt fich_Digi} and {\tt fich_Imaster} are not set to \NULL{} but rather to pointers into predefined paths, such as {\tt\str{.\char`\\\char`\\}}. These are static globlal strings within the Aerotri library, and so neither they should be freed and the function \funcion{libera_trabajoAT} will not free them, as if they were \NULL pointers. The programmer need not care at all about this.

\section{TrabajoAerotri}

{\elemento
	\byte{u8int}{sensor;}
	\byte{u8int}{modo_toma;}
	\byte{u8int}{modo_medida;}
	\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}

{\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}{\%Manual points may be present too}
}

{\explicacion
\byte{sensor}{0, conic; 1, local model (always pass 0)}
\byte{modo_toma}{The way (the geometry) the photographs were taken. It is only used in the approximate values computation, which only slightly depends on it.}
\byte{modo_medida}{This is not yet taken into account, but future versions of the library will likely pay attention this parameter to carry the computation in one or other way according as to whether the measurement was manual or automatic, especialy with regard to the robust adjustment.}
}

The variable {\tt modo_toma} is used in the approximate values computation. The mode \symbolic{Unknown} is essentially the same as the mode \sumbolyc{Generico}. In case the photographs were taken parallel and laying approximately on the same plane, as is usually the case in aerial photogrammetry, passing \macro{ATMODOTOMA_Plano} helps preventing errors in the computation of approximate values.

\section{Trabajo_Ficheros}

{\elemento
	\lbyte{char16_t}{*fotos,}{\%Pointer to the photographs file name}
	\lbyte{\phantom{char16_t}}{*aproximadas,}{\%Pointer to the approximate values file}
	\lbyte{\phantom{char16_t}}{*apoyo,}{\%Pointer to control file}
	\lbyte{\phantom{char16_t}}{*gpsins,}{\%Pointer to the gps/ins file}
	\lbyte{\phantom{char16_t}}{*interna;}{\%Pointer to the interior orientation file (camera file)}
	\byte{u8int}{generar;}
}
\endelemento{Trabajo_Ficheros}

This structure contains the pointers to the names of input files plus the variable {\tt generar}. Some of the files may not exist, in which case the corresponding pointer must be \NULL.

The file {\tt fotos} is mandatory. {\tt aproximadas} is mandatory for the block adjustment, and the function \funcion{calcula_trabajo_aerotri} will automatically compute it in case it does not exist. The presence of the mandatory files is checked by the functions \funcion{prepara_trabajo_relativa,} \funcion{prepara_trabajo_absoluta} and \funcion{calcula_trabajo_aerotri}.

The shifting of the origin to the principal point and the removal of the distortions specified in the {\tt interna} file will be applied to the coordinates of the photographs file. Therefore, the file {\tt interna} should not be specified if the coordinates inside the photographs file have already been refined; i. e., reduced to the principal point and removed the distortion. It is strongly recommended that the photo coordinates be stored in raw pixels (no to confuse with the RAW format, the photographs may very well be stored in JPG at the moment of their being taken), with the origin at the top-left corner of the photograph, and that the interior orientation of the camera be specified in the {\tt interna} file. This way, if the triangulation adjustment includes self-calibrating parameters, as will usually be the case, Aerotri may combine the original {\tt interna} file with the parameters computed into a new interior orientation file.

If the photographs file format is either Aerotri or PATB, each photograph is followed in the file by the focal length. The focal length specified in the {\tt interna} file will have precedence with respect to those values.

If a file of control points is not included not a gps/ins file, the adjustment will be carried out in an arbitrary coordinate system. If any of these files or both of them are specified by the point within are not enough to define the coordinate system, the adjustment function will return an error. The reason for this is that, when those files are specified, the user intent is always that they carry enough points, and when this is not satisfied is because of some error. This behaviour of the program may be changed so that the adjustment would proceed, in a partly-defined, partly-arbitrary coordinate system. This is explained in the section {\it change_absparams\/} from the previous chapter.

{\tt generar} is a parameter whose lowest bits are flags, which if set to~1 mandate that a file in the Aerotri format be generated in case the corresponding input file (for example, the gps/ins file) is not. The Aerotri program passes~5 in this parameter, which when written in binary is {\tt 00101}, which instructs the block adjustment function to generate photographs' and control point files if the input ones are not of Aerotri format. Most photographs file formats do not include any value for the focal length, for the suppose that value will be specified in the interior orientation file. In those cases, the generated file with Aerotri format will write the value 1.0 for all photographs. According to the explanation two paragraphs above this is irrelevant since the value of the focal length will be taken from the {\tt interna} file.

\section{Trabajo_TipoFicheros}

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

This structure specifies the format of each input file, plus the parameter {\tt tdapr}. The possible values for each file format are:

{\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}
}

If a certain input file does not exist, its corresponding variable in this structure will be ignored. The values for the Aerotri formats are the result of the program history and the compatibility of new versions with old work files. The parenthesized values should not be used and will never be generated by the Aerotri GUI. The different formats for each input file are described in the Aerotri user manual.

{\explicacion
\byte{tdapr}{Type of approximate values. 0: Any values whatsoever; 2: The adjusted values of a previous adjustment}
}

The value~1 for {\tt tdapr} is used internally by Aerotri. If the value passed in {\tt tdapr} is~2 but Aerotri notices that some of the adjustment settings differ from those of the previous adjustment as specified in the approximate values file, such as the coordinate system or the self-calibration parameters, Aerotri will “downgrade” its value to~1.


\section{Trabajo_DatosGPS}
{\elemento
	\byte{u8int}{tdgps,tdins;}
	\byte{bint}{signoins;}
}
\endelemento{Trabajo_DatosGPS}

{\defines
\byte{ATTrabajo_TDGPS_Offset}{255}{Constant global error}
\byte{ATTrabajo_TDGPS_NoError}{0}{}
\byte{ATTrabajo_TDGPS_Constant}{1}{}
\byte{ATTrabajo_TDGPS_Linear}{2}{}
}

{\explicacion
\byte{tdgps,tdins}{Kind of systematic errors present in the gps and ins data. 0, no error; 1, constant error; 2, linear error; 255, offset}
\byte{signoins}{0: Aerotri internal criterion; 1: most common criterion in ins files}
}

The systematic error components are independent for each strip. This means that a different set of parameters is computed for each strip. The systematic error type \symbolic{offset} means a constant error equal to all the strips, and only applies to INS data. The kind of error to be expected is 1/0, i. e., constant for the GPS and errorless for the INS, or 2/0 in case the computation of the GPS coordinates is of lower quality. The INS may bear an \symbolic{offset} error if the calibration between the relative position of the inertial system and the camera axis is not completely right, and \symbolic{constant} if the program which processed the INS data did not transform the rotation properly. In case it not be desired to bother the user asking what the error types are, the safest option is to pass 2/1, yet 1/\symbolic{offset} will almost always be enough. The Aerotri default values are 1/1.

The \macro{ATTrabajo_TDGPS_Offset} expand to an arbitrary value. For all the others either the macros of the numbers $0$, $1$, $2$ may be used, for these values will never change because they have an intrinsic meaning which affords its use in arithmetic operations, and the Aerotri library code does so. The values are the degrees of freedom for each coordinate of the corresponding systematic errors.

In {\tt signoins}, the value~$1$ should be passed. A zero means a sense of positive rotations in accordance with the standard criterion in mathematics and is the one used by Aerotri internally. But the established criterion in photogrammetry is the opposite, hence pass~$1$.

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{u8int}{xy;}
	\byte{u8int}{XY;}
	\byte{u8int}{planiZ;}
}
\endelemento{EstimacionConjuntas}

These parameters are relevant for a robust adjustment and are ignored in a least squares computation. They specify whether a large error in one of a point's coordinates implies that the other coordinate should also be removed; that is to say, they instruct a joint or individual handling of the coordinates in the robust adjustment.

{\tt xy} refers to the $x$ and~$y$ photo coordinates; {\tt XY} to the two planimetric coordinates of control points and {\tt planiZ} to the planimetric coordinates on one side and the $Z$~coordinate at the other. The most common right setting is 1/1/0; i. e., that the errors in each of the $x$ and~$y$ photo coordinates are not independent, neither those of the $X$ and~$Y$ coordinates of control points, but the error in the $Z$~coordinates is indenpenden of the planimetric error.

\section{Trabajo_Autocalib}

{\elemento
	\lbyte{bint}{existe;}{\%Whether self-calibration has been selected for the adjustment}
	\byte{struct}{\{}{\narrower\edef\oldparindent{\the\parindent} \parindent 0pt
		\byte{bint}{f;}
		\byte{bint}{pp;}
		\byte{bint}{distorsion;}
		\byte{struct}{\{}{\advance\leftskip-\oldparindent \advance\leftskip-\oldparindent
			\byte{bint}{radsim;}
			\byte{bint}{tansim;}
			\byte{bint}{asimetricas;}
		}\byte{}{\} componentes;}
	}\byte{}{\} selected;}
	\byte{Config_distorsion}{config_dist;}
}
\endelemento{Trabajo_AutoCalib}

If the parameter {\tt existe} equals \false{} all the other fields of the structure will not be read by the functions that perform computations, but they will obviously do by the function \funcion{escribe_trabajoAT.} The variables within the structure {\tt selected} tells which parameters have been selected for computation.

{\explicacion
\lbyte{bint}{f;}{Focal length}
\lbyte{bint}{pp;}{Principal point}
\lbyte{bint}{distorsion;}{Distortion parameters}
}

If {\tt distorsion} is set to \false{} no distortion components are computed in the adjustment. Other than the distortion function, the self-calibration may include the refinement of the focal length and the principal point. If {\tt distorsion} equals \true, the structure {\tt componentes} details what distortion parameter sets have been selected for computation. There are three sets of parameters:

{\explicacion
\byte{radsim}{Symmetric radial distortion}
\byte{tansim}{Symmetric tangential distortion}
\byte{asimetricas}{Asymmetric distortion}
}

Each of these parameter sets is in turn detailed in {\tt config_dist}. For instance, certain bits from {\tt config_dist} will specify for each of the components $a_2$,\dots,$a_5$ of the symmetric radial distortion whether it has been selected for computation, which also needs {\tt radsim} to be \true.

\subsection{Config_distorsion}

{\elemento
	\lbyte{float}{semidiag;}{\%Photograph half-diagonal, i. e., $r_{\rm max.}$}
	\lbyte{u8int}{modelo_poli;}{\%Polynomic model}
	\lbyte{u8int}{modelo_asim;}{\%Asymmetric distiortion model}
	\lbyte{u8int}{condicion_radsim;}{\%Defining condition for the linear term of the Drs}
	\byte{float}{r1;}
	\lbyte{u16int}{param_radsim;}{\%flags indicating which of the parameters from the Drs will be computed: $a_1$, $a_2$, $a_3$\dots{}, starting by the lowest bit.}
	\lbyte{u16int}{param_tansim;}{\%The same, for the symmetric tangential distortion.}
	\lbyte{uint}{param_asim1;}{\%The same, for the first series of the asymmetric components.}
	\lbyte{uint}{param_asim2;}{\%The same, for the second series of the asymmetric components.}
}
\endelemento{Config_distorsion}

{\defines \macrovalwidth=20pt
\byte{CAL_MODPOL_IMPAR}{1}{}
\byte{CAL_MODPOL_COMPLETO}{2}{}
\byte{CAL_MODASIM_RADTAN}{1}{\%radial/tangential}
\byte{CAL_MODASIM_VECTOR}{2}{\%rotatin vector}
\byte{CAL_CONDICIONR_ORTO}{0}{\%that the radial distortion be orthogonal to the focal length ($a_1=0$)}
\byte{CAL_CONDICIONR_R1}{1}{\%Take $a_1$ so that Drs(r1)=0}
\byte{CAL_CONDICIONR_MM}{2}{\%Take $a_1$ so that |Drs min|=|Drs max|}
}

{\explicacion
\byte{semidiag}{It is usually left to the program to guess the right value for $r_{\rm max.}$. It will search the maximum value of~$r$ and take a round value that fits to it. For this purpose, a value of infinity or NaN should be assigned to this variable, which can be achieved, for instance, by means of the macros from \fichero{system.h}. In particular, the code {\tt NAN_F(semidiag)} assigns semidiag a NaN.}
\byte{modelo_poli}{For compatibility with other distortion models, it is recommended to always pass \macro{CAL_MODPOL_IMPAR}.}
\byte{modelo_asim}{Unless there is some reason for the contrary, always pass \macro{CAL_MODASIM_RADTAN}.}
\byte{condicion_radsim}{It is recommended to always use \macro{CAL_CONDICIONR_ORTO}.}
\byte{r1}{If {\tt condicion_radsim} is \macro{CAL_CONDICIONR_R1}, this is the value for which it is desired to have Drs(r1)=0. So, in particular, if  {\tt condicion_radsim} is \macro{CAL_CONDICIONR_ORTO} this value will be ignored.}
\byte{param_radsim}{In case the symmetric radial distorion has been selected, this field specifies which components will be computed. The lowest bit set to~$1$ means that $a_1$~should be computed, the second lowest bit refers to~$a_2$, and so forth. At present, components up to~$a_5$ have been programmed..}
}

The fields {\tt param_tansim}, {\tt param_asim1} and {\tt param_asim2} are the analogous to {\tt param_radsim} for the symmetric tangential components and the two series of the asymmetric components. In case the asymmetric model is \symbolic{radial/tangential}, the latter are the radial asymmetric ($c_1$, $c_2$,... ) and tangential asymmetric ($d_1$, $d_2$,... ) components. The number of programmed components for each asymmetric series is~12.

An element of type \estructura{Config_distorsion} created by the Aerotri user interface will always have set to zero the bits corresponding to the components $a_1$, $b_1$, $c_1$ and~$c_2$, because these components should never exist no matter what the distortion of the camera is, and the very concept of their computation together with the photographs' orientation parameters is nonsense. In order to understand this the programmer may read the “Calibracion” manual which is included with the Aerotri installer.

Neither does the Aerotri user interface ask for the polynomic model nor for the asymmetric one. It will always pass \symbolic{impar} and \symbolic{radial/tangential} to the library adjustment functions. Nor will it ask for the variable {\tt condicion_radsim}; it will always asign the value \symbolic{orthogonal}. Therefore it also does not ask for {\tt r1}, since for the \symbolic{orthogonal} condition does not apply.

La 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{u8int}{usa_gps;}{\%0: no; 1: sí (de momento se trata igual que 2); 2: Emplear sólo si están todos}
	\lbyte{bint}{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{u8int}{unigiros}
	\byte{bint}{reescribe_cpp;}
	\byte{u8int}{estimador;}
	\byte{bint}{bgirok;}
	\lbyte{bint}{fijas;}{\%Apoyo variable}
	\lbyte{bint}{completo;}{\%Pasar 1}
	\lbyte{u8int}{interp_gps;}{\%0, no; 1, sólo interpolar; 2, también extrapolar}
	\byte{bint}{interp_resgps;}
	\byte{u8int}{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 Trabajo_Opciones. Si es $-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 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 NAN_F.

\section{Trabajo_Sistema}

{\elemento
	\lbyte{uint}{nsistema;}{\%SIS_Rectangular... SIS_Geograficas}
	\lbyte{u8int}{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{bint}{LatLong;}{\%0 si el orden es φ,λ; 1 si es λ,φ}
}
\endelemento{TSistema_ValoresProy}

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 λ,φ.}
}

\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;}
}
\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)$.

\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 stadí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{bint}{log_ajuste;}{\%Fichero de log para el ajuste}
	\lbyte{bint}{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{bint}{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 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.

Falta por tanto 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.}

{\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 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. -1 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]==-1} 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]==-1} 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 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{OrientacionInterna}

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

La estructura OrientacionInterna representa una orientación interna de Aerotri. El array de 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, const [\blue OrientacionInterna] *interna){\kern-40pt\null
\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: Radia 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{InternaMala}

{\elemento
	\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}
}
\endelemento{InternaMala}

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 llama InternaMala, si bien es de largo es más usado.

{\explicacion
\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}
}

\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 OrientacionInterna en una InternaMala 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
