# -*- coding: utf-8 -*-

"""
/***************************************************************************
 LFTools
                                 A QGIS plugin
 Tools for cartographic production and spatial analysis.
 Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
                              -------------------
        begin                : 2026-01-08
        copyright            : (C) 2026 by Leandro Franca
        email                : suporte@geoone.com.br
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
"""

__author__ = 'Leandro Franca'
__date__ = '2026-01-08'
__copyright__ = '(C) 2026 by Leandro Franca'
__revision__ = '$Format:%H$'


from qgis.core import *
from qgis.utils import qgsfunction
from .Funcs import areaSGL, perimetroSGL


@qgsfunction(args='auto', group='GeoINCRA')
def areaINCRA (geometry, layer_crs, feature, parent):
    """
    Esta função calcula a área de um <b>PolygonZ</b> ou <b>MultiPoligonZ</b> segundo o mesmo método adotado pelo <b>SIGEF/INCRA</b>. O cálculo parte das coordenadas geodésicas dos vértices, que são inicialmente convertidas para o sistema cartesiano geocêntrico tridimensional, referenciado ao centro da Terra. Em seguida, define-se a origem do <b>Sistema Geodésico Local (SGL)</b> a partir das <b>médias das coordenadas*</b> do conjunto de vértices. 
    A partir dessa origem, as coordenadas são transformadas para esse SGL, no qual o polígono pode ser tratado como plano, mantendo o rigor geodésico por estar associado à cota média do imóvel e livre de distorções inerentes às projeções cartográficas. 
    Por fim, a área é calculada por meio da fórmula de Gauss aplicada às coordenadas locais, em conformidade com o Manual Técnico de Georreferenciamento de Imóveis Rurais do INCRA.
    <p><i>*Obs.: Esta função difere da função <b>areaLTP</b> do <b><a href="https://geoone.com.br/lftools-o-plugin-para-topografia-no-qgis/" target="_blank">plugin LFTools</a></b>, que utiliza o centroide do imóvel como origem do sistema local, o que pode resultar em pequenas diferenças nas últimas casas decimais da área calculada.</i></p>
    <h2>Exemplo:</h2>
    <ul>
      <li> areaINCRA(geometria, layer_crs) -> área INCRA </li>
      <li> areaINCRA($geometry, 'EPSG:31985') -> 447503.674 </li>
    </ul>
    <div>
    <p><b>Sobre a área calculada pelo INCRA:</b></p>
    <p>
    <b><a href="https://geoone.com.br/sistema-geodesico-local/" target="_blank">França, L. Sistema Geodésico Local. GeoOne. 2022.</a></b>
    </p>
  </div>
    """
    layer_crs = QgsCoordinateReferenceSystem(layer_crs)
    geom = geometry
    if not layer_crs.isGeographic():
        crsProj = layer_crs
        crsGeo = QgsCoordinateReferenceSystem(crsProj.geographicCrsAuthId())
        coordinateTransformer = QgsCoordinateTransform()
        coordinateTransformer.setDestinationCrs(crsGeo)
        coordinateTransformer.setSourceCrs(crsProj)
        geom.transform(coordinateTransformer)
    else:
        crsGeo = layer_crs
    geomGeo = geom
    try:
        return areaSGL(geomGeo, crsGeo)
    except:
        return 'Verifique o tipo de geometria!'


@qgsfunction(args='auto', group='GeoINCRA', name = '$areaINCRA')
def areaINCRA2 (feature, parent, context):
    """
    Esta função calcula a área de um <b>PolygonZ</b> ou <b>MultiPoligonZ</b> segundo o mesmo método adotado pelo <b>SIGEF/INCRA</b>. O cálculo parte das coordenadas geodésicas dos vértices, que são inicialmente convertidas para o sistema cartesiano geocêntrico tridimensional, referenciado ao centro da Terra. Em seguida, define-se a origem do <b>Sistema Geodésico Local (SGL)</b> a partir das <b>médias das coordenadas*</b> do conjunto de vértices. 
    A partir dessa origem, as coordenadas são transformadas para esse SGL, no qual o polígono pode ser tratado como plano, mantendo o rigor geodésico por estar associado à cota média do imóvel e livre de distorções inerentes às projeções cartográficas. 
    Por fim, a área é calculada por meio da fórmula de Gauss aplicada às coordenadas locais, em conformidade com o Manual Técnico de Georreferenciamento de Imóveis Rurais do INCRA.
    <p><i>*Obs.: Esta função difere da função <b>areaLTP</b> do <b><a href="https://geoone.com.br/lftools-o-plugin-para-topografia-no-qgis/" target="_blank">plugin LFTools</a></b>, que utiliza o centroide do imóvel como origem do sistema local, o que pode resultar em pequenas diferenças nas últimas casas decimais da área calculada.</i></p>
    <h2>Exemplo:</h2>
    <ul>
      <li> $areaINCRA -> 607503.4867 </li>
    </ul>
    <div>
    <p><b>Sobre o Sistema Geodésico Local (SGL):</b></p>
    <p>
    <b><a href="https://geoone.com.br/sistema-geodesico-local/" target="_blank">França, L. Sistema Geodésico Local. GeoOne. 2022.</a></b>
    </p>
  </div>
    """
    layer_id = context.variable('layer_id')
    layer = QgsProject.instance().mapLayer(layer_id)
    geom = feature.geometry()
    if not layer.crs().isGeographic():
        crsProj = layer.crs()
        crsGeo = QgsCoordinateReferenceSystem(crsProj.geographicCrsAuthId())
        coordinateTransformer = QgsCoordinateTransform()
        coordinateTransformer.setDestinationCrs(crsGeo)
        coordinateTransformer.setSourceCrs(crsProj)
        geom.transform(coordinateTransformer)
    else:
        crsGeo = layer.crs()
    geomGeo = geom
    try:
      return areaSGL(geomGeo, crsGeo)
    except:
      return 'Verifique o tipo de geometria!'


@qgsfunction(args='auto', group='GeoINCRA')
def perimetroINCRA (geometry, layer_crs, feature, parent):
    """
    Esta função calcula o perímetro de uma <b>LinestringZ</b> segundo o mesmo método adotado pelo <b>SIGEF/INCRA</b>. O cálculo parte das coordenadas geodésicas dos vértices, que são inicialmente convertidas para o sistema cartesiano geocêntrico tridimensional, referenciado ao centro da Terra. Em seguida, define-se a origem do <b>Sistema Geodésico Local (SGL)</b> a partir das <b>médias das coordenadas</b> do conjunto de vértices. 
    A partir dessa origem, as coordenadas são transformadas para esse SGL, no qual o polígono pode ser tratado como plano, mantendo o rigor geodésico por estar associado à cota média do imóvel e livre de distorções inerentes às projeções cartográficas. 
    Por fim, o perímetro é calculado por meio da distância euclidiana aplicada às coordenadas locais, em conformidade com o Manual Técnico de Georreferenciamento de Imóveis Rurais do INCRA.
    <h2>Exemplo:</h2>
    <ul>
      <li> perimetroINCRA(geometry, layer_crs) -> LTP area </li>
      <li> perimetroINCRA($geometry, 'EPSG:31983') -> 447503.415 </li>
    </ul>
    <div>
    <p><b>Sobre o Sistema Geodésico Local (SGL):</b></p>
    <p>
    <b><a href="https://geoone.com.br/sistema-geodesico-local/" target="_blank">França, L. Sistema Geodésico Local. GeoOne. 2022.</a></b>
    </p>
  </div>
    """
    layer_crs = QgsCoordinateReferenceSystem(layer_crs)
    geom = geometry
    if layer_crs.isGeographic():
        crsProj = layer_crs
        crsGeo = QgsCoordinateReferenceSystem(crsProj.geographicCrsAuthId())
        coordinateTransformer = QgsCoordinateTransform()
        coordinateTransformer.setDestinationCrs(crsGeo)
        coordinateTransformer.setSourceCrs(crsProj)
        geom.transform(coordinateTransformer)
    else:
        crsGeo = layer_crs
    geomGeo = geom
    try:
        return perimetroSGL(geomGeo, crsGeo)
    except:
        return 'Verifique o tipo de geometria!'


@qgsfunction(args='auto', group='GeoINCRA', name = '$perimetroINCRA')
def perimetroINCRA2 (feature, parent, context):
    """
    Esta função calcula o perímetro de uma <b>LinestringZ</b> segundo o mesmo método adotado pelo <b>SIGEF/INCRA</b>. O cálculo parte das coordenadas geodésicas dos vértices, que são inicialmente convertidas para o sistema cartesiano geocêntrico tridimensional, referenciado ao centro da Terra. Em seguida, define-se a origem do <b>Sistema Geodésico Local (SGL)</b> a partir das <b>média das coordenadas</b> do conjunto de vértices. 
    A partir dessa origem, as coordenadas são transformadas para esse SGL, no qual o polígono pode ser tratado como plano, mantendo o rigor geodésico por estar associado à cota média do imóvel e livre de distorções inerentes às projeções cartográficas. 
    Por fim, o perímetro é calculado por meio da distância euclidiana aplicada às coordenadas locais, em conformidade com o Manual Técnico de Georreferenciamento de Imóveis Rurais do INCRA.
    <h2>Exemplo:</h2>
    <ul>
      <li> $perimetroINCRA -> 4156.483 </li>
    </ul>
    <div>
    <p><b>Sobre o Sistema Geodésico Local (SGL):</b></p>
    <p>
    <b><a href="https://geoone.com.br/sistema-geodesico-local/" target="_blank">França, L. Sistema Geodésico Local. GeoOne. 2022.</a></b>
    </p>
  </div>
    """
    layer_id = context.variable('layer_id')
    layer = QgsProject.instance().mapLayer(layer_id)
    geom = feature.geometry()
    if not layer.crs().isGeographic():
        crsProj = layer.crs()
        crsGeo = QgsCoordinateReferenceSystem(crsProj.geographicCrsAuthId())
        coordinateTransformer = QgsCoordinateTransform()
        coordinateTransformer.setDestinationCrs(crsGeo)
        coordinateTransformer.setSourceCrs(crsProj)
        geom.transform(coordinateTransformer)
    else:
        crsGeo = layer.crs()
    geomGeo = geom
    try:
        return perimetroSGL(geomGeo, crsGeo)
    except:
        return 'Verifique o tipo de geometria!'