1825 lines
70 KiB
C#
1825 lines
70 KiB
C#
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;
|
|
|
|
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(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
|
|
{
|
|
|
|
}
|
|
});
|
|
task.Wait();
|
|
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<FeatureClassDefinition>(dataset);
|
|
spatref = fcdef.GetSpatialReference();
|
|
}
|
|
catch
|
|
{
|
|
|
|
}
|
|
});
|
|
task.Wait();
|
|
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<Geodatabase> GetGdb(string pathGdb)
|
|
{
|
|
Geodatabase fileGeodatabase = null;
|
|
if (string.IsNullOrEmpty(pathGdb))
|
|
return null;
|
|
ReiniciaOutStr();
|
|
return ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run((Func<Geodatabase>)(() =>
|
|
{
|
|
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 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 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<FeatureClass> GetFtClass(string nameFtclss, Geodatabase gdb)
|
|
{
|
|
FeatureClass ftclss = null;
|
|
if (string.IsNullOrEmpty(nameFtclss))
|
|
return null;
|
|
ReiniciaOutStr();
|
|
return ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run((Func<FeatureClass>)(() =>
|
|
{
|
|
try
|
|
{
|
|
ftclss = gdb.OpenDataset<FeatureClass>(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<FeatureClass> GetFtClassFromShp(string pathShp)
|
|
{
|
|
FeatureClass ftclss = null;
|
|
ReiniciaOutStr();
|
|
return ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run((Func<FeatureClass>)(() =>
|
|
{
|
|
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<FeatureClass>(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 Task<ArcGIS.Core.Data.Field> GetFieldByName(FeatureClass ftClss, string fieldName)
|
|
{
|
|
FeatureClassDefinition ftcldef = ftClss.GetDefinition();
|
|
ReiniciaOutStr();
|
|
ArcGIS.Core.Data.Field field = null;
|
|
return ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run((Func<ArcGIS.Core.Data.Field>)(() =>
|
|
{
|
|
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<List<long>> GetIds(FeatureClass fc, ArcGIS.Core.Data.QueryFilter filt)
|
|
{
|
|
ReiniciaOutStr();
|
|
List<long> ids = new List<long>();
|
|
Selection sel = null;
|
|
return ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run((Func<List<long>>)(() =>
|
|
{
|
|
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<long> 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<ObservableCollection<string>> GetFields(FeatureClass fc)
|
|
{
|
|
FeatureClassDefinition ftcldef = null;
|
|
IReadOnlyList<ArcGIS.Core.Data.Field> fields = null;
|
|
ReiniciaOutStr();
|
|
ObservableCollection<string> fields_st = new ObservableCollection<string>();
|
|
return ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run((Func<ObservableCollection<string>>)(() =>
|
|
{
|
|
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<string> fields = GetFields(fc).Result;
|
|
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<string> 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);
|
|
}
|
|
}
|
|
|
|
|
|
//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<ObservableCollection<string>> 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 Task<ObservableCollection<string>> GetFieldVals(FeatureClass fc, string fieldName, bool uniquevals)
|
|
{
|
|
ObservableCollection<string> attribs_st = new ObservableCollection<string>();
|
|
ReiniciaOutStr();
|
|
return ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run((Func<ObservableCollection<string>>)(() =>
|
|
{
|
|
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<ArcGIS.Core.Geometry.Geometry> GetGeomConvexHull(FeatureClass fclss, ArcGIS.Core.Data.QueryFilter filter)
|
|
{
|
|
ArcGIS.Core.Geometry.Geometry geomIni = null;
|
|
|
|
return ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run((Func<ArcGIS.Core.Geometry.Geometry>)(() =>
|
|
{
|
|
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<ArcGIS.Core.Geometry.Geometry>();
|
|
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<ArcGIS.Core.Geometry.Geometry> GetGeomSel(FeatureClass fclss, string fieldName, ObservableCollection<string> 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<ArcGIS.Core.Geometry.Geometry>)(() =>
|
|
{
|
|
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<string> GetUniqueVals(string capa, string campo)
|
|
{
|
|
ObservableCollection<string> 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>()
|
|
{ ArcGIS.Core.Data.StatisticsFunction.Count });
|
|
|
|
// Create TableStatisticsDescription
|
|
TableStatisticsDescription tableStatisticsDescription = new TableStatisticsDescription(new List<StatisticsDescription>() { uniqStatDesc });
|
|
tableStatisticsDescription.GroupBy = new List<ArcGIS.Core.Data.Field>() { fld };
|
|
tableStatisticsDescription.OrderBy = new List<SortDescription>() { new SortDescription(fld) };
|
|
|
|
// Calculate Statistics
|
|
IReadOnlyList<TableStatisticsResult> statisticsResults = ftclass.CalculateStatistics(tableStatisticsDescription);
|
|
TableStatisticsResult statRes = statisticsResults.ElementAt(0); //solo hay 1 grupo
|
|
|
|
// Code to process results goes here...
|
|
uniqueVals = new ObservableCollection<string>();
|
|
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<int> GetNumElems(FeatureClass fc, string consulta = "")
|
|
{
|
|
int n = -1;
|
|
ReiniciaOutStr();
|
|
return ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run((Func<int>)(() =>
|
|
{
|
|
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;
|
|
}
|
|
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 = GetFtClass(pathLayerIn);
|
|
if (fc == null)
|
|
{
|
|
OutStr = "Error al abrir Feature Class en exportación";
|
|
return false;
|
|
}
|
|
List<long> ids = new List<long>();
|
|
|
|
//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<bool> IsPtoInGeom(Coordinate2D pto, ArcGIS.Core.Geometry.Geometry geom)
|
|
{
|
|
Respuesta<bool> resp = new Respuesta<bool>();
|
|
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<ArcGIS.Core.Geometry.Geometry> BufferGeom(ArcGIS.Core.Geometry.Geometry geom, double buffer)
|
|
{
|
|
Respuesta<ArcGIS.Core.Geometry.Geometry> resp = new Respuesta<ArcGIS.Core.Geometry.Geometry>();
|
|
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<ArcGIS.Core.Geometry.Geometry> AddPtoInGeom(Coordinate2D pto, ArcGIS.Core.Geometry.Geometry geom)
|
|
{
|
|
Respuesta<ArcGIS.Core.Geometry.Geometry> resp = new Respuesta<ArcGIS.Core.Geometry.Geometry>();
|
|
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<long> 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<long> 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<Table>(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<long> quita = new List<long>();
|
|
|
|
int j = 0;
|
|
List<long> 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)
|
|
return false;
|
|
MapView.Active.Map.RemoveLayer(lyr);
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Cierra todas las capas abiertas
|
|
*/
|
|
public static bool CloseAllLayers()
|
|
{
|
|
try
|
|
{
|
|
var lyrs = MapView.Active.Map.Layers;
|
|
foreach (FeatureLayer fl in lyrs)
|
|
{
|
|
if (fl != null)
|
|
MapView.Active.Map.RemoveLayer(fl);
|
|
}
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
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<bool> CheckDataset(Geodatabase gdb, string datasetName)
|
|
{
|
|
|
|
return ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run((Func<bool>)(() =>
|
|
{
|
|
try
|
|
{
|
|
FeatureClass ftclss = gdb.OpenDataset<FeatureClass>(datasetName);
|
|
ftclss.Dispose();
|
|
return true;
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
}));
|
|
}
|
|
|
|
/**
|
|
* 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<int> CreateDataset(string gdbPath, string datasetName, ArcGIS.Core.Geometry.SpatialReference spatref, out string datasetNameOut)
|
|
{
|
|
Respuesta<int> res = new Respuesta<int> { 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
|
|
if (CheckDataset(gdb, datasetName).Result)
|
|
{
|
|
//comprueba si tiene la misma referencia espacial
|
|
featureDatasetDefinition = gdb.GetDefinition<FeatureDatasetDefinition>(datasetName);
|
|
if (featureDatasetDefinition.GetSpatialReference().Equals(spatref))
|
|
{
|
|
res.Value = 0; //no hay nada que crear, existe y coincide la spatial ref
|
|
return res;
|
|
}
|
|
else
|
|
{
|
|
//crea un nuevo dataset y avisa
|
|
datasetName = datasetName + "_1";
|
|
datasetNameOut = datasetName;
|
|
}
|
|
}
|
|
//no existe, lo crea
|
|
var task = ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run((Func<Respuesta<bool>>)(() =>
|
|
{
|
|
Respuesta<bool> res2 = new Respuesta<bool> { 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<bool> ImportShp(string nom_shp, string Gdb_dataset, string namefc)
|
|
{
|
|
var res = new Respuesta<bool> { Value = false };
|
|
string[] args = { nom_shp, Gdb_dataset, namefc };
|
|
// execute the tool
|
|
FeatureClass fc = GetFtClassFromShp(nom_shp).Result;
|
|
if (fc == null)
|
|
return res;
|
|
|
|
try
|
|
{
|
|
ArcGIS.Core.Geometry.SpatialReference spatref = GetSpatRef(fc);
|
|
var environments = Geoprocessing.MakeEnvironmentArray(outputCoordinateSystem: spatref);
|
|
IGPResult gpResult = Geoprocessing.ExecuteToolAsync("FeatureClassToFeatureClass_conversion", args, environments).Result;
|
|
if (gpResult.IsCanceled)
|
|
{
|
|
return res;
|
|
}
|
|
if (gpResult.IsFailed)
|
|
{
|
|
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;
|
|
}
|
|
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;
|
|
}
|
|
finally
|
|
{
|
|
Free(fc);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Borrar una feature class de un dataset
|
|
*/
|
|
public static Respuesta<bool> DeleteFeatureClass(string gdbPath, string featureClassPath)
|
|
{
|
|
var res = new Respuesta<bool> { 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<bool>>)(() =>
|
|
{
|
|
Respuesta<bool> resp = new Respuesta<bool> { 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 OpenLayer(string ftclasspath, string campValUniq, bool visible)
|
|
{
|
|
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
|
|
{
|
|
System.Uri ftclass_uri = new System.Uri(ftclasspath); //creating uri for the ftclass
|
|
QueuedTask.Run(() =>
|
|
{
|
|
Layer layer = LayerFactory.Instance.CreateLayer(ftclass_uri, mapView.Map, indexNumber, ftclassname);
|
|
var selectedLayer = mapView.GetSelectedLayers()[0] as FeatureLayer;
|
|
//Do something with selected layer
|
|
selectedLayer.SetVisibility(visible);
|
|
});
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
}
|