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

一种误差较小的轮廓面积计算算法

1.背景

        基于微分思想的轮廓面积计算方法之一是将多边形轮廓边与X轴会Y轴进行围合,形成一个个梯形,每个梯形的面积有符号,累计求和即得到多边形轮廓的面积。详见博主之前的文章,

记录导致计算轮廓面积出错的一个坑点-CSDN博客文章浏览阅读377次,点赞4次,收藏9次。计算轮廓面积是常见的几何算法话题,获取轮廓面积、计算轮廓法线等场景会涉及到。计算轮廓面积的方法有很多,一种常用的是微积分思路的分段求和办法,即组成轮廓的每条线段与X轴或Y轴进行有向投影,轮廓边线与X轴或Y轴的投影之和即为轮廓的有向面积。其中第0、1、6的投影为正,第2、3、4、5的投影为负,累积即为轮廓面积(绿色填充部分)。如上所示,如果关心面积的正负时,一般将轮廓移到第一或第四象限再求面积。满足上述条件时,逆时针轮廓的面积为正,顺时针轮廓的面积为负。https://blog.csdn.net/baidu_38621657/article/details/140853728

        如果出现轮廓跨Y轴的情况,则需要将轮廓平移到Y轴右侧,此时面积符号为逆正顺负(当然平移到Y轴左侧也可以,如果那样所计算面积的符号为“顺正逆负”)。

        但是这种方法可能会出现精度误差较大,从而导致面积值和符号计算错误的情况,究其原因是因为对轮廓做了偏置处理,而这种处理会带来误差,偏置的距离越大误差可能越大,详细原因见博主此前的文章:《关于float浮点值二进制存储和运算精度损失的话题》。

关于float浮点值二进制存储和运算精度损失的话题_float的二进制存储和输出-CSDN博客文章浏览阅读1k次,点赞8次,收藏18次。浮点值的存储、运算都可能会带来精度损失,了解精度损失背后的机制原因方便我们更好的了解什么情况下会发生精度损失、什么情况下精度损失较大,以及思考怎么避免或减少精度损失。_float的二进制存储和输出https://blog.csdn.net/baidu_38621657/article/details/141027014        需要尽量减少和简化计算过程,保持算法的简便整洁,注意这里的简化不是接受更大的误差的意思,指的是简化逻辑,使用精简准确的公式或算法过程。

对于此种情况(轮廓跨越Y轴)该怎么处理,避免不必要的操作过程,从而减少精度损失呢?

2. 公式推导

博主比较懒, 推导过程就不详细讲述了,有兴趣可以和博主联系或关注博主公众号。

3. 代码

/// <summary>
/// 求有向面积,顺时针为负,逆时针为正
/// </summary>
/// <param name="polygon"></param>
/// <returns></returns>
double GetArea2(const list<Line>& polygon, const Transform& trsW2L)
{//  目前只支持边为线段的轮廓double dArea = 0;for (auto curve : polygon){Vector3f pt0, pt1;Transform::MultPoint(trsW2L, curve.pt0, pt0);Transform::MultPoint(trsW2L, curve.pt1, pt1);double areaThis = 0.0;if (pt0.X >= 0.f){if (pt1.X >= 0.f)areaThis = (pt0.X + pt1.X) * (pt1.Y - pt0.Y) * 0.5;else{double s1 = (pt1.Y - pt0.Y) * pt0.X * pt0.X * 0.5 / (pt0.X - pt1.X);double s2 = -(pt1.Y - pt0.Y) * pt1.X * pt1.X * 0.5 / (pt0.X - pt1.X);areaThis = s1 + s2;}}else{if (pt1.X >= 0.f){double s1 = -(pt1.Y - pt0.Y) * pt0.X * pt0.X * 0.5 / (pt1.X - pt0.X);double s2 = (pt1.Y - pt0.Y) * pt1.X * pt1.X * 0.5 / (pt1.X - pt0.X);areaThis = s1 + s2;}else{areaThis = (pt0.X + pt1.X) * (pt1.Y - pt0.Y) * 0.5;}}dArea += areaThis;}return dArea;
}

各种象限和跨象限情况的单元测试均通过。

欢迎交流,相互学习,公众号:geometrylib

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 数字通信世界编辑部数字通信世界杂志社2024年第8期目录
  • 知识付费小程序搭建:开启知识变现新时代
  • QPushButton设置信号与槽一在UI界面直接设置槽函数
  • 企业微信hook协议接口,聚合群聊客户管理工具开发
  • Pinia 与 Vuex 对比
  • DeepWalk【图神经网络论文精读】笔记
  • Linux软件管理
  • 我的AI绘画之旅——中层管理员的副业探索与收获
  • Vitis AI 综合实践(DPU example: dpu_resnet50.ipynb)
  • 密钥分发与公钥认证:保障网络通信的安全
  • css画个熊猫
  • 数据结构--栈和队列
  • 乾元通多卡聚合技术在无人配送车应用领域通信保障方案
  • vue3+ts文件流导出xlsx表格需要token
  • Qt text-align和padding属性
  • [case10]使用RSQL实现端到端的动态查询
  • 《Javascript数据结构和算法》笔记-「字典和散列表」
  • 【108天】Java——《Head First Java》笔记(第1-4章)
  • Github访问慢解决办法
  • github指令
  • laravel 用artisan创建自己的模板
  • SAP云平台运行环境Cloud Foundry和Neo的区别
  • SegmentFault 社区上线小程序开发频道,助力小程序开发者生态
  • Spark学习笔记之相关记录
  • Vue.js 移动端适配之 vw 解决方案
  • vuex 笔记整理
  • Webpack 4 学习01(基础配置)
  • Webpack入门之遇到的那些坑,系列示例Demo
  • 编写高质量JavaScript代码之并发
  • 从零搭建Koa2 Server
  • 模型微调
  • 浅谈Kotlin实战篇之自定义View图片圆角简单应用(一)
  • 如何实现 font-size 的响应式
  • 深入 Nginx 之配置篇
  • 好程序员web前端教程分享CSS不同元素margin的计算 ...
  • ​2021半年盘点,不想你错过的重磅新书
  • ​补​充​经​纬​恒​润​一​面​
  • !! 2.对十份论文和报告中的关于OpenCV和Android NDK开发的总结
  • $$$$GB2312-80区位编码表$$$$
  • $.each()与$(selector).each()
  • (51单片机)第五章-A/D和D/A工作原理-A/D
  • (C++17) optional的使用
  • (笔记)M1使用hombrew安装qemu
  • (二)【Jmeter】专栏实战项目靶场drupal部署
  • (附源码)spring boot基于Java的电影院售票与管理系统毕业设计 011449
  • (附源码)spring boot网络空间安全实验教学示范中心网站 毕业设计 111454
  • (四)opengl函数加载和错误处理
  • (一)python发送HTTP 请求的两种方式(get和post )
  • (原创)可支持最大高度的NestedScrollView
  • (转)我也是一只IT小小鸟
  • ***检测工具之RKHunter AIDE
  • .Mobi域名介绍
  • .MSSQLSERVER 导入导出 命令集--堪称经典,值得借鉴!
  • .Net 6.0 处理跨域的方式
  • .NET MAUI Sqlite程序应用-数据库配置(一)