You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
429 lines
18 KiB
C#
429 lines
18 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using GeoSigmaDrawLib;
|
|
using NetTopologySuite.Geometries;
|
|
using FortAnalysis;
|
|
using SigmaDrawerElement;
|
|
using System.IO;
|
|
using NetTopologySuite;
|
|
using Clipper2Lib;
|
|
using System.Drawing;
|
|
using GeoSigma.SigmaDrawerStyle;
|
|
|
|
namespace FortAnalyzeLib
|
|
{
|
|
public class FortAnalyze
|
|
{
|
|
private GeometryFactory gf = null;
|
|
int splitNum = 30;
|
|
public FortAnalyze()
|
|
{
|
|
const int srid = 25832;
|
|
this.gf = NtsGeometryServices.Instance.CreateGeometryFactory(srid);
|
|
}
|
|
public bool ExcuteAnalyze(string inputFile, string faultLayer, string outputFile = null)
|
|
{
|
|
DrawerData drawerSource = new DrawerData();
|
|
if (drawerSource.OpenFile(inputFile) == false)
|
|
{
|
|
return false;
|
|
}
|
|
string strData = string.Empty;
|
|
int nCount = drawerSource.LayerGetCurves(faultLayer, ref strData);
|
|
|
|
if (nCount <= 0)
|
|
{
|
|
return false;
|
|
}
|
|
// 原始多边形区域
|
|
List<Polygon> lstSourceLine = new List<Polygon>();
|
|
List<LineString[]> lstSourceSplit = new List<LineString[]>();
|
|
List<LineString[]> lstSourceSplitCenter = new List<LineString[]>();
|
|
|
|
// 区域最小外接矩形
|
|
List<Vector2[]> lstRect = new List<Vector2[]>();
|
|
DrawerElementHelp elementHelp = new DrawerElementHelp();
|
|
List<DrawerElementProperty> propertys = elementHelp.DeserializeList(strData);
|
|
foreach (DrawerElementProperty property in propertys)
|
|
{
|
|
DrawerPline pLine = property.Element as DrawerPline;
|
|
List<Vector2> lstPoint = CreatePoints(pLine.Coordinate);
|
|
lstSourceLine.Add(CreatePolygon(pLine.Coordinate));
|
|
Vector2[] rect = RotatingCalipers2.getMinimumBoundingRectangle(lstPoint);
|
|
lstRect.Add(rect);
|
|
//lstRect.Add(CreateDrawerLine(rect));
|
|
}
|
|
|
|
// 将原始断裂带三等分
|
|
for (int m = 0; m < lstRect.Count; m++)
|
|
{
|
|
PathD pathStart = new PathD();
|
|
PathD pathMiddle1 = new PathD();
|
|
PathD pathMiddle2 = new PathD();
|
|
PathD pathEnd = new PathD();
|
|
|
|
Vector2[] rect = lstRect[m];
|
|
Polygon plySource = lstSourceLine[m];
|
|
|
|
PathsD pathsSource = new PathsD();
|
|
PathD pathSource = new PathD();
|
|
foreach (Coordinate coor in plySource.Coordinates)
|
|
{
|
|
pathSource.Add(new Clipper2Lib.PointD(coor.X, coor.Y));
|
|
}
|
|
|
|
pathsSource.Add(pathSource);
|
|
|
|
//LinearRing[] rectParts = new LinearRing[3];
|
|
// 定义矩形的四个顶点
|
|
Coordinate p1 = new Coordinate(rect[0].X, rect[0].Y);
|
|
Coordinate p2 = new Coordinate(rect[1].X, rect[1].Y);
|
|
Coordinate p3 = new Coordinate(rect[2].X, rect[2].Y);
|
|
Coordinate p4 = new Coordinate(rect[3].X, rect[3].Y);
|
|
// 计算长边的长度
|
|
double length1 = p1.Distance(p2);
|
|
double length2 = p2.Distance(p3);
|
|
Coordinate pStart1 = p1;
|
|
Coordinate pEnd1 = p2;
|
|
Coordinate pStart2 = p4;
|
|
Coordinate pEnd2 = p3;
|
|
// 确定长边的两个顶点
|
|
if (length1 < length2)
|
|
{
|
|
pStart1 = p2;
|
|
pEnd1 = p3;
|
|
|
|
pStart2 = p1;
|
|
pEnd2 = p4;
|
|
}
|
|
LineSegment seg1 = new LineSegment(pStart1, pEnd1);
|
|
LineSegment seg2 = new LineSegment(pStart2, pEnd2);
|
|
for (int i = 0; i < splitNum - 1; i++)
|
|
{
|
|
Coordinate cooFraction1 = seg1.PointAlong((i + 1) / (double)splitNum);
|
|
Coordinate cooFraction2 = seg2.PointAlong((i + 1) / (double)splitNum);
|
|
PathsD clipPaths = new PathsD();
|
|
PathD clipLine = new PathD();
|
|
clipLine.Add(new Clipper2Lib.PointD(cooFraction1.X, cooFraction1.Y));
|
|
clipLine.Add(new Clipper2Lib.PointD(cooFraction2.X, cooFraction2.Y));
|
|
clipPaths.Add(clipLine);
|
|
|
|
LineSegment segCross = CaculateCross(plySource
|
|
, new LineSegment(cooFraction1, cooFraction2));
|
|
|
|
pathStart.Add(new Clipper2Lib.PointD(segCross.P0.X, segCross.P0.Y));
|
|
pathEnd.Add(new Clipper2Lib.PointD(segCross.P1.X, segCross.P1.Y));
|
|
}
|
|
// 生成分割线
|
|
for (int i = 0; i < pathStart.Count; i++)
|
|
{
|
|
LineSegment segCross = new LineSegment(new Coordinate(pathStart[i].x, pathStart[i].y)
|
|
, new Coordinate(pathEnd[i].x, pathEnd[i].y));
|
|
Coordinate coor1 = segCross.PointAlong(1 / 3.0f);
|
|
Coordinate coor2 = segCross.PointAlong(2 / 3.0f);
|
|
|
|
pathMiddle1.Add(new Clipper2Lib.PointD(coor1.X, coor1.Y));
|
|
pathMiddle2.Add(new Clipper2Lib.PointD(coor2.X, coor2.Y));
|
|
}
|
|
// 生成三个区域
|
|
LineString[] polySplit = new LineString[3];
|
|
LineString[] polySplitCenter = new LineString[3];
|
|
List<Coordinate> lstCoor1 = new List<Coordinate>();
|
|
for (int i = 0; i < pathStart.Count; i++)
|
|
{
|
|
lstCoor1.Add(new Coordinate(pathStart[i].x, pathStart[i].y));
|
|
}
|
|
for (int i = pathMiddle1.Count - 1; i >= 0; i--)
|
|
{
|
|
lstCoor1.Add(new Coordinate(pathMiddle1[i].x, pathMiddle1[i].y));
|
|
}
|
|
polySplit[0] = gf.CreateLineString(lstCoor1.ToArray());
|
|
// 生成中心线
|
|
List<Coordinate> lstCenter1 = new List<Coordinate>();
|
|
for (int i = 0; i < pathStart.Count; i++)
|
|
{
|
|
LineSegment sg = new LineSegment(new Coordinate(pathStart[i].x, pathStart[i].y)
|
|
, new Coordinate(pathMiddle1[i].x, pathMiddle1[i].y));
|
|
lstCenter1.Add(sg.PointAlong(0.5));
|
|
}
|
|
polySplitCenter[0] = gf.CreateLineString(lstCenter1.ToArray());
|
|
|
|
List<Coordinate> lstCoor2 = new List<Coordinate>();
|
|
for (int i = 0; i < pathMiddle1.Count; i++)
|
|
{
|
|
lstCoor2.Add(new Coordinate(pathMiddle1[i].x, pathMiddle1[i].y));
|
|
}
|
|
for (int i = pathMiddle2.Count - 1; i >= 0; i--)
|
|
{
|
|
lstCoor2.Add(new Coordinate(pathMiddle2[i].x, pathMiddle2[i].y));
|
|
}
|
|
polySplit[1] = gf.CreateLineString(lstCoor2.ToArray());
|
|
// 生成中心线
|
|
List<Coordinate> lstCenter2 = new List<Coordinate>();
|
|
for (int i = 0; i < pathMiddle1.Count; i++)
|
|
{
|
|
LineSegment sg = new LineSegment(new Coordinate(pathMiddle1[i].x, pathMiddle1[i].y)
|
|
, new Coordinate(pathMiddle2[i].x, pathMiddle2[i].y));
|
|
lstCenter2.Add(sg.PointAlong(0.5));
|
|
}
|
|
polySplitCenter[1] = gf.CreateLineString(lstCenter2.ToArray());
|
|
|
|
List<Coordinate> lstCoor3 = new List<Coordinate>();
|
|
for (int i = 0; i < pathMiddle2.Count; i++)
|
|
{
|
|
lstCoor3.Add(new Coordinate(pathMiddle2[i].x, pathMiddle2[i].y));
|
|
}
|
|
for (int i = pathEnd.Count - 1; i >= 0; i--)
|
|
{
|
|
lstCoor3.Add(new Coordinate(pathEnd[i].x, pathEnd[i].y));
|
|
}
|
|
polySplit[2] = gf.CreateLineString(lstCoor3.ToArray());
|
|
// 生成中心线
|
|
List<Coordinate> lstCenter3 = new List<Coordinate>();
|
|
for (int i = 0; i < pathMiddle2.Count; i++)
|
|
{
|
|
LineSegment sg = new LineSegment(new Coordinate(pathMiddle2[i].x, pathMiddle2[i].y)
|
|
, new Coordinate(pathEnd[i].x, pathEnd[i].y));
|
|
lstCenter3.Add(sg.PointAlong(0.5));
|
|
}
|
|
polySplitCenter[2] = gf.CreateLineString(lstCenter3.ToArray());
|
|
|
|
lstSourceSplit.Add(polySplit);
|
|
lstSourceSplitCenter.Add(polySplitCenter);
|
|
}
|
|
|
|
StringBuilder strbOutput = new StringBuilder();
|
|
//strbOutput.AppendLine($"Layer M 外接矩形");
|
|
//foreach (Vector2[] rect in lstRect)
|
|
//{
|
|
// DrawerPline line = CreateDrawerLine(rect);
|
|
// strbOutput.AppendLine(line.ToDfdString());
|
|
//}
|
|
|
|
//strbOutput.AppendLine($"Layer M 拆分区域");
|
|
////foreach (Geometry[] splitedSource in lstSplitted)
|
|
//for (int m = 0; m < lstSourceSplit.Count; m++)
|
|
//{
|
|
// LineString[] splitedSource = lstSourceSplit[m];
|
|
// for (int i = 0; i < 3; i++)
|
|
// {
|
|
// LineString geometry = splitedSource[i];
|
|
|
|
// DrawerPline line = CreateDrawerLine(geometry);
|
|
// strbOutput.AppendLine(line.ToDfdString());
|
|
// }
|
|
//}
|
|
|
|
|
|
//drawer.AddBufferData(strbOutput.ToString());
|
|
|
|
strbOutput = new StringBuilder();
|
|
// 计算形态
|
|
for (int i = 0; i < lstSourceSplitCenter.Count; i++)
|
|
{
|
|
LineString[] lineCenters = lstSourceSplitCenter[i];
|
|
string strLayer = CaculateFortType(drawerSource, lineCenters);
|
|
|
|
strbOutput.AppendLine($"Layer M {strLayer}");
|
|
strbOutput.AppendLine(CreateDrawerLine(lstSourceLine[i]).ToDfdString());
|
|
}
|
|
if(!String.IsNullOrEmpty(outputFile))
|
|
{
|
|
DrawerData drawer = new DrawerData();
|
|
drawer.AddBufferData(strbOutput.ToString());
|
|
SetLayerColor(drawer, "地堑", Color.FromArgb(255, 0, 0));
|
|
SetLayerColor(drawer, "地垒", Color.FromArgb(0, 255, 0));
|
|
SetLayerColor(drawer, "阶地", Color.FromArgb(0, 0, 255));
|
|
|
|
drawer.SaveAs(outputFile);
|
|
drawer.Dispose();
|
|
}
|
|
else
|
|
{
|
|
string[] saLayers = new string[] { "地堑", "地垒", "阶地" };
|
|
drawerSource.DeleteLayer(saLayers, true);
|
|
drawerSource.AddBufferData(strbOutput.ToString());
|
|
SetLayerColor(drawerSource, "地堑", Color.FromArgb(255, 0, 0));
|
|
SetLayerColor(drawerSource, "地垒", Color.FromArgb(0, 255, 0));
|
|
SetLayerColor(drawerSource, "阶地", Color.FromArgb(0, 0, 255));
|
|
|
|
drawerSource.SaveAs(inputFile);
|
|
}
|
|
drawerSource.Dispose();
|
|
return true;
|
|
}
|
|
private static void SetLayerColor(DrawerData drawer, string layerName, Color color)
|
|
{
|
|
CurveProperty propertyFill = new CurveProperty();
|
|
propertyFill.LineColor = color;
|
|
propertyFill.CurveType = (int)LineType.PLINE_SOLID;
|
|
drawer.CreateLayerCurveStyle(layerName, CurveStyleType.CurveProperties, propertyFill.SerialXml());
|
|
CurveProperty propertyLine = new CurveProperty();
|
|
propertyLine.LineColor = Color.FromArgb(0, 0, 0);
|
|
propertyLine.CurveType = (int)LineType.PLINE_ZERO;
|
|
string strStyleData = propertyLine.SerialXml();
|
|
strStyleData = strStyleData.Replace("true", "1");
|
|
strStyleData = strStyleData.Replace("false", "0");
|
|
drawer.SetLayerHowtoViewCurve(layerName, strStyleData, 1);
|
|
}
|
|
/// <summary>
|
|
/// 判断构造类型
|
|
/// </summary>
|
|
/// <param name="drawerSource"></param>
|
|
/// <param name="geometries"></param>
|
|
/// <returns></returns>
|
|
private string CaculateFortType(DrawerData drawerSource, Geometry[] geometries)
|
|
{
|
|
List<FortType> fortsDL = new List<FortType>();
|
|
//List<FortType> fortsDQ = new List<FortType>();
|
|
//List<FortType> fortsJD = new List<FortType>();
|
|
Coordinate[] coors1 = geometries[0].Coordinates;
|
|
Coordinate[] coors2 = geometries[1].Coordinates;
|
|
Coordinate[] coors3 = geometries[2].Coordinates;
|
|
for (int i = 0; i < coors1.Length; i++)
|
|
{
|
|
double dZ1 = drawerSource.MeshGetZ(coors1[i].X, coors1[i].Y);
|
|
double dZ2 = drawerSource.MeshGetZ(coors2[i].X, coors2[i].Y);
|
|
double dZ3 = drawerSource.MeshGetZ(coors3[i].X, coors3[i].Y);
|
|
|
|
if (dZ1 < -1E30 || dZ2 < -1E30 || dZ3 < -1E30)
|
|
{
|
|
continue;
|
|
}
|
|
if (dZ2 > dZ1 && dZ2 > dZ3)
|
|
{
|
|
fortsDL.Add(FortType.地垒);
|
|
}
|
|
else if (dZ2 < dZ1 && dZ2 < dZ3)
|
|
{
|
|
fortsDL.Add(FortType.地堑);
|
|
}
|
|
else
|
|
{
|
|
fortsDL.Add(FortType.阶地);
|
|
}
|
|
}
|
|
int nCountDL = fortsDL.Count(it => it == FortType.地垒);
|
|
int nCountDQ = fortsDL.Count(it => it == FortType.地堑);
|
|
int nCountJD = fortsDL.Count(it => it == FortType.阶地);
|
|
int nCountMax = Math.Max(Math.Max(nCountDL, nCountDQ), nCountJD);
|
|
if (nCountDL == nCountMax)
|
|
{
|
|
return $"{FortType.地垒}";
|
|
}
|
|
else if (nCountDQ == nCountMax)
|
|
{
|
|
return $"{FortType.地堑}";
|
|
}
|
|
else
|
|
{
|
|
return $"{FortType.阶地}";
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// 计算线段与多边形相交形成的线段
|
|
/// </summary>
|
|
/// <param name="polygon"></param>
|
|
/// <param name="segClip"></param>
|
|
/// <returns></returns>
|
|
private LineSegment CaculateCross(Polygon polygon, LineSegment segClip)
|
|
{
|
|
int nLen = polygon.Coordinates.Length;
|
|
List<Coordinate> lstCross = new List<Coordinate>();
|
|
for (int i = 0; i < nLen - 1; i++)
|
|
{
|
|
LineSegment seg = new LineSegment(polygon.Coordinates[i], polygon.Coordinates[i + 1]);
|
|
Coordinate coor = seg.Intersection(segClip);
|
|
if (coor != null)
|
|
{
|
|
lstCross.Add(coor);
|
|
}
|
|
}
|
|
if (lstCross.Count < 2)
|
|
{
|
|
lstCross.Clear();
|
|
for (int i = 0; i < nLen - 1; i++)
|
|
{
|
|
LineSegment seg = new LineSegment(polygon.Coordinates[i], polygon.Coordinates[i + 1]);
|
|
Coordinate coor = seg.Intersection(segClip);
|
|
if (coor != null)
|
|
{
|
|
lstCross.Add(coor);
|
|
}
|
|
else
|
|
{
|
|
if (gf.CreatePoint(segClip.P0).Distance(
|
|
gf.CreateLineString(new Coordinate[] { seg.P0, seg.P1 })) < 0.1)
|
|
{
|
|
lstCross.Add(segClip.P0);
|
|
}
|
|
if (gf.CreatePoint(segClip.P1).Distance(
|
|
gf.CreateLineString(new Coordinate[] { seg.P0, seg.P1 })) < 0.1)
|
|
{
|
|
lstCross.Add(segClip.P1);
|
|
}
|
|
}
|
|
}
|
|
if (lstCross.Count < 2)
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
lstCross.Sort((a, b) => { return a.Distance(segClip.P0).CompareTo(b.Distance(segClip.P0)); });
|
|
|
|
return new LineSegment(lstCross[0], lstCross[1]);
|
|
}
|
|
private List<Vector2> CreatePoints(string data)
|
|
{
|
|
List<Vector2> lstPt = new List<Vector2>();
|
|
TextReader tr = new StringReader(data);
|
|
string strLine = string.Empty;
|
|
while ((strLine = tr.ReadLine()) != null)
|
|
{
|
|
string[] saCoor = strLine.Split(',');
|
|
lstPt.Add(new Vector2(Convert.ToDouble(saCoor[0]), Convert.ToDouble(saCoor[1])));
|
|
}
|
|
return lstPt;
|
|
}
|
|
private Polygon CreatePolygon(string data)
|
|
{
|
|
List<Coordinate> lstPt = new List<Coordinate>();
|
|
TextReader tr = new StringReader(data);
|
|
string strLine = string.Empty;
|
|
while ((strLine = tr.ReadLine()) != null)
|
|
{
|
|
string[] saCoor = strLine.Split(',');
|
|
lstPt.Add(new Coordinate(Convert.ToDouble(saCoor[0]), Convert.ToDouble(saCoor[1])));
|
|
}
|
|
if (lstPt[0] != lstPt[lstPt.Count - 1])
|
|
{
|
|
lstPt.Add(lstPt[0].Copy());
|
|
}
|
|
return gf.CreatePolygon(lstPt.ToArray());
|
|
}
|
|
private DrawerPline CreateDrawerLine(Geometry points)
|
|
{
|
|
StringBuilder strbData = new StringBuilder();
|
|
foreach (Coordinate pt in points.Coordinates)
|
|
{
|
|
strbData.AppendLine($"{pt.X},{pt.Y}");
|
|
}
|
|
strbData.AppendLine();
|
|
DrawerPline pline = new DrawerPline();
|
|
pline.Coordinate = strbData.ToString();
|
|
pline.Layer = "外接矩形";
|
|
|
|
return pline;
|
|
}
|
|
}
|
|
enum FortType
|
|
{
|
|
地垒 = 1,
|
|
地堑 = 2,
|
|
阶地 = 3,
|
|
}
|
|
}
|