[面试题] 判断二维空间中一点是否在旋转矩形内部

news2024/11/13 15:56:33

[面试题]:判断二维空间中一点是否在旋转矩形内部

参考
1. 判断点是否在一个矩形内
2. 向量点乘与叉乘的概念及几何意义
3. 向量叉乘
4. 向量叉乘的正负意义
5. 本工程完整代码

题目描述

已知条件旋转矩形中心center(x,y), 旋转矩形的长l 和 宽w, 以及与X轴旋转角度theta。
返回值是否在其内部,即返回是/否。


一. 主要介绍两种方法

1.1 面积法

每一个点到矩形任意两个顶点组成三角形面积,共有四个△,判断它们面积之和是否等于矩形的面积。

// 计算三角形面积
double CalculateTriangleArea(const Point& a, const Point& b, const Point& c){
    // 向量叉乘x1y2-x2y1的大小的一半
    double res = 0;
    if((a.x == b.x && a.y == b.y )|| (a.x == c.x && a.y == c.y )|| (b.x == c.x && b.y == c.y)) return res;
    Vector2d ba(a.x -b.x, a.y - b.y);
    Vector2d bc(c.x -b.x, c.y - b.y);
    res = fabs(ba.x*bc.y - bc.x*ba.y) * 0.5;
    return res;
}
    // 旋转矩形4个角点ABCD
    Point A(cloud.points[0].x, cloud.points[0].y);
    Point B(cloud.points[1].x, cloud.points[1].y);
    Point C(cloud.points[2].x, cloud.points[2].y);
    Point D(cloud.points[3].x, cloud.points[3].y);
    
    // 法一: 面积法, 分别计算点p与矩形四个边组成的面积,求和
    auto area1 = CalculateTriangleArea(A, B, p);
    auto area2 = CalculateTriangleArea(B, C, p);
    auto area3 = CalculateTriangleArea(C, D, p);
    auto area4 = CalculateTriangleArea(D, A, p);
    if(fabs(area1+area2+area3+area4 - w*h)< 1e-3) return true;
    else return false;

1.2 叉乘的方向性

只需要判断该点是否在上下两条边和左右两条边之间就行。从向量叉乘的方向性考虑,叉积( x 1 , y 1 ) × ( x 2 , y 2 ) = x 1 ∗ y 2 − x 2 ∗ y 1,大小表示两个向量围成的平行四边形的面积,正负表示两个向量的相对位置
在这里插入图片描述

    // 法二: 向量方向性, 满足(BA*Bp)(DC*Dp)>=0,先叉乘,利用叉乘正负判断方向,矩形对面所夹着的点方向相同
    Vector2d BA(A.x -B.x, A.y - B.y);
    Vector2d Bp(p.x -B.x, p.y - B.y);
    Vector2d DC(C.x -D.x, C.y - D.y);
    Vector2d Dp(p.x -D.x, p.y - D.y);
    /* 若严格按照ABCD顺序来,两个数都是大于0,乘积的方式是顾忌到矩形4个顶点的ABCD顺时针排序还是逆时针排序 */
    auto val1 = (BA.x * Bp.y - Bp.x * BA.y) * (DC.x * Dp.y - Dp.x * DC.y);
    Vector2d DA(D.x -A.x, D.y - A.y);
    Vector2d BC(B.x -C.x, B.y - C.y);
    auto val2 = (DA.x * Dp.y - Dp.x * DA.y)* (BC.x * Bp.y - Bp.x * BC.y);
    if(val1 >=0 && val2 >=0) return true;
    else return false;

二. OpenCV添加了可视化效果

效果如下图,方便调试,查看结果。
在这里插入图片描述

// 绘制箭头
void DrawArrow(cv::Mat &img, cv::Point pStart, cv::Point pEnd, int len,
               int alpha, cv::Scalar &color, int thickness, int lineType) {
  cv::Point arrow;

  double angle =
      atan2((double)(pStart.y - pEnd.y), (double)(pStart.x - pEnd.x));
  cv::line(img, pStart, pEnd, color, thickness, lineType);

  arrow.x = pEnd.x + len * cos(angle + PI * alpha / 180);
  arrow.y = pEnd.y + len * sin(angle + PI * alpha / 180);
  cv::line(img, pEnd, arrow, color, thickness, lineType);
  arrow.x = pEnd.x + len * cos(angle - PI * alpha / 180);
  arrow.y = pEnd.y + len * sin(angle - PI * alpha / 180);
  cv::line(img, pEnd, arrow, color, thickness, lineType);
}


// Debug: 绘制旋转矩形和待测试点
void DrawRotateRectangle(const pcl::PointCloud<pcl::PointXYZ>& cloud, const Point& p){
    int img_x = 200, img_y = 200;
    cv::Scalar arrow_color = cv::Scalar(0, 0, 0);
    cv::Mat img(img_y, img_x, CV_8UC3, cv::Scalar(255, 255, 255));
    DrawArrow(img, cv::Point(img_x/2.0, img_y -20),
            cv::Point(img_x/2.0, 20), 6, 45, arrow_color, 2, 8);
    DrawArrow(img, cv::Point(20, img_y/2.0),
            cv::Point(img_x-20, img_y/2.0), 6, 45, arrow_color, 2, 8);
    for(int i=0; i<4; ++i){
      if(i < 3){
        cv::line(img, cv::Point(cloud.points[i].x+100, -cloud.points[i].y+100), cv::Point(cloud.points[i+1].x+100, -cloud.points[i+1].y+100), arrow_color, 2, 8);
      }else{
        cv::line(img, cv::Point(cloud.points[i].x+100, -cloud.points[i].y+100), cv::Point(cloud.points[0].x+100, -cloud.points[0].y+100), arrow_color, 2, 8);
      }
    }
    cv::circle(img, cv::Point(p.x+100, -p.y+100), 2, arrow_color, 2, 8);
    cv::imshow("rotate_rectangle", img);
    cv::waitKey(0);
}

三. 利用中心center,长宽,theta还原四个角点坐标

    // 还原4个角点坐标
    pcl::PointCloud<pcl::PointXYZ> cloud;
    cloud.points.emplace_back(pcl::PointXYZ(-w/2.0, h/2.0, 0));
    cloud.points.emplace_back(pcl::PointXYZ(-w/2.0, -h/2.0, 0));
    cloud.points.emplace_back(pcl::PointXYZ(w/2.0, -h/2.0, 0));
    cloud.points.emplace_back(pcl::PointXYZ(w/2.0, h/2.0, 0));

    // DrawRotateRectangle(cloud, p);
    Eigen::Matrix4d mat = Eigen::Matrix4d::Identity();
    // 旋转矩阵形式
    mat << cos(theta*PI/ 180.0), -sin(theta*PI/ 180.0), 0, center.x,
           sin(theta*PI/ 180.0), cos(theta*PI/ 180.0),  0, center.y,
           0,                    0,                     1, 0,
           0,                    0,                     0, 1 ;
    std::cout << "mat: " << mat << std::endl;
    pcl::transformPointCloud(cloud, cloud, mat);

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

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

相关文章

asp.net基于web的学生选课成绩管理系统86程序

系统使用Visual studio.net2010作为系统开发环境&#xff0c;并采用ASP.NET技术&#xff0c;使用C#语言&#xff0c;以SQL Server为后台数据库。 本系统主要包含了“登录模块”、“系统用户管理模块”、“课程信息管理模块”、“教师信息管理模块”、“班级信息管理模块”、“…

Word控件Spire.Doc 【打印】教程(2):保打印word文档不显示打印处理对话框

Spire.Doc for .NET是一款专门对 Word 文档进行操作的 .NET 类库。在于帮助开发人员无需安装 Microsoft Word情况下&#xff0c;轻松快捷高效地创建、编辑、转换和打印 Microsoft Word 文档。拥有近10年专业开发经验Spire系列办公文档开发工具&#xff0c;专注于创建、编辑、转…

对标世界一流|弹性应对“供应链不确定性常态化” ——快消与重资产行业的经验互鉴

1963年&#xff0c;气象学家洛伦兹提出的“蝴蝶效应”表示&#xff1a;“一只蝴蝶在巴西扇动翅膀&#xff0c;有可能会在美国德克萨斯州引起一场龙卷风”。本文希望通过提供快消行业的先进实践&#xff0c;帮助重资产企业从“蝴蝶扇动翅膀”之前就开始行动&#xff0c;避免“龙…

Design principle: Immutability不可变性与对mutable变量的Synchronization方法

不可变性&#xff08;Immutability&#xff09;在设计模式中是指一个对象在创建后其状态就不能改变。这是一种编程思想和设计原则。在某些情况下&#xff0c;使用不变对象可以带来许多好处&#xff1a; 简化代码 make things very simple&#xff1a;不可变对象在创建后状态不会…

【问题排查篇】一次业务问题对 ES 的 cardinality 原理探究 | 京东云技术团队

作者&#xff1a;京东科技 王长春 业务问题 小编工作中负责业务的一个服务端系统&#xff0c;使用了 Elasticsearch 服务做数据存储&#xff0c;业务运营人员反馈&#xff0c;用户在使用该产品时发现&#xff0c;用户后台统计的订单笔数和导出的订单笔数不一致&#xff01; …

21.动态组件 component与keep-alive

目录 1 基本使用 2 按钮切换组件 3 keep-alive 3.1 在切换组件的时候&#xff0c;默认情况下被切换的组件就会被销毁 3.1.1 数据情况 3.1.2 生命周期函数情况 3.2 使用 keep-alive 3.3 keep-alive的生命周期函数 3.4 缓存指定组件 include 3.5 不缓存指定组…

【51单片机】点亮一个LED灯(看开发板原理图十分重要)

&#x1f38a;专栏【51单片机】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【The Right Path】 &#x1f970;大一同学小吉&#xff0c;欢迎并且感谢大家指出我的问题&#x1f970; 目录 &#x1f354;基础内容 &#x1f3f3…

HMS Core 6.10.0版本发布公告

分析服务 ◆ 事件分析下新增商品订阅分析报告&#xff0c;帮助开发者了解应用内用户付费订阅概况&#xff0c;评估订阅付费价值&#xff1b; ◆ 营销分析、用户质量、转化分析以及过滤器中&#xff0c;新增广告系列/广告任务通过ID进行搜索的功能&#xff0c;通过更便捷高效的…

【笔试强训选择题】Day8.习题(错题)解析

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;笔试强训选择题 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01;&#xff01; 文章目录…

Skywalking

Skywalking skywalking是一个apm系统&#xff0c;包含监控&#xff0c;追踪&#xff0c;并拥有故障诊断能力的 分布式系统 一、Skywalking介绍 1.什么是SkyWalking Skywalking是由国内开源爱好者吴晟开源并提交到Apache孵化器的产品&#xff0c;它同时吸收了Zipkin /Pinpoint …

C语言初阶之常量和变量

常量和变量 什么是常量和变量常量示例 定义变量的方法变量的命名变量的分类示例 变量的使用变量的作用域和生命周期作用域生命周期 结语 什么是常量和变量 在C程序执行过程中&#xff0c;其值不发生改变的量称为常量&#xff0c;其值可变的量称为变量。它们可与数据类型结合起…

BoldReports Embedded Reporting 5.1 Crack

Embed Paginated Reports 嵌入式报告平台&#xff0c;商业智能报告解决方案&#xff0c;探索满足各种业务需求的报告功能&#xff0c;所有功能View Features&#xff0c;像素完美报告&#xff0c;创建像素完美的分页业务报表&#xff0c;随处部署&#xff0c;选择适合您的部署环…

Android---ANR问题分析

目录 ANR 概念 超时检测机制 如何避免 ANR 问题&#xff1f; ANR 分析 ANR 问题线上监控 ANR 概念 ANR(Application Not Response)&#xff0c;是指应用程序未响应&#xff0c;Android 系统对于一些事情需要在一定时间范围内完成&#xff0c;如果超过预定时间未能得到有效…

VSCode作业1:猜数字游戏和简单计数器(包含完整代码)

目录 猜数字游戏 一、使用‘random’函数获取随机数 二、 分情况讨论输入值大小情况 三、HTML代码 四、CSS样式及运行效果 简单计数器&#xff08;计时器&#xff09; 一、使用‘setInterval’函数实现计数效果 二、使用’clearInterval‘函数实现暂停计数和重新计数效果 …

【机器学习】sklearn的集成学习用于图像分类从0到1,注意点和坑点

文章目录 前言1.需求分析1.1 场景1.2 解决方案 2. 代码2.1 提取特征2.2 构建分类器2.4 集成模型2.5 总的训练代码 3.fast api 封装4.总结 前言 深度学习崛起后&#xff0c;好像机器学习就没落了&#xff0c;但在固定场景下&#xff0c;还是很好用的。下面就是展厅项目的识别任…

解决Edge Dev更新后NewBing侧边栏消失的问题,并使用NewBing作画

文章目录 解决Edge Dev更新后NewBing侧边栏消失的问题&#xff0c;并使用NewBing作画问题来源操作步骤打开侧边栏步骤尝试让NewBing给出图像输出表情包或者其他图片使用NewBing作画 查看聊天记录插件 总结 解决Edge Dev更新后NewBing侧边栏消失的问题&#xff0c;并使用NewBing…

标签制作软件如何批量制作DotCode码

DotCode码是由不连续的点组成的二维条形码符号。设计的初衷是工业流水线上使用高速喷墨/激光打印机印刷产品有效期、批号以及序列号等。其尺寸是灵活可变的&#xff0c;可以根据货品表面的大小来调整印刷。下面带大家一起看一下在标签制作软件中如何批量制作&#xff1a; 打开…

STM32F4_十进制和BCD码的转换

目录 前言 1. BCD码 2. BCD码和十进制转换的算法 前言 最近在学习STM32单片机&#xff08;不仅仅是32&#xff09;的RTC实时时钟系统的过程中&#xff0c;需要配置时钟的时间、日期&#xff1b;这些都需要实现BCD码和十进制之间进行转换。这里和大家一起学习BCD码和十进制之…

C++函数必备简单知识

目录 1、函数的定义与声明 &#xff08;1&#xff09;定义 &#xff08;2&#xff09;声明 2、指针传参 3、引用 4、函数的引用传参 5、函数重载 overlord &#xff08;1&#xff09;参数数量不同 &#xff08;2&#xff09;参数类型不同 6、避免overlord歧义 7、内…

Opencv+Python图像像素处理

目录 二值图像的像素访问、修改 单个像素访问、修改 多个像素修改 彩色图像&#xff08;三维数组&#xff09; 像素访问、修改 BGR模式 像素访问、修改 二值图像的像素访问、修改 单个像素访问、修改 import numpy as np import cv2 as cv # 使用Numpy库中的函数zeros()可…