【C#】计算多边形的面积

一、问题分析

在 C# 中计算多边形面积的一种常见方法是使用顶点坐标。

假设您有一个由一系列 (x, y) 顶点坐标定义的多边形,您可以使用"鞋带公式"(也称为高斯公式)来计算其面积。

如果是计算多边形的面积可以分为正常多边形、dicom图像中的多边形,这两种多边形可能考虑是否需要像素间距的转换问题。

二、考虑像素间距转换

在处理 DICOM 图像中的多边形面积计算时,如果需要更精确的结果,通常是需要考虑像素间距的。

像素间距在 DICOM 图像中用于描述每个像素在实际物理空间中的大小。如果不考虑像素间距,计算得到的面积只是基于像素坐标的数值,而不是真实的物理面积。

以下是一个示例,展示如何在计算多边形面积时考虑像素间距:

2.1 方法一

cs 复制代码
using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        // 假设多边形的顶点坐标列表
        List<Point> points = new List<Point>
        {
            new Point(0, 0),
            new Point(1, 0),
            new Point(1, 1),
            new Point(0, 1)
        };

        // 假设像素间距
        double pixelSpacingX = 0.5; 
        double pixelSpacingY = 0.5;

        double area = CalculatePolygonAreaWithSpacing(points, pixelSpacingX, pixelSpacingY);
        Console.WriteLine($"考虑像素间距后的多边形面积为: {area}");
    }

    static double CalculatePolygonAreaWithSpacing(List<Point> points, double pixelSpacingX, double pixelSpacingY)
    {
        int count = points.Count;
        double area0 = 0;
        double area1 = 0;

        for (int i = 0; i < count; i++)
        {
            var x = points[i].X * pixelSpacingX;
            var y = (i + 1 < count? points[i + 1].Y : points[0].Y) * pixelSpacingY;
            area0 += x * y;

            var lat = points[i].Y * pixelSpacingY;
            var lon = (i + 1 < count? points[i + 1].X : points[0].X) * pixelSpacingX;
            area1 += x * y;
        }

        return Math.Round(Math.Abs(0.5 * (area0 - area1)), 2); 
    }

    class Point
    {
        public double X { get; set; }
        public double Y { get; set; }

        public Point(double x, double y)
        {
            X = x;
            Y = y;
        }
    }
}

2.2 方法二

cs 复制代码
public double CalculatePolygonArea()
{
    Tuple<double, double>[] tupleArray = new Tuple<double, double>[m_MaxPointNum];
    for (int i = 0; i < m_MaxPointNum; i++)
    {
        var point = m_Points[i];
        tupleArray[i] = Tuple.Create((double)point.X, (double)point.Y);
    }
    WhaleFC.Image.DicomImg dcm = (WhaleFC.Image.DicomImg)m_WndPara.GetDCM();
    double[] nArrPixelSpacing = dcm.GetPixelSpacing();
    double nPixelSpacingY = nArrPixelSpacing[0];
    double nPixelSpacingX = nArrPixelSpacing[1];
    double area = 0;
    for (int i = 0; i < m_MaxPointNum; i++)
    {
        double x1 = tupleArray[i].Item1 * nPixelSpacingX;
        double y1 = tupleArray[i].Item2 * nPixelSpacingY;
        double x2 = tupleArray[(i + 1) % m_MaxPointNum].Item1 * nPixelSpacingX;
        double y2 = tupleArray[(i + 1) % m_MaxPointNum].Item2 * nPixelSpacingY;
        area += (x1 * y2) - (x2 * y1);
    }
    return Math.Abs(area / 2.0);
}

三、不考虑像素间距转换

要计算 DICOM(Digital Imaging and Communications in Medicine,医学数字成像和通信)图像中多边形的面积,一种常见的方法是使用鞋带公式(Shoelace Formula)或称为高斯面积公式。以下是使用 C#实现计算多边形面积的示例代码:

3.1 方法一

cs 复制代码
using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        // 假设多边形的顶点坐标列表
        List<Point> points = new List<Point>
        {
            new Point(0, 0),
            new Point(1, 0),
            new Point(1, 1),
            new Point(0, 1)
        };

        double area = CalculatePolygonArea(points);
        Console.WriteLine($"多边形面积为: {area}");
    }

    static double CalculatePolygonArea(List<Point> points)
    {
        int count = points.Count;
        double area0 = 0;
        double area1 = 0;

        for (int i = 0; i < count; i++)
        {
            var x = points[i].X;
            var y = i + 1 < count? points[i + 1].Y : points[0].Y;
            area0 += x * y;

            var lat = points[i].Y;
            var lon = i + 1 < count? points[i + 1].X : points[0].X;
            area1 += x * y;
        }

        return Math.Round(Math.Abs(0.5 * (area0 - area1)), 2); 
    }

    class Point
    {
        public double X { get; set; }
        public double Y { get; set; }

        public Point(double x, double y)
        {
            X = x;
            Y = y;
        }
    }
}

3.2 方法二

cs 复制代码
//计算多边形面积
public double CalculatePolygonArea(Point[] points)
{
    double area = 0;
    int j = points.Length - 1;
    for (int i = 0; i < points.Length; i++)
    {
        area += (points[j].X + points[i].X) * (points[j].Y - points[i].Y);
        j = i;
    }
    return Math.Abs(area / 2.0);
}

四、注意点

4.1 多边形是闭合的

请注意,为了确保多边形闭合,最后一个顶点和第一个顶点应该是相同的。如果提供的顶点不形成闭合多边形,则该函数会自动处理这种情况,因为它通过取模操作将最后一个顶点与第一个顶点关联起来。

4.2 多边形的重叠部分需要注意

多边形的重叠部分是否重复计算???

如果一个多边形的边相互交叉,那么按照鞋带公式计算得到的面积可能不会反映实际的几何形状,因为该公式假设多边形是简单且非自相交的。对于自相交多边形(即星形多边形),简单的鞋带公式可能无法正确计算面积,因为它可能会重复计算重叠区域。

为了正确处理自相交多边形的情况,一种方法是将其分解成多个不相交的简单多边形(通常是三角形),然后分别计算这些简单多边形的面积并进行求和。这通常涉及到更复杂的算法,例如三角剖分或者扫描线算法。

下面是一个简化的示例,使用一种方法来近似处理自相交多边形。这种方法基于对多边形边的处理,尝试确定每条边对面积的贡献。如果一条边跨越了另一条边,则需要调整计算逻辑以避免重叠区域被重复计算。但是请注意,这并不是一个完美的解决方案,对于复杂的自相交多边形,这种方法可能不会总是给出正确的结果。

以下是一个简化的处理自相交多边形的方法:

cs 复制代码
using System;
using System.Collections.Generic;

public class PolygonAreaCalculator
{
    public static double CalculatePolygonArea(List<Point> points)
    {
        if (points.Count < 3)
            throw new ArgumentException("There must be at least three points to define a polygon.");

        // Add the first point at the end to close the polygon.
        points.Add(points[0]);

        double area = 0.0;
        int n = points.Count;

        for (int i = 0; i < n - 1; i++)
        {
            Point p1 = points[i];
            Point p2 = points[i + 1];

            // Calculate the area contribution of each edge.
            area += (p1.X * p2.Y - p2.X * p1.Y);

            // Check if this edge crosses any other edges.
            for (int j = i + 2; j < n - 1; j++)
            {
                Point p3 = points[j];
                Point p4 = points[j + 1];

                // Check if the line segments (p1, p2) and (p3, p4) intersect.
                if (SegmentsIntersect(p1, p2, p3, p4))
                {
                    // Adjust the area calculation based on the intersection.
                    // This part is simplified and may not handle all cases correctly.
                    // A more sophisticated algorithm would be needed for complex cases.
                    area -= (p1.X * p2.Y - p2.X * p1.Y);
                }
            }
        }

        // Take the absolute value and divide by 2 to get the final area.
        return Math.Abs(area) / 2.0;
    }

    private static bool SegmentsIntersect(Point p1, Point p2, Point p3, Point p4)
    {
        // Implement a simple line segment intersection check.
        // This is a simplified version that does not handle all edge cases.
        double d1 = Direction(p3, p4, p1) * Direction(p3, p4, p2);
        double d2 = Direction(p1, p2, p3) * Direction(p1, p2, p4);

        return (d1 <= 0) && (d2 <= 0);
    }

    private static double Direction(Point p1, Point p2, Point p3)
    {
        return (p2.Y - p1.Y) * (p3.X - p2.X) - (p2.X - p1.X) * (p3.Y - p2.Y);
    }
}

public struct Point
{
    public double X;
    public double Y;

    public Point(double x, double y)
    {
        X = x;
        Y = y;
    }
}

这个方法尝试检查每条边是否与其他边相交,并根据交点调整面积计算。然而,这仍然是一种简化的处理方式,对于复杂的自相交多边形,需要更高级的算法来正确地计算面积。

如果您确实需要处理复杂的自相交多边形,并希望获得准确的结果,您可能需要考虑使用专门的几何处理库,如 CGAL (Computational Geometry Algorithms Library) 或者类似的库。

4.3 获取GDI+获取两个多边形区域相交、非相交区域

【C#】 使用GDI+获取两个多边形区域相交、非相交区域-CSDN博客文章浏览阅读227次。【C#】 使用GDI+获取两个多边形区域相交、非相交区域https://blog.csdn.net/wangnaisheng/article/details/140527315

4.4 在一个给定的宽、高范围内,获取到该多边形内部的所有坐标集合?

【C#】在一个给定的宽、高范围内,获取到该多边形内部的所有坐标集合?-CSDN博客文章浏览阅读594次,点赞9次,收藏7次。【C#】在一个给定的宽、高范围内,获取到该多边形内部的所有坐标集合?https://blog.csdn.net/wangnaisheng/article/details/140513467

相关推荐
李宥小哥6 小时前
C#基础10-结构体和枚举
java·开发语言·c#
2401_841495648 小时前
【计算机视觉】分水岭实现医学诊断
图像处理·人工智能·python·算法·计算机视觉·分水岭算法·医学ct图像分割
格林威11 小时前
常规可见光相机在工业视觉检测中的应用
图像处理·人工智能·数码相机·计算机视觉·视觉检测
扶尔魔ocy14 小时前
【QT常用技术讲解】multimedia实现指定分辨率打开摄像头
图像处理·qt
格林威15 小时前
工业视觉检测里的 “柔性” 是什么?
图像处理·人工智能·深度学习·yolo·计算机视觉·视觉检测
格林威18 小时前
不同光谱的工业相机有哪些?能做什么?
图像处理·人工智能·深度学习·数码相机·计算机视觉·视觉检测
CiLerLinux18 小时前
第三十八章 ESP32S3 SPIFFS 实验
图像处理·人工智能·单片机·嵌入式硬件
要做朋鱼燕1 天前
【OpenCV】图像处理入门:从基础到实战技巧
图像处理·人工智能·opencv
不枯石1 天前
Matlab通过GUI实现点云的随机一致性(RANSAC)配准
开发语言·图像处理·算法·计算机视觉·matlab
那雨倾城1 天前
PiscCode:基于OpenCV的前景物体检测
图像处理·python·opencv·计算机视觉