You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
962 lines
39 KiB
962 lines
39 KiB
using Kingo.DataAnalysis.Model; |
|
using Kingo.ThreadManager; |
|
using OSGeo.OGR; |
|
using System; |
|
using System.Collections.Generic; |
|
using System.Data; |
|
using System.IO; |
|
using System.Linq; |
|
using System.Threading; |
|
|
|
namespace Kingo.DataAnalysis |
|
{ |
|
public delegate void CustomEventHandler(object data, object state); |
|
public delegate void UpdateProgressHandler(string pTaskName, object value); |
|
public delegate void TaskRunCallbackHandler(TaskParameter parm); |
|
public delegate void AnalysisResultSaveToDBHandler(object pResult); |
|
public class KoDataAnalysis |
|
{ |
|
private string DBPath; |
|
public List<AnalysisResultInfo> WriteDBList = new List<AnalysisResultInfo>(); |
|
public bool IsAnalysisComplete = false; |
|
public bool IsWriteComplete = false; |
|
public event CustomEventHandler WriteDBEvent; |
|
/// <summary> |
|
/// 更新进度 |
|
/// </summary> |
|
public UpdateProgressHandler UpdateProgressCallback; |
|
public TaskRunCallbackHandler TaskRunComplateCallback; |
|
public TaskRunCallbackHandler ScreenShotCallback; |
|
public AnalysisResultSaveToDBHandler AnalysisResultSaveToDB; |
|
public static Dictionary<string, ProgressModel> AnalyProgress = new Dictionary<string, ProgressModel>(); |
|
public ThreadManager2 ThreadPool = new ThreadManager2(); |
|
|
|
public string GetTime(DateTime timeA) |
|
{ |
|
//timeA 表示需要计算 |
|
DateTime timeB = DateTime.Now; //获取当前时间 |
|
TimeSpan ts = timeB - timeA; //计算时间差 |
|
string time = ts.TotalSeconds.ToString(); //将时间差转换为秒 |
|
return time; |
|
} |
|
List<string> AllTasks = new List<string>(); |
|
|
|
public string MuitProcessAnalyssis(BaseAnalysisData pCfg) |
|
{ |
|
DateTime StartTime = DateTime.Now; |
|
string resultDBPath = string.Empty; |
|
try |
|
{ |
|
foreach (var TaskData in pCfg.TaskList!) |
|
{ |
|
if (!AnalyProgress.ContainsKey(TaskData.Code)) |
|
AnalyProgress.Add(TaskData.Code, new ProgressModel()); |
|
DBPath = TaskData.SJLJ!; |
|
if (pCfg.Config == null) |
|
{ |
|
pCfg.Message = "分析配置为空!"; |
|
break; |
|
} |
|
if (TaskData == null) |
|
throw new Exception("参数中未指定任务图层!"); |
|
Layer layer = GetLayer(TaskData); |
|
int DataCount = layer.GetFeatureCount(1).ToInt(); |
|
|
|
int subTaskNum = 0; |
|
string relTables = string.Join(",", pCfg.RelDataList.Select(x => x.TCMC)); |
|
//pCfg.RelDataList = GetDataInfo(TaskData.XZQDM, relTables); |
|
foreach (var relData in pCfg.RelDataList!) |
|
{ |
|
if (!relData.SFFX || relData.XZQDM != TaskData.XZQDM) continue; |
|
if (string.IsNullOrWhiteSpace(relData.SJLJ)) |
|
{ |
|
pCfg.Message += "未指定图层【" + relData.TCMC + "】的图层路径!"; |
|
continue; |
|
} |
|
Layer RelLayer = GetLayer(relData); |
|
int count = RelLayer.GetFeatureCount(1).ToInt(); |
|
if (count > 0) |
|
subTaskNum++; |
|
RelLayer.Dispose(); |
|
} |
|
|
|
int TaskCount = (ProcessManager.Instance.MaxThreadNum) / pCfg.TaskList.Length; |
|
if (TaskCount == 0) |
|
{ |
|
TaskCount = 1; |
|
} |
|
int f = (int)DataCount / TaskCount; |
|
int s = (int)DataCount % TaskCount; |
|
int StartIdx = 0; |
|
int EndIdx = f; |
|
//List<CustomThread<MultTaskParameter>> Tasks = new List<CustomThread<MultTaskParameter>>(); |
|
FileInfo file = new FileInfo(TaskData.SJLJ); |
|
resultDBPath = Path.Combine(file.DirectoryName, "Out", file.Name.Replace(file.Extension, "") + "_Out" + ".sqlite"); |
|
if (File.Exists(resultDBPath)) |
|
{ |
|
File.Delete(resultDBPath); |
|
} |
|
for (int i = 0; i < TaskCount; i++) |
|
{ |
|
StartIdx = i * f; |
|
if (i == TaskCount - 1) |
|
{ |
|
f = f + s; |
|
} |
|
EndIdx = f * (i + 1) - 1; |
|
if (EndIdx >= DataCount) |
|
EndIdx = DataCount - 1; |
|
|
|
|
|
MultTaskParameter mParm = new MultTaskParameter(); |
|
mParm.ProcessName = TaskData.Code; |
|
mParm.TaskCode = TaskData.Code; |
|
mParm.TaskName = TaskData.Code + (i + 1); |
|
mParm.TaskStartIdx = StartIdx; |
|
mParm.TaskEndIdx = EndIdx; |
|
mParm.Data = TaskData; |
|
mParm.TaskConfig = pCfg.Config; |
|
mParm.DataPath = TaskData.SJLJ; |
|
mParm.RelTables = string.Join(",", pCfg.RelDataList.Select(x => x.TCMC));//.Aggregate("", (f, s) => f + (s + ",")); |
|
|
|
TaskInfo task = new TaskInfo(); |
|
task.Parameter = mParm; |
|
task.ExeFun = new TaskCallback(ExeGPForProces); |
|
task.ExeComplatFun = new TaskCallback(TaskRunComplate); |
|
|
|
int taskDataNum = EndIdx - StartIdx + 1; |
|
ThreadPool.AddTask(task); |
|
if (AnalyProgress[TaskData.Code].SubProgress == null) |
|
AnalyProgress[TaskData.Code].SubProgress = new List<ProgressModel>(); |
|
if (pCfg.Config.ImgScreen || pCfg.Config.ShpScreen) |
|
{ |
|
AnalyProgress[TaskData.Code].SubProgress!.Add(new ProgressModel() { ProName = mParm.TaskName, Count = taskDataNum * (subTaskNum + 1) }); |
|
} |
|
else |
|
{ |
|
AnalyProgress[TaskData.Code].SubProgress!.Add(new ProgressModel() { ProName = mParm.TaskName, Count = taskDataNum * (subTaskNum + 0) }); |
|
} |
|
} |
|
} |
|
ThreadPool.ExeTask(); |
|
return resultDBPath; |
|
} |
|
catch (Exception ex) |
|
{ |
|
throw ex; |
|
//LogAPI.Debug("分析失败:" + ex.Message); |
|
//LogAPI.Debug(ex); |
|
//return "分析失败:" + ex.Message; |
|
} |
|
finally |
|
{ |
|
//LogAPI.Debug("任务结束……,共耗时:" + GetTime(StartTime) + "秒"); |
|
} |
|
} |
|
|
|
private object TempLock = new object(); |
|
private void TaskRunComplate(TaskParameter pTaskParm) |
|
{ |
|
lock (TempLock) |
|
{ |
|
TaskRunComplateCallback?.Invoke(pTaskParm); |
|
} |
|
} |
|
|
|
string processLock = string.Empty; |
|
public long TaskDataCount = 0; |
|
long NowCount = 0; |
|
private AnalysisConfig mAnalysisCfg = null; |
|
OSGeo.OSR.SpatialReference T_SP = new OSGeo.OSR.SpatialReference(""); |
|
public string DataAnalysis(BaseAnalysisData pCfg, string pTaskName, int pStartIdx = 0, int pEndIdx = -1) |
|
{ |
|
DataSource MemDs = null; |
|
List<Layer> TaskLayers = new List<Layer>(); |
|
DateTime StartTime = DateTime.Now; |
|
try |
|
{ |
|
//DBPath = pCfg.DbPath; |
|
|
|
//if (pCfg.Config == null) |
|
// pCfg.Config = GetAnalysisCfg(""); |
|
mAnalysisCfg = pCfg.Config; |
|
T_SP.ImportFromEPSG(mAnalysisCfg.ShpWKID); |
|
if (mAnalysisCfg.ShpWKID == 4326) |
|
{ |
|
T_SP.SetAxisMappingStrategy(OSGeo.OSR.AxisMappingStrategy.OAMS_TRADITIONAL_GIS_ORDER); |
|
} |
|
DataModel TaskData = pCfg.TaskList.First();//.FirstOrDefault(f => f.IsTaskLayer); |
|
//DataInfo[] SubRelDatas = pCfg.DataList.Where(w => w.IsSubTaskLayer).ToArray(); |
|
DataModel[] RelDatas = pCfg.RelDataList.Where(w => w.SFFX).ToArray(); |
|
//TaskData.SJLJ = DBPath; |
|
|
|
if (TaskData == null) |
|
throw new Exception("参数中未指定任务图层!"); |
|
|
|
|
|
Thread doworkThread = new Thread(new ParameterizedThreadStart(InsertDB)); |
|
doworkThread.IsBackground = true; |
|
doworkThread.Name = "写入数据线程" + Guid.NewGuid().ToString(); |
|
doworkThread.Start(pCfg); |
|
|
|
//List<CustomThread<AnalysisThreadParm2>> ListTasks = new List<CustomThread<AnalysisThreadParm2>>(); |
|
|
|
TaskDataCount = 0; |
|
Layer TaskLayer = GetLayer(TaskData); |
|
long num = 0; |
|
if (pEndIdx > -1) |
|
num = pEndIdx - pStartIdx + 1; |
|
else |
|
num = TaskLayer.GetFeatureCount(1); |
|
TaskLayer.Dispose(); |
|
|
|
foreach (var relData in RelDatas) |
|
{ |
|
if (!relData.SFFX) continue; |
|
RelLayerDataInfo relResultData = new RelLayerDataInfo(); |
|
|
|
Layer RelLayer = GetLayer(relData); |
|
int DataCount = RelLayer.GetFeatureCount(1).ToInt(); |
|
if (DataCount == 0) continue; |
|
|
|
AnalysisThreadParm2 parm = new AnalysisThreadParm2(); |
|
parm.TaskCode = pCfg.Code; |
|
parm.LayerName = TaskData.TCMC; |
|
parm.TaskName = pTaskName; |
|
parm.TaskInfo = TaskData; |
|
parm.TaskStartIdx = pStartIdx; |
|
parm.TaskEndIdx = pEndIdx; |
|
parm.RelInfo = relData; |
|
|
|
TaskInfo task = new TaskInfo(); |
|
task.Parameter = parm; |
|
task.ExeFun = new TaskCallback(AnalysisLayer); |
|
task.ExeComplatFun = new TaskCallback(Callback); |
|
ThreadPool.AddTask(task); |
|
TaskDataCount = TaskDataCount + num; |
|
} |
|
if (pCfg.Config.ShpScreen || pCfg.Config.ImgScreen) |
|
{ |
|
ThreadPool.AddTask(new TaskInfo() |
|
{ |
|
ExeFun = ScreenShot, |
|
ExeComplatFun = Callback, |
|
Parameter = new TaskParameter() { TaskName = pTaskName, Data = pCfg, TaskStartIdx = pStartIdx, TaskEndIdx = pEndIdx } |
|
}); |
|
TaskDataCount = TaskDataCount + num; |
|
} |
|
ThreadPool.ExeTask(); |
|
try |
|
{ |
|
string tempFolder = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Temp"); |
|
DirectoryInfo dir = new DirectoryInfo(tempFolder); |
|
dir.Delete(); |
|
} |
|
catch (Exception ex) |
|
{ |
|
|
|
} |
|
IsAnalysisComplete = true; |
|
while (!IsWriteComplete) |
|
{ |
|
|
|
} |
|
|
|
//LogAPI.Debug("数据分析完成,共耗时:" + GetTime(StartTime) + "秒"); |
|
|
|
return DBPath; |
|
} |
|
catch (Exception ex) |
|
{ |
|
//LogAPI.Debug(ex); |
|
return "分析失败" + ex.Message; |
|
} |
|
finally |
|
{ |
|
MemDs?.Dispose(); |
|
if (TaskLayers != null) |
|
{ |
|
foreach (var item in TaskLayers) |
|
{ |
|
item?.Dispose(); |
|
} |
|
} |
|
} |
|
} |
|
|
|
private void Clear(string OutTempPath) |
|
{ |
|
try |
|
{ |
|
FileInfo tempFile = new FileInfo(OutTempPath); |
|
tempFile.Directory.Parent.Delete(true); |
|
} |
|
catch (Exception ex) |
|
{ |
|
|
|
} |
|
} |
|
|
|
public void SetpProgress(string pTaskName, int pSetp = 1) |
|
{ |
|
NowCount += pSetp; |
|
UpdateProgressCallback?.Invoke(pTaskName, NowCount); |
|
} |
|
public virtual BaseAnalysisData GetDataInfo(string pDataPath, string relLayers) |
|
{ |
|
return new BaseAnalysisData(); |
|
} |
|
|
|
private void ScreenShot(object p) |
|
{ |
|
try |
|
{ |
|
if (!(p is TaskParameter)) return; |
|
TaskParameter taskParm = p as TaskParameter; |
|
BaseAnalysisData pCfg = taskParm.Data as BaseAnalysisData; |
|
if (pCfg == null || pCfg.TaskList == null || pCfg.Config == null) return; |
|
|
|
if (pCfg.Config.ShpScreen || pCfg.Config.ImgScreen) |
|
{ |
|
ScreenShotCallback?.Invoke(taskParm); |
|
} |
|
} |
|
catch (Exception ex) |
|
{ |
|
//LogAPI.Debug(ex); |
|
throw ex; |
|
} |
|
} |
|
private static int TestNum = 0; |
|
public void UpdateProgress(object data) |
|
{ |
|
//lock (key) |
|
//{ |
|
string val = data.ToTrim(); |
|
string[] valArr = val.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries); |
|
if (valArr.Length == 2 && AnalyProgress.Count > 0) |
|
{ |
|
foreach (var item in AnalyProgress.Keys) |
|
{ |
|
var progress = AnalyProgress[item].GetProModel(valArr[0]); |
|
if (progress != null) |
|
{ |
|
progress.Value = valArr[1].ToInt(); |
|
//LogAPI.Debug(AnalyProgress[item].Value + "/" + AnalyProgress[item].Count + "=" + AnalyProgress[item].Percentage); |
|
} |
|
} |
|
} |
|
//} |
|
} |
|
string err = string.Empty; |
|
string key = string.Empty; |
|
public void ExeGPForProces(TaskParameter pTaskParm) |
|
{ |
|
MultTaskParameter parm = pTaskParm as MultTaskParameter; |
|
key = parm.TaskName; |
|
Dictionary<string, string> dicParm = new Dictionary<string, string>(); |
|
dicParm.Add("TaskName", parm.TaskName); |
|
dicParm.Add("DataPath", parm.DataPath); |
|
dicParm.Add("StartIdx", parm.TaskStartIdx.ToTrim()); |
|
dicParm.Add("EndIdx", parm.TaskEndIdx.ToTrim()); |
|
dicParm.Add("OutPath", parm.OutPath); |
|
dicParm.Add("RelLayers", parm.RelTables); |
|
|
|
string strParm2 = System.Text.Json.JsonSerializer.Serialize(dicParm); |
|
|
|
ProcessManager.Instance.WorkerPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "DataAnalysisProcess"); |
|
ProcessManager.Instance.ExeTask(strParm2, UpdateProgress); |
|
return; |
|
} |
|
|
|
|
|
private void GetFieldValue(Feature pFeature, int pFieldIdx, string pFieldSuffix, ref Dictionary<string, object> pResult) |
|
{ |
|
FieldDefn mField = pFeature.GetFieldDefnRef(pFieldIdx); |
|
string fieldName = string.IsNullOrWhiteSpace(pFieldSuffix) ? mField.GetName() : mField.GetName() + "_" + pFieldSuffix; |
|
if (pResult.ContainsKey(fieldName)) |
|
return; |
|
switch (mField.GetFieldType()) |
|
{ |
|
case FieldType.OFTInteger: |
|
case FieldType.OFTIntegerList: |
|
case FieldType.OFTInteger64: |
|
case FieldType.OFTInteger64List: |
|
pResult.Add(fieldName + "|INTEGER", pFeature.GetFieldAsInteger(pFieldIdx)); |
|
//rFieldInfo.Add(fieldName, "INTEGER"); |
|
//lstFieldIndex.Add(fieldName, i); |
|
break; |
|
case FieldType.OFTReal: |
|
case FieldType.OFTRealList: |
|
case FieldType.OFTString: |
|
case FieldType.OFTStringList: |
|
case FieldType.OFTWideString: |
|
case FieldType.OFTWideStringList: |
|
pResult.Add(fieldName + "|TEXT", pFeature.GetFieldAsString(pFieldIdx)); |
|
//rFieldInfo.Add(fieldName, "TEXT"); |
|
//lstFieldIndex.Add(fieldName, i); |
|
break; |
|
case FieldType.OFTBinary: |
|
//pResult.Add(fieldName, pFeature.GetFieldAsString(pFieldIdx)); |
|
//rFieldInfo.Add(fieldName, "BLOB"); |
|
//lstFieldIndex.Add(fieldName, i); |
|
break; |
|
case FieldType.OFTDate: |
|
case FieldType.OFTTime: |
|
case FieldType.OFTDateTime: |
|
pResult.Add(fieldName + "|TEXT", pFeature.GetFieldAsString(pFieldIdx)); |
|
//rFieldInfo.Add(fieldName, "DATE"); |
|
//lstFieldIndex.Add(fieldName, i); |
|
break; |
|
default: |
|
break; |
|
} |
|
mField.Dispose(); |
|
} |
|
|
|
private void AnalysisGeometry(Geometry pGeo, Layer pRelLayer, DataModel pRelData, ref RelLayerDataInfo rResult, bool IsSubTask = false, string strMapCfg = "") |
|
{ |
|
rResult.RelLayerName = pRelData?.TCMC!; |
|
|
|
OSGeo.OSR.SpatialReference tSP = pGeo.GetSpatialReference(); |
|
Layer layer = pRelLayer;// GetLayer(pRelData!); |
|
int wkid = 0; |
|
layer.SetSpatialFilter(null); |
|
layer.ResetReading(); |
|
|
|
int TempWkid = 0; |
|
if (tSP != null) |
|
TempWkid = tSP.GetAttrValue("AUTHORITY", 1).ToInt(); |
|
if (TempWkid != 0 && wkid == 0) |
|
wkid = TempWkid; |
|
Feature firstFeature = null; |
|
Feature f = null; |
|
try |
|
{ |
|
firstFeature = layer.GetNextFeature(); |
|
layer.ResetReading(); |
|
f = null; |
|
layer.SetSpatialFilter(null); |
|
if (layer.GetFeatureCount(0) > 0) |
|
layer.SetSpatialFilter(pGeo); |
|
List<Geometry> ScreenGeoList = new List<Geometry>(); |
|
while ((f = layer.GetNextFeature()) != null) |
|
{ |
|
Geometry resultGeo = null; |
|
Geometry geo = f.GetGeometryRef(); |
|
|
|
resultGeo = pGeo.Intersection(geo); |
|
if (resultGeo.GetGeometryType() != wkbGeometryType.wkbMultiPolygon && resultGeo.GetGeometryType() != wkbGeometryType.wkbPolygon) continue; |
|
double? area = resultGeo?.Area(); |
|
if (area < 5) continue; |
|
int geoCount = resultGeo.GetGeometryCount(); |
|
string strGeo = string.Empty; |
|
if (geoCount > 1 && resultGeo.GetGeometryType() == wkbGeometryType.wkbMultiPolygon) |
|
{ |
|
var tempSP = resultGeo.GetSpatialReference(); |
|
Geometry newGeo = new Geometry(wkbGeometryType.wkbMultiPolygon); |
|
for (int i = 0; i < geoCount; i++) |
|
{ |
|
Geometry tempGeo = resultGeo.GetGeometryRef(i); |
|
double ringArea = tempGeo.GetArea(); |
|
wkbGeometryType geoType = tempGeo.GetGeometryType(); |
|
if (geoType == wkbGeometryType.wkbPolygon) |
|
{ |
|
newGeo.AddGeometry(tempGeo); |
|
} |
|
tempGeo.Dispose(); |
|
} |
|
resultGeo = newGeo; |
|
resultGeo.AssignSpatialReference(tempSP); |
|
area = resultGeo.GetArea(); |
|
//newGeo.Dispose(); |
|
|
|
} |
|
Geometry bufGeo = resultGeo.Buffer(-0.1, 0); |
|
if (bufGeo.GetArea() == 0) |
|
{ |
|
bufGeo = resultGeo.Buffer(0.01, 0); |
|
} |
|
if (bufGeo.GetSpatialReference().IsSame(T_SP, null) == 0) |
|
{ |
|
bufGeo.TransformTo(T_SP); |
|
} |
|
if (resultGeo.GetSpatialReference().IsSame(T_SP, null) == 0) |
|
{ |
|
resultGeo.TransformTo(T_SP); |
|
} |
|
resultGeo.ExportToWkt(out strGeo); |
|
Dictionary<string, object> dicResult = new Dictionary<string, object> |
|
{ |
|
{ "FID_" + pRelData!.TCMC + "|INT", f.GetFID() }, |
|
{$"Area_{pRelData!.TCMC}|NUMERIC",geo.GetArea()}, |
|
}; |
|
if (pRelData!.TCMC!.Contains("Rel")) |
|
{ |
|
dicResult.Clear(); |
|
} |
|
for (int i = 0; i < f.GetFieldCount(); i++) |
|
{ |
|
FieldDefn mField = f.GetFieldDefnRef(i); |
|
if (mField.GetName().ToUpper() == "SHAPE" || mField.GetName().ToUpper() == "AREA") continue; |
|
if (pRelData!.ZD.ToTrim().ToUpper().Contains(mField.GetName().ToUpper()) || pRelData!.ZD == "*" || pRelData!.SX!.ToUpper().Contains(mField.GetName().ToUpper()) || pRelData!.SX == "*") |
|
{ |
|
GetFieldValue(f, i, pRelData!.TCMC.Contains("Rel_") ? "" : pRelData!.TCMC, ref dicResult); |
|
} |
|
mField.Dispose(); |
|
} |
|
dicResult.Add("AREA|NUMERIC", area); |
|
|
|
//if (mAnalysisCfg.ShpWKID == 4326) |
|
// bufGeo.SwapXY(); |
|
|
|
bufGeo.ExportToWkt(out string strWkt); |
|
NetTopologySuite.IO.WKTReader reader = new NetTopologySuite.IO.WKTReader(); |
|
var point = reader.Read(strWkt).InteriorPoint; |
|
|
|
|
|
if (IsSubTask) |
|
{ |
|
OSGeo.OSR.SpatialReference sr = layer.GetSpatialRef(); |
|
var TempWkid2 = ""; |
|
if (sr != null) |
|
TempWkid2 = sr.GetAttrValue("AUTHORITY", 1); |
|
dicResult.Add($"SHAPE|MULTIPOLYGON|{TempWkid2}", resultGeo); |
|
} |
|
else |
|
{ |
|
dicResult.Add("Shape|Text", strGeo); |
|
dicResult.Add("WKID|INT", mAnalysisCfg.ShpWKID); |
|
dicResult.Add("X|NUMERIC", point.X); |
|
dicResult.Add("Y|NUMERIC", point.Y); |
|
dicResult.Add("XZQDM|Text", ""); |
|
} |
|
rResult.RelData.Add(dicResult); |
|
|
|
geo.Dispose(); |
|
resultGeo.Dispose(); |
|
} |
|
if (rResult.RelData.Count == 0) |
|
{ |
|
|
|
Dictionary<string, string> DicField = new Dictionary<string, string>(); |
|
//无相交记录,仅记录字段信息 |
|
Dictionary<string, object> dicResult = new Dictionary<string, object> |
|
{ |
|
{ "FID_" + pRelData!.TCMC + "|INT", null }, |
|
{$"Area_{pRelData!.TCMC}|NUMERIC", null} |
|
}; |
|
if (pRelData!.TCMC!.Contains("Rel")) |
|
{ |
|
dicResult.Clear(); |
|
} |
|
if (firstFeature != null) |
|
{ |
|
for (int i = 0; i < firstFeature.GetFieldCount(); i++) |
|
{ |
|
FieldDefn mField = firstFeature.GetFieldDefnRef(i); |
|
if (mField.GetName().ToUpper() == "AREA") continue; |
|
if (pRelData!.ZD.ToTrim().ToUpper().Contains(mField.GetName().ToUpper()) || pRelData!.ZD == "*" || pRelData!.SX!.ToUpper().Contains(mField.GetName().ToUpper()) || pRelData!.SX == "*") |
|
{ |
|
GetFieldInfo(mField, pRelData!.TCMC.Contains("Rel_") ? "" : pRelData!.TCMC, ref DicField); |
|
} |
|
mField.Dispose(); |
|
} |
|
} |
|
foreach (var item in DicField.Keys) |
|
{ |
|
dicResult.Add(item + "|" + DicField[item], null); |
|
} |
|
dicResult.Add("AREA|NUMERIC", null); |
|
if (IsSubTask) |
|
{ |
|
OSGeo.OSR.SpatialReference sr = layer.GetSpatialRef(); |
|
var TempWkid2 = ""; |
|
if (sr != null) |
|
TempWkid2 = sr.GetAttrValue("AUTHORITY", 1); |
|
dicResult.Add($"SHAPE|MULTIPOLYGON|{TempWkid2}", null); |
|
} |
|
else |
|
{ |
|
dicResult.Add("Shape|Text", ""); |
|
dicResult.Add("WKID|INT", 0); |
|
dicResult.Add("X|NUMERIC", 0); |
|
dicResult.Add("Y|NUMERIC", 0); |
|
dicResult.Add("XZQDM|Text", ""); |
|
} |
|
rResult.RelData.Add(dicResult); |
|
} |
|
} |
|
catch (Exception ex) |
|
{ |
|
return; |
|
throw ex; |
|
} |
|
finally |
|
{ |
|
firstFeature?.Dispose(); |
|
f?.Dispose(); |
|
} |
|
|
|
|
|
} |
|
|
|
Stream outputStream = Console.OpenStandardOutput(); |
|
object mLock = new object(); |
|
//Layer pTaskLayer = new Layer(); |
|
private void AnalysisLayer(object parm) |
|
{ |
|
DataSource memDs = null; |
|
Layer RelLayer = null; |
|
try |
|
{ |
|
if (!(parm is AnalysisThreadParm2)) |
|
return; |
|
AnalysisThreadParm2 AnalyParm = parm as AnalysisThreadParm2; |
|
Layer pTaskLayer = GetLayer(AnalyParm.TaskInfo); |
|
string TaskName = pTaskLayer.GetName(); |
|
DataModel pTaskInfo = AnalyParm.TaskInfo; |
|
DataModel pRelData = AnalyParm.RelInfo; |
|
Feature TaskFet = null; |
|
List<AnalysisResultInfo> result = new List<AnalysisResultInfo>(); |
|
|
|
Layer tempLayer = GetLayer(pRelData); |
|
|
|
OSGeo.OSR.SpatialReference spatialreference = tempLayer.GetSpatialRef(); |
|
string taskName = AnalyParm.TaskName; |
|
if (AnalyParm.SubTask != null) |
|
{ |
|
lock (mLock) |
|
{ |
|
taskName = AnalyParm.SubTask.TaskName; |
|
memDs = CreateMemoryLayer(tempLayer, out RelLayer, AnalyParm.SubTask.TaskStartIdx, AnalyParm.SubTask.TaskEndIdx, taskName); |
|
} |
|
} |
|
else |
|
{ |
|
RelLayer = tempLayer; |
|
} |
|
|
|
if (RelLayer.GetFeatureCount(1) == 0) |
|
return; |
|
//LogAPI.Debug(taskName + "--开始……"); |
|
//LogAPI.Debug(pTaskLayer.GetFeatureCount(1).ToTrim()); |
|
int idx = -1; |
|
while ((TaskFet = pTaskLayer.GetNextFeature()) != null) |
|
{ |
|
idx++; |
|
if (idx < AnalyParm.TaskStartIdx) |
|
{ |
|
continue; |
|
} |
|
if (idx > AnalyParm.TaskEndIdx) |
|
{ |
|
break; |
|
} |
|
SetpProgress(AnalyParm.TaskName); |
|
|
|
string tbbh = TaskFet.GetFieldAsString(pTaskInfo.ZD.Split(',')[0]); |
|
AnalysisResultInfo ResultItem = new AnalysisResultInfo(); |
|
ResultItem.TaskLayerName = pTaskInfo.TCMC!; |
|
Dictionary<string, object> dicResult = new Dictionary<string, object>(); |
|
|
|
dicResult.Add($"FID_{pTaskInfo.TCMC}|INT", TaskFet.GetFID()); |
|
for (int i = 0; i < TaskFet.GetFieldCount(); i++) |
|
{ |
|
FieldDefn mField = TaskFet.GetFieldDefnRef(i); |
|
if (mField.GetName().ToUpper() == "SHAPE") continue; |
|
if (pTaskInfo.ZD!.ToUpper().Contains(mField.GetName().ToUpper()) || pTaskInfo.ZD == "*" || pTaskInfo.SX!.ToUpper().Contains(mField.GetName().ToUpper()) || pTaskInfo.SX == "*") |
|
{ |
|
GetFieldValue(TaskFet, i, pTaskInfo?.TCMC, ref dicResult); |
|
} |
|
mField.Dispose(); |
|
} |
|
Geometry geometry = TaskFet.GetGeometryRef(); |
|
dicResult.Add($"Area_{pTaskInfo.TCMC!}|NUMERIC", geometry.Area()); |
|
ResultItem.TaskData = dicResult; |
|
|
|
|
|
RelLayerDataInfo relResultData = new RelLayerDataInfo(); |
|
|
|
|
|
if (geometry.GetSpatialReference().IsSame(spatialreference, null) == 0) |
|
geometry.TransformTo(spatialreference); |
|
|
|
AnalysisGeometry(geometry, RelLayer, pRelData, ref relResultData); |
|
|
|
ResultItem.RelLayerData.Add(relResultData); |
|
result.Add(ResultItem); |
|
if (result.Count > 500) |
|
{ |
|
lock (WriteDBList) |
|
{ |
|
WriteDBList.AddRange(result); |
|
} |
|
result.Clear(); |
|
} |
|
geometry.Dispose(); |
|
TaskFet.Dispose(); |
|
} |
|
if (result.Count > 0) |
|
{ |
|
lock (WriteDBList) |
|
{ |
|
WriteDBList.AddRange(result); |
|
} |
|
result.Clear(); |
|
} |
|
|
|
//LogAPI.Debug(taskName + "结束,剩余:" + ThreadManager2.Instance.ActiveCount); |
|
TaskFet?.Dispose(); |
|
pTaskLayer?.Dispose(); |
|
} |
|
catch (Exception ex) |
|
{ |
|
throw ex; |
|
} |
|
finally |
|
{ |
|
RelLayer?.Dispose(); |
|
memDs?.Dispose(); |
|
} |
|
} |
|
private void GetFieldInfo(FieldDefn pFieldDefn, string pFieldPrefix, ref Dictionary<string, string> rFieldInfo) |
|
{ |
|
string fieldName = string.IsNullOrWhiteSpace(pFieldPrefix) ? pFieldDefn.GetName() : pFieldDefn.GetName() + "_" + pFieldPrefix; |
|
if (rFieldInfo.ContainsKey(fieldName)) |
|
return; |
|
switch (pFieldDefn.GetFieldType()) |
|
{ |
|
case FieldType.OFTInteger: |
|
case FieldType.OFTIntegerList: |
|
case FieldType.OFTInteger64: |
|
case FieldType.OFTInteger64List: |
|
rFieldInfo.Add(fieldName, "INTEGER"); |
|
//lstFieldIndex.Add(fieldName, i); |
|
break; |
|
case FieldType.OFTReal: |
|
case FieldType.OFTRealList: |
|
rFieldInfo.Add(fieldName, "REAL"); |
|
//lstFieldIndex.Add(fieldName, i); |
|
break; |
|
case FieldType.OFTString: |
|
case FieldType.OFTStringList: |
|
case FieldType.OFTWideString: |
|
case FieldType.OFTWideStringList: |
|
rFieldInfo.Add(fieldName, "TEXT"); |
|
//lstFieldIndex.Add(fieldName, i); |
|
break; |
|
case FieldType.OFTBinary: |
|
rFieldInfo.Add(fieldName, "BLOB"); |
|
//lstFieldIndex.Add(fieldName, i); |
|
break; |
|
case FieldType.OFTDate: |
|
case FieldType.OFTTime: |
|
case FieldType.OFTDateTime: |
|
rFieldInfo.Add(fieldName, "DATE"); |
|
//lstFieldIndex.Add(fieldName, i); |
|
break; |
|
default: |
|
break; |
|
} |
|
} |
|
public Layer GetLayer(DataModel pData, bool IsUpdate = false) |
|
{ |
|
Layer result = null; |
|
if (pData == null) return result; |
|
DataSource ds = null; |
|
Layer lay = null; |
|
try |
|
{ |
|
ds = Ogr.Open(string.IsNullOrWhiteSpace(pData.SJLJ) ? DBPath : pData.SJLJ, IsUpdate ? 1 : 0); |
|
if (ds == null) |
|
{ |
|
pData.Message = "数据分析失败,打开数据库异常!"; |
|
} |
|
for (int i = 0; i < ds?.GetLayerCount(); i++) |
|
{ |
|
lay = ds.GetLayerByIndex(i); |
|
if (lay.GetName() == pData.TCMC || lay.GetNameEx() == pData.TCMC || pData.SJLJ.ToLower().EndsWith(".shp")) |
|
{ |
|
result = lay; |
|
return result; |
|
} |
|
} |
|
result = ds.GetLayerByName(pData.TCMC); |
|
|
|
if (result == null) |
|
{ |
|
pData.Message = "数据分析失败,打开图层失败!"; |
|
} |
|
} |
|
catch (Exception ex) |
|
{ |
|
pData.Message = ex.Message; |
|
} |
|
finally |
|
{ |
|
} |
|
return result; |
|
} |
|
|
|
private DataSource CreateMemoryLayer(Layer pLyr, out Layer MemLayer, int pStartIdx = 0, int pEndIdx = -1, string MemLayerName = "MemoLay", string MemDSName = "MemTaskDS") |
|
{ |
|
OSGeo.OGR.Driver memDriver = Ogr.GetDriverByName("Memory"); |
|
DataSource memDs = memDriver.CreateDataSource(MemDSName, null); |
|
|
|
//MemLayers = new List<Layer>(); |
|
|
|
long FeatureCount = pLyr.GetFeatureCount(0); |
|
if (pEndIdx == -1) |
|
pEndIdx = FeatureCount.ToInt(); |
|
//int f = (int)FeatureCount / Count; |
|
//int s = (int)FeatureCount % Count; |
|
int j = 0; |
|
//for (int i = 0; i < Count; i++) |
|
//{ |
|
// if (i == Count - 1) |
|
// { |
|
// f = f + s; |
|
// } |
|
string memLayerName = MemLayerName; |
|
MemLayer = memDs.CreateLayer(memLayerName, pLyr.GetSpatialRef(), pLyr.GetGeomType(), null); |
|
|
|
FeatureDefn featureDefn = pLyr.GetLayerDefn(); |
|
Feature feature = null; |
|
while ((feature = pLyr.GetNextFeature()) != null) |
|
{ |
|
if (j < pStartIdx) |
|
{ |
|
j++; |
|
continue; |
|
} |
|
if (j > pEndIdx) |
|
{ |
|
j++; |
|
break; |
|
} |
|
//if (j < f * (i + 1) - 1) |
|
//{ |
|
Feature memFeature = new Feature(featureDefn); |
|
memFeature.SetFrom(feature, 1); |
|
|
|
MemLayer.CreateFeature(memFeature); |
|
memFeature.Dispose(); |
|
feature.Dispose(); |
|
//} |
|
//else |
|
//{ |
|
// Feature memFeature = new Feature(featureDefn); |
|
// memFeature.SetFrom(feature, 1); |
|
|
|
// MemLayer.CreateFeature(memFeature); |
|
// memFeature.Dispose(); |
|
// feature.Dispose(); |
|
// j++; |
|
// break; |
|
//} |
|
j++; |
|
} |
|
//for (int j = f * i; j < pLyr.GetFeatureCount(0) && j < f * (i + 1); j++) |
|
//{ |
|
// Feature feature = pLyr.GetFeature(j); |
|
// if (feature == null) |
|
// { |
|
// continue; |
|
// } |
|
|
|
// Feature memFeature = new Feature(featureDefn); |
|
// memFeature.SetFrom(feature, 1); |
|
|
|
// memLayer.CreateFeature(memFeature); |
|
// memFeature.Dispose(); |
|
// feature.Dispose(); |
|
//} |
|
// MemLayers.Add(memLayer); |
|
//} |
|
return memDs; |
|
|
|
} |
|
|
|
private void InsertDB(object pOutDB) |
|
{ |
|
try |
|
{ |
|
AnalysisResultSaveToDB?.Invoke(pOutDB); |
|
} |
|
catch (Exception ex) |
|
{ |
|
//LogAPI.Debug("写入数据处理程序创建失败:" + ex.Message); |
|
} |
|
finally |
|
{ |
|
|
|
} |
|
} |
|
|
|
|
|
private void Callback(TaskParameter pData) |
|
{ |
|
//线程执行完,数据写入数据库,注意并发问题 |
|
|
|
//AnalysisThreadParm2 AnalyParm = pData as AnalysisThreadParm2; |
|
//if (pData != null) |
|
//{ |
|
// Layer pTaskLayer = pData.TaskLayer; |
|
// LogAPI.Debug(pTaskLayer.GetName() + "结束"); |
|
//} |
|
} |
|
} |
|
class AnalysisThreadParm2 : TaskParameter |
|
{ |
|
//public string Code { get; set; } |
|
public string LayerName { get; set; } |
|
public DataModel TaskInfo { get; set; } |
|
public DataModel RelInfo { get; set; } |
|
public string MaxCountLayerName { get; set; } |
|
} |
|
class AnalysisThreadParm |
|
{ |
|
public DataModel[]? TaskDatas { get; set; } |
|
public DataModel[]? AnalysisDatas { get; set; } |
|
public object Data { get; set; } |
|
} |
|
public class AnalysisResultInfo |
|
{ |
|
public AnalysisResultInfo() |
|
{ |
|
TaskData = new Dictionary<string, object>(); |
|
RelLayerData = new List<RelLayerDataInfo>(); |
|
ScreenImgs = new List<BaseImageInfo>(); |
|
} |
|
public string TaskLayerName { get; set; } |
|
public string RelLayerName { get; set; } |
|
public Dictionary<string, object> TaskData { get; set; } |
|
public List<RelLayerDataInfo> RelLayerData { get; set; } |
|
public List<BaseImageInfo> ScreenImgs { get; set; } |
|
} |
|
public class RelLayerDataInfo |
|
{ |
|
public RelLayerDataInfo() |
|
{ |
|
RelData = new List<Dictionary<string, object>>(); |
|
} |
|
public string RelLayerName { get; set; } |
|
public BaseImageInfo ScreenImg { get; set; } |
|
public List<Dictionary<string, object>> RelData { get; set; } |
|
|
|
} |
|
public class BaseImageInfo |
|
{ |
|
public string TBBH { get; set; } |
|
public string Extend { get; set; } |
|
public int Width { get; set; } |
|
public int Height { get; set; } |
|
|
|
public byte[] Data { get; set; } |
|
public string PicFormat { get; set; } |
|
public string DataType { get; set; } |
|
public string DataName { get; set; } |
|
public int WKID { get; set; } |
|
} |
|
}
|
|
|