OliviaAddInPro/Services/EjecServ.cs

692 lines
30 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OliviaAddInPro.Model;
using ArcGIS.Core.Data;
using ArcGIS.Core.Geometry;
using OliviaAddInPro.Helper;
using ArcGIS.Core.Internal.Data;
using ArcGIS.Desktop.Framework.Threading.Tasks;
using System.Windows;
namespace OliviaAddInPro.Services
{
public enum ModosEjec
{
Sectoriza,
Planifica,
SoloPlanifica
}
//Clase que realiza las funciones de la ejecución
public class EjecServ
{
//Cadenas de nombres internos para la exportación/importación de los archivos
public string PREF_NAME_EXPORT = "data_";
public string EXT_SHP = ".shp";
public string PREF_NAME_EXPORT_NW = "nw_";
public string NAME_CSV = "_L";
public string EXT_CSV = ".csv";
public string NAME_RUTA2 = "_R2";
public string NAME_RUTA2_OUT = "_Viajes";
public string NAME_AUX = "_aux";
public string NAME_SECT = "_Sector";
public string NAME_CONTROL_OUT = "_Control";
public string NAME_CONTROL = "_C";
public string NAME_RUTA_OUT = "_Ruta";
public string NAME_RUTA = "_R";
public string NAME_RUTA_AUX = "_Raux";
public string NAME_INSTAL = "_I";
public string NAME_INSTAL_OUT = "_Instalacion";
public string ErrStr = "";
SpatialQueryFilter filtroEspacial = null;
SpatialReference spatRef = null;
SpatialReference spatRefData = null;
public TratamientoComun com;
/**
* Acciones para comenzar ejecución
* Modo 0, sectorizar
* Modo 1, planificar
*/
public bool ExportaEjec(ModosEjec modo, out string ErrStr)
{
ErrStr = string.Empty;
try
{
com.ProgrSrc.Init("Exportando datos");
//Comprueba que tiene las columnas necesarias para planificar
if ((modo == ModosEjec.Planifica) && !CompruebaPlanif())
{
ErrStr = "En la capa de ámbitos seleccionada no se encuentran columnas de SECTOR y/o SECUENCIA, necesarias para planificar";
return false;
}
//Cuenta las filas que cumplen la consulta
int nelems = HelperGdb.GetNumElems(com.CapaElems, com.ConsultaAmbs);
if (nelems <= 0)
{
ErrStr = "No existen ámbitos que cumplan las condiciones introducidas para la exportación " + com.ConsultaAmbs;
return false;
}
com.ProgrSrc.IncMessage(0, "Exportando geometria");
//Obtiene la geometría que envuelve a los ámbitos
Geometry geom_export = null;
geom_export = GetGeomAmbitsExport();
if (geom_export == null || geom_export.IsEmpty)
{
ErrStr = "No se ha podido generar geometría de los ámbitos" + com.ConsultaAmbs + ErrStr;
return false;
}
//mira spatialreference de los datos de entrada
spatRefData = geom_export.SpatialReference;
//crea el filtro de exportación
filtroEspacial = HelperGdb.CreateFiler(com.ConsultaAmbs, geom_export);
if (filtroEspacial == null)
{
ErrStr = "Error al crear el filtro de exportacion de los ámbitos";
return false;
}
//Termina de preparar nombre
//Prepara nombre
string fechaHora = string.Empty;
//se consigue el tiempo en este instante para añadirlo a los nombres de los archivos de salida (shapefiles)
fechaHora = DateTime.Now.ToString("yyyyMMdd_Hmmss");
//Pone nombre al shape en función de los ámbitos, el tratamiento, y los polígonos + timestamp
com.NombreShpExport = PREF_NAME_EXPORT + com.NombreShpExp_PrefTto + "_" + fechaHora + EXT_SHP;
com.ProgrSrc.IncMessage(10, "Exportando ámbitos de trabajo");
//exporta los datos de entrada
if (!HelperGdb.ExportShp2(com.CapaElems, filtroEspacial, com.NombreShpExport, OliviaGlob.Paths.DirData, com.ProgrSrc._ProgrSrc, null, 40))
{
ErrStr = "Error al exportar los ámbitos: " + HelperGdb.OutStr;
return false;
}
if (com.ProgrSrc._ProgrSrc.Getcancelled())
{
ErrStr = Resource1.String_cancel_progreso;
return false;
}
//Guarda el nombre
OliviaGlob.Paths.PathData = OliviaGlob.Paths.DirData + com.NombreShpExport;
com.ProgrSrc.IncMessage(10, "Preparando exportación de red navegable");//50%
//hace intersecciones espaciales en caso de ámbitos lineales para quitar los que tienen más parte fuera de la zona que dentro
//REVISAR
/*if (((com.GeomNiv != null) || (com.GeomZon != null)) &&
(OliviaGlob.IsReco() || (OliviaGlob.IsLimp() && (com.TipoTto < (int)LimpiezaDef.TiposTto.TtoPapeVaci))))
{
if (!HelperGdb.RemoveRowsGeom(OliviaGlob.Paths.PathData, geom_export, 0.4))
{
ErrStr = "Error al quitar los ámbitos que sobresalen: " + HelperGdb.OutStr;
return false;
}
}*/
///////////////////////////////////////////////////////////////////////////
//comprueba, si hay restricciones de circulación y hay instalación, que la instalación no está en ellas
if (!com.CoordsInstal.IsEmpty && (com.CoordsInstal.X != 0) && (com.GeomRestr != null))
{
Respuesta<bool> resp = HelperGdb.IsPtoInGeom(com.CoordsInstal, com.GeomRestr);
if (!resp.Value && resp.HasError)
{
ErrStr = "Error al comprobar si la instalación está contenida en el polígono de restricciones: " + resp.Error.ElementAt(0);
return false;
}
else if (resp.Value) //sí está contenido en las restricciones
{
ErrStr = "Error, la instalación está en la zona restringida a la circulación ";
return false;
}
}
///////////////////////////////////////////////////////////////////////////
//exporta la red navegable (buffer, le quita las restr...)
//se obtiene la geometría a intersecar con la red, que será la que contiene
//a todos los ámbitos y la instalación, ampliada un buffer, mayor si hay
//restricciones de circulación
geom_export = HelperGdb.BufferGeom(geom_export, com.BuffExport).Value;
if (geom_export == null)
{
ErrStr = "Error al añadir buffer a la geometría";
return false;
}
//quita las restricciones
if (com.GeomRestr != null)
{
geom_export = HelperGdb.QuitaGeom(geom_export, com.GeomRestr);
if (geom_export == null)
{
ErrStr = "Error al intersecar con las restricciones.";
return false;
}
}
//////////////////////////////////////////////////////////////
//comprueba si la geometría de exportación contiene a la instalación y a la planta de descarga
Coordinate2D[] coords = { com.CoordsInstal, com.CoordsPlanta };
for (int i = 0; i < coords.Length; i++)
{
if (!coords[i].IsEmpty && (coords[i].X != 0))
{
Respuesta<bool> resp = HelperGdb.IsPtoInGeom(coords[i], geom_export);
if (!resp.Value) //si no lo contiene
{
//ha ido mal
if (resp.HasError)
{
ErrStr = "Error al comprobar si la instalación está contenida en el polígono de exportación: " + resp.Error.ElementAt(0);
return false;
}
else
{
//amplía la geom
Respuesta<ArcGIS.Core.Geometry.Geometry> respGeom = HelperGdb.AddPtoInGeom(coords[i], geom_export);
if (respGeom.Value == null)
{
//ha ido mal
if (resp.HasError)
ErrStr = resp.Error.ElementAt(0);
else
ErrStr = "Error al incluir punto de instalación en polígono de exportación.";
return false;
}
//actualiza la geometría
geom_export = respGeom.Value;
}
}
}
}
//mira spatialreference del nw
/*FeatureClass fc = HelperGdb.GetFtClass(OliviaGlob.Paths.PathGdbNw);
if (fc != null)
{
spatRef = fc.GetDefinition().GetSpatialReference();
//AQUÍ COMPARAR SI ES IGUAL QUE SPATREFDEF Y SI NO, REPROYECTAR
if (spatRef.Wkid != spatRefData.Wkid)
{
var sp_ref = SpatialReferenceBuilder.CreateSpatialReference(102629); // NAD83 SP AL E FIPS 0101 Feet
var envi = Geoprocessing.MakeEnvironmentArray(outputCoordinateSystem: sp_ref);
//https://pro.arcgis.com/es/pro-app/2.8/tool-reference/environment-settings/output-coordinate-system.htm
//ProjectionTransformation transf_forTarget = ProjectionTransformation.Create(spatRef, spatRefData);
//geom_export=GeometryEngine.Instance.ProjectEx(geom_export, transf_forTarget);
//transf_forTarget.Transformation
/*
* FALTA HACER
* /
}
}*/
//Hace el filtro con la geometría final
filtroEspacial = HelperGdb.CreateFiler(String.Empty, geom_export);
if (filtroEspacial == null)
{
ErrStr = "Error al crear el filtro de exportacion de la red navegable";
return false;
}
com.ProgrSrc.IncMessage(10, "Exportando red navegable");//60%
//Prepara nombre de exportación
com.NombreShpExportNw = PREF_NAME_EXPORT_NW + fechaHora + EXT_SHP;
//exporta los datos de entrada
if (!HelperGdb.ExportShp2(OliviaGlob.Paths.PathGdbNw, filtroEspacial, com.NombreShpExportNw, OliviaGlob.Paths.DirData, com.ProgrSrc._ProgrSrc, spatRefData,100))
{
ErrStr = "Error al exportar la red navegable: " + HelperGdb.OutStr;
return false;
}
//guarda los nombres del shape
OliviaGlob.Paths.PathNW = OliviaGlob.Paths.DirData + com.NombreShpExportNw;
if (com.ProgrSrc._ProgrSrc.Getcancelled())
{
ErrStr = Resource1.String_cancel_progreso;
return false;
}
}
catch (Exception ex)
{
ErrStr = "Errores al exportar para comenzar la ejecución: " + ex.Message;
return false;
}
return true;
}
/**
* Prepara la geometría para exportar los ámbitos
*/
public Geometry GetGeomAmbitsExport()
{
Geometry geomAux = null;
Geometry geomAmbits = null;
ErrStr = string.Empty;
FeatureClass fc = HelperGdb.GetFtClass(com.CapaElems);
if (fc == null)
{
ErrStr = "No se ha podido abrir la clase " + com.CapaElems;
return null;
}
//Hace la intersección de zonas y niveles
geomAux = null;
if (com.GeomNiv != null || com.GeomZon != null)
{
geomAux = HelperGdb.IntersectGeom(com.GeomNiv, com.GeomZon);
if (geomAux == null)
{
ErrStr = "Error al intersecar zonas y/o niveles.";
return null;
}
if (geomAux.IsEmpty)
{
ErrStr = "No existen ámbitos en la intersección entre zonas y/o niveles.";
return null;
}
}
//comprueba que, en el caso de ejes de vía, hayan metido polígono de exportación
if ((geomAux == null) && (com.CapaElems == OliviaGlob.Paths.PathGdbNw))
{
ErrStr = "Al emplear ejes de calle como ámbitos es necesario indicar polígono de exportación";
return null;
}
//prepara el filtro con consulta y espacial
SpatialQueryFilter filtro = HelperGdb.CreateFiler(com.ConsultaAmbs, geomAux);
if (geomAux == null)
{
//Ahora hace la geometría de los ámbitos que cumplen la consulta, si no hay ya geometría
geomAmbits = HelperGdb.GetGeomConvexHull(fc, filtro).Result;
if (geomAmbits == null || geomAmbits.IsEmpty)
{
ErrStr = "No se ha podido generar geometría de los ámbitos" + com.ConsultaAmbs + HelperGdb.OutStr;
return null;
}
geomAux = geomAmbits;
}
//le quita las restricciones
if (com.GeomRestr != null)
{
geomAux = HelperGdb.QuitaGeom(geomAux, com.GeomRestr);
if (geomAux == null)
{
ErrStr = "Error al intersecar con las restricciones.";
return null;
}
}
HelperGdb.Free(fc);
return geomAux;
}
/**
* Devuelve el string a concatenar en el nombre del path dependiendo de los polígonos seleccionados (zonas, turnos... etc)
*/
public string DameStrPoligs()
{
string str = "";
if (com.TextGeomNiv != "" && com.GeomNiv != null)
str += "_N" + com.TextGeomNiv;
if (com.TextGeomZon != "" && com.GeomZon != null)
str += "_Z" + com.TextGeomZon;
if (com.TextGeomRestr != "" && com.GeomRestr != null)
str += "_R" + com.TextGeomRestr;
return str;
}
public bool ComprCamposPlanif(string pathCapa)
{
int NCAMPS = 2;
string[] camps;
camps = new string[NCAMPS];
camps[0] = LimpiezaDef.Campos.consulta_sector;
camps[1] = LimpiezaDef.Campos.consulta_secuen;
return HelperGdb.CheckFileds(pathCapa, camps) == 0;
}
/**
* Comprueba lo necesario para ver si hay campos para la planificación
*/
public bool CompruebaPlanif()
{
//si ha importado no hace falta que compruebe, seguro que las tiene
if (OliviaGlob.IsConfig2())
return true;
//no ha importado, comprueba capa
if (ComprCamposPlanif(com.CapaElems))
return true;
return false;
}
/**
* Realiza las funciones de importación de la sectorización
*/
public Respuesta<string> ImportSecto(string GdbFileName)
{
var res = Import(GdbFileName, 0);
if (res.HasError || string.IsNullOrEmpty(res.Value))
{
return res;
}
//////////////////////////////////////////////////
//abre las capas, pintando los sectores
bool mal = false;
string path_import = res.Value;
string path_lyr = path_import;
if(HelperGdb.OpenLayerUniqueValue(path_lyr, LimpiezaDef.Campos.consulta_sector))
{
res.Error.Add("Error al abrir capa "+ path_lyr + " con Valor único.");
res.Value = string.Empty;
mal = true;
}
if(!mal)
res.Value = path_import;
return res;
}
/**
* Realiza las funciones de importación, modo 0 secto, modo 1 planif
*/
public Respuesta<string> Import(string GdbFileName, int modo)
{
var res = new Respuesta<string> { Value = string.Empty };
/////////////////////////////////////////
string path_shape = OliviaGlob.Paths.PathData;
string dir_shp = System.IO.Path.GetDirectoryName(path_shape);
string shapefile = System.IO.Path.GetFileNameWithoutExtension(path_shape);
int ind = shapefile.IndexOf("_", 0);
string prefijo = shapefile.Substring(ind + 1, 1);
//////////////////////////////////////////////////////////////////////////////////
//decodifica el nombre del shapefile para asignarle el correspondiente nombre en la GDB a la que se importa el shape
string tratamiento = string.Empty;
string ambitos = string.Empty;
com.decode_gdb(shapefile, out tratamiento, out ambitos); //supsuestamente distingue si es limpieza o recogida
/*
if (prefijo == "T")
{
com.decode_gdb(shapefile, out tratamiento, out ambitos);
}
else if (prefijo == "F")
{
com.decode_gdb(shapefile, out tratamiento, out ambitos);
}*/
if(string.IsNullOrEmpty(tratamiento) || string.IsNullOrEmpty(ambitos))
{
res.Error.Add(string.Format("Nombre del archivo a importar erróneo. No se reconoce el prefijo introducido: {0}", prefijo));
return res;
}
bool reco_o_limp_con_instala = (prefijo == "F") ||
((prefijo == "T") && !com.CoordsInstal.Equals(new Coordinate2D(0, 0)));
bool reco_tramos = System.IO.File.Exists(System.IO.Path.Combine(dir_shp, shapefile + NAME_RUTA2 + EXT_SHP));
/////////////////////////////////////////
//crea el dataset o comprueba si existe
string datasetNameOut = string.Empty;
var resp = HelperGdb.CreateDataset(GdbFileName, tratamiento, spatRefData, out datasetNameOut);
string err_spatref = "Atención, no coincide la proyección de las FeatureClass del Dataset ya creado con la del FeatureClass a importar";
if (resp.Value == 1)
{
res.Error.Add("Error al crear el Dataset para importar " + tratamiento);
return res;
}
else if (resp.Value == 2)
{
//avisa
HelperGlobal.ponMsg(err_spatref +", se ha creado un nuevo dataset "+ datasetNameOut );
tratamiento = datasetNameOut;
}
string dataset = tratamiento;
//NO hace falta preguntar ni comprobar el ftclass porque pone el timestamp y el nombre es único
/*
/////////////////////////////////////////
//pregunta a ver si se quiere ese nombre u otro
bool replace = false;
string dataset = tratamiento;
bool sal = true;
string ambitos_aux;
//repite por si se ha equivocado hasta que elige el nombre de clase
do
{
sal = true;
ambitos_aux = HelperGdb.SaveFileDlg("Guardar Feature Class como...", GdbFileName + "\\" + tratamiento, null, null,
ArcGIS.Desktop.Core.BrowseProjectFilter.GetFilter("esri_browseDialogFilters_featureClasses_all"));
if (string.IsNullOrEmpty(ambitos_aux))
sal = HelperGlobal.ponMsg("¿Desea cancelar el proceso de imporación?",
MessageBoxImage.Question, "OLIVIA", MessageBoxButton.YesNo);
} while (!sal);
if (!string.IsNullOrEmpty(ambitos_aux))
{
//sustituye los ámbitos por los elegidos
ambitos = System.IO.Path.GetFileNameWithoutExtension(ambitos_aux);
replace = System.IO.File.Exists(ambitos_aux);
dataset = System.IO.Path.GetFileNameWithoutExtension(System.IO.Path.GetDirectoryName(ambitos_aux)) ;
}
else {
res.Error.Add("Se ha cancelado la importación de resultados. Se cancela la elección de nombre de la Feature Class.");
return res;
}
//comprueba si la proyección es la misma la del dataset que la que llega
if (!dataset.Equals(tratamiento))
{
//ha cambiado de dataset al elegir
//comprueba las proyecciones
if (!HelperGdb.GetSpatRef(GdbFileName, dataset).Equals(spatRefData))
{
//avisa
HelperGlobal.ponMsg(err_spatref);
}
}
*/
/////////////////////////////////////////
//todo ok, se pone a importar
string err_st=string.Empty;
string name = ambitos;
string path_import = GdbFileName + "\\" + dataset + "\\" + ambitos;
int NIMPORT;
string[] noms_shp = null;
string[] noms_gdb = null;
int i;
int ii = 0;
NIMPORT = 0;
if (modo == 0) //sectoriza
{
NIMPORT = 1;
noms_shp = new string[NIMPORT];
noms_gdb = new string[NIMPORT];
noms_shp[0] = shapefile;
noms_gdb[0] = ambitos;
/*noms_shp[1] = shapefile + NAME_AUX;
noms_gdb[1] = ambitos + NAME_SECT;*/
}
else if (modo == 1) //planifica
{
if (reco_o_limp_con_instala)
NIMPORT = 5;
else
NIMPORT = 4;
if (reco_tramos)
NIMPORT++;
noms_shp = new string[NIMPORT];
noms_gdb = new string[NIMPORT];
noms_shp[0] = shapefile;
noms_gdb[0] = ambitos;
/*noms_shp[1] = shapefile + NAME_AUX;
noms_gdb[1] = ambitos + NAME_SECT;*/
noms_shp[1] = shapefile + NAME_CONTROL;
noms_gdb[1] = ambitos + NAME_CONTROL_OUT;
noms_shp[2] = shapefile + NAME_RUTA;
noms_gdb[2] = ambitos + NAME_RUTA_OUT;
noms_shp[3] = shapefile + NAME_RUTA_AUX;
noms_gdb[3] = ambitos + NAME_RUTA_OUT + NAME_AUX;
ii = 4;
if (reco_o_limp_con_instala)
{
noms_shp[4] = shapefile + NAME_INSTAL;
noms_gdb[4] = ambitos + NAME_INSTAL_OUT;
ii++;
}
if (reco_tramos)
{
noms_shp[ii] = shapefile + NAME_RUTA2;
noms_gdb[ii] = ambitos + NAME_RUTA2_OUT;
}
}
if (noms_gdb == null || noms_shp==null)
{
res.Error.Add("Errores al crear los nombres de las Feature Class");
return res;
}
Respuesta<bool> resp2;
try
{
/////////////////////////////////////////
//se embucla para hacer todas las importaciones necesarias
for (i = 0; i < NIMPORT; i++)
{
//mira a ver si hay que borrar para reemplazar
/*if (replace)
{
resp2 = HelperGdb.DeleteFeatureClass(GdbFileName, noms_gdb[i]);
if (!resp2.Value)
{
err_st = "Error al sobreescribir la capa " + noms_gdb[i];
if (resp2.HasError)
err_st += " " + resp2.Error.First();
break;
}
}*/
resp2 = HelperGdb.ImportShp(dir_shp + "\\" + noms_shp[i] + HelperGdb.SHP_EXT, GdbFileName + "\\" + dataset, noms_gdb[i]);
if (!resp2.Value)
{
err_st = "Error al importar la capa " + noms_gdb[i];
if (resp2.HasError)
err_st += " " + resp2.Error.First();
break;
}
}
if (i < NIMPORT)
{
res.Error.Add("Errores en la importación: "+err_st);
return res;
}
}
catch
{
res.Error.Add("Errores en la importación");
return res;
}
finally
{
}
res.Value = path_import;
return res;
}
/**
* Realiza las funciones de importación de la planificación
*/
public Respuesta<string> ImportPlanif(string GdbFileName)
{
var res = Import(GdbFileName, 1);
if (res.HasError || string.IsNullOrEmpty(res.Value))
{
res.Value = string.Empty;
return res;
}
//////////////////////////////////////////////////
//abre las capas, pintando los sectores
string path_import = res.Value;
/////////////////////////////////////////////////////
//la primera capa que se añade es la de ruta, se le quita la visualización porque lo que interesa
//de esa capa es poder acceder si fuera necesario a la tabla de atributos. shape + name_ruta_out
bool mal = false;
string path_lyr = path_import + NAME_RUTA_OUT;
if (!HelperGdb.OpenLayerUniqueValue(path_lyr, LimpiezaDef.Campos.consulta_sector,false))
mal = true;
/////////////////////////////////////////////////////
//la siguiente es la de ruta2, se le quita la visualización porque lo que interesa
//de esa capa es poder acceder si fuera necesario a la tabla de atributos. shape + name_ruta2_out
if (!mal)
{
path_lyr = path_import + NAME_RUTA2_OUT;
if (!HelperGdb.OpenLayerUniqueValue(path_lyr, LimpiezaDef.Campos.consulta_sector, false))
mal = true;
}
/////////////////////////////////////////////////////
//se añade la capa de ruta_aux y se pinta por sectores - shape + name_ruta_out + name_aux
if (!mal)
{
path_lyr = path_import + NAME_RUTA_OUT + NAME_AUX;
if (!HelperGdb.OpenLayerUniqueValue(path_lyr, LimpiezaDef.Campos.consulta_sector, false))
mal = true;
}
/////////////////////////////////////////////////////
//se añade la capa de ambitos original con la secto, y se pinta por sectores - shape
if (!mal)
{
path_lyr = path_import;
if (!HelperGdb.OpenLayerUniqueValue(path_lyr, LimpiezaDef.Campos.consulta_sector, false))
mal = true;
}
/////////////////////////////////////////////////////
//se añade la capa de la ruta a las instalaciones, comprueba si hay configurada coordenadas de la instalación - shape + name_inst_out
if (!mal)
{
path_lyr = path_import + NAME_INSTAL_OUT;
if (!HelperGdb.OpenLayerUniqueValue(path_lyr, LimpiezaDef.Campos.consulta_sector, false))
mal = true;
}
//se abre la capa de puntos de control y se pintan por el sector al que pertenecen - shape + name_control_out
if (!mal)
{
path_lyr = path_import + NAME_CONTROL_OUT;
if (!HelperGdb.OpenLayerUniqueValue(path_lyr, LimpiezaDef.Campos.consulta_sector, false))
mal = true;
}
/////////////////////////////////////////////////////
if (mal)
{
res.Value = string.Empty;
res.Error.Add("Error al abrir capa " + path_lyr + " con Valor único.");
}
else
{
res.Value = path_import;
}
return res;
}
/**
* Cierra del mapa las capas de trabajo después de la exportación
*/
public void CierraCapas()
{
string capa_principal = System.IO.Path.GetFileNameWithoutExtension(OliviaGlob.Paths.PathData);
string capa_principal_nw = System.IO.Path.GetFileNameWithoutExtension(OliviaGlob.Paths.PathNW);
HelperGdb.CloseLayer(capa_principal);
HelperGdb.CloseLayer(capa_principal_nw);
}
}
}