/* -*- coding: utf-8 -*- */
/**
\ingroup geom
@{
\file dpeucker.h
\brief Declaración de funciones para el aligerado de polilíneas, 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 17 de agosto de 2013
\copyright
Copyright (c) 2013-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 _DPEUCKER_H_
#define _DPEUCKER_H_
/******************************************************************************/
/******************************************************************************/
#include<stdlib.h>
#include"libgeoc/dpeuckera.h"
#include"libgeoc/dpeuckere.h"
#include"libgeoc/dpeuckerp.h"
#include"libgeoc/errores.h"
/******************************************************************************/
/******************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************/
/******************************************************************************/
/**
\brief Elimina vértices de una polilínea mediante una familia de algoritmos
       basados en el de Douglas-Peucker.
\param[in] x Vector que contiene las coordenadas X o las longitudes, en
           radianes, de los vértices de la polilínea de trabajo.
\param[in] y Vector que contiene las coordenadas Y o las latitudes, en radianes,
           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. Dos posibilidades:
           - Si se trabaja en coordenadas planas, este argumento ha de estar en
             las mismas unidades que las coordenadas de los vértices.
           - Si se trabaja sobre la esfera, este argumento ha de ser una
             longitud de arco de círculo máximo sobre la esfera de radio unidad.
\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: Utiliza el algoritmo de Douglas-Peucker
             original, que no es robusto.
           - #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/arcos de la polilínea
             aligerada que se van creando no intersectarán con ninguno de los
             segmentos/arcos 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/arcos de la polilínea
             aligerada que se van creando no intersectarán con ninguno de los
             segmentos/arcos 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/arcos 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/arcos 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[in] esf Identificador de trabajo sobre la superficie de la esfera. Dos
           posibilidades:
           - 0: No se trabaja sobre la superficie de la esfera, sino en el
             plano.
           - Distinto de 0: Se trabaja sobre la superficie de la esfera de radio
             unidad.
\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 25 de mayo de 2012: Creación de la función.
\date 08 de agosto de 2013: Comprobación de casos especiales.
\date 17 de agosto de 2013: 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 21 de septiembre de 2013: Adición de la capacidad de trabajar sobre la
      esfera con el algoritmo de Douglas-Peucker original.
\todo Esta función todavía no está probada.
*/
size_t* AligeraPolilinea(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,
                         const int esf,
                         size_t* nPtosSal);
/******************************************************************************/
/******************************************************************************/
/**
\brief Elimina vértices de una polilínea mediante el algoritmo original de
       Douglas-Peucker.
\param[in] x Vector que contiene las coordenadas X o las longitudes, en
           radianes, de los vértices de la polilínea de trabajo.
\param[in] y Vector que contiene las coordenadas Y o las latitudes, en radianes,
           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. Dos posibilidades:
           - Si se trabaja en coordenadas planas, este argumento ha de estar en
             las mismas unidades que las coordenadas de los vértices.
           - Si se trabaja sobre la esfera, este argumento ha de ser una
             longitud de arco de círculo máximo sobre la esfera de radio unidad.
\param[in] esf Identificador de trabajo sobre la superficie de la esfera. Dos
           posibilidades:
           - 0: No se trabaja sobre la superficie de la esfera, sino en el
             plano.
           - Distinto de 0: Se trabaja sobre la superficie de la esfera de radio
             unidad.
\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 puede devolver resultados erróneos si algún segmento base es
      mayor o igual que \f$\pi\f$.
\date 21 de septiembre de 2013: Creación de la función.
\todo Esta función todavía no está probada.
*/
size_t* DouglasPeuckerOriginal(const double* x,
                               const double* y,
                               const size_t nPtos,
                               const size_t incX,
                               const size_t incY,
                               const double tol,
                               const int esf,
                               size_t* nPtosSal);
/******************************************************************************/
/******************************************************************************/
/**
\brief Elimina vértices de una polilínea 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/arcos de tal forma que se eliminan todos
       aquellos puntos que queden a una distancia menor o igual a \em tol del
       segmento/arco 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 o las longitudes, en
           radianes, de los vértices de la polilínea de trabajo.
\param[in] y Vector que contiene las coordenadas Y o las latitudes, en radianes,
           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. Dos posibilidades:
           - Si se trabaja en coordenadas planas, este argumento ha de estar en
             las mismas unidades que las coordenadas de los vértices.
           - Si se trabaja sobre la esfera, este argumento ha de ser una
             longitud de arco de círculo máximo sobre la esfera de radio unidad.
\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/arcos de la polilínea
             aligerada que se van creando no intersectarán con ninguno de los
             segmentos/arcos 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/arcos de la polilínea
             aligerada que se van creando no intersectarán con ninguno de los
             segmentos/arcos 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/arcos 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/arcos 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[in] esf Identificador de trabajo sobre la superficie de la esfera. Dos
           posibilidades:
           - 0: No se trabaja sobre la superficie de la esfera, sino en el
             plano.
           - Distinto de 0: Se trabaja sobre la superficie de la esfera de radio
             unidad.
\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.
\todo Esta función todavía no está probada.
*/
size_t* DouglasPeuckerRobusto(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,
                              const int esf,
                              size_t* nPtosSal);
/******************************************************************************/
/******************************************************************************/
#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; */
