记录导致计算轮廓面积出错的一个坑点

news2025/5/22 13:26:00

1.前言

        计算轮廓面积是常见的几何算法话题,获取轮廓面积、计算轮廓法线等场景会涉及到。计算轮廓面积的方法有很多,一种常用的是微积分思路的分段求和办法,即组成轮廓的每条线段与X轴或Y轴进行有向投影,轮廓边线与X轴或Y轴的投影之和即为轮廓的有向面积。

上图中轮廓共有7条边,每条边与Y轴投影,投影面积有向,每个投影均为梯形,计算公式为:

double areaThis = (abs(d0X) + abs(d1X)) * (d1Y - d0Y) * 0.5;

其中第0、1、6的投影为正,第2、3、4、5的投影为负,累积即为轮廓面积(绿色填充部分)。 

如上所示,如果关心面积的正负时,一般将轮廓移到第一或第四象限再求面积。满足上述条件时,逆时针轮廓的面积为正,顺时针轮廓的面积为负。

2.问题

在调试问题时发现上图中的轮廓面积计算为负,摸不着头脑 !=-=,好吧,那就调试,发现此轮廓有如下特点:

  • X坐标很大;
  • 同时边线之间并不是“紧密连接”的,而是在一定误差内连接;
  • 边线都比较短;

2.1. 问题分析

正常来说该轮廓面积为正,且值比较小,为什么会计算错误呢?

轮廓的边没有紧密连接,之间是有缝隙的,也就是如果紧密连接的话需要再加很短的线,轮廓的“准确”面积应该要包括要“紧密”连接而添加的短线与坐标轴的有向投影面积。

加之该轮廓X坐标值很大,上述系列短线与Y轴投影面积值(梯形)加起来就比较大了,影响到了最终的面积和的值,甚至影响了面积和的符号!

3. 解决办法

3.1. 方案一

将轮廓偏置到贴近Y轴位置,再进行面积计算,这样导致该问题的的“短线”围成的面积会很小,不足以影响轮廓边线“不紧密连接”导致的误差。

这种办法是一种中和兼容的处理办法,兼容轮廓边线可能不紧密连接的情况,同时也需要计算轮廓的包围盒最小点,以将轮廓偏置到贴近Y轴的第一或第四象限,也增加了计算的耗时。

3.2. 方案二

处理导致此问题的轮廓,在生成轮廓或计算面积前将轮廓边线紧密连接。

4. 写在后面

double GeometryUtils::GetArea(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 d0X = pt0.X + 100000.0;
         double d0Y = pt0.Y + 100000.0;
         double d1X = pt1.X + 100000.0;
         double d1Y = pt1.Y + 100000.0;

         double areaThis = (abs(d0X) + abs(d1X)) * (d1Y - d0Y) * 0.5;
         dArea += areaThis;
     }

     return dArea;
}

根据需要进行方案的选取,博主采用了方案二,具体是在生成轮廓的函数中进行了处理保证轮廓边线“紧密连接”,这有利于规避由“不紧密连接”带来的很多问题,降低问题处理的复杂度,同时减少了兼容处理过程,也可以节省了时间。

欢迎交流:公众号:geometrylib

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1968617.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【SQL Server】SQL Server基础知识概览

目录 第1章&#xff1a;SQL Server 概览 SQL Server 版本介绍 SQL Server 架构 SQL Server 组件 第1章&#xff1a;SQL Server 概览 SQL Server 版本介绍 SQL Server 是 Microsoft 开发的一款关系型数据库管理系统 (RDBMS)&#xff0c;广泛应用于企业级数据存储和处理场景…

Mysql学习-day15

Mysql学习-day15 1. 行列转换 在MySQL中&#xff0c;行列转换可以通过使用CASE语句结合聚合函数来实现。 表t_score数据如图所示 我们想要以学科为列名&#xff0c;展示每个学生的科目成绩&#xff0c;可以先用CASE语句来选出每科的成绩&#xff0c;再进行求和。 选择科目时…

【C++】模拟实现list

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 目录 一.了解项目及其功能 &#x1f4cc;了解list官方标准 了解模拟实现list &#x1f4cc;了解更底层的list实现 二.list迭代器和vector迭代器的异同 &#x1f4cc;迭代…

SSH实现电脑VScode免密登录到虚拟机其原理

在网上想看一下这个原理。发现写的还是比较乱&#xff0c;所以自己总结了一份方便回顾 SSH免密登录的原理主要基于非对称密钥加密技术&#xff0c;比较常用的是RSA算法。 以下是SSH免密登录的详细步骤和原理&#xff1a; 1. 生成密钥对 在客户端上生成一对密钥&#xff0c;…

系统复习Java日志体系

一&#xff0c;我们采用硬编码体验一下几个使用比较多的日志 分别导入几种日志的 jar 包 <?xml version"1.0" encoding"UTF-8"?><project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSch…

【已解决】YOLOv8加载模型报错:super().__init__(torch._C.PyTorchFileReader(name_or_buffer))

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

C#——Json数据存储

本文使用的软件为VS2022&#xff0c;不同的软件使用上有些许差异。 C#数据存储 关于数据存储&#xff0c;一般在退出控制台之后&#xff0c;暂存的数据都会释放掉&#xff0c;有没有什么方法能够在下一次进入的时候还能加载上一次的数据呢&#xff1f;答案是有的&#xff0c;关…

利用Arcgis设置分式标注(分子分母标注)

因工作需要&#xff0c;需要设置分式标注&#xff0c;下面详细介绍下如何利用arcgis 设置分式标注&#xff0c;以下操作以供参考&#xff0c;如有疑义可提出。 一、准备工作 软件&#xff1a;arcmap 示例数据&#xff1a;行政区shp矢量图 二、操作步骤 1.添加数据 将行政区sh…

Golang | Leetcode Golang题解之第307题区域和检索-数组可修改

题目&#xff1a; 题解&#xff1a; type NumArray struct {nums, tree []int }func Constructor(nums []int) NumArray {tree : make([]int, len(nums)1)na : NumArray{nums, tree}for i, num : range nums {na.add(i1, num)}return na }func (na *NumArray) add(index, val …

MinIO安装(思路、方法、步骤(以centos8安装为例))

MinIO安装&#xff08;思路、方法、步骤&#xff08;以centos8安装为例&#xff09;&#xff09; 简介 MinIO 是一个高性能、开源的对象存储系统&#xff0c;旨在提供简单、可扩展的存储解决方案&#xff0c;特别适用于大数据、AI 和 ML 应用。 步骤记录 首先我们进入官网看…

前端使用 Konva 实现可视化设计器(19)- 连接线 - 直线、折线

本章响应小伙伴的反馈&#xff0c;除了算法自动画连接线&#xff08;仍需优化完善&#xff09;&#xff0c;实现了可以手动绘制直线、折线连接线功能。 请大家动动小手&#xff0c;给我一个免费的 Star 吧~ 大家如果发现了 Bug&#xff0c;欢迎来提 Issue 哟~ github源码 gitee…

最全个人笔记【Makefile】

1. 基本概念 1.1 make是什么 当一个项目中要编译的文件很多时&#xff0c;手工使用编译器一个个进行编译&#xff0c;很明显不具有可操作性&#xff0c;此时必须借助某些软件&#xff0c;协助我们有序地、正确地自动编译整个工程的所有该编译的文件。这样的软件被称为 工程管…

Simulink|基于粒子群算法的永磁同步电机多参数辨识

目录 主要内容 模型研究 结果一览 下载链接 主要内容 仿真程序参考文献《改进粒子群算法的永磁同步电机多参数辨识》&#xff0c;采用粒子群算法与simulink模型结合的方式&#xff0c;对永磁同步电机进行多参数辨识。程序以定子绕组电阻、d轴电感、q轴电感和永磁…

ai写作免费版工具上哪找?一文详解5大ai写作神器

面对写作难题&#xff0c;你是否曾感到力不从心&#xff1f;从创意枯竭到语法错误&#xff0c;每个写作环节都可能成为挑战。但如今&#xff0c;有了ai写作工具的帮助&#xff0c;这些难题都能迎刃而解。今天&#xff0c;就让我们一起来看看ai写作免费网页版应该怎么选吧&#…

Win11系统文件资源管理器鼠标右键卡顿解决方法

引用链接&#xff1a; Windows 11文件资源管理器崩溃怎么解决&#xff1f;看看这7个解决办法&#xff01;

订单搜索分页查询业务

文章目录 概要整体架构流程技术细节小结 概要 订单搜索分页查询是电商、物流、零售等众多行业中的常见需求&#xff0c;主要用于管理和分析大量订单数据. 需求分析以及接口设计 技术细节 1.Controller层: 根据接口设计来写 ApiOperation("订单搜索")GetMapping(…

使用plink和git进行数据处理

首先使用git进行plink环境配置&#xff0c;显示环境安装成功&#xff0c;在此环境下可以使用plink 在基因型数据处理过程中&#xff0c;看到vcf文件后首要做的就是将vcf文件转成二进制文件&#xff0c;输入命令 plink --vcf genotype.vcf --allow-extra-chr --recode --out tes…

滑动窗口代码实现

public int minSubArrayLen(int target, int[] nums) {int len nums.length;int res len 1;//最大是len&#xff0c;如果最后res结果还是n1说明没有答案返回0int sum0;int left0;for(int right0; right<len; right){sumnums[right];while(sum>target){//不需要判断rig…

算法 —— 递推

目录 递推 数楼梯 斐波那契数列 一维数组递推 P1002 过河卒 二维数组递推 P1044 栈 卡特兰数 递推 将一个很大的任务分解成规模小一些的子任务&#xff0c;子任务分成更小的子任务&#xff0c;直到遇到初始条件&#xff0c;最后整理归纳解决大任务的思想就是递推与递…

Kafka基本概念,工作流程介绍

1、消息队列与Kafka 1.1、Kafka简介 Kafka使用scala开发&#xff0c;支持多语言客户端&#xff08;c、java、python、go等&#xff09; Kafka最先由LinkedIn公司开发&#xff0c;之后成为Apache的顶级项目。 Kafka是一个分布式的、分区化、可复制提交的日志服务 LinkedIn使…