当前位置: 首页 > news >正文

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

一、问题分析

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

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

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

 

二、考虑像素间距转换

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

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

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

2.1 方法一

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 方法二

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 方法一

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 方法二

//计算多边形面积
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 多边形的重叠部分需要注意 

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

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

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

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

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

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

 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Redis的面试题
  • 数据类型练习
  • 25-原理图BOM的输出
  • 智慧宠物护理:智能听诊器引领健康监测新潮流
  • 利用 Docker 和 Poetry 优化 Python 应用部署
  • 鸿蒙(API 12 Beta3版)【时域可分层视频编码】 音视频编码
  • YOLOv8改进 | 主干网络 | 用EfficientNet卷积替换backbone【教程+代码 】
  • Python爬虫:下载4K壁纸
  • 六、go函数
  • 我与数据库的七年之痒:从初识到没它不行
  • Hive SQL ——窗口函数源码阅读
  • C++第一讲:开篇
  • LVS(Linux Virtual Server)负载均衡详解
  • PC端与移动端皆可用的在线3D模型评审预览工具,随时随地掌握细节
  • haproxy是什么?以及haproxy基础实验
  • 2017-08-04 前端日报
  • Docker容器管理
  • Git的一些常用操作
  • IndexedDB
  • isset在php5.6-和php7.0+的一些差异
  • javascript 总结(常用工具类的封装)
  • Java教程_软件开发基础
  • java正则表式的使用
  • JS数组方法汇总
  • Laravel深入学习6 - 应用体系结构:解耦事件处理器
  • Linux Process Manage
  • Protobuf3语言指南
  • React+TypeScript入门
  • Sublime text 3 3103 注册码
  • UMLCHINA 首席专家潘加宇鼎力推荐
  • WePY 在小程序性能调优上做出的探究
  • 从地狱到天堂,Node 回调向 async/await 转变
  • 构建工具 - 收藏集 - 掘金
  • 互联网大裁员:Java程序员失工作,焉知不能进ali?
  • 简析gRPC client 连接管理
  • 排序(1):冒泡排序
  • 如何打造100亿SDK累计覆盖量的大数据系统
  • 如何优雅地使用 Sublime Text
  • 线上 python http server profile 实践
  • 由插件封装引出的一丢丢思考
  • ​​​​​​​sokit v1.3抓手机应用socket数据包: Socket是传输控制层协议,WebSocket是应用层协议。
  • #14vue3生成表单并跳转到外部地址的方式
  • #我与Java虚拟机的故事#连载15:完整阅读的第一本技术书籍
  • (04)Hive的相关概念——order by 、sort by、distribute by 、cluster by
  • (152)时序收敛--->(02)时序收敛二
  • (2024,Flag-DiT,文本引导的多模态生成,SR,统一的标记化,RoPE、RMSNorm 和流匹配)Lumina-T2X
  • (day 12)JavaScript学习笔记(数组3)
  • (DenseNet)Densely Connected Convolutional Networks--Gao Huang
  • (HAL)STM32F103C6T8——软件模拟I2C驱动0.96寸OLED屏幕
  • (SpringBoot)第七章:SpringBoot日志文件
  • (ZT) 理解系统底层的概念是多么重要(by趋势科技邹飞)
  • (阿里云万网)-域名注册购买实名流程
  • (附源码)springboot“微印象”在线打印预约系统 毕业设计 061642
  • (附源码)基于SpringBoot和Vue的厨到家服务平台的设计与实现 毕业设计 063133
  • (四)进入MySQL 【事务】