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#

1 month ago
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,
}
}