540 lines
22 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|