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 lstSourceLine = new List(); List lstSourceSplit = new List(); List lstSourceSplitCenter = new List(); // 区域最小外接矩形 List lstRect = new List(); DrawerElementHelp elementHelp = new DrawerElementHelp(); List propertys = elementHelp.DeserializeList(strData); foreach (DrawerElementProperty property in propertys) { DrawerPline pLine = property.Element as DrawerPline; List 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 lstCoor1 = new List(); 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 lstCenter1 = new List(); 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 lstCoor2 = new List(); 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 lstCenter2 = new List(); 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 lstCoor3 = new List(); 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 lstCenter3 = new List(); 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); } /// /// 判断构造类型 /// /// /// /// private string CaculateFortType(DrawerData drawerSource, Geometry[] geometries) { List fortsDL = new List(); //List fortsDQ = new List(); //List fortsJD = new List(); 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.阶地}"; } } /// /// 计算线段与多边形相交形成的线段 /// /// /// /// private LineSegment CaculateCross(Polygon polygon, LineSegment segClip) { int nLen = polygon.Coordinates.Length; List lstCross = new List(); 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 CreatePoints(string data) { List lstPt = new List(); 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 lstPt = new List(); 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, } }