OliviaAddIn/OliviaAddIn/Gdb/DatosGDBLimp.cs

540 lines
22 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OliviaDef;
using System.Windows.Forms;
using ESRI.ArcGIS.ArcMap;
using ESRI.ArcGIS.DataSourcesFile;
using ESRI.ArcGIS.DataSourcesGDB;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Carto;
using System.IO;
using ESRI.ArcGIS.GeoDatabaseUI;
namespace OliviaAddIn
{
/**
* @file DatosGDBLimp.cs
* Clase con funciones para lectura de GDB relacionado con limpieza viaria.
* Contiene definiciones y funciones necesarias para exportar los datos de GDB a SHP, y viceversa
* concretados con las opciones de configuración de la limpieza viaria.
*/
/**
* Clase con funciones para lectura de GDB relacionado con limpieza viaria.
* Contiene definiciones y funciones necesarias para exportar los datos de GDB a SHP, y viceversa
* concretados con las opciones de configuración de la limpieza viaria.
*/
public class DatosGDBLimp : DatosGDB
{
//*************************************************************************************
//Variables
//*************************************************************************************
//Métodos
public DatosGDBLimp()
{
rellena_ftclass();
}
/**
* Rellenea el array ftclass con el nombre de las tablas de las que se extraerán datos
*/
public void rellena_ftclass()
{
int i;
LimpiezaDef.ftclass[(int)LimpiezaDef.AmbitsTra.AmbEjeCalle] = OliviaGlob.Capas.ftclass_ejes;
for(i = (int)LimpiezaDef.AmbitsTra.AmbBordLibreMec; i < (int)LimpiezaDef.AmbitsTra.AmbConte; i++)
{
LimpiezaDef.ftclass[i] = LimpiezaDef.Capas.ftclass_limp_mec;
}
LimpiezaDef.ftclass[(int)LimpiezaDef.AmbitsTra.AmbConte] = LimpiezaDef.Capas.ftclass_cont;
for(i=(int)LimpiezaDef.AmbitsTra.AmbPape; i<(int)LimpiezaDef.AmbitsTra.AmbN; i++)
{
LimpiezaDef.ftclass[i] = LimpiezaDef.Capas.ftclass_mobi;
}
}
/**
* Lee la geodatabase dónde están los datos referentes a los ámbitos de trabajo
*/
public bool[] lee_amb_gdb(Limpieza limp)
{
String consulta;
int numero_lin;
bool[] amb_gdb = new bool[(int)LimpiezaDef.AmbitsTra.AmbN];//se inician a false
string ftclass;
//mira a ver si hay ejes de calle
ftclass = LimpiezaDef.ftclass[(int)LimpiezaDef.AmbitsTra.AmbEjeCalle];
consulta = LimpiezaDef.filtro_str[(int)LimpiezaDef.AmbitsTra.AmbEjeCalle];
numero_lin = FunGDB.cuenta_filas_ftclass(OliviaGlob.Paths.PathGdbNw, ftclass, consulta);
if (numero_lin > 0)
{
amb_gdb[(int)LimpiezaDef.AmbitsTra.AmbEjeCalle] = true;
}
//mira a ver si hay el resto de capas y tienen entidades
for (int i = (int)LimpiezaDef.AmbitsTra.AmbBordLibreMec; i < (int)LimpiezaDef.AmbitsTra.AmbN; i++)
{
consulta = LimpiezaDef.filtro_str[i];
if (path_class == null) //como tradicionalmente, hay una gdb y los nombres de las feature classes del archivo de configuración
{
ftclass = LimpiezaDef.ftclass[i];
numero_lin = FunGDB.cuenta_filas_ftclass(OliviaGlob.Paths.PathGdbGen, ftclass, consulta);
}
else
numero_lin = FunGDB.cuenta_filas_ftclass(path_class, consulta);
if (numero_lin > 0)
{
amb_gdb[i] = true;
}
}
return amb_gdb;
}
/*
* Lee la capa que se ha seleccionzdo de limpieza y se comprueba que los campos que se han editado corresponden con la capa
* (es decir, se puede leer la capa con los campos configurados)
*/
public bool comprueba_campos_limp(Limpieza limp)
{
int ind_campo;
string[] camps;
int i;
ITable tabla;
int NCAMPS = 2;
if(path_class!=null)
tabla = FunGDB.dame_tabla_clase(path_class);
else
tabla = FunGDB.dame_tabla_clase(OliviaGlob.Paths.PathGdbGen, LimpiezaDef.Capas.ftclass_limp_mec);
if (tabla == null)
{
if (path_class != null)
limp.err_st = "No se encuentra la capa " + path_class;
else
limp.err_st = "No se encuentra la capa " + LimpiezaDef.Capas.ftclass_limp_mec;
return false;
}
//se comprueba que existen todos los campos que se han configurado en la capa seleccionada para la recogida
camps = new string[NCAMPS];
camps[0] = LimpiezaDef.Campos.consulta_entidad;
camps[1] = LimpiezaDef.Campos.consulta_mecan;
for (i = 0; i < NCAMPS; i++)
{
ind_campo = tabla.FindField(camps[i]);
if (ind_campo == -1)
{
limp.err_st = "No se encuentra el campo " + camps[i];
break;
}
}
if (i < NCAMPS)
return false;
return true;
}
/**
* Devuelve qué consulta hay que hacer, el filtro de los ámbitos y el nombre de la clase donde están
*/
public string dame_consul_amb_clas(Limpieza limp, out string ambitos, out string nom_class)
{
string consulta, orstr;
consulta = null;
ambitos = "";
orstr = null;
nom_class = null;
for (int i = 0; i < limp.amb_tra_sel.Length; i++)
{
if (limp.amb_tra_sel[i])
{
if(nom_class==null)
nom_class = LimpiezaDef.ftclass[i];
consulta = consulta + orstr + "(" + LimpiezaDef.filtro_str[i] + ")";
ambitos = ambitos + i.ToString("00");
if (orstr == null)
orstr = " OR ";
}
}
ambitos = "_A" + ambitos;
if (consulta == "()")
consulta = "";
return consulta;
}
/**
* Descodifica el nombre del sahpefile de entrada identificando el tipo de tratamiento y los ámbitos de trabajo
*/
public void decode_gdb(string shapefile, out string tratamiento, out string ambitos)
{
int aux, auxl, mbito, indice, tratamient;
string auxili, ambi, auxi;
indice = shapefile.IndexOf("_");
indice = indice + 2;//para saltarse la T que va antes del identificador del tipo de tratamiento
auxili = shapefile.Substring(indice, 2);
tratamient = Convert.ToInt32(auxili);
tratamiento = LimpiezaDef.tto_gdb[tratamient];
OliviaGlob.cartela_tto = LimpiezaDef.tipos_tto_str[tratamient];
indice = shapefile.IndexOf("_", indice);
indice = indice + 2;//para saltarse la A que va antes del identificador de los ámbitos que intervienen
aux = shapefile.IndexOf("_", indice);
auxl = aux - indice;
auxi = "";
while (auxl > 0)
{
ambi = shapefile.Substring(indice, 2);
mbito = Convert.ToInt32(ambi);
indice = indice + 2;
auxl = auxl - 2;
if (auxl != 0)
auxi = auxi + LimpiezaDef.ambs_gdb[mbito] + "_";
else
auxi = auxi + LimpiezaDef.ambs_gdb[mbito];
}
ambitos = LimpiezaDef.preftto_gdb[tratamient] + "_" + auxi;
//quita los espacios
tratamiento = tratamiento.Replace(" ", "_");
ambitos = ambitos.Replace(" ", "_");
auxi = shapefile;
//para poner la zona cuando es seleccionada
for (int i = 0; i < 2; i++)
{
indice = auxi.LastIndexOf("_");
auxi = auxi.Substring(0, indice);
}
auxl = indice - aux;
if (auxl <= 0)
return;
auxili = shapefile.Substring(aux, auxl);
ambitos = ambitos + auxili;
}
/**
* Exporta a shapefile las red navegable y los ámbitos de trabajo seleccionados. El archivo de salida será el nombre del tratamiento escogido.
*/
public bool exporta(Limpieza limp, bool comp_planif)
{
int cont=0;
string fecha_hora = "", ambitos = "";
string consulta = "";
IQueryFilter filtro = null;
IGeometry geom_zonniv = null;
IGeometry geom_ambits = null;
string nomb_class_limp = null;
IDatasetName datasetn=null;
bool hayzonniv = false;
if (limp == null)
{
err_st = "No se han recibido correctamente los datos para la exportación";
return false;
}
/////////////////////////////////////////////
//lee ambitos de trabajo
consulta = dame_consul_amb_clas(limp, out ambitos, out nomb_class_limp);
if (consulta == null)
{
err_st = "Error al configurar consulta";
return false;
}
/////////////////////////////////////////////
//si va a planificar antes comprueba que estén las columnas de sector y secuencia
if (comp_planif)
{
if (!comprueba_planif(path_class, nomb_class_limp))
{
err_st = "No existen en la tabla " + path_class + " columna de SECTOR y/o SECUENCIA, necesarias para planificar";
return false;
}
}
//si path_secto!=null, hay que actualizar la sectorización, si ==null, en los datos de entrada ya hay sectorización
//y secuencia y se van a exportar
//////////////////////////////////////////////////
if (path_class == null) //como tradicionalmente, hay una gdb y los nombres de las feature classes del archivo de configuración
{
if(nomb_class_limp==OliviaGlob.Capas.ftclass_ejes)
cont = FunGDB.cuenta_filas_ftclass(OliviaGlob.Paths.PathGdbNw, nomb_class_limp, consulta);
else
cont = FunGDB.cuenta_filas_ftclass(OliviaGlob.Paths.PathGdbGen, nomb_class_limp, consulta);
}
else
cont = FunGDB.cuenta_filas_ftclass(path_class, consulta);
if (cont <= 0)
{
err_st = "No existen ámbitos que cumplan las condiciones introducidas para la exportación "+consulta;
return false;
}
/////////////////////////////////////////////
//consigue el polígono común a las dos geometrías: zonas y niveles
//si no hay zonas ni niveles, es null
geom_zonniv = FunGDB.intersec_geoms(limp.geom_zonas, limp.geom_niveles);
//además, le quita las restricciones
if (geom_zonniv != null && limp.geom_rest_acces != null)
{
geom_zonniv = FunGDB.diferencia_geoms(geom_zonniv, limp.geom_rest_acces);
}
if (geom_zonniv != null && geom_zonniv.IsEmpty)
{
err_st = "Error, la geometría resultado de intersecar zonas, niveles y restricciones de circulación está vacía";
return false;
}
if (geom_zonniv == null && comp_planif && (path_secto != null))
{
//en este caso coge la geom de la secto
//obtiene el polígono que engloba los ámbitos
geom_zonniv = FunGDB.dame_geom_envelope(path_secto);
if (geom_zonniv == null)
{
err_st = "Error al obtener polígono de datos";
return false;
}
hayzonniv = false;
}
if (geom_zonniv == null && nomb_class_limp == OliviaGlob.Capas.ftclass_ejes)
{
err_st = "Al emplear ejes de calle como ámbitos es necesario indicar polígono de exportación";
return false;
}
/////////////////////////////////////////////
//crea el filtro en base a las consultas configuradas
filtro = crea_filtro(limp, nomb_class_limp, consulta, geom_zonniv);
if (filtro == null)
{
err_st = "Error al crear el filtro para la exportación";
return false;
}
/////////////////////////////////////////////
//se consigue el tiempo en este instante para añadirlo a los nombres de los archivos de salida (shapefiles)
fecha_hora = DateTime.Now.ToString("yyyyMMdd_Hmmss");
/////////////////////////////////////////////
//exporta los ámbitos
if (!exporta_data(limp, filtro, nomb_class_limp, ambitos, fecha_hora, out datasetn))
{
err_st = "Error al exportar data. "+err_st;
return false;
}
OliviaGlob.Paths.PathData = OliviaGlob.Paths.DirData + datasetn.Name;
//hace intersecciones espaciales en caso de ámbitos lineales para quitar los que tienen más parte fuera de la zona que dentro
if (geom_zonniv != null && (limp.tipo_tto < (int)LimpiezaDef.TiposTto.TtoPapeVaci) && hayzonniv)
{
if (!quita_amb_sobresalen(OliviaGlob.Paths.PathData, geom_zonniv,0.4))
{
err_st = "Error al quitar los ámbitos que sobresalen";
return false;
}
}
//quita los ámbitos que caen en la zona de restricciones, si es que no había zonas y no se ha quitado ya
if (geom_zonniv == null && limp.geom_rest_acces != null)
{
if (!quita_amb_restric(OliviaGlob.Paths.PathData, limp.geom_rest_acces, (limp.tipo_tto < (int)LimpiezaDef.TiposTto.TtoPapeVaci)))
{
err_st = "Error al quitar los ámbitos en zona de restricción";
return false;
}
}
//comprueba que sigue habiendo ámbitos exportados
cont = FunGDB.cuenta_filas_ftclass(OliviaGlob.Paths.PathData, "");
if (cont <= 0)
{
err_st = "No existen ámbitos que cumplan las condiciones geométricas introducidas";
return false;
}
//ahora si está en modo planificación exporta la sectorización
if (comp_planif && (path_secto!=null))
{
if (!actualiza_secto(OliviaGlob.Paths.PathData, path_secto))
{
err_st = "Error al exportar campos de SECTOR y/o SECUENCIA de la capa "+ path_secto + " " + err_st;
return false;
}
}
///////////////////////////////////////////////////////////////////////////
//obtiene el polígono que engloba los ámbitos
geom_ambits = FunGDB.dame_geom_envelope(OliviaGlob.Paths.PathData);
if (geom_ambits == null)
{
err_st = "Error al obtener polígono de datos";
return false;
}
///////////////////////////////////////////////////////////////////////////
//amplia el poligono para englobar las instalaciones
if (limp.coords_instala[0] != 0 && limp.coords_instala[1] != 0)
{
//hay instalación
if (!FunGDB.is_pto_in_geom(limp.coords_instala[0], limp.coords_instala[1], geom_ambits))
geom_ambits = FunGDB.amplia_geom(geom_ambits, limp.coords_instala[0], limp.coords_instala[1]);
//comprueba, si hay restricciones de circulación, que la instalación no está en ellas
if (limp.geom_rest_acces != null)
{
if (FunGDB.is_pto_in_geom(limp.coords_instala[0], limp.coords_instala[1], limp.geom_rest_acces))
{
err_st = "Error, la instalación sal/lleg está en la zona restringida a la circulación";
return false;
}
}
}
///////////////////////////////////////////////////////////////////////////
//exporta la red navegable
if (!exporta_nw(geom_ambits, limp.geom_rest_acces,limp.rest_circ[limp.tipo_tto], fecha_hora, out datasetn))
{
return false;
}
//guarda los nombres del shape
OliviaGlob.Paths.PathNW = OliviaGlob.Paths.DirData + datasetn.Name;
//Guarda el nombre que lo escribirá en el shp resultado
OliviaGlob.nomb_tto = LimpiezaDef.tto_gdb[limp.tipo_tto];
return true;
}
/*
* Dado un nombre de featureclass, una consulta y una geometría, interseca entre un poligono dado (geom) y una capa lineal (fc1)
*/
public IQueryFilter dame_filt_inter(Limpieza limp, string ftclass, string consulta, IGeometry geom)
{
string dir = null;
IFeatureClass fc = null;
IQueryFilter fil= null;
if (ftclass == OliviaGlob.Capas.ftclass_ejes)
dir = OliviaGlob.Paths.PathGdbNw;
else if (path_class == null)
dir = OliviaGlob.Paths.PathGdbGen;
if (dir != null)
fc = FunGDB.abre_ftclass(dir, ftclass);
else
fc = FunGDB.abre_ftclass(path_class);
if (fc == null)
return null;
fil=base.dame_filt_inter(fc, consulta, geom);
FunGDB.libera(fc);
return fil;
}
/**
* Realiza las intersecciones espaciales de los ámbitos
*/
public IQueryFilter crea_filtro(Limpieza limp, string nomb_class, string consulta, IGeometry geom1)
{
IQueryFilter filtro;
//crea el filtro espacial y el añadido de consulta de atributos si fuera necesario
filtro = dame_filt_inter(limp,nomb_class, consulta, geom1);
if (filtro == null)
{
err_st = "Error al intersecar el ámbito de limpieza con la zona de estudio";
return null;
}
//FALTA REDEFINIR - elena jun 18
//-------------------------------------------------------------------------------------------------------------------
//Cuando se trate del vaciado de papeleras habrá que verificar si está marca el checkbox que indica si sólo van a recogerse los que superen el umbral de carga.
//De modo que la secotrizacion y la planificacion se realizará sólo sobre los contenedores que superan un porcetaje de carga en la basura.
//Se conocen esos contenedores por el nombre de un campo que indicará si SI(hay que ir a recogerlos) o NO (no tienen suficiente carga y se pueden recoger en otro momento)
if ((limp.tipo_tto == (int)LimpiezaDef.TiposTto.TtoPapeVaci) && (limp.umbral_reco_conten == true))
{
if (filtro.WhereClause == "")
filtro.WhereClause = carga_conten + " >= " + limp.umbral_basura;
else
filtro.WhereClause = "(" + filtro.WhereClause + ") AND (" + carga_conten + " >= " + limp.umbral_basura + ")";
}
return filtro;
}
/**
* Devuelve el string a concatenar en el nombre del path dependiendo de los polígonos seleccionados (zonas, turnos... etc)
*/
public string dame_str_poligs(Limpieza limp)
{
string str = "";
if (limp.text_niv != "" && limp.geom_niveles != null)
str += "_N" + limp.text_niv;
if(limp.text_zon!="" && limp.geom_zonas!=null)
str += "_Z" + limp.text_zon;
if (limp.text_restr != "" && limp.geom_rest_acces != null)
str += "_R" + limp.text_restr;
return str;
}
/**
* Exporta los ámbitos de la gdb a un shape en datasetname
*/
public bool exporta_data(Limpieza limp, IQueryFilter filtro, string nomb_class, string ambitos, string fecha_hora, out IDatasetName shp_data_name)
{
string name="", err_str="";
string dir = null;
IDatasetName shp_dsn = null;
shp_data_name = null;
//Pone nombre al shape en función de los ámbitos, el tratamiento, y los polígonos + timestamp
name = name_export_amb + "T" + limp.tipo_tto.ToString("00") + ambitos + dame_str_poligs(limp) + "_" + fecha_hora + ext_shp;
if (nomb_class == OliviaGlob.Capas.ftclass_ejes)
dir = OliviaGlob.Paths.PathGdbNw;
else if (path_class == null)
dir = OliviaGlob.Paths.PathGdbGen;
if (dir == null)
{
dir = path_class;
nomb_class = null;
}
inicia_coords(dir, nomb_class);
if (!FunGDB.exporta(dir, nomb_class, OliviaGlob.Paths.DirData, name, filtro, out shp_dsn, out err_str))
{
err_st = err_str;
return false;
}
shp_data_name = (IDatasetName)shp_dsn;
return true;
}
}
}