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

736 lines
32 KiB

using System;
using System.Collections.Generic;
using System.Linq;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using KGIS.Framework.AE;
using KGIS.Framework.Utils;
using KGIS.Framework.Utils.Enum;
namespace Kingo.Plugin.EngineEditor.Commands.Tools
{
public class ControlsEditingTrackTool : BaseToolCommand
{
private IHookHelper m_hookHelper;
private EngineEditorClass m_editor = new EngineEditorClass();
/// <summary>
/// 画笔
/// </summary>
public IEngineEditSketch editSketch { get { return m_editor as IEngineEditSketch; } }
/// <summary>
/// 当前显示的图层
/// </summary>
private List<IFeatureLayer> VisibleLayers { get; set; }
private IPointCollection linePoint = new PolylineClass() as IPointCollection;
private IPointCollection LinePath
{
get
{
//IPointCollection temp = editSketch.Geometry as IPointCollection;
if (linePoint.PointCount > 0)
{
linePoint.RemovePoints(0, linePoint.PointCount);
}
if (editSketch.GeometryType == esriGeometryType.esriGeometryPolygon)
{
ITopologicalOperator topo = editSketch.Geometry as ITopologicalOperator;
linePoint = topo.Boundary as IPointCollection;
if (linePoint.PointCount > 1)
{
linePoint.RemovePoints(linePoint.PointCount - 1, 1);
}
RemovePointStartIndex = 2;
}
else if (editSketch.GeometryType == esriGeometryType.esriGeometryPolyline)
{
linePoint = editSketch.Geometry as IPointCollection;
RemovePointStartIndex = 1;
}
return linePoint;
}
}
//private IPointCollection LinePath = new PolylineClass() as IPointCollection;
/// <summary>
/// 捕捉对象
/// </summary>
private IEngineSnapEnvironment snapEnv = null;
/// <summary>
/// 捕捉的点
/// </summary>
private IPoint snapPoint = null;
int RemovePointStartIndex = 1;
public override void OnCreate(object hook)
{
try
{
base.OnCreate(hook);
if (m_hookHelper == null)
{
m_hookHelper = new HookHelperClass() { Hook = hook };
}
if (m_editor == null)
{
m_editor = new EngineEditorClass();
}
if (snapEnv == null)
{
snapEnv = (IEngineSnapEnvironment)m_editor;
}
}
catch (Exception ex)
{
LogAPI.Debug("追踪工具OnCreate初始化异常:" + ex.Message);
}
}
bool IsTracking = false;
public override void OnClick()
{
try
{
this.OnCreate(base.hook);
base.OnClick();
if (VisibleLayers == null)
{
VisibleLayers = new List<IFeatureLayer>();
}
VisibleLayers.Clear();
VisibleLayers = KGIS.Framework.Maps.MapsManager.Instance.MapService.GetAllVisibleLayerInMap<IFeatureLayer>();
//VisibleLayers.Add(m_editor.TargetLayer as IFeatureLayer);
lines.Clear();
snapLine = new KeyValuePair<int, IPolyline>();
PreviousSnapLine = new KeyValuePair<int, IPolyline>();
}
catch (Exception ex)
{
LogAPI.Debug("追踪工具OnClick异常:" + ex.Message);
}
}
public override void OnMouseDown(int button, int shift, int x, int y)
{
try
{
base.OnMouseDown(button, shift, x, y);
if (IsTracking == false)
{
IPoint point = this.m_hookHelper.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(x, y);
if (editSketch.Geometry == null || editSketch.Geometry.IsEmpty)
{
if (snapEnv != null)
{
this.SnapPoint(m_hookHelper.ActiveView, point, snapEnv);
snapPoint = point;
}
if (snapPoint != null)
{
editSketch.AddPoint(snapPoint, false);
editSketch.ModifySketch();
editSketch.RefreshSketch();
}
}
IsTracking = true;
}
else
{
if (snapPoint != null)
{
editSketch.AddPoint(snapPoint, false);
editSketch.ModifySketch();
editSketch.RefreshSketch();
}
IsTracking = false;
}
}
catch (Exception ex)
{
LogAPI.Debug("追踪工具OnMouseDown异常:" + ex.Message);
}
}
//private IPolyline snapLine = null;
List<IPoint> intersectPoints = new List<IPoint>();
/// <summary>
/// 捕捉到的所有线段集合
/// </summary>
//List<IPolyline> lines = new List<IPolyline>();
Dictionary<int, IPolyline> lines = new Dictionary<int, IPolyline>();
KeyValuePair<int, IPolyline> snapLine = new KeyValuePair<int, IPolyline>();
KeyValuePair<int, IPolyline> PreviousSnapLine = new KeyValuePair<int, IPolyline>();
public override void OnMouseMove(int button, int shift, int x, int y)
{
try
{
base.OnMouseMove(button, shift, x, y);
IPoint point = this.m_hookHelper.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(x, y);
if (LinePath.PointCount == 0 || !IsTracking)
{
return;
}
int index = LinePath.PointCount - 1;
if (lines.Count == 0)
{
//获取当前点所捕捉到的要素
lines = GeneratePolyline(snapPoint);
}
IPoint nearesPoint = null;
//鼠标点距离线段的最短距离
double d = -1;
foreach (int item in lines.Keys)
{
IProximityOperator operatorPr = lines[item] as IProximityOperator;
IPoint TempNearesPoint = operatorPr.ReturnNearestPoint(point, esriSegmentExtension.esriNoExtension);
double temp_D = operatorPr.ReturnDistance(point);
if (d == -1 || d > temp_D)
{
d = temp_D;
snapLine = new KeyValuePair<int, IPolyline>(item, lines[item]);
nearesPoint = TempNearesPoint;
}
}
if (PreviousSnapLine.Value == null)
{
PreviousSnapLine = snapLine;
}
if (nearesPoint == null || snapLine.Value == null)
{
return;
}
ITopologicalOperator topo = snapLine.Value as ITopologicalOperator;
topo.Simplify();
IGeometry geo = topo.Intersect(nearesPoint, esriGeometryDimension.esriGeometry0Dimension);
if (geo == null || geo.IsEmpty)
{
//Bug-12973 霍岩 2018-11-09 频繁释放ITopologicalOperator, IGeometry等对象导致COM与RCW分离异常
//System.Runtime.InteropServices.Marshal.FinalReleaseComObject(topo);
//System.Runtime.InteropServices.Marshal.FinalReleaseComObject(geo);
snapLine = new KeyValuePair<int, IPolyline>();
return;
}
if (snapEnv != null)
{
this.SnapPoint(m_hookHelper.ActiveView, nearesPoint, snapEnv);
snapPoint = nearesPoint;
}
if (LinePath.PointCount < 1)
{
return;
}
bool IsVPoint = false;
if (IsCheckPointInLine(snapPoint, PreviousSnapLine.Value, ref IsVPoint) || PreviousSnapLine.Key == snapLine.Key)
{
index = LinePath.PointCount - 1;
if (GetSubCurveAddEdit(PreviousSnapLine.Value, LinePath.get_Point(index), snapPoint))
{
PreviousSnapLine = snapLine;
}
else
{
//重新获取追踪线对象
lines = GeneratePolyline(snapPoint);
}
}
else
{
lines = GeneratePolyline(snapPoint);
//判断前后追踪的两条线是否存在交点
ITopologicalOperator tempTopo = PreviousSnapLine.Value as ITopologicalOperator;
tempTopo.Simplify();
IGeometry tempIpoint = tempTopo.Intersect(snapLine.Value, esriGeometryDimension.esriGeometry0Dimension);
if (tempIpoint != null && !tempIpoint.IsEmpty)
{
index = LinePath.PointCount - 1;
GetSubCurveAddEdit(PreviousSnapLine.Value, LinePath.get_Point(index), (tempIpoint as IPointCollection).get_Point(0));
PreviousSnapLine = snapLine;
//Bug-12973 霍岩 2018-11-09 频繁释放ITopologicalOperator, IGeometry等对象导致COM与RCW分离异常
//System.Runtime.InteropServices.Marshal.FinalReleaseComObject(tempIpoint);
//System.Runtime.InteropServices.Marshal.FinalReleaseComObject(tempTopo);
}
}
}
catch (Exception ex)
{
LogAPI.Debug("追踪工具OnMouseMove异常:" + ex.Message);
}
}
/// <summary>
/// 获取指定线上两点之间的线段,并添加到当前编辑对象中
/// </summary>
/// <param name="line">指定的线</param>
/// <param name="point1">点1</param>
/// <param name="point2">点2</param>
/// <returns>如果未获取到线段则返回false</returns>
public bool GetSubCurveAddEdit(IPolyline line, IPoint point1, IPoint point2)
{
bool result = false;
IPolyline templine = null;
IGeometry interLine = null;
IPointCollection ps = null;
ITopologicalOperator2 temptopo = null;
try
{
templine = GetSubCurve(line, point1, point2);//GetSubCurve
if (templine.IsEmpty || templine.Length == 0)
{
result = false;
return result;
}
temptopo = templine as ITopologicalOperator2;
temptopo.Simplify();
interLine = temptopo.Intersect(LinePath as IPolyline, esriGeometryDimension.esriGeometry1Dimension);
if (interLine == null || interLine.IsEmpty)
{
ps = templine as IPointCollection;
if (Math.Round(templine.FromPoint.X, 2) == Math.Round((LinePath as IPolyline).ToPoint.X, 2) && Math.Round(templine.FromPoint.Y, 2) == Math.Round((LinePath as IPolyline).ToPoint.Y, 2))
{
//判断最后一个点是否是线上的节点
if (!PointIsVertexPointForLine(templine.ToPoint, line))
{
ps.RemovePoints(ps.PointCount - 1, 1);
}
int count = ps.PointCount;
for (int i = 1; i < count; i++)
{
editSketch.AddPoint(ps.get_Point(i), true);
editSketch.ModifySketch();
editSketch.RefreshSketch();
}
}
else
{
//判断最后一个点是否是线上的节点
if (!PointIsVertexPointForLine(templine.FromPoint, line))
{
ps.RemovePoints(0, 1);
}
int count = ps.PointCount - 1;
for (int i = count; i > 0; i--)
{
editSketch.AddPoint(ps.get_Point(i), true);
editSketch.ModifySketch();
editSketch.RefreshSketch();
}
}
result = true;
}
else
{
for (int i = 0; i < (templine as IPointCollection).PointCount; i++)
{
if (LinePath.PointCount == 1)
break;
int index = LinePath.PointCount - 2;
bool IsVPoint = false;
if (!IsCheckPointInLine(LinePath.get_Point(index), snapLine.Value, ref IsVPoint))
{
break;
}
(editSketch.Geometry as IPointCollection).RemovePoints((editSketch.Geometry as IPointCollection).PointCount - RemovePointStartIndex, 1);
editSketch.ModifySketch();
editSketch.RefreshSketch();
}
}
}
finally
{
//Bug-12973 霍岩 2018-11-09 频繁释放ITopologicalOperator, IGeometry等对象导致COM与RCW分离异常
//if (templine != null)
//{
// System.Runtime.InteropServices.Marshal.FinalReleaseComObject(templine);
//}
//if (interLine != null)
//{
// System.Runtime.InteropServices.Marshal.FinalReleaseComObject(interLine);
//}
//if (ps != null)
//{
// System.Runtime.InteropServices.Marshal.FinalReleaseComObject(ps);
//}
//if (temptopo != null)
//{
// System.Runtime.InteropServices.Marshal.FinalReleaseComObject(temptopo);
//}
}
return result;
}
public bool PointIsVertexPointForLine(IPoint point, IPolyline line)
{
bool result = false;
IPointCollection points = line as IPointCollection;
for (int i = 0; i < points.PointCount; i++)
{
if (Math.Round(point.X, 2) == Math.Round(points.get_Point(i).X, 2) && Math.Round(point.Y, 2) == Math.Round(points.get_Point(i).Y, 2))
{
result = true;
break;
}
}
return result;
}
public override void OnDblClick()
{
try
{
snapLine = new KeyValuePair<int, IPolyline>();
PreviousSnapLine = new KeyValuePair<int, IPolyline>();
lines.Clear();
editSketch.FinishSketch();
base.OnDblClick();
}
catch (Exception ex)
{
LogAPI.Debug("追踪工具OnDblClick异常:" + ex.Message);
}
}
/// <summary>
/// 判断点是否在线上
/// </summary>
/// <param name="pPoint">点</param>
/// <param name="pLine">线</param>
/// <param name="pContainEndPoint">是否包含端点</param>
/// <returns></returns>
private bool IsCheckPointInLine(IPoint pPoint, IPolyline pLine, ref bool pContainEndPoint)
{
bool result = false;
pContainEndPoint = false;
try
{
if (pPoint != null && pLine != null)
{
if (!pLine.IsEmpty && !pPoint.IsEmpty)
{
ITopologicalOperator topo = pLine as ITopologicalOperator;
//Bug-12973 霍岩 2018-11-09 在拓扑操作前使其简化
topo.Simplify();
IGeometry geo = topo.Intersect(pPoint, esriGeometryDimension.esriGeometry0Dimension);
if (geo != null && !geo.IsEmpty)
{
IPoint p = geo as IPoint;
if ((Math.Round(p.X, 2) == Math.Round(pLine.FromPoint.X, 2) && Math.Round(p.Y, 2) == Math.Round(pLine.FromPoint.Y, 2)) || (Math.Round(p.X, 2) == Math.Round(pLine.ToPoint.X, 2) && Math.Round(p.Y, 2) == Math.Round(pLine.ToPoint.Y, 2)))
{
result = true;
pContainEndPoint = true;
}
else
{
result = true;
}
}
}
}
}
catch (Exception ex)
{
throw ex;
}
return result;
}
private IPolyline GetSubCurve(IPolyline inpolyLine, IPoint pnt1, IPoint pnt2)
{
double d1 = GetDistAlong(inpolyLine, pnt1);
double d2 = GetDistAlong(inpolyLine, pnt2);
var c = inpolyLine as ICurve;
ICurve outCurve;
c.GetSubcurve(d1, d2, false, out outCurve);
if (c == null || c.IsEmpty)
throw new Exception("aa");
var outPolyline = outCurve as IPolyline;
if (outPolyline == null)
{
outPolyline = new PolylineClass() as IPolyline;
var sc = outPolyline as ISegmentCollection;
sc.AddSegment((ISegment)outCurve);
((IGeometry)sc).SpatialReference = outCurve.SpatialReference;
}
return outPolyline;
}
private double GetDistAlong(IPolyline polyLine, IPoint pnt)
{
var outPnt = new PointClass() as IPoint;
double distAlong = double.NaN;
double distFrom = double.NaN;
bool bRight = false;
polyLine.QueryPointAndDistance(esriSegmentExtension.esriNoExtension, pnt, false, outPnt,
ref distAlong, ref distFrom, ref bRight);
return distAlong;
}
private IPolyline BuildLine(IPolyline pLine, IPoint p1, IPoint p2)
{
bool isSplit;
int splitIndex, segIndex;
//插入第一点,segIndex记录插入点的相对线的节点位置
pLine.SplitAtPoint(p1, true, false, out isSplit, out splitIndex, out segIndex);
int fIndex = segIndex;
//插入第二点
pLine.SplitAtPoint(p2, true, false, out isSplit, out splitIndex, out segIndex);
int sIndex = segIndex;
IPointCollection pPointCol = new PolylineClass();
//IPointCollection pPointCol2 = new PolylineClass();
object o = Type.Missing;
//比较一下插入第一点和第二点的节点次序
if (fIndex > sIndex)
{
int temp = fIndex;
fIndex = sIndex;
sIndex = temp;
}
else if (fIndex == sIndex)
{
pPointCol.AddPoint(p1, ref o, ref o);
pPointCol.AddPoint(p2, ref o, ref o);
return pPointCol as IPolyline;
}
//利用两点区间,获取线上区间所在的点,并将其转换为线
IPointCollection LineCol = pLine as IPointCollection;
for (int i = fIndex; i <= sIndex; i++)
{
pPointCol.AddPoint(LineCol.get_Point(i), ref o, ref o);
}
//for (int i = 0; i < LineCol.PointCount; i++)
//{
// if (i < fIndex || i > sIndex)
// {
// pPointCol2.AddPoint(LineCol.get_Point(i), ref o, ref o);
// }
//}
return pPointCol as IPolyline;
}
/// <summary>
/// 生成地类界线
/// </summary>
/// <param name="pFeature">地类图斑要素</param>
/// <param name="pFc">地类界线对应的要素类对象</param>
/// <returns></returns>
public void GenerateDLJX(IPoint point, Dictionary<int, IPolyline> lines)
{
Dictionary<int, IPolyline> dicLine = new Dictionary<int, IPolyline>();
foreach (var item in lines.Keys)
{
dicLine.Add(item, lines[item]);
}
lines.Clear();
try
{
if (point == null || lines == null)
return;
List<IFeature> featureList = FeatureAPI.Snapping(snapPoint, VisibleLayers, 10);
foreach (IFeature item in featureList)
{
List<IGeometry> polylineArray = FeatureAPI.FeatureToLine(item);
if (polylineArray == null)
{
continue;
}
foreach (IGeometry line in polylineArray)
{
if (dicLine.Count == 0)
{
lines.Add(lines.Count, line as IPolyline);
continue;
}
IGeometry OtherIntersect = null;
foreach (IPolyline his_Line in dicLine.Values)
{
//不相交部分
IGeometry No_InterGeo = FeatureAPI.Difference(his_Line, OtherIntersect);
IGeometryCollection No_InterList = No_InterGeo as IGeometryCollection;
if (No_InterList != null)
{
for (int i = 0; i < No_InterList.GeometryCount; i++)
{
IGeometryCollection pPolyline = new PolylineClass();
pPolyline.AddGeometry(No_InterList.get_Geometry(i));
lines.Add(lines.Count, pPolyline as IPolyline);
}
}
//相交部分
IGeometry intersectGeo = FeatureAPI.InterSect(line, his_Line);
if (OtherIntersect == null)
{
OtherIntersect = intersectGeo;
}
else
{
ITopologicalOperator topo = OtherIntersect as ITopologicalOperator;
if (topo != null)
{
topo.Simplify();
OtherIntersect = topo.Union(intersectGeo);
}
}
IGeometryCollection intersectList = intersectGeo as IGeometryCollection;
if (intersectGeo != null)
{
for (int i = 0; i < intersectList.GeometryCount; i++)
{
IGeometryCollection pPolyline = new PolylineClass();
pPolyline.AddGeometry(intersectList.get_Geometry(i));
lines.Add(lines.Count, pPolyline as IPolyline);
}
}
}
if (OtherIntersect != null)
{
//新生成的线与之不相交
IGeometry newGeoNoInter = FeatureAPI.Difference(line, OtherIntersect);
IGeometryCollection newGeoList = newGeoNoInter as IGeometryCollection;
if (newGeoList != null)
{
for (int i = 0; i < newGeoList.GeometryCount; i++)
{
IGeometryCollection pPolyline = new PolylineClass();
pPolyline.AddGeometry(newGeoList.get_Geometry(i));
lines.Add(lines.Count, pPolyline as IPolyline);
}
}
}
//lines = result.Values.ToList<IPolyline>();
}
//lines = result.Values.ToList<IPolyline>();
//if (result.Count == 0)
// result = polylineArray;
}
return;
}
catch (Exception ex)
{
throw ex;
}
}
public Dictionary<int, IPolyline> GeneratePolyline(IPoint point, Dictionary<int, IPolyline> lines)
{
Dictionary<int, IPolyline> result = new Dictionary<int, IPolyline>();
if (point == null || lines == null) return result;
try
{
//获取当前追踪的要素多边形
List<IFeature> snapFeatures = FeatureAPI.Snapping(point, VisibleLayers, 10);
//List<IFeature> snapFeatures = new List<IFeature>();
//if (snapFe.Count > 0)
//{
// //snapFeatures.Add(snapFe[0]);
// snapFeatures.AddRange(FeatureAPI.Snapping(snapFe[0].ShapeCopy, VisibleLayers, 1));
//}
if (snapFeatures == null) return result;
foreach (IFeature feautre in snapFeatures)
{
//将多边形要素转成线要素
List<IGeometry> featureToLines = FeatureAPI.PolygonToLine(feautre.ShapeCopy);
if (featureToLines == null) continue;
IPolyline tempLine = null;
foreach (IGeometry f_line in featureToLines)
{
if (lines.Count == 0)
{
result.Add(result.Count, f_line as IPolyline);
continue;
}
//将线要素与已有的线要素进行打断
foreach (IPolyline line in lines.Values)
{
ITopologicalOperator topo = line as ITopologicalOperator;
topo.Simplify();
IPolyline new_DifLine = topo.Difference(f_line) as IPolyline;
if (new_DifLine != null && !new_DifLine.IsEmpty)
result.Add(result.Count, new_DifLine);
IPolyline new_InterLine = topo.Intersect(f_line, esriGeometryDimension.esriGeometry1Dimension) as IPolyline;
if (new_InterLine != null && !new_InterLine.IsEmpty && new_DifLine != null && !new_DifLine.IsEmpty)
result.Add(result.Count, new_InterLine);
}
foreach (IPolyline line in lines.Values)
{
if (tempLine == null)
tempLine = f_line as IPolyline;
ITopologicalOperator topo = tempLine as ITopologicalOperator;
topo.Simplify();
tempLine = topo.Difference(line) as IPolyline;
if (tempLine == null || tempLine.IsEmpty)
break;
}
if (tempLine != null && !tempLine.IsEmpty)
result.Add(result.Count, tempLine);
}
}
return result;
}
catch (Exception ex)
{
LogAPI.Debug(ex);
throw ex;
}
}
public Dictionary<int, IPolyline> GeneratePolyline(IPoint point)
{
Dictionary<int, IPolyline> result = new Dictionary<int, IPolyline>();
if (point == null) return result;
try
{
//获取当前追踪的要素多边形
List<IFeature> snapFeatures = FeatureAPI.Snapping(point, VisibleLayers, 10);
if (snapFeatures == null) return result;
foreach (IFeature feautre in snapFeatures)
{
//将多边形要素转成线要素
List<IGeometry> featureToLines = FeatureAPI.PolygonToLine(feautre.ShapeCopy);
if (featureToLines == null) continue;
IPolyline tempLine = null;
foreach (IGeometry f_line in featureToLines)
{
tempLine = f_line as IPolyline;
List<IFeature> LineInsertFeature = FeatureAPI.Snapping(tempLine, VisibleLayers, 0.0001);
foreach (IFeature item in LineInsertFeature)
{
if (item.OID == feautre.OID)
continue;
ITopologicalOperator topo = tempLine as ITopologicalOperator;
topo.Simplify();
IPolyline newline = topo.Intersect(item.ShapeCopy, esriGeometryDimension.esriGeometry1Dimension) as IPolyline;
//IPolyline obj = result.Values.FirstOrDefault(f => Math.Round(f.Length, 0) == Math.Round(newline.Length, 0));
if (newline != null && !newline.IsEmpty && result.Values.FirstOrDefault(f => Math.Round(f.Length, 0) == Math.Round(newline.Length, 0)) == null)
result.Add(result.Count, newline);
tempLine = topo.Difference(item.ShapeCopy) as IPolyline;
}
if (!tempLine.IsEmpty && result.Values.FirstOrDefault(f => Math.Round(f.Length, 0) == Math.Round(tempLine.Length, 0)) == null)
result.Add(result.Count, tempLine);
}
}
return result;
}
catch (Exception ex)
{
throw ex;
}
}
public override bool Enabled
{
get
{
if (m_editor == null || m_editor.EditState != esriEngineEditState.esriEngineStateEditing)
{
return false;
}
return true;
}
}
public override enumProductType AttachProductType { get { return enumProductType.KDB; } }
}
}