浏览代码

多边形面积计算公式

懒得勤快 5 年之前
父节点
当前提交
ddf88d7cf8

+ 5 - 0
Masuit.Tools.Core/Masuit.Tools.Core.csproj

@@ -83,6 +83,10 @@ github:https://github.com/ldqk/Masuit.Tools</Description>
     <Compile Include="..\Masuit.Tools\Mapping\Visitor\ConverterExpressionVisitor.cs" Link="Mapping\Visitor\ConverterExpressionVisitor.cs" />
     <Compile Include="..\Masuit.Tools\Mapping\Visitor\MapperExpressionVisitor.cs" Link="Mapping\Visitor\MapperExpressionVisitor.cs" />
     <Compile Include="..\Masuit.Tools\Mapping\Visitor\PropertiesVisitor.cs" Link="Mapping\Visitor\PropertiesVisitor.cs" />
+    <Compile Include="..\Masuit.Tools\Maths\Point2D.cs" Link="Maths\Point2D.cs" />
+    <Compile Include="..\Masuit.Tools\Maths\RadarChart.cs" Link="Maths\RadarChart.cs" />
+    <Compile Include="..\Masuit.Tools\Maths\RadarChartEngine.cs" Link="Maths\RadarChartEngine.cs" />
+    <Compile Include="..\Masuit.Tools\Maths\Vector2D.cs" Link="Maths\Vector2D.cs" />
     <Compile Include="..\Masuit.Tools\Media\ImageUtilities.cs" Link="Media\ImageUtilities.cs" />
     <Compile Include="..\Masuit.Tools\Media\ThumbnailCutMode.cs" Link="Media\ThumbnailCutMode.cs" />
     <Compile Include="..\Masuit.Tools\Models\BaiduIP.cs" Link="Models\BaiduIP.cs" />
@@ -165,6 +169,7 @@ github:https://github.com/ldqk/Masuit.Tools</Description>
     <Folder Include="Systems\" />
     <Folder Include="Validator\" />
     <Folder Include="Win32\" />
+    <Folder Include="Maths\" />
   </ItemGroup>
 
 </Project>

+ 4 - 0
Masuit.Tools/Masuit.Tools.csproj

@@ -152,6 +152,10 @@
     <Compile Include="Mapping\Visitor\ConverterExpressionVisitor.cs" />
     <Compile Include="Mapping\Visitor\MapperExpressionVisitor.cs" />
     <Compile Include="Mapping\Visitor\PropertiesVisitor.cs" />
+    <Compile Include="Maths\RadarChartEngine.cs" />
+    <Compile Include="Maths\Point2D.cs" />
+    <Compile Include="Maths\RadarChart.cs" />
+    <Compile Include="Maths\Vector2D.cs" />
     <Compile Include="Media\ThumbnailCutMode.cs" />
     <Compile Include="Models\BaiduIP.cs" />
     <Compile Include="Models\IspInfo.cs" />

+ 24 - 0
Masuit.Tools/Maths/Point2D.cs

@@ -0,0 +1,24 @@
+namespace Masuit.Tools.Maths
+{
+    public class Point2D
+    {
+        public double X { get; set; }
+        public double Y { get; set; }
+
+        public Point2D(double x, double y)
+        {
+            X = x;
+            Y = y;
+        }
+
+        public static Vector2D operator -(Point2D first, Point2D second)
+        {
+            return new Vector2D(first.X - second.X, first.Y - second.Y);
+        }
+
+        public static Point2D operator +(Point2D pt, Vector2D vec)
+        {
+            return new Point2D(pt.X + vec.X, pt.Y + vec.Y);
+        }
+    }
+}

+ 33 - 0
Masuit.Tools/Maths/RadarChart.cs

@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+
+namespace Masuit.Tools.Maths
+{
+    public class RadarChart
+    {
+        public List<double> Data { get; set; }
+        public double StartAngle { get; set; } // 弧度
+
+        public RadarChart(List<double> data, double startAngle)
+        {
+            Data = new List<double>(data);
+            StartAngle = startAngle;
+        }
+
+        public List<Point2D> GetPoints()
+        {
+            int count = Data.Count;
+            List<Point2D> result = new List<Point2D>();
+            for (int ii = 0; ii < count; ii++)
+            {
+                double length = Data[ii];
+                double angle = StartAngle + Math.PI * 2 / count * ii;
+                double x = length * Math.Cos(angle);
+                double y = length * Math.Sin(angle);
+                result.Add(new Point2D(x, y));
+            }
+
+            return result;
+        }
+    }
+}

+ 85 - 0
Masuit.Tools/Maths/RadarChartEngine.cs

@@ -0,0 +1,85 @@
+using System;
+using System.Collections.Generic;
+
+namespace Masuit.Tools.Maths
+{
+    /// <summary>
+    /// 雷达图引擎
+    /// </summary>
+    public static class RadarChartEngine
+    {
+        /// <summary>
+        /// 计算多边形面积的函数
+        /// (以原点为基准点,分割为多个三角形)
+        /// 定理:任意多边形的面积可由任意一点与多边形上依次两点连线构成的三角形矢量面积求和得出。矢量面积=三角形两边矢量的叉乘。
+        /// </summary>
+        /// <param name="points"></param>
+        /// <returns></returns>
+        public static double ComputeArea(this List<Point2D> points)
+        {
+            double area = 0;
+            var iCount = points.Count;
+
+            for (var i = 0; i < iCount; i++)
+            {
+                area = area + (points[i].X * points[(i + 1) % iCount].Y - points[(i + 1) % iCount].X * points[i].Y);
+            }
+
+            return Math.Abs(0.5 * area);
+        }
+
+        /// <summary>
+        /// 获取两个多边形的相交区域
+        /// </summary>
+        /// <param name="first">多边形1</param>
+        /// <param name="second">多边形2</param>
+        /// <returns></returns>
+        public static List<Point2D> ComputeIntersection(this RadarChart first, RadarChart second)
+        {
+            double tol = 1e-6;
+            if (null == first || null == second)
+            {
+                throw new ArgumentException();
+            }
+
+            if (Math.Abs(first.StartAngle - second.StartAngle) > tol || first.Data.Count != second.Data.Count)
+            {
+                throw new ArgumentException();
+            }
+
+            int count = first.Data.Count;
+            List<Point2D> result = new List<Point2D>();
+            List<Point2D> firstPoints = first.GetPoints();
+            List<Point2D> secondPoints = second.GetPoints();
+            for (int i = 0; i < count; i++)
+            {
+                Point2D tmp = (first.Data[i] > second.Data[i]) ? secondPoints[i] : firstPoints[i];
+                result.Add(tmp);
+            }
+
+            for (int i = count; i > 0; i--)
+            {
+                int curIdx = i % count;
+                int preIdx = i - 1;
+                if (first.Data[curIdx] > second.Data[curIdx] == first.Data[preIdx] < second.Data[preIdx])
+                {
+                    var intersectPt = GetIntersect(firstPoints[preIdx], firstPoints[curIdx], secondPoints[preIdx], secondPoints[curIdx]);
+                    result.Insert(i, intersectPt);
+                }
+            }
+
+            return result;
+        }
+
+        private static Point2D GetIntersect(Point2D lineFirstStart, Point2D lineFirstEnd, Point2D lineSecondStart, Point2D lineSecondEnd)
+        {
+            Vector2D firstVec = lineFirstEnd - lineFirstStart;
+            Vector2D secondVec = lineSecondEnd - lineSecondStart;
+            double factor = firstVec.X * secondVec.Y - firstVec.Y * secondVec.X;
+            double dis = secondVec.X * (lineFirstStart.Y - lineSecondStart.Y) - secondVec.Y * (lineFirstStart.X - lineSecondStart.X);
+            double radio = dis / factor;
+
+            return lineFirstStart + firstVec * radio;
+        }
+    }
+}

+ 19 - 0
Masuit.Tools/Maths/Vector2D.cs

@@ -0,0 +1,19 @@
+namespace Masuit.Tools.Maths
+{
+    public class Vector2D
+    {
+        public double X { get; set; }
+        public double Y { get; set; }
+
+        public Vector2D(double x, double y)
+        {
+            X = x;
+            Y = y;
+        }
+
+        public static Vector2D operator *(Vector2D vec, double factor)
+        {
+            return new Vector2D(vec.X * factor, vec.Y * factor);
+        }
+    }
+}