OliviaAddInPro/Helper/HelperGdb.cs

1346 lines
53 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;
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;
}
//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 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(""));
}
//Display the filter in an Open Item dialog
OpenItemDialog aNewFilter = new OpenItemDialog
{
Title = titulo,
InitialLocation = initialLoc,
MultiSelect = false,
//Set the BrowseFilter property to Pro's Geodatabase filter.
BrowseFilter = filtro
};
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)
{
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;
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;
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;
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 async Task<FeatureClass> GetFtClassFromShp(string pathShp)
{
FeatureClass ftclss = null;
ReiniciaOutStr();
return await ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run((Func<FeatureClass>)(() =>
{
if (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;
}
//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, CancelableProgressorSource cps)
{
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>();
cps.Status = "Aplicando filtro espacial a exportación";
//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
cps.Status = "Exportando datos";
string[] args = { pathLayerIn, outpath, nameShp, whereClause };
// execute the tool
IGPResult gpResult = Geoprocessing.ExecuteToolAsync("FeatureClassToFeatureClass_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 });
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";
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";
//var progSrc = new CancelableProgressorSource();
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;
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;
}
});
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);
}
}
}
}