年度变更建库软件5.0版本
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.

762 lines
30 KiB

6 months ago
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Geometry;
using KGIS.Framework.Maps;
using KGIS.Framework.Platform;
using KGIS.Framework.Platform.Helper;
using KGIS.Framework.Utils;
using KGIS.Framework.Utils.Helper;
using Kingo.PluginServiceInterface;
using KUI.Windows;
using System;
using System.Collections.Generic;
namespace Kingo.Plugin.EngineEditor.Common
{
public class VerificationOfFeatureNodeDensity : IVerificationOfFeatureNodeDensity
{
readonly double MinLength = 0.2;
readonly double MaxDensityLength = 70;
readonly double MinDensityLength = 1;
List<BatchNodeInformation> batches = new List<BatchNodeInformation>();
List<IGeometry> retGeo = new List<IGeometry>();
Dictionary<int, IGeometry> dic = new Dictionary<int, IGeometry>();
double addOrDelete = 0;
private IHookHelper m_hookHelper;
private IMapService _MapService;
public VerificationOfFeatureNodeDensity(IHookHelper hookHelper)
{
try
{
m_hookHelper = hookHelper;
if (MapsManager.Instance != null)
_MapService = MapsManager.Instance.MapService;
}
catch (Exception ex)
{
LogAPI.Debug(ex);
}
}
public VerificationOfFeatureNodeDensity()
{
}
public Dictionary<int, IGeometry> Verification(IGeometry[] geometries)
{
dic.Clear();
try
{
for (int i = 0; i < geometries.Length; i++)
{
batches.Clear();
DrawAndShow(geometries[i]);
if (VerificationDensity(geometries[i]))
{
System.Windows.Forms.DialogResult result =
MessageHelper.ShowYesNoAndError("检测到存在节点密度小于1米或者大于70米的情况!是否自动优化");
if (result == System.Windows.Forms.DialogResult.No || result == System.Windows.Forms.DialogResult.Cancel)
{
continue;
}
else if (batches[0].MaxDensity == true)
{
ProgressHelper.ShowProcessBar("密度大于70米,正在为图形加点.....");
geometries[i] = AddPointDensity(geometries[i], 70, ref addOrDelete);
dic.Add(i, geometries[i]);
}
else if (batches[0].MinDensity == true)
{
ProgressHelper.ShowProcessBar("密度小于1米,正在处理……");
geometries[i] = DeletePointDensity(geometries[i], 1, ref addOrDelete);
dic.Add(i, geometries[i]);
}
}
batches.Clear();
if (VerificationMinLine(geometries[i]))
{
System.Windows.Forms.DialogResult result =
MessageHelper.ShowYesNoAndError(string.Format("检测到存在线段小于{0}的线段!是否自动优化", MinLength));
if (result == System.Windows.Forms.DialogResult.No || result == System.Windows.Forms.DialogResult.Cancel)
{
continue;
}
else
{
ProgressHelper.ShowProcessBar("正在处理过小线段……");
geometries[i] = DeletePointByMinLength(geometries[i]);
}
if (dic.ContainsKey(i))
{
dic[i] = geometries[i];
}
else
dic.Add(i, geometries[i]);
}
}
}
catch (Exception ex)
{
LogAPI.Debug(ex);
}
finally
{
//替换Env改动
//Env.Instance.KMap.HookHelper.ActiveView.GraphicsContainer.DeleteAllElements();
m_hookHelper.ActiveView.GraphicsContainer.DeleteAllElements();
ProgressHelper.CloseProcessBar();
}
return dic;
}
public IGeometry Verification(IGeometry geometries)
{
try
{
////替换Env改动
//if (!Env.Instance.IsSTWZJD)//是否自动检测图斑密度
//{
// return geometries;
//}
batches.Clear();
if (VerificationDensity(geometries))
{
DrawAndShow(geometries);
System.Windows.Forms.DialogResult result = MessageHelper.ShowYesNoAndError("检测到存在节点密度小于1米或者大于70米的情况!是否自动优化");
if (result == System.Windows.Forms.DialogResult.No || result == System.Windows.Forms.DialogResult.Cancel)
{
return geometries;
}
else if (batches[0].MaxDensity == true)
{
ProgressHelper.ShowProcessBar("密度大于70米,正在为图形加点.....");
geometries = AddPointDensity(geometries, 70, ref addOrDelete);
}
else if (batches[0].MinDensity == true)
{
addOrDelete = 0;
ProgressHelper.ShowProcessBar("密度小于1米,正在处理……");
geometries = DeletePointDensity(geometries, 1, ref addOrDelete);
}
}
batches.Clear();
if (!VerificationMinLine(geometries))
{
DrawAndShow(geometries);
System.Windows.Forms.DialogResult result = MessageHelper.ShowYesNoAndError(string.Format("检测到存在线段小于{0}的线段!是否自动优化", MinLength));
if (result == System.Windows.Forms.DialogResult.No || result == System.Windows.Forms.DialogResult.Cancel)
{
return geometries;
}
else
{
ProgressHelper.ShowProcessBar("正在处理过小线段……");
geometries = DeletePointByMinLength(geometries);
}
}
return geometries;
}
catch (Exception ex)
{
LogAPI.Debug(ex);
}
finally
{
//清除选择的红框
//替换Env改动
//Env.Instance.KMap.HookHelper.ActiveView.GraphicsContainer.DeleteAllElements();
m_hookHelper.ActiveView.GraphicsContainer.DeleteAllElements();
ProgressHelper.CloseProcessBar();
}
return geometries;
}
public IGeometry RepairGeometry(IGeometry geometries)
{
try
{
batches.Clear();
if (VerificationDensity(geometries))
{
if (batches[0].MaxDensity == true)
{
this.ShowLoading("密度大于70米,正在为图形加点.......", 0, 0);
geometries = AddPointDensity(geometries, 70, ref addOrDelete);
}
else if (batches[0].MinDensity == true)
{
addOrDelete = 0;
this.ShowLoading("密度小于1米,正在处理.......", 0, 0);
geometries = DeletePointDensity(geometries, 1, ref addOrDelete);
}
}
batches.Clear();
return geometries;
}
catch (Exception ex)
{
this.CloseLoading();
LogAPI.Debug(ex);
}
finally
{
this.CloseLoading();
}
return geometries;
}
public void DrawAndShow(IGeometry geometry, bool isClear = true)
{
if (_MapService != null)
{
_MapService.DrawGraph(geometry);
_MapService.Zoom(geometry);
if (isClear)
{
//替换Env改动
//CommonAPI.ClearFeatureSelection(Env.Instance.KMap.HookHelper.Hook as IMapControlDefault);
_MapService.ClearFeatureSelection(m_hookHelper.Hook as IMapControlDefault);
}
//替换Env改动
//Env.Instance.KMap.HookHelper.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, null);
m_hookHelper.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, null);
}
}
public IGeometry DeletePointByMinLength(IGeometry geometry)
{
ISegmentCollection segmentCollection = geometry as ISegmentCollection;
IPolyline polyline = null;
IPoint pointCurr = null;
IPoint pointBefore = null;
IPoint pointAfter = null;
int lineIndex = 0;
IGeometry retgeometry = geometry;
try
{
foreach (BatchNodeInformation item in batches)
{
try
{
lineIndex = item.oid;
if (lineIndex != 0)
{
pointBefore = segmentCollection.Segment[lineIndex - 1].FromPoint;
pointCurr = segmentCollection.Segment[lineIndex - 1].ToPoint;
pointAfter = item.line.ToPoint;
double angle = GetAngle(pointCurr, pointBefore, pointAfter);
angle = Math.Round(angle, 0, MidpointRounding.AwayFromZero);
if (angle == 180 || angle == 0)
{
DeletePoint(pointCurr, ref geometry, true);
retgeometry = geometry;
}
}
else if (lineIndex != (segmentCollection.SegmentCount - 1))
{
pointCurr = segmentCollection.Segment[lineIndex + 1].FromPoint;
pointAfter = segmentCollection.Segment[lineIndex + 1].ToPoint;
pointBefore = item.line.FromPoint;
double angle = GetAngle(pointCurr, pointBefore, pointAfter);
angle = Math.Round(angle, 0, MidpointRounding.AwayFromZero);
if (angle == 180 || angle == 0)
{
DeletePoint(pointCurr, ref geometry, true);
retgeometry = geometry;
}
}
}
catch (Exception ex)
{
LogAPI.Debug(ex);
}
}
return retgeometry;
}
catch (Exception ex)
{
LogAPI.Debug(ex);
throw ex;
}
finally
{
}
}
public IGeometry AddPointDensity(IGeometry geometry, double distinct, ref double addPoint)
{
IPolyline segmentFrist = null;
IPolyline[] polylines = new IPolyline[2];
ISegmentCollection segmentCurr = new PolylineClass() as ISegmentCollection;
IPolyline polyline = null;
IPoint point = null;
IPoint BeforePoint = null;
int max = 0;
int partIndexMax = 0;
double AddPoint = addPoint;
IGeometry retgeometry = geometry;
int JL = 0;//距离
try
{
foreach (BatchNodeInformation information in batches)
{
segmentCurr = geometry as ISegmentCollection;
if (AddPoint == 0)
{
AddPoint = information.length / distinct;
if (information.length % distinct > 0)
{
AddPoint++;
}
AddPoint = (int)AddPoint;
AddPoint -= (information.PointCount - 1);
AddPoint += 2;//多加2点,让距离不卡70;
JL = (int)(information.length / AddPoint);
}
double temp = 0;
for (int i = 0; i < segmentCurr.SegmentCount; i++)
{
if (AddPoint < 1)
{
break;
}
if (AddPoint == 1)
{
}
segmentFrist = getPolylineFromSegment(segmentCurr.Segment[i]);
for (int ind = 1; ind <= AddPoint; ind++)
{
if (segmentFrist.Length < JL && temp == 0)
{
temp = JL - segmentFrist.Length;
temp = temp < 1 ? 0 : temp;
break;
}
else if (temp != 0 && segmentFrist.Length < temp)
{
temp = temp - segmentFrist.Length;
temp = temp < 1 ? 0 : temp;
break;
}
if (temp != 0)
{
polylines = SpliteLineAtDistinct(segmentFrist, (int)(temp), false);
temp = 0;
}
else
{
polylines = SpliteLineAtDistinct(segmentFrist, (int)JL, false);
}
point = repeatPoint(polylines[0], polylines[1]);
if (AddPoint < 1)
{
break;
}
else
{
AddPoint--;
}
IPoint iHitPt = new ESRI.ArcGIS.Geometry.Point();
IHitTest iHitTest = geometry as IHitTest;
double hitDist = 0;
int partIndex = 0;
int vertexIndex = 0;
bool bRightSide = false;
polyline = GetPolyline(geometry);
IPointCollection pc = (SpliteLineAtPoint(polyline, point) as IPointCollection);
for (int j = 0; j < pc.PointCount; j++)
{
if (j == 0)
{
continue;
}
if (pc.Point[j].X == point.X && pc.Point[j].Y == point.Y)
{
BeforePoint = pc.Point[j - 1];
break;
}
}
bool isTrue = iHitTest.HitTest(BeforePoint, 0.0001, esriGeometryHitPartType.esriGeometryPartVertex,
iHitPt, ref hitDist, ref partIndex, ref vertexIndex, ref bRightSide);
if (isTrue)
{
max = vertexIndex;
partIndexMax = partIndex;
retgeometry = this.AddPoint(geometry, point, partIndexMax, max, false);
break;
}
}
}
}
addPoint = AddPoint;
return retgeometry;
}
catch (Exception ex)
{
LogAPI.Debug(ex);
return retgeometry;
throw;
}
finally
{
}
}
/// <summary>
/// 给图形加点
/// </summary>
/// <param name="geometry"></param>
/// <param name="point">要添加的点</param>
/// <param name="partIndex">片段顺序</param>
/// <param name="vertexIndex">点的索引</param>
/// <param name="beforeOrAfter">true:Before;false:After</param>
/// <returns></returns>
public IGeometry AddPoint(IGeometry geometry, IPoint point, int partIndex, int vertexIndex, bool beforeOrAfter = true)
{
IGeometryCollection collection = geometry as IGeometryCollection;
IGeometry geo = collection.get_Geometry(partIndex);
IPointCollection points = geo as IPointCollection;
object index = vertexIndex;
object mss = Type.Missing;
if (beforeOrAfter)
{
points.AddPoint(point, ref index, ref mss);
}
else
points.AddPoint(point, ref mss, ref index);
return geometry;
}
public IPolyline SpliteLineAtPoint(IPolyline LineCurve, IPoint SplitePoint)
{
IPolyline Lines = null;
bool isSplit;
int splitIndex, segIndex;
LineCurve.SplitAtPoint(SplitePoint, false, false, out isSplit, out splitIndex, out segIndex);
if (isSplit)
{
Lines = LineCurve as IPolyline;
}
return Lines;
}
private IPoint repeatPoint(IPolyline polyline1, IPolyline polyline2)
{
IPointCollection collection1 = polyline1 as IPointCollection;
IPointCollection collection2 = polyline2 as IPointCollection;
IPoint CenPoint = null;
try
{
for (int i = 0; i < collection1.PointCount; i++)
{
for (int j = 0; j < collection2.PointCount; j++)
{
if (collection1.Point[i].X == collection2.Point[j].X && collection1.Point[i].Y == collection2.Point[j].Y)
{
CenPoint = collection1.Point[i];
return CenPoint;
}
}
}
return CenPoint;
}
catch (Exception ex)
{
LogAPI.Debug(ex);
throw ex;
}
finally
{
}
}
public IPolyline[] SpliteLineAtDistinct(IPolyline LineCurve, int distinct, bool IsCopy = true)
{
IPolyline[] Lines = new IPolyline[2];
bool isSplit;
int splitIndex, segIndex;
IPolyline polyline = new PolylineClass();
if (IsCopy)
{
polyline.FromPoint = LineCurve.FromPoint;
polyline.ToPoint = LineCurve.ToPoint;
polyline.SpatialReference = LineCurve.SpatialReference;
}
else
{
polyline = LineCurve;
}
polyline.SplitAtDistance(distinct, false, false, out isSplit, out splitIndex, out segIndex);
if (isSplit)
{
IPolyline newLine = new PolylineClass();
ISegmentCollection lineSegCol = (ISegmentCollection)polyline;
ISegmentCollection newSegCol = (ISegmentCollection)newLine;
object o = Type.Missing;
for (int j = segIndex; j < lineSegCol.SegmentCount; j++)
{
newSegCol.AddSegment(lineSegCol.get_Segment(j), ref o, ref o);
}
lineSegCol.RemoveSegments(segIndex, lineSegCol.SegmentCount - segIndex, true);
lineSegCol.SegmentsChanged();
newSegCol.SegmentsChanged();
IPolyline oldLine = lineSegCol as IPolyline;
newLine = newSegCol as IPolyline;
Lines[0] = newLine;
Lines[1] = oldLine;
}
return Lines;
}
public bool VerificationDensity(IGeometry geometry)
{
try
{
bool isSucc = false;
//周长
ITopologicalOperator topo = geometry as ITopologicalOperator;
IPolyline line = topo.Boundary as IPolyline;
double zc = line.Length;
//点数
int PointCount = (geometry as IPointCollection).PointCount;
double Density = zc / (PointCount - 1);
if (MinDensityLength > Density)
{
isSucc = true;
batches.Add(new BatchNodeInformation() { length = zc, PointCount = PointCount, MinDensity = isSucc });
}
else if (Density > MaxDensityLength)
{
isSucc = true;
batches.Add(new BatchNodeInformation() { length = zc, PointCount = PointCount, MaxDensity = isSucc });
}
return isSucc;
}
catch (Exception ex)
{
LogAPI.Debug("验证 密度 函数异常,原因: " + ex + " ; ");
return false;
}
}
public bool VerificationMinLine(IGeometry geometry)
{
try
{
bool isSucc = true;
ISegmentCollection segmentCurr = geometry as ISegmentCollection;
IPolyline[] polylines = new IPolyline[2];
IPolyline polyline = null;
for (int i = 0; i < segmentCurr.SegmentCount; i++)
{
polyline = getPolylineFromSegment(segmentCurr.Segment[i]);
if (polyline.Length < 0.2)
{
isSucc = false;
batches.Add(new BatchNodeInformation() { line = polyline, length = polyline.Length, MinLength = isSucc, oid = i });
}
}
return isSucc;
}
catch (Exception ex)
{
LogAPI.Debug("验证 最小线段 函数异常,原因: " + ex + " ; ");
return true;
}
}
public IGeometry DeletePointDensity(IGeometry geometry, double distinct, ref double DelPoint)
{
IPoint point = null;
double AddPoint = DelPoint;
IPointCollection collection = null;
double angle = 0;
IGeometry Retgeometry = geometry;
try
{
foreach (BatchNodeInformation information in batches)
{
if (AddPoint == 0)
{
AddPoint = information.length / distinct;
if (information.length % distinct > 0)
{
AddPoint++;
}
if (AddPoint % 1 > 0)
{
AddPoint = (int)AddPoint + 1;
}
AddPoint = (information.PointCount - 1 - AddPoint);
}
collection = (geometry as IPointCollection);
for (int i = 0; i < collection.PointCount - 1; i++)
{
if (AddPoint < 1)
{
break;
}
if (i == 0)
{
continue;
}
try
{
angle = GetAngle(collection.Point[i], collection.Point[i - 1], collection.Point[i + 1]);
angle = Math.Round(angle, 0, MidpointRounding.AwayFromZero);
if (angle == 180 || angle == 0)
{
DeletePoint(collection.Point[i], ref geometry, true);
Retgeometry = geometry;
AddPoint--;
}
}
catch (Exception ex)
{
LogAPI.Debug(ex);
}
}
}
return Retgeometry;
}
catch (Exception ex)
{
LogAPI.Debug(ex);
return Retgeometry;
throw;
}
finally
{
}
}
private void DeletePoint(IPoint point, ref IGeometry geometry, bool isDelete = false)
{
IPointCollection collection = new PolylineClass() as IPointCollection;
IPointCollection pointCollection = new PolygonClass() as IPointCollection;
try
{
IPolyline polyline = GetPolyline(geometry);
collection.AddPoint(point);
geometry = RemovePointformLine(geometry, collection);
}
catch (Exception ex)
{
LogAPI.Debug(ex);
throw ex;
}
finally
{
}
}
public IGeometry RemovePointformLine(IGeometry geometry, IPointCollection point)
{
IGeometryCollection collection = geometry as IGeometryCollection;
IGeometry geo = null;
IPointCollection pointCollection = null;
try
{
var pHitTest = geometry as IHitTest;
var ptDelete = new PointClass();
double DbHitDis = 0;
int LngPrtIdx = 0;
int indexDelete = 0;
bool BoolHitRt = false;
var points = geometry as IPointCollection;
for (var j = 0; j < point.PointCount; j++)
{
var delpoint = point.Point[j];
var BoolHitTest = pHitTest.HitTest(delpoint, 0.0001, esriGeometryHitPartType.esriGeometryPartVertex, ptDelete, ref DbHitDis, ref LngPrtIdx, ref indexDelete, ref BoolHitRt);
geo = collection.get_Geometry(LngPrtIdx);
pointCollection = geo as IPointCollection;
IPoint pt = points.get_Point(indexDelete);
points.RemovePoints(indexDelete, 1);
}
return geometry;
}
catch (Exception ex)
{
LogAPI.Debug(ex);
}
finally
{
}
return geometry;
}
public IPolyline GetPolyline(IGeometry geometry)
{
IPolygon polygon = geometry as IPolygon;
ISegmentCollection segmentCollction = polygon as ISegmentCollection;
ISegmentCollection polyline = new Polyline() as ISegmentCollection;
object before = Type.Missing;
object after = Type.Missing;
for (int m = 0; m < segmentCollction.SegmentCount; m++)
{
ISegment pSeg = segmentCollction.get_Segment(m);
polyline.AddSegment(pSeg, ref before, ref after);
}
IPolyline pGeo = polyline as IPolyline;
return pGeo;
}
public static double GetAngle(IPoint cenPoint, IPoint firstPoint, IPoint secondPoint)
{
double ma_x = firstPoint.X - cenPoint.X;
double ma_y = firstPoint.Y - cenPoint.Y;
double mb_x = secondPoint.X - cenPoint.X;
double mb_y = secondPoint.Y - cenPoint.Y;
double v1 = (ma_x * mb_x) + (ma_y * mb_y);
double ma_val = Math.Sqrt(ma_x * ma_x + ma_y * ma_y);
double mb_val = Math.Sqrt(mb_x * mb_x + mb_y * mb_y);
if (ma_val * mb_val == 0)
{
return -1;
}
double cosM = v1 / (ma_val * mb_val);
double angleAMB = Math.Acos(cosM) * 180 / Math.PI;
return angleAMB;
}
private IPolyline getPolylineFromSegment(ISegment iSegment)
{
IGeometryCollection pGeoCol = new PolylineClass();
ISegmentCollection pSegCol = new PathClass();
ILine pLine = new LineClass();
pLine.FromPoint = iSegment.FromPoint;
pLine.ToPoint = iSegment.ToPoint;
object mis = Type.Missing;
pSegCol.AddSegment((ISegment)pLine, ref mis, ref mis);
pGeoCol.AddGeometry((IGeometry)pSegCol, ref mis, ref mis);
return (IPolyline)pGeoCol;
}
}
class BatchNodeInformation
{
public double length;
public int PointCount;
public int oid;
public IPolyline line;
public bool MaxDensity;
public bool MinDensity;
public bool MinLength;
}
}