/* -*- coding: utf-8 -*- */
/**
\ingroup geom
@{
\file dpeuckerp.h
\brief Declaración de funciones para el aligerado de polilíneas en el plano
       basadas en el algoritmo de Douglas-Peucker.
\author José Luis García Pallero, jgpallero@gmail.com
\note Este fichero contiene funciones paralelizadas con OpenMP.
\date 04 de julio de 2011
\copyright
Copyright (c) 2011-2014, José Luis García Pallero. All rights reserved.
\par
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
\par
- Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this
  list of conditions and the following disclaimer in the documentation and/or
  other materials provided with the distribution.
- Neither the name of the copyright holders nor the names of its contributors
  may be used to endorse or promote products derived from this software without
  specific prior written permission.
\par
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/******************************************************************************/
/******************************************************************************/
#ifndef _DPEUCKERP_H_
#define _DPEUCKERP_H_
/******************************************************************************/
/******************************************************************************/
#if defined(_OPENMP)
#include<omp.h>
#endif
#include<stdlib.h>
#include<math.h>
#include"libgeoc/dpeuckera.h"
#include"libgeoc/segmento.h"
#include"libgeoc/geocomp.h"
/******************************************************************************/
/******************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************/
/******************************************************************************/
/**
\brief Indica si hay alguna función compilada en paralelo con OpenMP en el
       fichero \ref dpeuckerp.c.
\return Dos posibles valores:
        - 0: No hay ninguna función compilada en paralelo con OpenMP.
        - Distinto de 0: Sí hay alguna función compilada en paralelo con OpenMP.
\note Esta función asume que el argumento \em version tiene suficiente memoria
      asignada (si es distinto de \p NULL).
\date 17 de agosto de 2013: Creación de la función.
\date 03 de abril de 2014: Particularización de la función sólo para el plano.
*/
int GeocParOmpDpeuckerp(char version[]);
/******************************************************************************/
/******************************************************************************/
/**
\brief Elimina vértices de una polilínea en el plano mediante el algoritmo de
       Douglas-Peucker.
\brief El algoritmo original está documentado en:

\brief Douglas, D. H., Peucker, T. K., 1973. Algorithms for the reduction of the
       number of points required to represent a digitized line or its
       caricature. The Canadian Cartographer 10 (2), 112–122.

       También se utiliza el criterio apuntado en:
       Ebisch, K., October 2002. A correction to the Douglas–Peucker line
       generalization algorithm. Computers and Geosciences 28 (8), 995–997.
\param[in] x Vector que contiene las coordenadas X de los vértices de la
           polilínea de trabajo.
\param[in] y Vector que contiene las coordenadas Y de los vértices de la
           polilínea de trabajo.
\param[in] nPtos Número de elementos de los vectores \em x e \em y.
\param[in] incX Posiciones de separación entre los elementos del vector \em x.
           Este argumento siempre ha de ser un número positivo.
\param[in] incY Posiciones de separación entre los elementos del vector \em y.
           Este argumento siempre ha de ser un número positivo.
\param[in] tol Tolerancia para eliminar vértices, en las mismas unidades que las
           coordenadas de los vértices.
\param[in] posIni Posición en los vectores de coordenadas del punto inicial del
           segmento base para añadir puntos a la línea simplificada.
\param[in] posFin Posición en los vectores de coordenadas del punto final del
           segmento base para añadir puntos a la línea simplificada.
\param[out] usados Vector de \em nPtos elementos para indicar los puntos que
            finalmente se usan en la polilínea simplificada. En la entrada,
            todos sus elementos han de contener el valor 0, excepto las
            posiciones \em 0 y \em nPtos-1, que han de contener el valor 1. En
            la salida, las posiciones correspondientes a los puntos de la línea
            inicial no utilizados almacenarán el valor \em 0, mientras que las
            posiciones de los puntos utilizados almacenarán el valor \em 1.
\note Esta función se puede ejecutar en paralelo con OpenMP.
\note Esta función es recursiva.
\note Esta función no comprueba si el número de elementos de los vectores \em x
      e \em y es congruente con el valor pasado en \em nPtos.
\note Esta función asume que los valores \em posIni y \em posFin son posiciones
      válidas.
\note Esta función asume que el vector \em usados contiene suficiente memoria
      asignada.
\date 25 de mayo de 2012: Creación de la función.
\todo Esta función todavía no está probada.
*/
void DouglasPeuckerOriginalPlano(const double* x,
                                 const double* y,
                                 const size_t nPtos,
                                 const size_t incX,
                                 const size_t incY,
                                 const double tol,
                                 const size_t posIni,
                                 const size_t posFin,
                                 char* usados);
/******************************************************************************/
/******************************************************************************/
/**
\brief Elimina vértices de una polilínea en el plano mediante un algoritmo no
       recursivo, inspirado en el de Douglas-Peucker.
\brief Este algoritmo, comenzando por el primer punto de la polilínea, va
       uniendo puntos en segmentos de tal forma que se eliminan todos aquellos
       puntos que queden a una distancia menor o igual a \em tol del segmento
       de trabajo. Así aplicado, pueden ocurrir casos singulares en los que la
       polilínea aligerada tenga casos de auto intersección entre sus lados
       resultantes. Para evitar esto, se puede aplicar la versión robusta del
       algoritmo.
\param[in] x Vector que contiene las coordenadas X de los vértices de la
           polilínea de trabajo.
\param[in] y Vector que contiene las coordenadas Y de los vértices de la
           polilínea de trabajo.
\param[in] nPtos Número de elementos de los vectores \em x e \em y.
\param[in] incX Posiciones de separación entre los elementos del vector \em x.
           Este argumento siempre ha de ser un número positivo.
\param[in] incY Posiciones de separación entre los elementos del vector \em y.
           Este argumento siempre ha de ser un número positivo.
\param[in] tol Tolerancia para eliminar vértices, en las mismas unidades que las
           coordenadas de éstos.
\param[in] paralelizaTol Identificador para evaluar o no en paralelo si los
           puntos candidatos están en tolerancia. Dos posibilidades:
           - 0: Se evalúa en serie (aunque la compilación se haya hecho en
             paralelo) si los puntos están en tolerancia.
           - Distinto de 0: Se evalúa en paralelo (sólo si se ha compilado en
             paralelo) si los puntos están en tolerancia.
\param[in] robusto Identificador para realizar o no un aligerado robusto. Ha de
           ser un elemento del tipo enumerado #GEOC_DPEUCKER_ROBUSTO. Varias
           posibilidades:
           - #GeocDPeuckerOriginal: En este caso esta opción es equivalente a
             pasar #GeocDPeuckerRobNo.
           - #GeocDPeuckerRobNo: Utiliza la variación no recursiva del algoritmo
             de Douglas-Peucker, que no es robusta.
           - #GeocDPeuckerRobSi: Se aplica el algoritmo robusto completo, que
             garantiza la no ocurrencia de auto intersecciones en la polilínea
             resultante. Internamente, primero se aplica el tratamiento robusto
             de la opción #GeocDPeuckerRobOrig y luego el de la opción
             #GeocDPeuckerRobAuto.
           - #GeocDPeuckerRobOrig: Se aplica un algoritmo semi robusto que
             consiste en garantizar que los segmentos de la polilínea aligerada
             que se van creando no intersectarán con ninguno de los segmentos
             que forman los vértices que quedan por procesar de la polilínea
             original. En casos muy especiales, este algoritmo puede seguir
             dando lugar a auto intersecciones.
           - #GeocDPeuckerRobAuto: Se aplica un algoritmo semi robusto que
             consiste en garantizar que los segmentos de la polilínea aligerada
             que se van creando no intersectarán con ninguno de los segmentos
             de la polilínea aligerada creados con anterioridad. En casos muy
             especiales, este algoritmo puede seguir dando lugar a auto
             intersecciones.
\param[in] nSegRobOrig Número de segmentos de la polilínea original a utilizar
           en el caso de tratamiento robusto con las opciones #GeocDPeuckerRobSi
           o #GeocDPeuckerRobOrig. Si se pasa el valor 0, se utilizan todos los
           segmentos hasta el final de la polilínea original.
\param[in] nSegRobAuto Número de segmentos de la polilínea aligerada a utilizar
           en el caso de tratamiento robusto con las opciones #GeocDPeuckerRobSi
           o #GeocDPeuckerRobAuto. Si se pasa el valor 0, se utilizan todos los
           segmentos hasta el inicio de la polilínea aligerada.
\param[out] nPtosSal Número de puntos de la polilínea aligerada.
\return Vector de \em nPtosSal elementos que contiene los índices en los
        vectores \em x e \em y de los vértices que formarán la polilínea
        aligerada. Si ocurre algún error de asignación de memoria se devuelve el
        valor \p NULL.
\note Esta función no comprueba si el número de elementos de los vectores \em x
      e \em y es congruente con el valor pasado en \em nPtos.
\note Esta función asume que \em nPtos es mayor que 0. En caso contrario,
      devuelve \p NULL, por lo que un valor de retorno igual a \p NULL sólo es
      indicativo de error cuando \em nPtos es mayor que 0.
\note Esta función comprueba los casos especiales con
      \ref CasosEspecialesAligeraPolilinea.
\note El argumento \em paralelizaTol \b SÓLO afecta a la paralelización de la
      comprobación de puntos en tolerancia. Los chequeos de intersección de
      segmentos/arcos siempre se hacen en paralelo (si el código ha sido
      compilado al efecto).
\date 07 de julio de 2011: Creación de la función.
\date 10 de julio de 2011: Cambio del tipo del argumento \em robusto al tipo
      enumerado #GEOC_DPEUCKER_ROBUSTO.
\date 14 de mayo de 2012: Corregido bug que hacía que no se escogiese bien el
      vértice a añadir a la polilínea aligerada.
\date 25 de mayo de 2012: Cambio de nombre de la función.
\date 17 de agosto de 2013: Comprobación de casos especiales y unificación de
      las funciones de aligerado en el plano y en la esfera.
\date 20 de agosto de 2013: Sustitución de las antiguas variables de entrada
      \em nPtosRobusto y \em nSegRobusto por \em nSegRobOrig y \em nSegRobAuto.
\date 23 de agosto de 2013: Adición del argumento de entrada \em paralelizaTol.
\date 01 de abril de 2014: Particularización de la función sólo para el plano.
\todo Esta función todavía no está probada.
*/
size_t* DouglasPeuckerRobustoPlano(const double* x,
                                   const double* y,
                                   const size_t nPtos,
                                   const size_t incX,
                                   const size_t incY,
                                   const double tol,
                                   const int paralelizaTol,
                                   const enum GEOC_DPEUCKER_ROBUSTO robusto,
                                   const size_t nSegRobOrig,
                                   const size_t nSegRobAuto,
                                   size_t* nPtosSal);
/******************************************************************************/
/******************************************************************************/
/**
\brief Comprueba, mediante una ejecución en paralelo, con OpenMP, si una serie
       de puntos entre los extremos de un segmento base están en tolerancia,
       según el criterio de la familia de algoritmos de Douglas-Peucker.
\param[in] x Vector que contiene las coordenadas X de los vértices de la
           polilínea de trabajo.
\param[in] y Vector que contiene las coordenadas Y de los vértices de la
           polilínea de trabajo.
\param[in] incX Posiciones de separación entre los elementos del vector \em x.
           Este argumento siempre ha de ser un número positivo.
\param[in] incY Posiciones de separación entre los elementos del vector \em y.
           Este argumento siempre ha de ser un número positivo.
\param[in] tol Tolerancia para eliminar vértices, en las mismas unidades que las
           coordenadas de éstos.
\param[in] posBaseIni Posición en los vectores \em x e \em y del punto inicial
           del segmento base.
\param[in] posBaseFin Posición en los vectores \em x e \em y del punto final del
           segmento base.
\param[in] posPtoIni Posición en los vectores \em x e \em y del punto inicial a
           partir del cual (incluido) se chequeará la tolerancia.
\param[in] posPtoFin Posición en los vectores \em x e \em y del punto inicial
           hasta el cual (incluido) se chequeará la tolerancia.
\return Identificador de que los puntos intermedios están o no en tolerancia.
        Dos posibilidades:
        - 0: Hay algún punto que se sale de tolerancia.
        - Distinto de 0: Todos los puntos están en tolerancia.
\note Esta función está paralelizada con OpenMP.
\note Esta función no comprueba si las posiciones pasadas en \em posBaseIni,
      \em posBaseFin, \em posPtoIni y \em posPtoFin son congruentes con el
      número de elementos de los vectores \em x e \em y.
\note Esta función asume que
      \em posBaseIni < \em posPtoIni <= \em posPtoFin < \em posBaseFin.
\date 18 de agosto de 2013: Creación de la función.
\date 27 de marzo de 2014: Adición de los argumentos \em xG, \em yG y \em zG.
\date 01 de abril de 2014: Particularización de la función sólo para el plano.
\todo Esta función todavía no está probada.
*/
int DouglasPeuckerPuntosEnTolPlanoOMP(const double* x,
                                      const double* y,
                                      const size_t incX,
                                      const size_t incY,
                                      const double tol,
                                      const size_t posBaseIni,
                                      const size_t posBaseFin,
                                      const size_t posPtoIni,
                                      const size_t posPtoFin);
/******************************************************************************/
/******************************************************************************/
/**
\brief Comprueba, mediante una ejecución en serie, si una serie de puntos entre
       los extremos de un segmento base están en tolerancia, según el criterio
       de la familia de algoritmos de Douglas-Peucker.
\param[in] x Vector que contiene las coordenadas X de los vértices de la
           polilínea de trabajo.
\param[in] y Vector que contiene las coordenadas Y de los vértices de la
           polilínea de trabajo.
\param[in] incX Posiciones de separación entre los elementos del vector \em x.
           Este argumento siempre ha de ser un número positivo.
\param[in] incY Posiciones de separación entre los elementos del vector \em y.
           Este argumento siempre ha de ser un número positivo.
\param[in] tol Tolerancia para eliminar vértices, en las mismas unidades que las
           coordenadas de éstos.
\param[in] posBaseIni Posición en los vectores \em x e \em y del punto inicial
           del segmento/arco base.
\param[in] posBaseFin Posición en los vectores \em x e \em y del punto final del
           segmento/arco base.
\param[in] posPtoIni Posición en los vectores \em x e \em y del punto inicial a
           partir del cual (incluido) se chequeará la tolerancia.
\param[in] posPtoFin Posición en los vectores \em x e \em y del punto inicial
           hasta el cual (incluido) se chequeará la tolerancia.
\return Identificador de que los puntos intermedios están o no en tolerancia.
        Dos posibilidades:
        - 0: Hay algún punto que se sale de tolerancia.
        - Distinto de 0: Todos los puntos están en tolerancia.
\note Esta función no comprueba si las posiciones pasadas en \em posBaseIni,
      \em posBaseFin, \em posPtoIni y \em posPtoFin son congruentes con el
      número de elementos de los vectores \em x e \em y.
\note Esta función asume que
      \em posBaseIni < \em posPtoIni <= \em posPtoFin < \em posBaseFin.
\date 18 de agosto de 2013: Creación de la función.
\date 27 de marzo de 2014: Adición de los argumentos \em xG, \em yG y \em zG.
\date 01 de abril de 2014: Particularización de la función sólo para el plano.
\todo Esta función todavía no está probada.
*/
int DouglasPeuckerPuntosEnTolPlanoSerie(const double* x,
                                        const double* y,
                                        const size_t incX,
                                        const size_t incY,
                                        const double tol,
                                        const size_t posBaseIni,
                                        const size_t posBaseFin,
                                        const size_t posPtoIni,
                                        const size_t posPtoFin);
/******************************************************************************/
/******************************************************************************/
/**
\brief Aproximación robusta al aligerado de líneas consistente en evitar que los
       segmentos creados intersecten con los de la polilínea original a partir
       del punto de trabajo actual.
\param[in] x Vector que contiene las coordenadas X de los vértices de la
           polilínea de trabajo.
\param[in] y Vector que contiene las coordenadas Y de los vértices de la
           polilínea de trabajo.
\param[in] nPtos Número de elementos de los vectores \em x e \em y.
\param[in] incX Posiciones de separación entre los elementos del vector \em x.
           Este argumento siempre ha de ser un número positivo.
\param[in] incY Posiciones de separación entre los elementos del vector \em y.
           Este argumento siempre ha de ser un número positivo.
\param[in] segAUsar Número de segmentos a utilizar de la polilínea original. Si
           se pasa el valor 0 se utilizan todos los segmentos que quedan desde
           el punto de trabajo hasta el final.
\param[in] posIni Posición inicial del segmento a chequear.
\param[in,out] posFin Posición final del segmento a chequear. Al término de la
               ejecución de la función almacena la posición del punto que hace
               que el segmento de la polilínea aligerada no intersecte con
               ninguno de los que quedan de la polilínea original.
\note Esta función no comprueba si el número de elementos de los vectores \em x
      e \em y es congruente con el valor pasado en \em nPtos.
\note Esta función no comprueba si los índices pasados en los argumentos
      \em posIni y \em posFin son congruentes con el tamaño de los vectores
      pasado en \em nPtos.
\date 07 de julio de 2011: Creación de la función.
\date 25 de mayo de 2012: Cambio de nombre de la función.
\date 18 de agosto de 2013: Unificación para el uso sobre el plano y sobre la
      esfera.
\date 20 de agosto de 2013: Reorganización interna de la ejecución en serie y en
      paralelo de la función.
\date 27 de marzo de 2014: Adición de los argumentos \em xG, \em yG y \em zG.
\date 01 de abril de 2014: Particularización de la función sólo para el plano.
\todo Esta función todavía no está probada.
*/
void DouglasPeuckerRobIntersecOrigPlano(const double* x,
                                        const double* y,
                                        const size_t nPtos,
                                        const size_t incX,
                                        const size_t incY,
                                        const size_t segAUsar,
                                        const size_t posIni,
                                        size_t* posFin);
/******************************************************************************/
/******************************************************************************/
/**
\brief Comprueba, mediante una ejecución en paralelo con OpenMP, si una serie de
       segmentos se cortan con un segmento/arco base AB, a partir de éste en
       adelante.
\param[in] xA Coordenada X del punto A.
\param[in] yA Coordenada Y del punto A.
\param[in] xB Coordenada X del punto B.
\param[in] yB Coordenada Y del punto B.
\param[in] x Vector que contiene las coordenadas X de los vértices de la
           polilínea de trabajo.
\param[in] y Vector que contiene las coordenadas Y  de los vértices de la
           polilínea de trabajo.
\param[in] incX Posiciones de separación entre los elementos del vector \em x.
           Este argumento siempre ha de ser un número positivo.
\param[in] incY Posiciones de separación entre los elementos del vector \em y.
           Este argumento siempre ha de ser un número positivo.
\param[in] posIni Posición en los vectores \em x e \em y del punto inicial a
           partir del cual (incluido) se comenzarán a chequear segmentos.
\param[in] posFin Posición en los vectores \em x e \em y del punto final hasta
           el cual (incluido) se chequearán segmentos.
\return Dos posibilidades:
        - 0: No hay ninguna intersección entre AB y los segmentos desde
          \em posIni hasta \em posFin.
        - Distinto de 0: Hay al menos una intersección entre AB y los segmentos
          desde \em posIni hasta \em posFin.
\note Esta función está paralelizada con OpenMP.
\note Esta función no comprueba si los argumentos \em posIni y \em posFin son
      congruentes con las dimensiones de los vectores \em x e \em y.
\note Esta función asume que \em posIni<\em posFin.
\note Esta función utiliza internamente la función
      \ref DouglasPeuckerRobIntersecPlano, que no es robusta. En consecuencia,
      los resultados de esta función tampoco lo son.
\date 20 de agosto de 2013: Creación de la función.
\date 27 de marzo de 2014: Adición de los argumentos \em xG, \em yG y \em zG.
\date 01 de abril de 2014: Particularización de la función sólo para el plano.
\todo Esta función todavía no está probada.
*/
int DouglasPeuckerRobIntersecOrigPlanoOMP(const double xA,
                                          const double yA,
                                          const double xB,
                                          const double yB,
                                          const double* x,
                                          const double* y,
                                          const size_t incX,
                                          const size_t incY,
                                          const size_t posIni,
                                          const size_t posFin);
/******************************************************************************/
/******************************************************************************/
/**
\brief Comprueba, mediante una ejecución en serie, si una serie de segmentos
       se cortan con un segmento base AB, a partir de éste en adelante.
\param[in] xA Coordenada X del punto A.
\param[in] yA Coordenada Y del punto A.
\param[in] xB Coordenada X del punto B.
\param[in] yB Coordenada Y del punto B.
\param[in] x Vector que contiene las coordenadas X de los vértices de la
           polilínea de trabajo.
\param[in] y Vector que contiene las coordenadas Y de los vértices de la
           polilínea de trabajo.
\param[in] incX Posiciones de separación entre los elementos del vector \em x.
           Este argumento siempre ha de ser un número positivo.
\param[in] incY Posiciones de separación entre los elementos del vector \em y.
           Este argumento siempre ha de ser un número positivo.
\param[in] posIni Posición en los vectores \em x e \em y del punto inicial a
           partir del cual (incluido) se comenzarán a chequear segmentos.
\param[in] posFin Posición en los vectores \em x e \em y del punto final hasta
           el cual (incluido) se chequearán segmentos.
\return Dos posibilidades:
        - 0: No hay ninguna intersección entre AB y los segmentos desde
          \em posIni hasta \em posFin.
        - Distinto de 0: Hay al menos una intersección entre AB y los segmentos
          desde \em posIni hasta \em posFin.
\note Esta función no comprueba si los argumentos \em posIni y \em posFin son
      congruentes con las dimensiones de los vectores \em x e \em y.
\note Esta función asume que \em posIni<\em posFin.
\note Esta función utiliza internamente la función
      \ref DouglasPeuckerRobIntersecPlano, que no es robusta. En consecuencia,
      los resultados de esta función tampoco lo son.
\date 20 de agosto de 2013: Creación de la función.
\date 27 de marzo de 2014: Adición de los argumentos \em xG, \em yG y \em zG.
\date 01 de abril de 2014: Particularización de la función sólo para el plano.
\todo Esta función todavía no está probada.
*/
int DouglasPeuckerRobIntersecOrigPlanoSerie(const double xA,
                                            const double yA,
                                            const double xB,
                                            const double yB,
                                            const double* x,
                                            const double* y,
                                            const size_t incX,
                                            const size_t incY,
                                            const size_t posIni,
                                            const size_t posFin);
/******************************************************************************/
/******************************************************************************/
/**
\brief Aproximación robusta al aligerado de líneas consistente en evitar que los
       segmentos creados intersecten con los anteriores de la polilínea
       aligerada.
\param[in] x Vector que contiene las coordenadas X de los vértices de la
           polilínea de trabajo.
\param[in] y Vector que contiene las coordenadas Y de los vértices de la
           polilínea de trabajo.
\param[in] incX Posiciones de separación entre los elementos del vector \em x.
           Este argumento siempre ha de ser un número positivo.
\param[in] incY Posiciones de separación entre los elementos del vector \em y.
           Este argumento siempre ha de ser un número positivo.
\param[in] posIni Posición (en los vectores \em x e \em y) inicial del
           segmento a chequear.
\param[in,out] posFin Posición (en los vectores \em x e \em y) final del
               segmento a chequear. Al término de la ejecución de la función
               almacena la posición del punto que hace que el segmento de la
               polilínea aligerada no intersecte con ninguno de los
               anteriormente calculados.
\param[in] posAlig Vector de posiciones de \em x e \em y utilizadas en la
           polilínea aligerada.
\param[in] nPosAlig Número de elementos de \em posAlig.
\param[in] segAUsar Número de segmentos a utilizar de la polilínea aligerada. Si
           se pasa el valor 0 se utilizan todos los segmentos anteriores.
\note Esta función no comprueba si el número de elementos de los vectores \em x
      e \em y.
\note Esta función no comprueba si los índices pasados en los argumentos
      \em posIni y \em posFin son congruentes con el tamaño de los vectores
      pasado en \em nPtos.
\note Esta función no comprueba si los índices almacenados en \em posAlig son
      congruentes con el tamaño de los vectores \em x e \em y.
\note Esta función no comprueba si el valor pasado en \em nPosAlig es congruente
      con el tamaño del vector \em posAlig.
\date 05 de julio de 2011: Creación de la función.
\date 14 de mayo de 2012: Modificación del argumento \em nPosAlig para que
      contenga el tamaño real del vector \em posAlig.
\date 25 de mayo de 2012: Cambio de nombre de la función.
\date 18 de agosto de 2013: Unificación para el uso sobre el plano y sobre la
      esfera.
\date 20 de agosto de 2013: Reorganización interna de la ejecución en serie y en
      paralelo de la función.
\date 27 de marzo de 2014: Adición de los argumentos \em xG, \em yG y \em zG.
\date 01 de abril de 2014: Particularización de la función sólo para el plano.
\todo Esta función todavía no está probada.
*/
void DouglasPeuckerRobAutoIntersecPlano(const double* x,
                                        const double* y,
                                        const size_t incX,
                                        const size_t incY,
                                        const size_t posIni,
                                        size_t* posFin,
                                        const size_t* posAlig,
                                        const size_t nPosAlig,
                                        const size_t segAUsar);
/******************************************************************************/
/******************************************************************************/
/**
\brief Comprueba, mediante una ejecución en paralelo con OpenMP, si una serie de
       segmentos de la polilínea ya aligerada se cortan con un segmento base AB,
       a partir de éste hacia atrás.
\param[in] xA Coordenada X del punto A.
\param[in] yA Coordenada Y del punto A.
\param[in] xB Coordenada X del punto B.
\param[in] yB Coordenada Y del punto B.
\param[in] x Vector que contiene las coordenadas X de los vértices de la
           polilínea de trabajo.
\param[in] y Vector que contiene las coordenadas Y de los vértices de la
           polilínea de trabajo.
\param[in] incX Posiciones de separación entre los elementos del vector \em x.
           Este argumento siempre ha de ser un número positivo.
\param[in] incY Posiciones de separación entre los elementos del vector \em y.
           Este argumento siempre ha de ser un número positivo.
\param[in] posAlig Vector de posiciones de \em x e \em y utilizadas en la
           polilínea aligerada.
\param[in] nPosAlig Número de elementos de \em posAlig.
\param[in] posIni Posición en el vector \em posAlig del punto inicial a partir
           del cual (incluido) se comenzarán a chequear segmentos.
\param[in] posFin Posición en el vector \em posAlig del punto final hasta el
           cual (incluido) se chequearán segmentos.
\return Dos posibilidades:
        - 0: No hay ninguna intersección entre AB y los segmentos.
        - Distinto de 0: Hay al menos una intersección entre AB y los segmentos.
\note Esta función está paralelizada con OpenMP.
\note Esta función no comprueba si los índices almacenados en \em posAlig son
      congruentes con el tamaño de los vectores \em x e \em y.
\note Esta función no comprueba si los valores pasados en \em posIni, \em posFin
      y \em nPosAlig son congruentes con el tamaño del vector \em posAlig.
\note Esta función asume que \em posIni>\em posFin (ya que vamos hacia atrás).
\date 20 de agosto de 2013: Creación de la función.
\date 01 de abril de 2014: Particularización de la función sólo para el plano.
\todo Esta función todavía no está probada.
*/
int DouglasPeuckerRobAutoIntersecPlanoOMP(const double xA,
                                          const double yA,
                                          const double xB,
                                          const double yB,
                                          const double* x,
                                          const double* y,
                                          const size_t incX,
                                          const size_t incY,
                                          const size_t* posAlig,
                                          const size_t nPosAlig,
                                          const size_t posIni,
                                          const size_t posFin);
/******************************************************************************/
/******************************************************************************/
/**
\brief Comprueba, mediante una ejecución en serie, si una serie de segmentos de
       la polilínea ya aligerada se cortan con un segmento base AB, a partir de
       éste hacia atrás.
\param[in] xA Coordenada X del punto A.
\param[in] yA Coordenada Y del punto A.
\param[in] xB Coordenada X del punto B.
\param[in] yB Coordenada Y del punto B.
\param[in] x Vector que contiene las coordenadas X de los vértices de la
           polilínea de trabajo.
\param[in] y Vector que contiene las coordenadas Y de los vértices de la
           polilínea de trabajo.
\param[in] incX Posiciones de separación entre los elementos del vector \em x.
           Este argumento siempre ha de ser un número positivo.
\param[in] incY Posiciones de separación entre los elementos del vector \em y.
           Este argumento siempre ha de ser un número positivo.
\param[in] posAlig Vector de posiciones de \em x e \em y utilizadas en la
           polilínea aligerada.
\param[in] nPosAlig Número de elementos de \em posAlig.
\param[in] posIni Posición en el vector \em posAlig del punto inicial a partir
           del cual (incluido) se comenzarán a chequear segmentos.
\param[in] posFin Posición en el vector \em posAlig del punto final hasta el
           cual (incluido) se chequearán segmentos.
\return Dos posibilidades:
        - 0: No hay ninguna intersección entre AB y los segmentos.
        - Distinto de 0: Hay al menos una intersección entre AB y los segmentos.
\note Esta función no comprueba si los índices almacenados en \em posAlig son
      congruentes con el tamaño de los vectores \em x e \em y.
\note Esta función no comprueba si los valores pasados en \em posIni, \em posFin
      y \em nPosAlig son congruentes con el tamaño del vector \em posAlig.
\note Esta función asume que \em posIni>\em posFin (ya que vamos hacia atrás).
\date 20 de agosto de 2013: Creación de la función.
\date 01 de abril de 2014: Particularización de la función sólo para el plano.
\todo Esta función todavía no está probada.
*/
int DouglasPeuckerRobAutoIntersecPlanoSerie(const double xA,
                                            const double yA,
                                            const double xB,
                                            const double yB,
                                            const double* x,
                                            const double* y,
                                            const size_t incX,
                                            const size_t incY,
                                            const size_t* posAlig,
                                            const size_t nPosAlig,
                                            const size_t posIni,
                                            const size_t posFin);
/******************************************************************************/
/******************************************************************************/
/**
\brief Calcula la intersección de dos segmentos AB y CD en el plano.
\param[in] xA Coordenada X del punto A.
\param[in] yA Coordenada Y del punto A.
\param[in] xB Coordenada X del punto B.
\param[in] yB Coordenada Y del punto B.
\param[in] xC Coordenada X del punto C.
\param[in] yC Coordenada Y del punto C.
\param[in] xD Coordenada X del punto D.
\param[in] yD Coordenada Y del punto D.
\param[in] posFinAB Posición del punto final del segmento AB en los vectores
           originales de coordenadas.
\param[in] posIniCD Posición del punto inicial del segmento CD en los vectores
           originales de coordenadas.
\return Dos posibilidades:
        - 0: No hay intersección entre AB y CD.
        - Distinto de 0: Sí hay intersección entre AB y CD.
\note Esta función utiliza internamente las funciones \ref IntersecSegmentos2D o
      \ref IntersecSegmentos2DSimple, que no son robustas. En consecuencia, los
      resultados de esta función tampoco lo son.
\date 20 de agosto de 2013: Creación de la función.
\date 28 de marzo de 2014: Adición de los argumentos \em xGC, \em yGC, \em zGC,
      \em xGD, \em yGD y \em zGD.
\date 01 de abril de 2014: Particularización de la función sólo para el plano.
\todo Esta función todavía no está probada.
*/
int DouglasPeuckerRobIntersecPlano(const double xA,
                                   const double yA,
                                   const double xB,
                                   const double yB,
                                   const double xC,
                                   const double yC,
                                   const double xD,
                                   const double yD,
                                   const size_t posFinAB,
                                   const size_t posIniCD);
/******************************************************************************/
/******************************************************************************/
/**
\brief Calcula la distancia a un segmento del punto más alejado de un conjunto
       de puntos candidatos para su uso en el aligerado de polilíneas mediante
       el algoritmo de Douglas-Peucker.
\brief Esta función implementa el criterio apuntado en:

\brief Ebisch, K., October 2002. A correction to the Douglas–Peucker line
       generalization algorithm. Computers and Geosciences 28 (8), 995–997.
\param[in] x Vector que contiene las coordenadas X de los vértices de la
           polilínea de trabajo.
\param[in] y Vector que contiene las coordenadas Y de los vértices de la
           polilínea de trabajo.
\param[in] incX Posiciones de separación entre los elementos del vector \em x.
           Este argumento siempre ha de ser un número positivo.
\param[in] incY Posiciones de separación entre los elementos del vector \em y.
           Este argumento siempre ha de ser un número positivo.
\param[in] posIni Posición en los vectores de coordenadas del punto inicial del
           segmento base.
\param[in] posFin Posición en los vectores de coordenadas del punto final del
           segmento base.
\param[out] pos Posición en los vectores de coordenadas del punto más alejado de
            la línea base. Si \em posFin es el punto inmediatamente posterior a
            \em posIni, esta variable devuelve \em posIni.
\return Distancia del punto más alejado a la línea base. Si \em posFin es el
        punto inmediatamente posterior a \em posIni, se devuelve el valor -1.0.
\note Esta función no comprueba si el número de elementos de los vectores \em x
      e \em y es congruente con los valores pasados en \em posIni y \em posFin.
\date 25 de mayo de 2012: Creación de la función.
\date 16 de marzo de 2014: Reestructuración de la función para el cálculo de la
      distancia de una forma más eficiente por medio de la transformación del
      sistema de coordenadas original.
\todo Esta función todavía no está probada.
*/
double DouglasPeuckerDistMaxPlano(const double* x,
                                  const double* y,
                                  const size_t incX,
                                  const size_t incY,
                                  const size_t posIni,
                                  const size_t posFin,
                                  size_t* pos);
/******************************************************************************/
/******************************************************************************/
/**
\brief Calcula los parámetros de rotación para girar el sistema de coordenadas
       con origen en el punto inicial de la base y llevar el eje X a coincidir
       con ella, para su uso en el aligerado de polilíneas mediante el algoritmo
       de Douglas-Peucker.
\param[in] xBase2RB1 Coordenada X del punto final de la base en el sistema de
           coordenadas original, reducida al punto inicial.
\param[in] yBase2RB1 Coordenada Y del punto final de la base en el sistema de
           coordenadas original, reducida al punto inicial.
\param[out] sAlfa Seno del ángulo de rotación para llevar el eje X del sistema
            de coordenadas (con origen en el punto inicial de la base) a
            coincidir con el segmento base.
\param[out] cAlfa Coseno del ángulo de rotación para llevar el eje X del sistema
            de coordenadas (con origen en el punto inicial de la base) a
            coincidir con el segmento base.
\param[out] lonBase Longitud de la base.
\date 16 de marzo de 2014: Creación de la función.
\todo Esta función todavía no está probada.
*/
void DouglasPeuckerParamRotaBase(const double xBase2RB1,
                                 const double yBase2RB1,
                                 double* sAlfa,
                                 double* cAlfa,
                                 double* lonBase);
/******************************************************************************/
/******************************************************************************/
/**
\brief Calcula la distancia de un punto a un segmento AB para su uso en el
       aligerado de polilíneas mediante el algoritmo de Douglas-Peucker.
\brief Esta función implementa el criterio apuntado en:

\brief Ebisch, K., October 2002. A correction to the Douglas–Peucker line
       generalization algorithm. Computers and Geosciences 28 (8), 995–997.
\param[in] lonBase Longitud de la base.
\param[in] sAlfa Seno del ángulo de rotación para llevar el eje X del sistema de
           coordenadas (con origen en el punto inicial de la base) a coincidir
           con el segmento base.
\param[in] cAlfa Coseno del ángulo de rotación para llevar el eje X del sistema
           de coordenadas (con origen en el punto inicial de la base) a
           coincidir con el segmento base.
\param[in] xVertRB1 Coordenada X del punto de trabajo en el sistema de
           coordenadas original, reducida al punto inicial de la base.
\param[in] yVertRB1 Coordenada Y del punto de trabajo en el sistema de
           coordenadas original, reducida al punto inicial de la base.
\return Distancia del punto a la línea base.
\note Los argumentos \em lonBase, \em sAlfa y \em cAlfa son los parámetros
      calculados por la función \ref DouglasPeuckerParamRotaBase.
\date 16 de marzo de 2014: Creación de la función.
\todo Esta función todavía no está probada.
*/
double DouglasPeuckerDistMaxPlanoAux(const double lonBase,
                                     const double sAlfa,
                                     const double cAlfa,
                                     const double xVertRB1,
                                     const double yVertRB1);
/******************************************************************************/
/******************************************************************************/
#ifdef __cplusplus
}
#endif
/******************************************************************************/
/******************************************************************************/
#endif
/******************************************************************************/
/******************************************************************************/
/** @} */
/******************************************************************************/
/******************************************************************************/
/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
/* kate: backspace-indents on; show-tabs on; */
/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
