GMap.net 地图标绘实现(四):箭头
- DoubleArrow:钳击
/// <summary>/// 钳击/// </summary>public class DoubleArrow : GMapPolygon, IPlot{protected string geo_type = string.Empty;protected PointLatLng[] points;private PlotTypes type;private double headHeightFactor = 0.0;private double headWidthFactor = 0.0;private double neckHeightFactor = 0.15;private double neckWidthFactor = 0.15;private PointLatLng connPoint;private PointLatLng tempPoint4;private int fixPointCount = 0;public DoubleArrow(PointLatLng[] points,string name= "DoubleArrow"): base(points.ToList(), name){this.points = points;this.geo_type = "RootTest";this.type = PlotTypes.DOUBLE_ARROW;this.headHeightFactor = 0.25;this.headWidthFactor = 0.3;this.neckHeightFactor = 0.85;this.neckWidthFactor = 0.15;this.connPoint = PointLatLng.Empty;this.tempPoint4 = PointLatLng.Empty; ;this.fixPointCount = 4;this.SetPoints(points);}public void FinishDrawing(){List<PointLatLng> pointList = points.ToList();if (this.GetPointCount() == 3 && this.tempPoint4 != null)pointList.Add(this.tempPoint4);if (this.connPoint != null)pointList.Add(this.connPoint);this.points = pointList.ToArray();}public void Generate(){var count = this.GetPointCount();if (count < 2){return;}if (count == 2){this.Points.Clear();var temp=GeometryUtil.ConvertCoordinates(points.ToList(), ProjNet.CoordinateSystems.ProjectedCoordinateSystem.WebMercator, ProjNet.CoordinateSystems.GeographicCoordinateSystem.WGS84);this.Points.AddRange(temp);return;}var pnt1 = this.points[0];var pnt2 = this.points[1];var pnt3 = this.points[2];count = this.GetPointCount();if (count == 3)this.tempPoint4 = this.GetTempPoint4(pnt1, pnt2, pnt3);elsethis.tempPoint4 = this.points[3];if (count == 3 || count == 4)this.connPoint = PlotUtil.Mid(pnt1, pnt2);elsethis.connPoint = this.points[4];PointLatLng[] leftArrowPnts;PointLatLng[] rightArrowPnts;if (PlotUtil.IsClockWise(pnt1, pnt2, pnt3)){leftArrowPnts = this.GetArrowPoints(pnt1, this.connPoint, this.tempPoint4, false);rightArrowPnts = this.GetArrowPoints(this.connPoint, pnt2, pnt3, true);}else{leftArrowPnts = this.GetArrowPoints(pnt2, this.connPoint, pnt3, false);rightArrowPnts = this.GetArrowPoints(this.connPoint, pnt1, this.tempPoint4, true);}var m = leftArrowPnts.Length;var t = (m - 5) / 2;var llBodyPnts = leftArrowPnts.Take(t).ToArray();var lArrowPnts = leftArrowPnts.Skip(t).Take(5).ToArray();var lrBodyPnts = leftArrowPnts.Skip(t + 5).Take(m - (t + 5)).ToArray();var rlBodyPnts = rightArrowPnts.Take(t).ToArray();var rArrowPnts = rightArrowPnts.Skip(t).Take(5).ToArray();var rrBodyPnts = rightArrowPnts.Skip(t + 5).Take(m - (t + 5)).ToArray();rlBodyPnts = PlotUtil.GetBezierPoints(rlBodyPnts).ToArray();var bodyPnts = PlotUtil.GetBezierPoints(rrBodyPnts.Concat(llBodyPnts.Skip(1)).ToArray());lrBodyPnts = PlotUtil.GetBezierPoints(lrBodyPnts).ToArray();var pnts = rlBodyPnts.Concat(rArrowPnts.Concat(bodyPnts).Concat(lArrowPnts).Concat(lrBodyPnts).ToArray());var temps = GeometryUtil.ConvertCoordinates(pnts.ToList(), ProjNet.CoordinateSystems.ProjectedCoordinateSystem.WebMercator, ProjNet.CoordinateSystems.GeographicCoordinateSystem.WGS84);this.Points.Clear();this.Points.AddRange(temps);}private PointLatLng[] GetArrowPoints(PointLatLng pnt1, PointLatLng pnt2, PointLatLng pnt3, bool clockWise){var midPnt = PlotUtil.Mid(pnt1, pnt2);var len = PlotUtil.Distance(midPnt, pnt3);var midPnt1 = PlotUtil.GetThirdPoint(pnt3, midPnt, 0, len * 0.3, true);var midPnt2 = PlotUtil.GetThirdPoint(pnt3, midPnt, 0, len * 0.5, true);//var midPnt3=PlotUtils.getThirdPoint(pnt3, midPnt, 0, len * 0.7, true);midPnt1 = PlotUtil.GetThirdPoint(midPnt, midPnt1, Constants.HALF_PI, len / 5, clockWise);midPnt2 = PlotUtil.GetThirdPoint(midPnt, midPnt2, Constants.HALF_PI, len / 4, clockWise);//midPnt3=PlotUtils.getThirdPoint(midPnt, midPnt3, Constants.HALF_PI, len / 5, clockWise);var points = new PointLatLng[] { midPnt, midPnt1, midPnt2, pnt3 };// 计算箭头部分var arrowPnts = this.GetArrowHeadPoints(points, this.headHeightFactor, this.headWidthFactor, this.neckHeightFactor, this.neckWidthFactor);var neckLeftPoint = arrowPnts[0];var neckRightPoint = arrowPnts[4];// 计算箭身部分var tailWidthFactor = PlotUtil.Distance(pnt1, pnt2) / PlotUtil.GetBaseLength(points.ToList()) / 2;var bodyPnts = this.GetArrowBodyPoints(points, neckLeftPoint, neckRightPoint, tailWidthFactor).ToArray();var n = bodyPnts.Length;var lPoints = bodyPnts.Take(n / 2).ToList();var rPoints = bodyPnts.Skip(n / 2).Take(n).ToList();lPoints.Add(neckLeftPoint);rPoints.Add(neckRightPoint);lPoints.Reverse();lPoints.Add(pnt2);rPoints.Reverse();rPoints.Add(pnt1);lPoints.Reverse();return lPoints.Concat(arrowPnts).Concat(rPoints).ToArray();}private PointLatLng[] GetArrowBodyPoints(PointLatLng[] points, PointLatLng neckLeft, PointLatLng neckRight, double tailWidthFactor){var allLen = PlotUtil.WholeDistance(points.ToList());var len = PlotUtil.GetBaseLength(points.ToList());var tailWidth = len * tailWidthFactor;var neckWidth = PlotUtil.Distance(neckLeft, neckRight);var widthDif = (tailWidth - neckWidth) / 2;double tempLen = 0.0;List<PointLatLng> leftBodyPnts = new List<PointLatLng>();List<PointLatLng> rightBodyPnts = new List<PointLatLng>();for (var i = 1; i < points.Length - 1; i++){var angle = PlotUtil.GetAngleOfThreePoints(points[i - 1], points[i], points[i + 1]) / 2;tempLen += PlotUtil.Distance(points[i - 1], points[i]);var w = (tailWidth / 2 - tempLen / allLen * widthDif) / Math.Sin(angle);var left = PlotUtil.GetThirdPoint(points[i - 1], points[i], Math.PI - angle, w, true);var right = PlotUtil.GetThirdPoint(points[i - 1], points[i], angle, w, false);leftBodyPnts.Add(left);rightBodyPnts.Add(right);}return leftBodyPnts.Concat(rightBodyPnts).ToArray();}private PointLatLng[] GetArrowHeadPoints(PointLatLng[] points, double headHeightFactor, double headWidthFactor, double neckHeightFactor, double neckWidthFactor){var len = PlotUtil.GetBaseLength(points.ToList());var headHeight = len * headHeightFactor;var headPnt = points[points.Length - 1];//var tailWidth = PlotUtil.Distance(tailLeft, tailRight);var headWidth = headHeight * headWidthFactor;var neckWidth = headHeight * neckWidthFactor;var neckHeight = headHeight * neckHeightFactor;var headEndPnt = PlotUtil.GetThirdPoint(points[points.Length - 2], headPnt, 0, headHeight, true);var neckEndPnt = PlotUtil.GetThirdPoint(points[points.Length - 2], headPnt, 0, neckHeight, true);var headLeft = PlotUtil.GetThirdPoint(headPnt, headEndPnt, Constants.HALF_PI, headWidth, false);var headRight = PlotUtil.GetThirdPoint(headPnt, headEndPnt, Constants.HALF_PI, headWidth, true);var neckLeft = PlotUtil.GetThirdPoint(headPnt, neckEndPnt, Constants.HALF_PI, neckWidth, false);var neckRight = PlotUtil.GetThirdPoint(headPnt, neckEndPnt, Constants.HALF_PI, neckWidth, true);return new PointLatLng[] { neckLeft, headLeft, headPnt, headRight, neckRight };}private PointLatLng GetTempPoint4(PointLatLng linePnt1, PointLatLng linePnt2, PointLatLng point){var midPnt = PlotUtil.Mid(linePnt1, linePnt2);var len = PlotUtil.Distance(midPnt, point);var angle = PlotUtil.GetAngleOfThreePoints(linePnt1, midPnt, point);PointLatLng symPnt;double distance1;double distance2;PointLatLng mid;if (angle < Constants.HALF_PI){distance1 = len * Math.Sin(angle);distance2 = len * Math.Cos(angle);mid = PlotUtil.GetThirdPoint(linePnt1, midPnt, Constants.HALF_PI, distance1, false);symPnt = PlotUtil.GetThirdPoint(midPnt, mid, Constants.HALF_PI, distance2, true);}else if (angle >= Constants.HALF_PI && angle < Math.PI){distance1 = len * Math.Sin(Math.PI - angle);distance2 = len * Math.Cos(Math.PI - angle);mid = PlotUtil.GetThirdPoint(linePnt1, midPnt, Constants.HALF_PI, distance1, false);symPnt = PlotUtil.GetThirdPoint(midPnt, mid, Constants.HALF_PI, distance2, false);}else if (angle >= Math.PI && angle < Math.PI * 1.5){distance1 = len * Math.Sin(angle - Math.PI);distance2 = len * Math.Cos(angle - Math.PI);mid = PlotUtil.GetThirdPoint(linePnt1, midPnt, Constants.HALF_PI, distance1, true);symPnt = PlotUtil.GetThirdPoint(midPnt, mid, Constants.HALF_PI, distance2, true);}else{distance1 = len * Math.Sin(Math.PI * 2 - angle);distance2 = len * Math.Cos(Math.PI * 2 - angle);mid = PlotUtil.GetThirdPoint(linePnt1, midPnt, Constants.HALF_PI, distance1, true);symPnt = PlotUtil.GetThirdPoint(midPnt, mid, Constants.HALF_PI, distance2, false);}return symPnt;}public int GetPointCount(){return this.points.Length;}public PointLatLng[] GetPoints(){return this.points;}public bool IsPlot(){return true;}public void SetPoints(PointLatLng[] value){//将经纬度坐标转为投影坐标参与计算if (value != null)value = GeometryUtil.WGS84ToWebMercator2(value.ToList()).ToArray();this.points = (value != null) ? value : new PointLatLng[] { };if (this.points.Length >= 1)this.Generate();}public void UpdateLastPoint(PointLatLng point){this.UpdatePoint(point, this.points.Length - 1);}public void UpdatePoint(PointLatLng point, int index){if (index >= 0 && index < this.points.Length){this.points[index] = point;this.Generate();}}}
- StraightArrow:直箭头
/// <summary>/// 直箭头/// </summary>public class StraightArrow : GMapRoute,IPlot{protected string geo_type = string.Empty;protected PointLatLng[] points;private PlotTypes type;private int fixPointCount = 0;private double maxArrowLength = 0.0;private int arrowLengthScale=5;public StraightArrow(PointLatLng[] points,string name= "StraightArrow"):base(points.ToList(), name){this.points = points;this.geo_type = "RootTest";this.type = PlotTypes.STRAIGHT_ARROW;this.fixPointCount = 2;this.maxArrowLength = 3000000;this.arrowLengthScale = 5;this.SetPoints(points);}public void FinishDrawing(){}public void Generate(){if (this.GetPointCount() < 2){return;}var pnts = this.GetPoints();var pnt1 = pnts[0];var pnt2 = pnts[1];var distance = PlotUtil.Distance(pnt1, pnt2);var len = distance / this.arrowLengthScale;len = len > this.maxArrowLength ? this.maxArrowLength : len;var leftPnt = PlotUtil.GetThirdPoint(pnt1, pnt2, Math.PI / 6, len, false);var rightPnt = PlotUtil.GetThirdPoint(pnt1, pnt2, Math.PI / 6, len, true);List<PointLatLng> tempPoints = new PointLatLng[] { pnt1, pnt2, leftPnt, pnt2, rightPnt }.ToList();var temps = GeometryUtil.ConvertCoordinates(tempPoints, ProjNet.CoordinateSystems.ProjectedCoordinateSystem.WebMercator, ProjNet.CoordinateSystems.GeographicCoordinateSystem.WGS84);this.Points.Clear();this.Points.AddRange(temps);}public int GetPointCount(){return this.points.Length;}public PointLatLng[] GetPoints(){return this.points;}public bool IsPlot(){return true;}public void SetPoints(PointLatLng[] value){//将经纬度坐标转为投影坐标参与计算if (value != null)value = GeometryUtil.WGS84ToWebMercator2(value.ToList()).ToArray();this.points = (value != null) ? value : new PointLatLng[] { };if (this.points.Length >= 1)this.Generate();}public void UpdateLastPoint(PointLatLng point){this.UpdatePoint(point, this.points.Length - 1);}public void UpdatePoint(PointLatLng point, int index){if (index >= 0 && index < this.points.Length){this.points[index] = point;this.Generate();}}}
- FineArrow:细直箭头
/// <summary>/// 细直箭头/// </summary>public class FineArrow : GMapPolygon, IPlot{protected string geo_type = string.Empty;protected PointLatLng[] points;protected PlotTypes type = PlotTypes.FINE_ARROW;protected double tailWidthFactor = 0.15;protected double neckWidthFactor = 0.2;protected double headWidthFactor = 0.25;protected double headAngle = Math.PI / 8.5;protected double neckAngle = Math.PI / 13;private int fixPointCount = 2;public FineArrow(PointLatLng[] points):base(points.ToList(), "FineArrow"){this.points = points;this.geo_type = "RootTest";this.type = PlotTypes.FINE_ARROW;this.tailWidthFactor = 0.15;this.neckWidthFactor = 0.2;this.headWidthFactor = 0.25;this.headAngle = Math.PI / 8.5;this.neckAngle = Math.PI / 13;this.fixPointCount = 2;this.SetPoints(points);}public void FinishDrawing(){}public void Generate(){var count = this.GetPointCount();if (count < 2){return;}var pnts = this.GetPoints();var pnt1 = pnts[0];var pnt2 = pnts[1];var len = PlotUtil.GetBaseLength(pnts.ToList());var tailWidth = len * this.tailWidthFactor;var neckWidth = len * this.neckWidthFactor;var headWidth = len * this.headWidthFactor;var tailLeft = PlotUtil.GetThirdPoint(pnt2, pnt1, Constants.HALF_PI, tailWidth, true);var tailRight = PlotUtil.GetThirdPoint(pnt2, pnt1, Constants.HALF_PI, tailWidth, false);var headLeft = PlotUtil.GetThirdPoint(pnt1, pnt2, this.headAngle, headWidth, false);var headRight = PlotUtil.GetThirdPoint(pnt1, pnt2, this.headAngle, headWidth, true);var neckLeft = PlotUtil.GetThirdPoint(pnt1, pnt2, this.neckAngle, neckWidth, false);var neckRight = PlotUtil.GetThirdPoint(pnt1, pnt2, this.neckAngle, neckWidth, true);var pList = new PointLatLng[]{ tailLeft, neckLeft, headLeft, pnt2, headRight, neckRight, tailRight };var temps = GeometryUtil.ConvertCoordinates(pList.ToList(), ProjNet.CoordinateSystems.ProjectedCoordinateSystem.WebMercator, ProjNet.CoordinateSystems.GeographicCoordinateSystem.WGS84);this.Points.Clear();this.Points.AddRange(temps);}public int GetPointCount(){return this.points.Length;}public PointLatLng[] GetPoints(){return this.points;}public bool IsPlot(){return true;}public void SetPoints(PointLatLng[] value){//将经纬度坐标转为投影坐标参与计算if (value != null)value = GeometryUtil.WGS84ToWebMercator2(value.ToList()).ToArray();this.points = (value != null) ? value : new PointLatLng[] { };if (this.points.Length >= 1)this.Generate();}public void UpdateLastPoint(PointLatLng point){this.UpdatePoint(point, this.points.Length - 1);}public void UpdatePoint(PointLatLng point, int index){if (index >= 0 && index < this.points.Length){this.points[index] = point;this.Generate();}}}
- AssaultDirection:突击方向
/// <summary>/// 突击方向/// </summary>public class AssaultDirection:FineArrow{public AssaultDirection(PointLatLng[] points):base(points){this.type = PlotTypes.ASSAULT_DIRECTION;this.tailWidthFactor = 0.2;this.neckWidthFactor = 0.25;this.headWidthFactor = 0.3;this.headAngle = Math.PI / 4;this.neckAngle = Math.PI * 0.17741;this.SetPoints(points);}}
- AttackArrow:进攻方向
/// <summary>/// 进攻方向/// </summary>public class AttackArrow : GMapPolygon, IPlot{protected string geo_type = string.Empty;protected PointLatLng[] points;protected PlotTypes type = PlotTypes.ATTACK_ARROW;protected double headHeightFactor = 0.18;protected double headWidthFactor = 0.3;protected double neckHeightFactor = 0.85;protected double neckWidthFactor = 0.15;protected double headTailFactor = 0.8;public AttackArrow(PointLatLng[] points,string name= "AttackArrow"):base(points.ToList(), name){this.points = points;this.geo_type = "RootTest";this.type = PlotTypes.ATTACK_ARROW;this.headHeightFactor = 0.18;this.headWidthFactor = 0.3;this.neckHeightFactor = 0.85;this.neckWidthFactor = 0.15;this.headTailFactor = 0.8;this.SetPoints(points);}public void FinishDrawing(){}public virtual void Generate(){if (this.GetPointCount() < 2){return;}if (this.GetPointCount() == 2){var temp = GeometryUtil.ConvertCoordinates(this.points.ToList(), ProjNet.CoordinateSystems.ProjectedCoordinateSystem.WebMercator, ProjNet.CoordinateSystems.GeographicCoordinateSystem.WGS84);this.Points.Clear();this.Points.AddRange(temp);return;}var pnts = this.GetPoints();// 计算箭尾var tailLeft = pnts[0];var tailRight = pnts[1];if (PlotUtil.IsClockWise(pnts[0], pnts[1], pnts[2])){tailLeft = pnts[1];tailRight = pnts[0];}var midTail = PlotUtil.Mid(tailLeft, tailRight);var bonePnts = new PointLatLng[] { midTail }.Concat(pnts.Skip(2)).ToArray();// 计算箭头var headPnts = this.GetArrowHeadPoints(bonePnts, tailLeft, tailRight);var neckLeft = headPnts[0];var neckRight = headPnts[4];var tailWidthFactor = PlotUtil.Distance(tailLeft, tailRight) / PlotUtil.GetBaseLength(bonePnts.ToList());// 计算箭身var bodyPnts = this.GetArrowBodyPoints(bonePnts, neckLeft, neckRight, tailWidthFactor);// 整合var count = bodyPnts.Length;var leftPnts = new PointLatLng[] { tailLeft }.Concat(bodyPnts.Take(count / 2)).ToList();leftPnts.RemoveAt(1);leftPnts.Add(neckLeft);var rightPnts = new PointLatLng[] { tailRight }.Concat(bodyPnts.Skip(count / 2).Take(bodyPnts.Length)).ToList();rightPnts.RemoveAt(1);rightPnts.Add(neckRight);leftPnts = PlotUtil.GetQBSplinePoints(leftPnts.ToArray());rightPnts = PlotUtil.GetQBSplinePoints(rightPnts.ToArray());//右侧曲线节点反转rightPnts.Reverse();List<PointLatLng> tempPoints = leftPnts.ToArray().Concat(headPnts).Concat(rightPnts).ToList();var temps = GeometryUtil.ConvertCoordinates(tempPoints, ProjNet.CoordinateSystems.ProjectedCoordinateSystem.WebMercator, ProjNet.CoordinateSystems.GeographicCoordinateSystem.WGS84);this.Points.Clear();this.Points.AddRange(temps);}protected PointLatLng[] GetArrowHeadPoints(PointLatLng[] points, PointLatLng tailLeft, PointLatLng tailRight){var len = PlotUtil.GetBaseLength(points.ToList());var headHeight = len * this.headHeightFactor;var headPnt = points[points.Length - 1];len = PlotUtil.Distance(headPnt, points[points.Length - 2]);var tailWidth = PlotUtil.Distance(tailLeft, tailRight);if (headHeight > tailWidth * this.headTailFactor){headHeight = tailWidth * this.headTailFactor;}var headWidth = headHeight * this.headWidthFactor;var neckWidth = headHeight * this.neckWidthFactor;headHeight = headHeight > len ? len : headHeight;var neckHeight = headHeight * this.neckHeightFactor;var headEndPnt = PlotUtil.GetThirdPoint(points[points.Length - 2], headPnt, 0, headHeight, true);var neckEndPnt = PlotUtil.GetThirdPoint(points[points.Length - 2], headPnt, 0, neckHeight, true);var headLeft = PlotUtil.GetThirdPoint(headPnt, headEndPnt, Constants.HALF_PI, headWidth, false);var headRight = PlotUtil.GetThirdPoint(headPnt, headEndPnt, Constants.HALF_PI, headWidth, true);var neckLeft = PlotUtil.GetThirdPoint(headPnt, neckEndPnt, Constants.HALF_PI, neckWidth, false);var neckRight = PlotUtil.GetThirdPoint(headPnt, neckEndPnt, Constants.HALF_PI, neckWidth, true);return new PointLatLng[] { neckLeft, headLeft, headPnt, headRight, neckRight };}protected PointLatLng[] GetArrowBodyPoints(PointLatLng[] bonePnts, PointLatLng neckLeft, PointLatLng neckRight, double tailWidthFactor){var allLen = PlotUtil.WholeDistance(points.ToList());var len = PlotUtil.GetBaseLength(points.ToList());var tailWidth = len * tailWidthFactor;var neckWidth = PlotUtil.Distance(neckLeft, neckRight);var widthDif = (tailWidth - neckWidth) / 2;var tempLen = 0.0;List<PointLatLng> leftBodyPnts = new List<PointLatLng>();List<PointLatLng> rightBodyPnts = new List<PointLatLng>();for (int i = 1; i < points.Length - 1; i++){var angle = PlotUtil.GetAngleOfThreePoints(points[i - 1], points[i], points[i + 1]) / 2;tempLen += PlotUtil.Distance(points[i - 1], points[i]);var w = (tailWidth / 2 - tempLen / allLen * widthDif) / Math.Sin(angle);var left = PlotUtil.GetThirdPoint(points[i - 1], points[i], Math.PI - angle, w, true);var right = PlotUtil.GetThirdPoint(points[i - 1], points[i], angle, w, false);leftBodyPnts.Add(left);rightBodyPnts.Add(right);}return leftBodyPnts.Concat(rightBodyPnts).ToArray();}public int GetPointCount(){return points.Length;}public PointLatLng[] GetPoints(){return this.points;}public bool IsPlot(){return true;}public void SetPoints(PointLatLng[] value){//将经纬度坐标转为投影坐标参与计算if (value != null)value = GeometryUtil.WGS84ToWebMercator2(value.ToList()).ToArray();this.points = (value != null) ? value : new PointLatLng[] { };if (this.points.Length >= 1)this.Generate();}public void UpdateLastPoint(PointLatLng point){this.UpdatePoint(point, this.points.Length - 1);}public void UpdatePoint(PointLatLng point, int index){if (index >= 0 && index < this.points.Length){this.points[index] = point;this.Generate();}}}
- TailedAttackArrow:进攻方向(尾)
/// <summary>/// 进攻箭头(尾)/// </summary>public class TailedAttackArrow:AttackArrow{private double tailWidthFactor = 0.1;private double swallowTailFactor = 1;private PointLatLng swallowTailPnt;public TailedAttackArrow(PointLatLng[] points,string name= "TailedAttackArrow"):base(points,name){this.points = points;this.geo_type = "RootTest";this.type = PlotTypes.TAILED_ATTACK_ARROW;this.headHeightFactor = 0.18;this.headWidthFactor = 0.3;this.neckHeightFactor = 0.85;this.neckWidthFactor = 0.15;this.tailWidthFactor = 0.1;this.headTailFactor = 0.8;this.swallowTailFactor = 1;this.swallowTailPnt = PointLatLng.Empty; ;this.SetPoints(points);}public override void Generate(){var count = this.GetPointCount();if (count < 2){return;}if (this.GetPointCount() == 2){this.Points.Clear();var temp = GeometryUtil.ConvertCoordinates(this.points.ToList(), ProjNet.CoordinateSystems.ProjectedCoordinateSystem.WebMercator, ProjNet.CoordinateSystems.GeographicCoordinateSystem.WGS84);this.Points.AddRange(temp);return;}var pnts = this.GetPoints();var tailLeft = pnts[0];var tailRight = pnts[1];if (PlotUtil.IsClockWise(pnts[0], pnts[1], pnts[2])){tailLeft = pnts[1];tailRight = pnts[0];}var midTail = PlotUtil.Mid(tailLeft, tailRight);var bonePnts = new PointLatLng[] { midTail }.Concat(pnts.Skip(2).Take(pnts.Length)).ToArray();var headPnts = this.GetArrowHeadPoints(bonePnts, tailLeft, tailRight);var neckLeft = headPnts[0];var neckRight = headPnts[4];var tailWidth = PlotUtil.Distance(tailLeft, tailRight);var allLen = PlotUtil.GetBaseLength(bonePnts.ToList());var len = allLen * this.tailWidthFactor * this.swallowTailFactor;this.swallowTailPnt = PlotUtil.GetThirdPoint(bonePnts[1], bonePnts[0], 0, len, true);var factor = tailWidth / allLen;var bodyPnts = this.GetArrowBodyPoints(bonePnts, neckLeft, neckRight, factor);count = bodyPnts.Length;var leftPnts = new PointLatLng[] { tailLeft }.Concat(bodyPnts.Take(count / 2)).ToList();leftPnts.RemoveAt(1);leftPnts.Add(neckLeft);var rightPnts = new PointLatLng[] { tailRight }.Concat(bodyPnts.Skip(count / 2)).ToList();rightPnts.RemoveAt(1);rightPnts.Add(neckRight);leftPnts = PlotUtil.GetQBSplinePoints(leftPnts.ToArray());rightPnts = PlotUtil.GetQBSplinePoints(rightPnts.ToArray());rightPnts.Reverse();List<PointLatLng> tempPoints = leftPnts.Concat(headPnts).Concat(rightPnts).Concat(new PointLatLng[] { swallowTailPnt, leftPnts[0] }).ToList();var temps = GeometryUtil.ConvertCoordinates(tempPoints, ProjNet.CoordinateSystems.ProjectedCoordinateSystem.WebMercator, ProjNet.CoordinateSystems.GeographicCoordinateSystem.WGS84);this.Points.Clear();this.Points.AddRange(temps);}}
- SquadCombat:分队战斗行动
/// <summary>/// 分队战斗行动/// </summary>public class SquadCombat:AttackArrow{private double tailWidthFactor = 0.0;public SquadCombat(PointLatLng[] points):base(points){this.type = PlotTypes.SQUAD_COMBAT;this.headHeightFactor = 0.18;this.headWidthFactor = 0.3;this.neckHeightFactor = 0.85;this.neckWidthFactor = 0.15;this.tailWidthFactor = 0.1;this.SetPoints(points);}public override void Generate(){var count = this.GetPointCount();if (count < 2){return;}var pnts = this.GetPoints();var tailPnts = this.GetTailPoints(pnts);var headPnts = this.GetArrowHeadPoints(pnts, tailPnts[0], tailPnts[1]);var neckLeft = headPnts[0];var neckRight = headPnts[4];var bodyPnts = this.GetArrowBodyPoints(pnts, neckLeft, neckRight, this.tailWidthFactor);count = bodyPnts.Length;var leftPnts = new PointLatLng[] { tailPnts[0] }.Concat(bodyPnts.Take(count / 2)).ToList();leftPnts.Add(neckLeft);var rightPnts = new PointLatLng[] { tailPnts[1] }.Concat(bodyPnts.Skip(count / 2).Take(count)).ToList();rightPnts.Add(neckRight);leftPnts = PlotUtil.GetQBSplinePoints(leftPnts.ToArray());rightPnts = PlotUtil.GetQBSplinePoints(rightPnts.ToArray());rightPnts.Reverse();List<PointLatLng> tempPoints = leftPnts.Concat(headPnts.Concat(rightPnts)).ToList();var temps = GeometryUtil.ConvertCoordinates(tempPoints, ProjNet.CoordinateSystems.ProjectedCoordinateSystem.WebMercator, ProjNet.CoordinateSystems.GeographicCoordinateSystem.WGS84);this.Points.Clear();this.Points.AddRange(temps);}private PointLatLng[] GetTailPoints(PointLatLng[] pnts){var allLen = PlotUtil.GetBaseLength(points.ToList());var tailWidth = allLen * this.tailWidthFactor;var tailLeft = PlotUtil.GetThirdPoint(points[1], points[0], Constants.HALF_PI, tailWidth, false);var tailRight = PlotUtil.GetThirdPoint(points[1], points[0], Constants.HALF_PI, tailWidth, true);return new PointLatLng[] { tailLeft, tailRight };}}
- TailedSquadCombat:分队战斗行动(尾)
/// <summary>/// 分队战斗行动(尾)/// </summary>public class TailedSquadCombat: AttackArrow{private double tailWidthFactor = 0.0;private double swallowTailFactor = 1;private PointLatLng swallowTailPnt;public TailedSquadCombat(PointLatLng[] points,string name="TailedSquadCombat"):base(points,name){this.points = points;this.geo_type = "RootTest";this.type = PlotTypes.TAILED_SQUAD_COMBAT;this.headHeightFactor = 0.18;this.headWidthFactor = 0.3;this.neckHeightFactor = 0.85;this.neckWidthFactor = 0.15;this.tailWidthFactor = 0.1;this.swallowTailFactor = 1;this.swallowTailPnt = PointLatLng.Empty ;this.SetPoints(points);}public override void Generate(){var count = this.GetPointCount();if (count < 2){return;}var pnts = this.GetPoints();var tailPnts = this.GetTailPoints(pnts);var headPnts = this.GetArrowHeadPoints(pnts, tailPnts[0], tailPnts[2]);var neckLeft = headPnts[0];var neckRight = headPnts[4];var bodyPnts = this.GetArrowBodyPoints(pnts, neckLeft, neckRight, this.tailWidthFactor);count = bodyPnts.Length;var leftPnts = new PointLatLng[] { tailPnts[0] }.Concat(bodyPnts.Take(count / 2)).ToList();leftPnts.Add(neckLeft);var rightPnts = new PointLatLng[] { tailPnts[2] }.Concat(bodyPnts.Skip(count / 2).Take(count)).ToList();rightPnts.Add(neckRight);leftPnts = PlotUtil.GetQBSplinePoints(leftPnts.ToArray());rightPnts = PlotUtil.GetQBSplinePoints(rightPnts.ToArray());rightPnts.Reverse();List<PointLatLng> tempPoints = leftPnts.Concat(headPnts).Concat(rightPnts).Concat(new PointLatLng[] { tailPnts[1], leftPnts[0] }).ToList();var temps = GeometryUtil.ConvertCoordinates(tempPoints, ProjNet.CoordinateSystems.ProjectedCoordinateSystem.WebMercator, ProjNet.CoordinateSystems.GeographicCoordinateSystem.WGS84);this.Points.Clear();this.Points.AddRange(temps);}private PointLatLng[] GetTailPoints(PointLatLng[] points){var allLen = PlotUtil.GetBaseLength(points.ToList());var tailWidth = allLen * this.tailWidthFactor;var tailLeft = PlotUtil.GetThirdPoint(points[1], points[0], Constants.HALF_PI, tailWidth, false);var tailRight = PlotUtil.GetThirdPoint(points[1], points[0], Constants.HALF_PI, tailWidth, true);var len = tailWidth * this.swallowTailFactor;var swallowTailPnt = PlotUtil.GetThirdPoint(points[1], points[0], 0, len, true);return new PointLatLng[] { tailLeft, swallowTailPnt, tailRight };}}
- 坐标列表去重:基于List的Distinct方法去重
public class PointLatLngComparer : IEqualityComparer<PointLatLng>{public bool Equals(PointLatLng x, PointLatLng y){return x.Lat == y.Lat && x.Lng == y.Lng;}public int GetHashCode(PointLatLng obj){return string.Format("{0},{1}", obj.Lng, obj.Lat).GetHashCode();}}
//controlPoints 是List<PointLatLng>的变量,坐标去重
controlPoints = controlPoints.Distinct(new PointLatLngComparer()).ToList();