using System; using System.Collections.Generic; using System.Linq; using System.Security.Policy; using System.Text; using System.Threading.Tasks; using ArcGIS.Desktop.Catalog; using ArcGIS.Desktop.Core; using ArcGIS.Desktop.Framework; using System.Collections.ObjectModel; using ArcGIS.Core.Geometry; using ArcGIS.Core.Data; using ArcGIS.Desktop.Mapping; using ArcGIS.Core.Internal.CIM; using ArcGIS.Desktop.Internal.Layouts.Utilities; using ArcGIS.Desktop.Core.Geoprocessing; using ArcGIS.Desktop.Framework.Threading.Tasks; using ArcGIS.Desktop.Editing; using OliviaAddInPro.Model; using System.IO; using System.Diagnostics; using OliviaAddInPro.View; using OliviaAddInPro.Model.contract; using ArcGIS.Core.Data.DDL; using ArcGIS.Core.CIM; using System.Threading; namespace OliviaAddInPro.Helper { public static class HelperGdb { private static string ObjectId = "OBJECTID"; private static string out_str = string.Empty; public static string OutStr { get { /*string val = ""; val.CopyFrom(out_str); out_str = string.Empty; //lo borra cada vez que se consulta return val;*/ return out_str; } set { out_str = value; } } private static string texto_sal = string.Empty; public static string TextoSal { get { /*string val = ""; val.CopyFrom(texto_sal); texto_sal = string.Empty; //lo borra cada vez que se consulta return val; */ return texto_sal; } set { texto_sal = value; } } public static string SHP_EXT = ".shp"; public static string GDB_EXT = ".gdb"; [Flags] public enum TiposOpenFileDlg { OpenFtrClassLine = 1, OpenFtrClassPoint = 2, OpenFtrClassPolygon = 4, OpenGdb = 8, } private static void ReiniciaOutStr() { out_str = string.Empty; } //Proceso para sacar un diálogo y seleccionar una o varias geometrías de dentro de una fclass public static ArcGIS.Core.Geometry.Geometry OpenGeom(TiposOpenFileDlg tipo, out string txt_sal, string initialLoc = "") { //inicialmente ArcGIS.Core.Geometry.Geometry geom = null; txt_sal = Resource1.String_selec_capa; //abre FeatureClass fc = HelperGdb.OpenFtClassDialog(tipo); if (fc != null) { //hace geom geom = SelecLeeGeom(fc, out txt_sal, true); if (geom == null && (HelperGdb.OutStr.Length > 0)) HelperGlobal.ponMsg(HelperGdb.OutStr, System.Windows.MessageBoxImage.Error); HelperGdb.Free(fc); } return geom; } /* * Saca ventana para seleccionar el campo del que leer para elegir la geometría */ private static ArcGIS.Core.Geometry.Geometry SelecLeeGeom(FeatureClass fc, out string text_sal, bool multisel) { ArcGIS.Core.Geometry.Geometry geomsal = null; text_sal = ""; if (fc != null) { //saca la ventana de selección de campo ShowProWndSelectFields selfwnd = new ShowProWndSelectFields(fc, multisel); if (selfwnd.SelFieldVals.Count > 0) { geomsal = HelperGdb.GetGeomSel(fc, selfwnd.SelField, selfwnd.SelFieldVals).Result; text_sal = HelperGdb.TextoSal; } } return geomsal; } /** * Devuelve el sistema de coordenadas de una capa */ public static ArcGIS.Core.Geometry.SpatialReference GetSpatRef(string ftclassName) { FeatureClass fc = GetFtClassFromShp(ftclassName).Result; if (fc == null) return null; ArcGIS.Core.Geometry.SpatialReference spatref = null; var task = ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() => { try { spatref = fc.GetDefinition().GetSpatialReference(); } catch { } finally { fc.Dispose(); } }); task.Wait(); return spatref; } public static ArcGIS.Core.Geometry.SpatialReference GetSpatRefSync(string ftclassName) { FeatureClass fc = GetFtClassFromShp(ftclassName).Result; if (fc == null) return null; ArcGIS.Core.Geometry.SpatialReference spatref = null; try { spatref = fc.GetDefinition().GetSpatialReference(); } catch { spatref = null; } finally { fc.Dispose(); } return spatref; } /** * Devuelve el sistema de coordenadas de una capa */ public static ArcGIS.Core.Geometry.SpatialReference GetSpatRef(FeatureClass fc) { if (fc == null) return null; ArcGIS.Core.Geometry.SpatialReference spatref = null; var task = ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() => { try { spatref = fc.GetDefinition().GetSpatialReference(); } catch { spatref = null; } }); return spatref; } public static ArcGIS.Core.Geometry.SpatialReference GetSpatRefSync(FeatureClass fc) { if (fc == null) return null; ArcGIS.Core.Geometry.SpatialReference spatref = null; try { spatref = fc.GetDefinition().GetSpatialReference(); } catch { spatref = null; } return spatref; } /** * Devuelve el sistema de coordenadas de un dataset */ public static ArcGIS.Core.Geometry.SpatialReference GetSpatRef(string gdbName, string dataset) { if (gdbName == null || string.IsNullOrEmpty(dataset)) return null; Geodatabase gdb = null; FeatureClassDefinition fcdef = null; try { gdb = GetGdb(gdbName).Result; if (gdb == null) return null; ArcGIS.Core.Geometry.SpatialReference spatref = null; var task = ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() => { try { fcdef = gdb.GetDefinition(dataset); spatref = fcdef.GetSpatialReference(); } catch { fcdef = null; } }); task.Wait(); return spatref; } catch { return null; } finally { Free(gdb); Free(fcdef); } } /** * Devuelve el sistema de coordenadas de un dataset */ public static ArcGIS.Core.Geometry.SpatialReference GetSpatRefSync(string gdbName, string dataset) { if (gdbName == null || string.IsNullOrEmpty(dataset)) return null; Geodatabase gdb = null; FeatureClassDefinition fcdef = null; try { gdb = GetGdb(gdbName).Result; if (gdb == null) return null; ArcGIS.Core.Geometry.SpatialReference spatref = null; try { fcdef = gdb.GetDefinition(dataset); spatref = fcdef.GetSpatialReference(); } catch { fcdef = null; } return spatref; } catch { return null; } finally { Free(gdb); Free(fcdef); } } //Dado el tipo de FtClass y una posición inicial abre un diálogo de búsqueda de ftclass //si se cancela o no es una feature class lo que se ha abierto devuelve null //si no, devuelve la featureclass directamente abierta public static FeatureClass OpenFtClassDialog(TiposOpenFileDlg tipo, string initialLoc = "") { FeatureClass fc = null; ReiniciaOutStr(); string path = OpenFileDialog(tipo, initialLoc); if (!string.IsNullOrEmpty(path)) { fc = GetFtClass(path); } return fc; } //Libera el objeto public static void Free(IDisposable obj) { if (obj != null) obj.Dispose(); } //Devuelve el Path del archivo seleccionado o un string vacío si se ha cancelado public static string OpenFileDialog(TiposOpenFileDlg tipo, string initialLoc = "", string tit_ = "") { string titulo; ReiniciaOutStr(); titulo = "Abrir Archivo"; //Create a browse filter that uses Pro's "esri_browseDialogFilters_geodatabases" filter. //The browse filter is used in an OpenItemDialog. //fuentes filtros //https://github.com/Esri/arcgis-pro-sdk-community-samples/blob/master/Map-Exploration/IdentifyWindow/Daml.cs BrowseProjectFilter filtro = new BrowseProjectFilter(); if ((tipo & TiposOpenFileDlg.OpenFtrClassLine) == TiposOpenFileDlg.OpenFtrClassLine) { filtro.AddFilter(BrowseProjectFilter.GetFilter("esri_browseDialogFilters_featureClasses_line")); titulo = "Abrir Feature Class"; } if ((tipo & TiposOpenFileDlg.OpenFtrClassPoint) == TiposOpenFileDlg.OpenFtrClassPoint) { filtro.AddFilter(BrowseProjectFilter.GetFilter("esri_browseDialogFilters_featureClasses_point")); titulo = "Abrir Feature Class"; } if ((tipo & TiposOpenFileDlg.OpenFtrClassPolygon) == TiposOpenFileDlg.OpenFtrClassPolygon) { filtro.AddFilter(BrowseProjectFilter.GetFilter("esri_browseDialogFilters_featureClasses_polygon")); titulo = "Abrir Feature Class"; } if ((tipo & TiposOpenFileDlg.OpenGdb) == TiposOpenFileDlg.OpenGdb) { filtro.AddFilter(BrowseProjectFilter.GetFilter("esri_browseDialogFilters_geodatabases")); titulo = "Abrir Geodatabase"; } if (tipo == 0) { filtro.AddFilter(BrowseProjectFilter.GetFilter("")); } if (!string.IsNullOrEmpty(tit_)) titulo = tit_; //Display the filter in an Open Item dialog OpenItemDialog aNewFilter = new OpenItemDialog { Title = titulo, MultiSelect = false, //Set the BrowseFilter property to Pro's Geodatabase filter. BrowseFilter = filtro }; if (!string.IsNullOrEmpty(initialLoc)) aNewFilter.InitialLocation = initialLoc; bool? ok = aNewFilter.ShowDialog(); if ((ok ?? true) && aNewFilter.Items.Count() > 0) return aNewFilter.Items.First().Path; else return string.Empty; } //Dado un path comprueba que sea de una gdb, termina en .gdb, o si tiene .gdb en medio lo corta ahí //y si no tiene devuelve vacío public static string GetPathGdb(string path) { if (path == null) return string.Empty; string pathGdb = string.Empty; int i = 0; if (path.Contains(GDB_EXT)) { i = path.IndexOf(GDB_EXT, 0, path.Length); pathGdb = path.Substring(0, i + 4); } return pathGdb; } //Dado un path aunque sea de una feature class, devuelve el path de la gdb que la contiene, o si //es de gdb directamente, y si no tiene .gdb, devuelve null public static Task GetGdb(string pathGdb) { Geodatabase fileGeodatabase = null; if (string.IsNullOrEmpty(pathGdb)) return null; ReiniciaOutStr(); return ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run((Func)(() => { string path = GetPathGdb(pathGdb); if (!string.IsNullOrEmpty(path)) { try { fileGeodatabase = new Geodatabase(new FileGeodatabaseConnectionPath(new Uri(path))); } catch (Exception ex) { HelperGdb.OutStr = "Error al abrir Geodatabase " + path + ": " + ex.Message; return null; } } return fileGeodatabase; })); //return fileGeodatabase; } //Dado un path aunque sea de una feature class, devuelve el path de la gdb que la contiene, o si //es de gdb directamente, y si no tiene .gdb, devuelve null public static Geodatabase GetGdbSync(string pathGdb) { Geodatabase fileGeodatabase = null; if (string.IsNullOrEmpty(pathGdb)) return null; ReiniciaOutStr(); string path = GetPathGdb(pathGdb); if (!string.IsNullOrEmpty(path)) { try { fileGeodatabase = new Geodatabase(new FileGeodatabaseConnectionPath(new Uri(path))); } catch (Exception ex) { HelperGdb.OutStr = "Error al abrir Geodatabase " + path + ": " + ex.Message; return null; } } return fileGeodatabase; } //Dado un path de una feature class devuelve la ftclass abierta directamente, //o null si ha habido algún problema o no lo ha encontrado public static FeatureClass GetFtClass(string pathFtClss) { FeatureClass ftclss = null; if (string.IsNullOrEmpty(pathFtClss)) return null; Geodatabase gdb = GetGdb(pathFtClss).Result; ReiniciaOutStr(); if (gdb != null) { ftclss = GetFtClass(System.IO.Path.GetFileNameWithoutExtension(pathFtClss), gdb).Result; } else //mira a ver si es shapefile { ftclss = GetFtClassFromShp(pathFtClss).Result; } Free(gdb); return ftclss; } //Dado un path de una feature class devuelve la ftclass abierta directamente, //o null si ha habido algún problema o no lo ha encontrado public static FeatureClass GetFtClassSync(string pathFtClss) { FeatureClass ftclss = null; if (string.IsNullOrEmpty(pathFtClss)) return null; Geodatabase gdb = GetGdbSync(pathFtClss); ReiniciaOutStr(); if (gdb != null) { ftclss = GetFtClassSync(System.IO.Path.GetFileNameWithoutExtension(pathFtClss), gdb); } else //mira a ver si es shapefile { ftclss = GetFtClassFromShpSync(pathFtClss); } Free(gdb); return ftclss; } //Dado el path de una gdb y el nombre de una feature class, devuelve la //feature class abierta, o null si hay algun problema public static Task GetFtClass(string nameFtclss, Geodatabase gdb) { FeatureClass ftclss = null; if (string.IsNullOrEmpty(nameFtclss)) return null; ReiniciaOutStr(); return ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run((Func)(() => { try { ftclss = gdb.OpenDataset(nameFtclss); } catch (Exception ex) { HelperGdb.OutStr = "Error al abrir Feature Class " + nameFtclss + ": " + ex.Message; return null; } return ftclss; })); } //Dado el path de una gdb y el nombre de una feature class, devuelve la //feature class abierta, o null si hay algun problema public static FeatureClass GetFtClassSync(string nameFtclss, Geodatabase gdb) { FeatureClass ftclss = null; if (string.IsNullOrEmpty(nameFtclss)) return null; ReiniciaOutStr(); try { ftclss = gdb.OpenDataset(nameFtclss); } catch (Exception ex) { HelperGdb.OutStr = "Error al abrir Feature Class " + nameFtclss + ": " + ex.Message; return null; } return ftclss; } //Abre una feature class cuando es un shapefile public static Task GetFtClassFromShp(string pathShp) { FeatureClass ftclss = null; ReiniciaOutStr(); return ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run((Func)(() => { if (!string.IsNullOrEmpty(pathShp) && pathShp.Contains(SHP_EXT)) { try { string shpname = System.IO.Path.GetFileNameWithoutExtension(pathShp); var shapeFileConnPath = new FileSystemConnectionPath(new Uri(System.IO.Path.GetDirectoryName(pathShp)), FileSystemDatastoreType.Shapefile); var shapefile = new FileSystemDatastore(shapeFileConnPath); ftclss = shapefile.OpenDataset(shpname); } catch (Exception ex) { HelperGdb.OutStr = "Error al abrir Shapefile " + pathShp + ": " + ex.Message; return null; } } return ftclss; })); } //Abre una feature class cuando es un shapefile public static FeatureClass GetFtClassFromShpSync(string pathShp) { FeatureClass ftclss = null; ReiniciaOutStr(); if (!string.IsNullOrEmpty(pathShp) && pathShp.Contains(SHP_EXT)) { try { string shpname = System.IO.Path.GetFileNameWithoutExtension(pathShp); var shapeFileConnPath = new FileSystemConnectionPath(new Uri(System.IO.Path.GetDirectoryName(pathShp)), FileSystemDatastoreType.Shapefile); var shapefile = new FileSystemDatastore(shapeFileConnPath); ftclss = shapefile.OpenDataset(shpname); } catch (Exception ex) { HelperGdb.OutStr = "Error al abrir Shapefile " + pathShp + ": " + ex.Message; return null; } } return ftclss; } //devuelve el campo dado el nombre private static ArcGIS.Core.Data.Field GetFieldByNameSinc(FeatureClass ftClss, string fieldName) { FeatureClassDefinition ftcldef = ftClss.GetDefinition(); ReiniciaOutStr(); ArcGIS.Core.Data.Field field = null; try { field = ftcldef.GetFields().First(x => x.Name.Equals(fieldName)); } catch (Exception ex) { HelperGdb.OutStr = "No se encuentra el campo " + fieldName + ": " + ex.Message; return null; } return field; } //Crea un filtro espacial a partir de una consulta y en todo caso, una geometría public static ArcGIS.Core.Data.SpatialQueryFilter CreateFiler(string consulta, ArcGIS.Core.Geometry.Geometry geom, SpatialRelationship rel = SpatialRelationship.Contains) { ArcGIS.Core.Data.SpatialQueryFilter filt = null; if (geom != null) { SpatialQueryFilter filtSpat = new SpatialQueryFilter { WhereClause = consulta, FilterGeometry = geom, SpatialRelationship = rel, }; filt = filtSpat; } else { filt = new ArcGIS.Core.Data.SpatialQueryFilter(); filt.WhereClause = consulta; } return filt; } //Devuelve la lista de IDs de la clase que cumplen la consulta public static Task> GetIds(FeatureClass fc, ArcGIS.Core.Data.QueryFilter filt) { ReiniciaOutStr(); List ids = new List(); Selection sel = null; return ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run((Func>)(() => { if (fc == null) return null; try { if (filt == null) filt = new ArcGIS.Core.Data.QueryFilter(); sel = fc.Select(filt, SelectionType.ObjectID, SelectionOption.Normal); int nsel = sel.GetCount(); IReadOnlyList ids_ = sel.GetObjectIDs(); ids = ids_.ToList(); return ids; } catch (Exception ex) { HelperGdb.OutStr = "Error al conseguir IDs " + fc.GetName() + ": " + ex.Message; return ids; } finally { Free(sel); } })); } //Devuelve la lista de IDs de la clase que cumplen la consulta public static List GetIdsSync(FeatureClass fc, ArcGIS.Core.Data.QueryFilter filt) { ReiniciaOutStr(); List ids = new List(); Selection sel = null; if (fc == null) return null; try { if (filt == null) filt = new ArcGIS.Core.Data.QueryFilter(); sel = fc.Select(filt, SelectionType.ObjectID, SelectionOption.Normal); int nsel = sel.GetCount(); IReadOnlyList ids_ = sel.GetObjectIDs(); ids = ids_.ToList(); return ids; } catch (Exception ex) { HelperGdb.OutStr = "Error al conseguir IDs " + fc.GetName() + ": " + ex.Message; return ids; } finally { Free(sel); } } //Devuelve una lista con los campos de una feature class public static Task> GetFields(FeatureClass fc) { FeatureClassDefinition ftcldef = null; IReadOnlyList fields = null; ReiniciaOutStr(); ObservableCollection fields_st = new ObservableCollection(); return ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run((Func>)(() => { if (fc == null) return null; try { ftcldef = fc.GetDefinition(); fields = ftcldef.GetFields(); foreach (ArcGIS.Core.Data.Field f in fields) { fields_st.Add(f.Name); } } catch (Exception ex) { HelperGdb.OutStr = "Error al leer los campos " + fc.GetName() + ": " + ex.Message; return fields_st; } return fields_st; })); } //Devuelve una lista con los campos de una feature class public static ObservableCollection GetFieldsSync(FeatureClass fc) { FeatureClassDefinition ftcldef = null; IReadOnlyList fields = null; ReiniciaOutStr(); ObservableCollection fields_st = new ObservableCollection(); if (fc == null) return null; try { ftcldef = fc.GetDefinition(); fields = ftcldef.GetFields(); foreach (ArcGIS.Core.Data.Field f in fields) { fields_st.Add(f.Name); } } catch (Exception ex) { HelperGdb.OutStr = "Error al leer los campos " + fc.GetName() + ": " + ex.Message; return fields_st; } return fields_st; } /* * Comprueba que en la capa dada exista un campo con nombre 'field' */ public static bool CheckField(string pathCapa, string field) { FeatureClass fc = GetFtClass(pathCapa); if (fc == null) { HelperGdb.OutStr = "No se puede abrir la capa"; return false; } ObservableCollection fields = GetFields(fc).Result; if (!fields.Contains(field)) { HelperGdb.OutStr = "No se encuentra el campo " + field; return false; } return true; } /* * Comprueba que en la capa dada exista un campo con nombre 'field' */ public static bool CheckFieldSync(string pathCapa, string field) { FeatureClass fc = GetFtClassSync(pathCapa); if (fc == null) { HelperGdb.OutStr = "No se puede abrir la capa"; return false; } ObservableCollection fields = GetFieldsSync(fc); if (!fields.Contains(field)) { HelperGdb.OutStr = "No se encuentra el campo " + field; return false; } return true; } /* * Lee la capa que se ha seleccionzdo de recogida y se comprueba que contiene los campos necesarios * Devuelve 0 si va todo bien, -1 si da error, y num>0 con los campos que no encuentra */ public static int CheckFileds(string pathCapa, string[] camps) { int i; FeatureClass fc = null; try { fc = GetFtClass(pathCapa); if (fc == null) { OutStr = "No se puede abrir la capa " + pathCapa; return -1; } ObservableCollection fields = GetFields(fc).Result; OutStr = "No se encuentran el/los campo/s: "; int mal = 0; for (i = 0; i < camps.Length; i++) { if (!fields.Contains(camps[i])) { OutStr = OutStr + camps[i] + " "; mal++; } } if (mal == 0) OutStr = ""; return mal; } catch { return -1; } finally { Free(fc); } } /* * Lee la capa que se ha seleccionzdo de recogida y se comprueba que contiene los campos necesarios * Devuelve 0 si va todo bien, -1 si da error, y num>0 con los campos que no encuentra */ public static int CheckFiledsSync(string pathCapa, string[] camps) { int i; FeatureClass fc = null; try { fc = GetFtClassSync(pathCapa); if (fc == null) { OutStr = "No se puede abrir la capa " + pathCapa; return -1; } ObservableCollection fields = GetFieldsSync(fc); OutStr = "No se encuentran el/los campo/s: "; int mal = 0; for (i = 0; i < camps.Length; i++) { if (!fields.Contains(camps[i])) { OutStr = OutStr + camps[i] + " "; mal++; } } if (mal == 0) OutStr = ""; return mal; } catch { return -1; } finally { Free(fc); } } //Devuelve comilla simple si el campo es de texto, o nada si es númerico //var whereClause = $"{SelectedField} = {Quote(f)}{FieldValue}{Quote(f)}"; public static string Quote(ArcGIS.Core.Data.Field f) { return f.FieldType == FieldType.String ? "'" : ""; } //Dado un nombre de campo, devuelve los valores que encuentra para ese nombre de campo public static Task> GetFieldVals(string capa, string fieldName, bool uniquevals) { FeatureClass fc = GetFtClass(capa); if (fc == null) return null; return GetFieldVals(fc, fieldName, uniquevals); } //Dado un nombre de campo, devuelve los valores que encuentra para ese nombre de campo public static ObservableCollection GetFieldValsSync(string capa, string fieldName, bool uniquevals) { FeatureClass fc = GetFtClassSync(capa); if (fc == null) return null; return GetFieldValsSync(fc, fieldName, uniquevals); } //Dado un nombre de campo, devuelve los valores que encuentra para ese nombre de campo public static Task> GetFieldVals(FeatureClass fc, string fieldName, bool uniquevals) { ObservableCollection attribs_st = new ObservableCollection(); ReiniciaOutStr(); return ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run((Func>)(() => { try { using (FeatureClassDefinition ftcldef = fc.GetDefinition()) { ArcGIS.Core.Data.Field field = ftcldef.GetFields().First(x => x.Name.Equals(fieldName)); using (RowCursor rowCursor = fc.Search()) { string str; while (rowCursor.MoveNext()) { using (Row row = rowCursor.Current) { str = Convert.ToString(row[fieldName]); if (uniquevals) { if (attribs_st.Contains(str)) continue; } attribs_st.Add(str); } } } } } catch (Exception ex) { HelperGdb.OutStr = "Error al leer los campos " + fc.GetName() + ": " + ex.Message; return attribs_st; } return attribs_st; })); } //Dado un nombre de campo, devuelve los valores que encuentra para ese nombre de campo public static ObservableCollection GetFieldValsSync(FeatureClass fc, string fieldName, bool uniquevals) { ObservableCollection attribs_st = new ObservableCollection(); ReiniciaOutStr(); try { using (FeatureClassDefinition ftcldef = fc.GetDefinition()) { ArcGIS.Core.Data.Field field = ftcldef.GetFields().First(x => x.Name.Equals(fieldName)); using (RowCursor rowCursor = fc.Search()) { string str; while (rowCursor.MoveNext()) { using (Row row = rowCursor.Current) { str = Convert.ToString(row[fieldName]); if (uniquevals) { if (attribs_st.Contains(str)) continue; } attribs_st.Add(str); } } } } } catch (Exception ex) { HelperGdb.OutStr = "Error al leer los campos " + fc.GetName() + ": " + ex.Message; return attribs_st; } return attribs_st; } /** * Devuelve una geometría que es la suma de la inicial y la que se añade Add */ public static ArcGIS.Core.Geometry.Geometry IntersectGeom(ArcGIS.Core.Geometry.Geometry geomIni, ArcGIS.Core.Geometry.Geometry geomInters, GeometryDimension resultDimension = GeometryDimension.esriGeometryNoDimension) { if (geomIni == null) return geomInters; if (geomInters == null) return geomIni; ArcGIS.Core.Geometry.Geometry geomSal = null; try { if (resultDimension == GeometryDimension.esriGeometryNoDimension) geomSal = GeometryEngine.Instance.Intersection(geomIni, geomInters); else geomSal = GeometryEngine.Instance.Intersection(geomIni, geomInters, resultDimension); return geomSal; } catch { return null; } } /** * Devuelve una geometría que es la suma de la inicial y la que se añade Add */ public static ArcGIS.Core.Geometry.Geometry UneGeom(ArcGIS.Core.Geometry.Geometry geomIni, ArcGIS.Core.Geometry.Geometry geomUne) { if (geomIni == null) return geomUne; if (geomUne == null) return geomIni; ArcGIS.Core.Geometry.Geometry geomSal = null; try { geomSal = GeometryEngine.Instance.Union(geomIni, geomUne); return geomSal; } catch { return null; } } /** * Devuelve una geometría a la que dada una geometría inicial se le quita Excl */ public static ArcGIS.Core.Geometry.Geometry QuitaGeom(ArcGIS.Core.Geometry.Geometry geomIni, ArcGIS.Core.Geometry.Geometry geomQuita) { if (geomIni == null) return geomQuita; if (geomQuita == null) return geomIni; ArcGIS.Core.Geometry.Geometry geomSal = null; try { geomSal = GeometryEngine.Instance.Difference(geomIni, geomQuita); return geomSal; } catch { return null; } } /** * Forma la envolvente convexa, el mínimo polígono, * que contiene los ámbitos para exportar, a partir de ahí la red navegable ampliando a un buffer */ public static Task GetGeomConvexHull(FeatureClass fclss, ArcGIS.Core.Data.QueryFilter filter) { ArcGIS.Core.Geometry.Geometry geomIni = null; return ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run((Func)(() => { geomIni = GetGeomUnique(fclss, filter); return geomIni; })); } /** * Forma la envolvente convexa, el mínimo polígono, * que contiene los ámbitos para exportar, a partir de ahí la red navegable ampliando a un buffer */ public static ArcGIS.Core.Geometry.Geometry GetGeomConvexHullSync(FeatureClass fclss, ArcGIS.Core.Data.QueryFilter filter) { ArcGIS.Core.Geometry.Geometry geomIni = null; geomIni = GetGeomUnique(fclss, filter); return geomIni; } /* * A partir de una capa recorre todos los elementos que cumplen el filtro y los une en una única geometría */ public static ArcGIS.Core.Geometry.Geometry GetGeomUnique(FeatureClass fclss, ArcGIS.Core.Data.QueryFilter filtro) { ArcGIS.Core.Geometry.Geometry geomsal = null; ReiniciaOutStr(); try { var geom = new List(); using (RowCursor rowCursor = fclss.Search(filtro)) { while (rowCursor.MoveNext()) { using (Row row = rowCursor.Current) { if (row is Feature ft) geom.Add(ft.GetShape()); } } geomsal = GeometryEngine.Instance.Union(geom); } } catch (Exception ex) { OutStr = "Error al leer generar geometría única " + OutStr + ex.Message; return geomsal; } return geomsal; } /** * Dado un campo de una feature class y el valor que se quiere para el campo * devuelve las geometrías que cumplen dicho criterio */ public static Task GetGeomSel(FeatureClass fclss, string fieldName, ObservableCollection selFieldVals) { ArcGIS.Core.Geometry.Geometry geomsal = null; ArcGIS.Core.Geometry.Geometry geomAux = null; string where = ""; ArcGIS.Core.Data.Field f; ArcGIS.Core.Data.QueryFilter filtro; bool ok = true; ReiniciaOutStr(); string txtsal = string.Empty; ReiniciaOutStr(); return ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run((Func)(() => { try { using (FeatureClassDefinition ftcldef = fclss.GetDefinition()) { f = ftcldef.GetFields().First(x => x.Name.Equals(fieldName)); //se embucla para unir las geoms for (int i = 0; i < selFieldVals.Count && ok; i++) { where = $"{fieldName} = {Quote(f)}{selFieldVals[i]}{Quote(f)}"; filtro = new ArcGIS.Core.Data.QueryFilter { WhereClause = where }; geomAux = GetGeomUnique(fclss, filtro); if (geomAux == null) { ok = false; continue; } geomsal = UneGeom(geomsal, geomAux); txtsal = txtsal + HelperGlobal.RevisaText(selFieldVals[i]); } TextoSal = txtsal; } } catch (Exception ex) { HelperGdb.OutStr = "Error al generar geometría en " + fclss.GetName() + " Con filtro " + where + ": " + ex.Message; return geomsal; } if (!ok) HelperGdb.OutStr = "Error al generar geometría en " + fclss.GetName() + " Con filtro " + where + HelperGdb.OutStr; return geomsal; })); } /** * Devuelve el número de entidades de una FeatureClass que cumplen la consulta, o todos si la consulta es empty */ public static int GetNumElems(string pathGdb, string ftclssName, string consulta = "") { Geodatabase gdb = GetGdb(pathGdb).Result; FeatureClass fc = null; int n = -1; if (gdb != null) { fc = GetFtClass(ftclssName, gdb).Result; if (fc != null) n = GetNumElems(fc, consulta).Result; } Free(fc); Free(gdb); return n; } /** * Devuelve los valores únicos de un campo dado */ public static ObservableCollection GetUniqueVals(string capa, string campo) { ObservableCollection uniqueVals = null; FeatureClass ftclass = GetFtClass(capa); if (ftclass == null) return null; using (FeatureClassDefinition featureClassDefinition = ftclass.GetDefinition()) { // Get fields ArcGIS.Core.Data.Field fld = featureClassDefinition.GetFields().First(x => x.Name.Equals(campo)); // Create StatisticsDescriptions StatisticsDescription uniqStatDesc = new StatisticsDescription(fld, new List() { ArcGIS.Core.Data.StatisticsFunction.Count }); // Create TableStatisticsDescription TableStatisticsDescription tableStatisticsDescription = new TableStatisticsDescription(new List() { uniqStatDesc }); tableStatisticsDescription.GroupBy = new List() { fld }; tableStatisticsDescription.OrderBy = new List() { new SortDescription(fld) }; // Calculate Statistics IReadOnlyList statisticsResults = ftclass.CalculateStatistics(tableStatisticsDescription); TableStatisticsResult statRes = statisticsResults.ElementAt(0); //solo hay 1 grupo // Code to process results goes here... uniqueVals = new ObservableCollection(); for (int i = 0; i < statRes.StatisticsResults.Count; i++) { uniqueVals.Add(statRes.StatisticsResults.ElementAt(i).ToString()); } } Free(ftclass); return uniqueVals; } /** * Devuelve el número de entidades de una FeatureClass que cumplen la consulta, o todos si la consulta es empty */ public static Task GetNumElems(FeatureClass fc, string consulta = "") { int n = -1; ReiniciaOutStr(); return ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run((Func)(() => { try { if (fc != null) { if (string.IsNullOrEmpty(consulta)) n = fc.GetCount(); else { //realiza consulta n = 0; using (Selection sel = fc.Select(new ArcGIS.Core.Data.QueryFilter { WhereClause = consulta }, SelectionType.ObjectID, SelectionOption.Normal)) n = sel.GetCount(); } } return n; } catch (Exception ex) { HelperGdb.OutStr = "Error al contar filas en " + fc.GetName() + ": " + ex.Message; return n; } })); } /** * Devuelve el número de entidades de una FeatureClass que cumplen la consulta, o todos si la consulta es empty */ public static int GetNumElemsSync(FeatureClass fc, string consulta = "") { int n = -1; ReiniciaOutStr(); try { if (fc != null) { if (string.IsNullOrEmpty(consulta)) n = fc.GetCount(); else { //realiza consulta n = 0; using (Selection sel = fc.Select(new ArcGIS.Core.Data.QueryFilter { WhereClause = consulta }, SelectionType.ObjectID, SelectionOption.Normal)) n = sel.GetCount(); } } return n; } catch (Exception ex) { HelperGdb.OutStr = "Error al contar filas en " + fc.GetName() + ": " + ex.Message; return n; } } /** * Devuelve el número de entidades de una FeatureClass que cumplen la consulta, o todos si la consulta es empty */ public static int GetNumElems(string pathFtClss, string consulta = "") { FeatureClass fc = GetFtClass(pathFtClss); int n = GetNumElems(fc, consulta).Result; Free(fc); return n; } public static int GetNumElemsSync(string pathFtClss, string consulta = "") { FeatureClass fc = GetFtClassSync(pathFtClss); int n = GetNumElemsSync(fc, consulta); Free(fc); return n; } static public bool RenameSHP(string dir, string path, string nameNew) { var extensions = new[] { "cpg", "dbf", "prj", "sbn", "sbx", "shp", "shp.xml", "shx" }; string old_ext = System.IO.Path.GetExtension(path); string name = System.IO.Path.GetFileName(path); if (!string.IsNullOrEmpty(old_ext)) name.Replace(old_ext, ""); string _ex = System.IO.Path.GetExtension(nameNew); string nn = nameNew; if (!string.IsNullOrEmpty(_ex)) nn = nn.Replace(_ex, ""); var res = true; foreach (var ex in extensions) { try { var po = string.Format("{0}{1}.{2}", dir, name, ex); var pn = string.Format("{0}{1}.{2}", dir, nn, ex); if (!File.Exists(po)) res = false;//no existe if (File.Exists(pn)) File.Delete(pn); File.Move(po, pn); } catch { res = false; } } return res; } public static bool ExportShp2(string pathLayerIn, SpatialQueryFilter filter, string nameShp, string outpath, IprocessManager cps, ArcGIS.Core.Geometry.SpatialReference sr = null, int incmax = 100) { if (!System.IO.Directory.Exists(outpath)) System.IO.Directory.CreateDirectory(outpath); FeatureClass fc = null; ///////////////////////////////////////////////////////// //Prepara una where_clause con las entidades que cumplen el filtro //Abre la featureclass try { fc = GetFtClassSync(pathLayerIn); if (fc == null) { OutStr = "Error al abrir Feature Class en exportación"; return false; } List ids = new List(); //Añade a la lista los ids que cumplen el filtro espacial using (RowCursor cursor = fc.Search(filter)) { while (cursor.MoveNext()) { using (Feature feature = (Feature)cursor.Current) { ids.Add(feature.GetObjectID()); } } } if (ids.Count <= 0) { OutStr = "Error al aplicar filtro espacial en exportación"; return false; } //convierte la lista de ids a string para la clause de la forma //(id1, id2, id3..) string whereClause = GetWhereClauseFromIds(ids); /////////////////////////////////////////////////////////// ///Exporta string[] args = { pathLayerIn, outpath, nameShp, whereClause }; // execute the tool if (sr == null) { sr = fc.GetDefinition().GetSpatialReference(); } var environments = Geoprocessing.MakeEnvironmentArray(outputCoordinateSystem: sr); //SpatialReferenceBuilder.CreateSpatialReference(3857) double valini = cps.GetProgress(); ; IGPResult gpResult = Geoprocessing.ExecuteToolAsync("FeatureClassToFeatureClass_conversion", args, environments, null, (event_name, o) => // implement delegate and handle events { switch (event_name) { case "OnValidate": // stop execute if any warnings //if ((o as IGPMessage[]).Any(it => it.Type == GPMessageType.Warning)) //_cts.Cancel(); break; case "OnProgressMessage": { string msg = string.Format("{0}: {1}", new object[] { event_name, (string)o }); Debug.WriteLine(msg); ; } break; case "OnProgressPos": { string msg2 = string.Format("{0}: {1} %", new object[] { event_name, (int)o }); Debug.WriteLine(msg2); var av = (int)o; if (av > 0) { cps.SetProgress(valini + (Math.Min((double)av / 100.0, 100.0) * Math.Min(incmax, 100 - valini))); } // if ((int)o < 0) //System.Windows.MessageBox.Show(msg2); //_cts.Cancel(); break; } } }).Result; if (gpResult.IsCanceled) { cps.Setcancelled(); return false; } if (gpResult.IsFailed) { string msg; if (gpResult.ErrorMessages != null) msg = gpResult.ErrorMessages.First().Text; else msg = "Errores en la exportación"; OutStr = "Error: " + msg; return false; } return true; } catch (Exception ex) { OutStr = "Error: " + ex.Message; return false; } finally { Free(fc); } } public static bool ExportShp(string pathLayerIn, SpatialQueryFilter filter, string nameShp, string outpath, CancelableProgressorSource cps, out string msgOut, ProgressorSource progrDialog = null) { msgOut = ""; if (!System.IO.Directory.Exists(outpath)) System.IO.Directory.CreateDirectory(outpath); //fc. /* using (RowCursor rowCursor = fc.Search(filter)) { while (rowCursor.MoveNext()) { using (Row row = rowCursor.Current) { if (row is Feature ft) { var sh = ft.GetShape(); sh = ft.GetShape(); sh. } } } }*/ //Selection selFeatures = featureClass.Select(filter, SelectionType.ObjectID, SelectionOption.Normal); // make a value array of strings to be passed to ExecuteToolAsync /* System.Threading.CancellationTokenSource _cts1 = new System.Threading.CancellationTokenSource(); cps.Status = "Guardando geometria a shp"; string[] args1 = { pathLayerIn, outpath }; IGPResult gpResult1 = Geoprocessing.ExecuteToolAsync("FeatureClassToFeatureClass", args1, null, _cts1.Token, (event_name, o) => // implement delegate and handle events { switch (event_name) { case "OnValidate": break; case "OnProgressMessage": { string msg = string.Format("{0}: {1}", new object[] { event_name, (string)o }); //progrDialog.Message = (string)o; Debug.WriteLine(msg); } break; case "OnProgressPos": { string msg2 = string.Format("{0}: {1} %", new object[] { event_name, (int)o }); Debug.WriteLine(msg2); break; } } }).Result; */ cps.Status = "Guardando geometria a shp"; string[] args = { pathLayerIn, outpath }; // execute the tool IGPResult gpResult = Geoprocessing.ExecuteToolAsync("FeatureClassToShapefile_conversion", args, null, cps.CancellationTokenSource.Token, (event_name, o) => // implement delegate and handle events { switch (event_name) { case "OnValidate": // stop execute if any warnings //if ((o as IGPMessage[]).Any(it => it.Type == GPMessageType.Warning)) //_cts.Cancel(); break; case "OnProgressMessage": { string msg = string.Format("{0}: {1}", new object[] { event_name, (string)o }); //progrDialog.Message = (string)o; Debug.WriteLine(msg); ; //System.Windows.MessageBox.Show(msg); //_cts.Cancel(); } break; case "OnProgressPos": { string msg2 = string.Format("{0}: {1} %", new object[] { event_name, (int)o }); Debug.WriteLine(msg2); var av = (int)0; if (av > 0) { cps.Value = (uint)(80 * av * 0.2); } // if ((int)o < 0) //System.Windows.MessageBox.Show(msg2); //_cts.Cancel(); break; } } }).Result; cps.Status = "Finalizando exportacion"; //renombrado de ficheros: if (!RenameSHP(outpath, pathLayerIn, nameShp)) { msgOut = "Error al exportar a shp."; return false; } /* //filtra entidades--- var pn = string.Format("{0}{1}.{2}", pathLayerIn, nameShp); FeatureClass fc = HelperGdb.GetFtClass(pn); var f = new ArcGIS.Core.Data.QueryFilter(); //f. fc.DeleteRows*/ return true; } /** * Comprueba si un punto está contenido en un polígono */ public static Respuesta IsPtoInGeom(Coordinate2D pto, ArcGIS.Core.Geometry.Geometry geom) { Respuesta resp = new Respuesta(); try { ArcGIS.Core.Geometry.Geometry geom_convexhull = GeometryEngine.Instance.ConvexHull(geom); ArcGIS.Core.Geometry.Polygon poli = (ArcGIS.Core.Geometry.Polygon)geom_convexhull; bool contains = GeometryEngine.Instance.Contains(poli, pto.ToMapPoint()); resp.Value = contains; return resp; } catch { resp.Value = false; resp.Error.Add("Error al comprobar si punto está contenido en polígono"); return resp; } } /** * Amplía la geometría para añadirele buffer */ public static Respuesta BufferGeom(ArcGIS.Core.Geometry.Geometry geom, double buffer) { Respuesta resp = new Respuesta(); ArcGIS.Core.Geometry.Geometry geomBuff = null; try { geomBuff = GeometryEngine.Instance.Buffer(geom, buffer); } catch { } resp.Value = geomBuff; return resp; } /**Amplía la geometría para que incluya el punto */ public static Respuesta AddPtoInGeom(Coordinate2D pto, ArcGIS.Core.Geometry.Geometry geom) { Respuesta resp = new Respuesta(); double buffer = 0;//m de distancia desde la instalación bool repite = true; ArcGIS.Core.Geometry.Geometry geom_pto, geom_sal; try { do { buffer += 100; geom_pto = GeometryEngine.Instance.Buffer(pto.ToMapPoint(), buffer); if (geom_pto == null || geom_pto.IsEmpty) { resp.Value = null; resp.Error.Add("Error al bufferear punto para incluirlo en polígono"); return resp; } //hace la convex hull, por si no fueran conexas las zonas repite = GeometryEngine.Instance.Disjoint(geom_pto, geom); /*if (geom_aux == null || geom_aux.IsEmpty) { ArcGIS.Core.Geometry.Envelope env1 = geom_sal.Extent; ArcGIS.Core.Geometry.Envelope env2 = geom_pto.Extent; ArcGIS.Core.Geometry.Envelope env3 = env1.Union(env2); geom_sal = (ArcGIS.Core.Geometry.Geometry) env3; //geom_sal = GeometryEngine.Instance.Envelope(geom_sal); if (geom_sal == null || geom_sal.IsEmpty) { resp.Value = null; resp.Error.Add("Error al hacer envolvente en unir punto al polígono"); return resp; } }*/ } while (repite); geom_sal = GeometryEngine.Instance.Union(geom_pto, geom); if (geom_sal == null || geom_sal.IsEmpty) { resp.Value = null; resp.Error.Add("Error al unir punto a polígono"); return resp; } resp.Value = geom_sal; return resp; } catch { resp.Value = null; resp.Error.Add("Error al incluir punto en polígono"); return resp; } } /* * Dada una lista de ids de elemento, crea una consulta en la que se llama a todos esos elementos * campo IN (id1, id2, id3..) */ public static string GetWhereClauseFromIds(List ids) { if (ids.Count <= 0) return string.Empty; string ids_str = "("; bool first = true; foreach (long i in ids) { if (first) { ids_str += i.ToString(); first = false; } else ids_str += "," + i.ToString(); } //el último ids_str += ")"; string whereClause = ObjectId + " IN " + ids_str; //Cambiar id a otro sitio return whereClause; /*string consulta, orstr; consulta = string.Empty; orstr = string.Empty; var n = ids.Count; for (int i = 0; i < n; i++) { consulta = consulta + orstr + "(" + RecogidaDef.campos.cons_id + "=" + ids.ElementAt(i) + ")"; if (String.IsNullOrEmpty(orstr)) orstr = " OR "; } if (consulta == "()") consulta = string.Empty; return consulta;*/ } /** * Elimina las filas indicadas del shp **/ public static bool RemoveRowsFromShp(FeatureClass fc, List quita) { //Crea la consulta var consulta = GetWhereClauseFromIds(quita); if (String.IsNullOrEmpty(consulta)) return false; string message = String.Empty; bool deletionResult = false; var task = ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() => { EditOperation editOperation = new EditOperation(); editOperation.Callback(context => { ArcGIS.Core.Data.QueryFilter openCutFilter = new ArcGIS.Core.Data.QueryFilter { WhereClause = consulta }; using (RowCursor rowCursor = fc.Search(openCutFilter, false)) { while (rowCursor.MoveNext()) { using (Row row = rowCursor.Current) { // In order to update the Map and/or the attribute table. Has to be called before the delete. context.Invalidate(row); row.Delete(); } } } }, fc); try { deletionResult = editOperation.Execute(); if (!deletionResult) { message = editOperation.ErrorMessage; } } catch (GeodatabaseException exObj) { message = exObj.Message; } }); task.Wait(); if (!string.IsNullOrEmpty(message)) { OutStr = message; return false; } else return true; /*FeatureClass fc = HelperGdb.GetFtClassFromShp(shp_path).Result; if (fc == null) return false; //Crea la consulta var consulta = GetWhereClauseFromIds(quita); if (String.IsNullOrEmpty(consulta)) return false; string message = String.Empty; bool deletionResult = false; ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() => { string shpname = System.IO.Path.GetFileNameWithoutExtension(shp_path); var shapeFileConnPath = new FileSystemConnectionPath(new Uri(System.IO.Path.GetDirectoryName(shp_path)), FileSystemDatastoreType.Shapefile); var shapefile = new FileSystemDatastore(shapeFileConnPath); using (Table table = shapefile.OpenDataset(shp_path)) { EditOperation editOperation = new EditOperation(); editOperation.Callback(context => { ArcGIS.Core.Data.QueryFilter openCutFilter = new ArcGIS.Core.Data.QueryFilter { WhereClause = consulta }; using (RowCursor rowCursor = table.Search(openCutFilter, false)) { while (rowCursor.MoveNext()) { using (Row row = rowCursor.Current) { // In order to update the Map and/or the attribute table. Has to be called before the delete. context.Invalidate(row); row.Delete(); } } } }, table); try { deletionResult = editOperation.Execute(); if (!deletionResult) { message = editOperation.ErrorMessage; } } catch (GeodatabaseException exObj) { message = exObj.Message; } } }); if (!string.IsNullOrEmpty(message)) { OutStr = message; return false; } else return true; */ } /** * Recorre los ámbitos lineales del shp viendo qué longitud tienen dentro de la geometría, y si * es menos de un porcentaje, lo quitan del shp **/ public static bool RemoveRowsGeom(string shp_path, ArcGIS.Core.Geometry.Geometry geom_zon, double porc) { FeatureClass fc = HelperGdb.GetFtClassFromShp(shp_path).Result; if (fc == null) return false; ArcGIS.Core.Geometry.Geometry geom = null; ArcGIS.Core.Geometry.Polyline line = null; Feature f = null; double longi_zon = 0, longi_tot = 0; List quita = new List(); int j = 0; List ids; try { //Obtiene los IDs ids = GetIds(fc, null).Result; //Recorre las features de la capa RowCursor cursor = fc.Search(); while (cursor.MoveNext()) { f = (Feature)cursor.Current; geom = f.GetShape(); line = (ArcGIS.Core.Geometry.Polyline)geom; longi_tot = line.Length; geom = IntersectGeom(geom_zon, line, GeometryDimension.esriGeometry1Dimension); line = (ArcGIS.Core.Geometry.Polyline)geom; longi_zon = line.Length;//se consigue la longitud de ámbito (linea) que interseca con el nivel) if ((longi_zon / longi_tot) < porc) { //quita esa línea quita.Add(ids[j]); } j++; Free(f); } Free(f); Free(cursor); //comprueba que no se haya quedado sin ámbitos if (quita.Count >= fc.GetCount()) { OutStr = "No quedan ámbitos que cumplan la geometría seleccionada."; return false; } //Quita los ámbitos del shp if (quita.Count > 0) { //borra las líneas que se han indicado if (!RemoveRowsFromShp(fc, quita)) return false; } Free(fc); return true; } catch (Exception) { return false; } finally { HelperGdb.Free(fc); HelperGdb.Free(f); } } /** * Dado un nombre de capa mira si está abierta y la cierra */ public static bool CloseLayer(string nombCapa) { try { var lyr = MapView.Active.Map.FindLayers(nombCapa).FirstOrDefault() as FeatureLayer; if (lyr!= null) MapView.Active.Map.RemoveLayer(lyr); return true; } catch (Exception ex) { return false; } } /** * Cierra todas las capas abiertas */ public static bool CloseAllLayers() { try { ReadOnlyObservableCollection lyrs= MapView.Active.Map.Layers; while(lyrs.Any()) { var fl = lyrs.FirstOrDefault(); if (fl != null) MapView.Active.Map.RemoveLayer(fl); } return true; } catch (Exception) { return false; } } /** * Saca diálogo para guardar un archivo */ public static string SaveFileDlg(string title_, string initloc_, string ext_, string filt_, BrowseProjectFilter brwsFilt = null) { //Display the filter in an Open Item dialog SaveItemDialog dlg = new SaveItemDialog { Title = title_, OverwritePrompt = true, }; if (!string.IsNullOrEmpty(initloc_)) dlg.InitialLocation = initloc_; else dlg.AlwaysUseInitialLocation = false; if (!string.IsNullOrEmpty(filt_)) dlg.Filter = filt_; if (!string.IsNullOrEmpty(ext_)) dlg.DefaultExt = ext_; if (brwsFilt != null) dlg.BrowseFilter = brwsFilt; bool? ok = dlg.ShowDialog(); if ((ok ?? true) && dlg.FilePath.Length > 0) return dlg.FilePath; else return string.Empty; } /** * Comprueva si una GDB contiene un Dataset */ public static Task CheckDataset(Geodatabase gdb, string datasetName) { return ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run((Func)(() => { try { FeatureDataset ftdst = gdb.OpenDataset(datasetName); ftdst.Dispose(); return true; } catch { return false; } })); } /** * Comprueba si el dataset dado tiene la referencia espacial dada * Devuelve 0 si es la misma, 2 si no es la misma, 1 si ha dado error */ public static Task CheckSpatRefDataset(Geodatabase gdb, string datasetName, ArcGIS.Core.Geometry.SpatialReference spatref) { return ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run((Func)(() => { try { FeatureDatasetDefinition featureDatasetDefinition = gdb.GetDefinition(datasetName); if(featureDatasetDefinition.GetSpatialReference().Equals(spatref)) return 0; return 2; } catch (Exception ex) { return 1; } })); } /** * Crea un FeatureDataset con el nombre dado y la spatialrefernece dada en la gdb dada * Devuelve 0 si no hay que crear nada o si lo ha creado bien, 2 si existe el dataset pero con otra referencia espacial, 1 si da error */ public static Respuesta CreateDataset(string gdbPath, string datasetName, ArcGIS.Core.Geometry.SpatialReference spatref, out string datasetNameOut) { Respuesta res = new Respuesta { Value = 1 }; datasetNameOut = string.Empty; Geodatabase gdb = null; FeatureDatasetDefinition featureDatasetDefinition = null; try { gdb = GetGdb(gdbPath).Result; if (gdb == null) { res.Value = 1; res.Error.Add("Error al abrir la gdb " + gdbPath); return res; } //comprueba si extiste ya el dataset var task1 = CheckDataset(gdb, datasetName); task1.Wait(); if (task1.Result) { //comprueba si tiene la misma referencia espacial var r = CheckSpatRefDataset(gdb, datasetName, spatref).Result; if (r==0) { res.Value = 0; //no hay nada que crear, existe y coincide la spatial ref return res; } else if(r==2) { //crea un nuevo dataset y avisa datasetName = datasetName + "_1"; datasetNameOut = datasetName; } else { //ha dado error al comprobar res.Value = 1; res.Error.Add("Errores al crear el Dataset " + datasetName); return res; } } //no existe, lo crea var task = ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run((Func>)(() => { Respuesta res2 = new Respuesta { Value = false }; SchemaBuilder schemaBuilder = null; try { schemaBuilder = new SchemaBuilder(gdb); // Create a FeatureDataset FeatureDatasetDescription featureDatasetDescription = new FeatureDatasetDescription(datasetName, spatref); schemaBuilder.Create(featureDatasetDescription); // Build status res2.Value = schemaBuilder.Build(); if (!res2.Value && schemaBuilder.ErrorMessages.Count > 0) res2.Error.Add(schemaBuilder.ErrorMessages.FirstOrDefault()); return res2; } catch { if (schemaBuilder != null && schemaBuilder.ErrorMessages.Count > 0) res2.Error.Add(schemaBuilder.ErrorMessages.FirstOrDefault()); else res2.Error.Add("Error 1 al crear Dataset."); return res2; } })); task.Wait(); if (task.Result.Value)//ha ido bien { if (string.IsNullOrEmpty(datasetNameOut)) res.Value = 0; else res.Value = 2;//avisa //actualiza la gdb Refresh(gdbPath); } else// Build errors { res.Value = 1; res.Error.Add(task.Result.Error.FirstOrDefault()); } return res; } catch (Exception ex) { res.Value = 1; res.Error.Add("Errores al crear el Dataset " + datasetName + " " + ex.Message); return res; } finally { Free(featureDatasetDefinition); Free(gdb); } } /** * Importa el shp en la gdb y el dataset, como una featureclass */ public static Respuesta ImportShp(string nom_shp, string Gdb_dataset, string namefc) { var res = new Respuesta { Value = false }; string[] args = { nom_shp, Gdb_dataset, namefc }; // execute the tool try { ArcGIS.Core.Geometry.SpatialReference spatref = GetSpatRef(nom_shp); var environments = Geoprocessing.MakeEnvironmentArray(outputCoordinateSystem: spatref); CancelableProgressorSource cps = new CancelableProgressorSource(); var completa = false; var gpres = Geoprocessing.ExecuteToolAsync("FeatureClassToFeatureClass_conversion", args, environments,cps.CancellationTokenSource.Token, (event_name, o) => // implement delegate and handle events { switch (event_name) { case "OnValidate": // stop execute if any warnings //if ((o as IGPMessage[]).Any(it => it.Type == GPMessageType.Warning)) //_cts.Cancel(); break; case "OnProgressMessage": { string msg = string.Format("{0}: {1}", new object[] { event_name, (string)o }); Debug.WriteLine(msg); ; } break; case "OnProgressPos": { string msg2 = string.Format("{0}: {1} %", new object[] { event_name, (int)o }); Debug.WriteLine(msg2); var av = (int)o; if ((int)o < 0) { completa = true; //System.Windows.MessageBox.Show(msg2); //cps.CancellationTokenSource.Cancel(); } break; } } }); while (!gpres.IsCompleted && gpres.IsCanceled && gpres.IsFaulted && !completa) Thread.Sleep(10); if (gpres.IsCanceled) { return res; } if (gpres.IsFaulted) { var gpResult = gpres.Result; string msg; if (gpResult.ErrorMessages != null) msg = gpResult.ErrorMessages.First().Text; else msg = "Errores en la importación"; res.Error.Add("Error: " + msg); return res; } try { gpres.Dispose(); } catch (Exception e) { string msg = ""; msg = e.Message; } res.Value = true; //actualiza la gdb Refresh(System.IO.Path.GetDirectoryName(Gdb_dataset)); return res; } catch (Exception ex) { res.Error.Add("Error: " + ex.Message); return res; } } /** * Borrar una feature class de un dataset */ public static Respuesta DeleteFeatureClass(string gdbPath, string featureClassPath) { var res = new Respuesta { Value = false }; FeatureClass ftclss = GetFtClass(featureClassPath); if (ftclss == null) return res; Geodatabase gdb = GetGdb(gdbPath).Result; if (gdb == null) return res; var task = ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run((Func>)(() => { Respuesta resp = new Respuesta { Value = false }; SchemaBuilder schemaBuilder = null; try { // Create a FeatureClassDescription object FeatureClassDescription featureClassDescription = new FeatureClassDescription(ftclss.GetDefinition()); // Create a SchemaBuilder object schemaBuilder = new SchemaBuilder(gdb); // Add the deletion fo the feature class to our list of DDL tasks schemaBuilder.Delete(featureClassDescription); // Execute the DDL resp.Value = schemaBuilder.Build(); if (!resp.Value && schemaBuilder.ErrorMessages.Count > 0) resp.Error.Add(schemaBuilder.ErrorMessages.FirstOrDefault()); return resp; } catch { resp.Error.Add(schemaBuilder.ErrorMessages.FirstOrDefault()); return resp; } })); if (task.Result.Value) res.Value = true; else { res.Error.Add(task.Result.Error.FirstOrDefault()); } Free(gdb); Free(ftclss); return res; } /** * Refresca la gdb después de añadir dataset y featureclass */ public static void Refresh(string gdbPath) { Item gdb = null; try { gdb = ItemFactory.Instance.Create(gdbPath); if (gdb == null) return; var contentItem = gdb; //Check if the MCT is required for Refresh() if (contentItem.IsMainThreadRequired) { //QueuedTask.Run must be used if item.IsMainThreadRequired //returns true QueuedTask.Run(() => contentItem.Refresh()); } else { //if item.IsMainThreadRequired returns false, any //thread can be used to invoke Refresh(), though //BackgroundTask is preferred. contentItem.Refresh(); //Or, via BackgroundTask ArcGIS.Core.Threading.Tasks.BackgroundTask.Run(() => contentItem.Refresh(), ArcGIS.Core.Threading.Tasks.BackgroundProgressor.None); } } catch { } } /** * Abre en el mapa la capa seleccionada, con los parámetros seleccionados */ public static bool OpenLayerUniqueValue(string ftclasspath, string campValUniq, bool visible=true) { var mapView = MapView.Active; int indexNumber = mapView.Map.Layers.Count; string ftclassname = System.IO.Path.GetFileNameWithoutExtension(ftclasspath); if (mapView != null)//Check if there is a map { try { System.Uri ftclass_uri = new System.Uri(ftclasspath); //creating uri for the ftclass //mira el tipo de geometría GeometryType tipo = GetGeomType(ftclasspath); if (tipo == GeometryType.Unknown) return false; var task = QueuedTask.Run(() => { Layer layer = null; FeatureLayer selectedLayer = null; try { layer = mapView.Map.FindLayer(ftclass_uri.ToString()); selectedLayer = layer as FeatureLayer; } catch { layer = null; } if (layer == null) { layer = LayerFactory.Instance.CreateLayer(ftclass_uri, mapView.Map, indexNumber, ftclassname); selectedLayer = mapView.GetSelectedLayers()[0] as FeatureLayer; } //Do something with selected layer SetSimpleRendererPoint(selectedLayer, campValUniq, tipo); selectedLayer.SetVisibility(visible); }); task.Wait(); } catch { return false; } } return true; } /* * Crea el renderer para la capa, dado un campo en el que fijarse y una simbología */ internal static void SetSimpleRendererPoint(FeatureLayer featureLayer, string field, GeometryType tipo) { if (featureLayer == null) return; //QueuedTask.Run(() => //{ try { String[] fields = new string[] { field }; //field to be used to retrieve unique values UniqueValueRendererDefinition uniqueValueRendererDef; CIMSymbolReference symbolTemplate=new CIMSymbolReference(); if (tipo == GeometryType.Point)//puntual { CIMPointSymbol pointSym = SymbolFactory.Instance.ConstructPointSymbol( ColorFactory.Instance.GreenRGB, 10.0, SimpleMarkerStyle.Circle); //constructing a point symbol as a template symbol symbolTemplate = pointSym.MakeSymbolReference(); } else if(tipo== GeometryType.Polyline)//lineal { CIMLineSymbol lineSym = SymbolFactory.Instance.ConstructLineSymbol(ColorFactory.Instance.GreenRGB, 3); symbolTemplate = lineSym.MakeSymbolReference(); } //constructing renderer definition for unique value renderer uniqueValueRendererDef = new UniqueValueRendererDefinition(fields, symbolTemplate); //creating a unique value renderer CIMUniqueValueRenderer uniqueValueRenderer = (CIMUniqueValueRenderer)featureLayer.CreateRenderer(uniqueValueRendererDef); //setting the renderer to the feature layer featureLayer.SetRenderer(uniqueValueRenderer); } catch (Exception ex) { } //}); } public static GeometryType GetGeomType(string ftclassName) { FeatureClass ftcl = GetFtClass(ftclassName); GeometryType tipo = GeometryType.Unknown; if (ftcl == null) return tipo ; var task = QueuedTask.Run(() => { tipo = ftcl.GetDefinition().GetShapeType(); }); task.Wait(); Free(ftcl); return tipo; } } }