【算法】【算法杂谈】判断点是否在三角形内部(面积法和向量法)

news2024/12/28 19:55:15

目录

  • 前言
  • 问题介绍
  • 解决方案
  • 代码编写
    • java语言版本
    • c语言版本
    • c++语言版本
  • 思考感悟
  • 写在最后

前言

当前所有算法都使用测试用例运行过,但是不保证100%的测试用例,如果存在问题务必联系批评指正~

在此感谢左大神让我对算法有了新的感悟认识!

问题介绍

原问题
给定三个点坐标代表三角形的三个顶点,再给定一个(x,y)点,判断该点是否在三角形内部

解决方案

原问题
方法一:面积法
1、利用海伦公式求出以改点为顶点,三角形各边为底边的三角形面积之和,如果该和大于三角形的总面积,那么点在外面,如果不大于,则点在里面
优点:容易想到,容易编写,只需要编写点到点之间的距离即可利用公式快速计算面积从而判断答案
缺点:由于海伦公式存在开根会导致精度缺失判断失误
方法二:向量法
如下图:
在这里插入图片描述
1、向量的叉乘,假设A(2,1) B(2,0),则AxB = 0-2 = -2 < 0 ,也就是说如果A向量旋转到B向量同向时,叉乘为负数,反之则为正数
2、由此可以得到一个点在向量的那一侧,如果在右侧,那么叉乘为负数,如果在左侧,那么叉乘为正数
3、为什么要这个准备工作呢?我们再看一张图:
在这里插入图片描述

4、如果D点在三角形内,那么我们就能够得到D点一定在ABC三条边的同一侧!
5、所以更具这个定理我们只需要写一个叉乘的方法就能够解决
优点:简单快捷、没有精度缺失问题
缺点:不容易想到,容易被方法一抢风头~

代码编写

java语言版本

原问题:
方法一:

   /**
     * 二轮测试:判断点是否在三角形的内部
     * 方法一:面积法
     * @param x1
     * @param y1
     * @param x2
     * @param y2
     * @param x3
     * @param y3
     * @param x
     * @param y
     * @return
     */
    public static boolean isInsideCp1(double x1, double y1,
                                      double x2, double y2,
                                      double x3, double y3,
                                      double x, double y) {
        return getSquare(x1, y1, x2, y2, x, y) + getSquare(x1, y1, x3, y3, x, y) + getSquare(x3, y3, x2, y2, x, y)
                <= getSquare(x1, y1, x2, y2, x3, y3);
    }

    /**
     * 给定三个点,求三角形面积
     * @param x1
     * @param y1
     * @param x2
     * @param y2
     * @param x3
     * @param y3
     * @return
     */
    private static double getSquare(double x1, double y1,
                                    double x2, double y2,
                                    double x3, double y3) {
        // 先求三边
        double len1 = getLen(x1, y1, x2, y2);
        double len2 = getLen(x1, y1, x3, y3);
        double len3 = getLen(x2, y2, x3, y3);
        double p = (len1 + len2 + len3)/2;
        return Math.sqrt(p * (p-len1) * (p - len2) * (p - len3));
    }

    /**
     * 计算两点之间的距离
     * @param x1
     * @param y1
     * @param x2
     * @param y2
     * @return
     */
    private static double getLen(double x1, double y1,
                                 double x2, double y2) {
        return Math.sqrt((x1-x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
    }


方法二:

    /**
     * 二轮测试:判断点是否在三角形内
     * 方法二:向量法
     * 该方法不存在精度问题导致的结果不准确
     * @param x1
     * @param y1
     * @param x2
     * @param y2
     * @param x3
     * @param y3
     * @param x
     * @param y
     * @return
     */
    public static boolean isInsideCp2(double x1, double y1,
                                      double x2, double y2,
                                      double x3, double y3,
                                      double x, double y) {
        // 判断点是否是顺时针顺序,如果不是则调整一下
        if (getCrossCp2(x1, y1, x3, y3, x2, y2) < 0) {
            // 说明x2,y2在右边,交换3和2
            double temx = x2;
            double temy = y2;
            x2 = x3;
            y2 = y3;
            x3 = temx;
            y3 = temy;
        }
        // 判断叉乘是否都是小于0
        if (getCrossCp2(x1, y1, x2, y2, x, y) <= 0
                && getCrossCp2(x2, y2, x3, y3, x, y) <= 0
                && getCrossCp2(x3, y3, x1, y1, x, y) <= 0) {
            return true;
        }
        return false;
    }


    /**
     * 计算x,y点在(x1, y2) -> (x2, y2) 向量的左边还是右边
     * 大于0,左边 小于0,右边
     * @param x1
     * @param y1
     * @param x2
     * @param y2
     * @param x
     * @param y
     * @return
     */
    public static double getCrossCp2(double x1, double y1,
                                     double x2, double y2,
                                     double x, double y) {
        // 以x1,y1为基准
        double xs = x2 - x1;
        double ys = y2 - y1;
        double xs1 = x - x1;
        double ys1 = y - y1;
        // 计算叉乘
        return xs * ys1 - ys * xs1;
    }





    public static void main(String[] args) {
        System.out.println(isInsideCp2(0 ,0, 2, 0, 1, 2, 1, 1));
    }

c语言版本

正在学习中

c++语言版本

正在学习中

思考感悟

这也是个数学题,如果知道解法后,对于编程来说不算什么大问题,比较简单。

写在最后

方案和代码仅提供学习和思考使用,切勿随意滥用!如有错误和不合理的地方,务必批评指正~
如果需要git源码可邮件给2260755767@qq.com
再次感谢左大神对我算法的指点迷津!

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

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

相关文章

netcore工程在linux下调用linux动态库

文章的内容可能看着枯燥&#xff0c;排版也存在一些问题&#xff0c;但是如果你遇到相关问题&#xff0c;真的无法解决的时候&#xff0c;不妨沉下心来好好阅读一下这篇文章&#xff0c;你会有所收获&#xff0c;也可以先跳到文章最后&#xff0c;看看是不是对你的问题有价值。…

Day955.到底是重构,还是重写? -遗留系统现代化实战

到底是重构&#xff0c;还是重写&#xff1f; Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于到底是重构&#xff0c;还是重写&#xff1f;的内容。 到底是重构&#xff0c;还是重写&#xff1f;这是一个困扰着很多团队的问题。 重构吧&#xff0c;遗留系统积重难…

神经网络模型入门及蠓虫分类问题简单实战

学习知识要实时简单回顾&#xff0c;我把学习的神经网络模型简单梳理一下&#xff0c;方便入门与复习。 神经网络模型 神经网络简介 人工神经网络是在现代神经科学的基础上提出和发展起来的&#xff0c;旨在反映人脑结构及功能的一种抽象数学模型。自 1943 年美国心理学家W.M…

【分段DP】ABC275 F

一万年没写DP了 这么简单的DP我居然没写出来 F - Erase Subarrays (atcoder.jp) 题意&#xff1a; 思路&#xff1a; 原本的思路是这样的&#xff1a; 看到3000的数据范围就是n^2的DP了 看到删子串&#xff0c;那么留下来的就是子序列&#xff0c;要使得剩下来的子序列的…

剑指Offer--05替换空格58左旋字符串

文章目录 一、剑指Offer--05.替换空格二、剑指Offer--58.左旋字符串 一、剑指Offer–05.替换空格 题目是这样的 意思是将字符串s中的空格替换为字符串"%20",如果只是替换一个字符还好&#xff0c;可以在原数组直接替换&#xff0c;但是是将空格替换为字符串&#xf…

Vue+Echarts 项目演练(下)收尾工作图表绘制

设置销售总量图表 中心容器地图设置 产品库存统计图 产品类别图表 项目可视化完结-整体展示 设置销售总量图表 在第一个容器中进行图表设置 <template><div><h2>A</h2><div class"chart" id"oneChart">容纳后期的图表…

shell编程规范与变量

shell脚本编程规范 shell脚本概述 将要执行的命令按顺序保存到一个文本文件给该文件可执行权限可结合各种Shell控制语句以完成更复杂的操作 Shell脚本应用场景 重复性操作交互性任务批量事务处理服务运行状态监控定时任务执行 什么是Shell 就是与内核沟通的界面、应用程序等…

[JAVA数据结构]顺序表ArrayList

目录 1.线性表 2.顺序表 3.ArrayList简介 4.ArrayList的使用 4.1ArrayList的构造方法 4.2ArrayList的常用操作 4.3ArrayList的遍历方法 4.4ArrayList的扩容机制 5.ArrayList的具体运用 ArrayList是一种基于数组的数据结构&#xff0c;是线性表的一种&#xff0c;也是…

[NLP]如何训练自己的大型语言模型

简介 大型语言模型&#xff0c;如OpenAI的GPT-4或谷歌的PaLM&#xff0c;已经在人工智能领域掀起了一场风暴。然而&#xff0c;大多数公司目前没有能力训练这些模型&#xff0c;而且完全依赖少数几家大型科技公司作为技术提供者。 在Replit&#xff0c;我们已经大量投资于所需…

linux-01-基础回顾-虚拟机安装linux(centos7)、linux常用命令

文章目录 Linux-Day01课程内容1. 前言1.1 什么是Linux1.2 为什么要学Linux1.3 学完Linux能干什么 2. Linux简介2.1 主流操作系统2.2 Linux发展历史2.3 Linux系统版本 3. Linux安装3.1 安装方式介绍3.2 安装VMware3.3 安装Linux3.4 网卡设置3.5 安装SSH连接工具3.5.1 SSH连接工具…

Neural ODE 神经常微分方程

Neural ODE ODE常微分方程 欧拉法求解&#xff1a;欧拉法求解过程是一个递归的过程&#xff0c;这个思想和牛顿法、梯度下降法是相似的。并且它将函数离散化&#xff0c;分割成一个个小段来求解。欧拉法求解的常微分方程的形式通常为 图片来自知乎Neural ODE&#xff0c;这个…

EventBus源码解析

文章目录 前言一、EventBus使用二、EventBus事件流程分析1.注册订阅者2.发布事件Event3.接收事件Event4.取消注册订阅者 三、发送粘性事件问答EventBus 以及它的优点EventBus原理 EventBus中设计模式为什么要使用 EventBus 来替代广播呢&#xff1f;说下 5 种线程模式的区别Eve…

进程、进程组、会话期

进程 在内核中&#xff0c;每个进程都使用一个不同的大于零的正整数来标识&#xff0c;称为进程号pid&#xff08;process ID&#xff09;。 进程组 一个进程可以通过 fork() 调用创建一个或多个子进程&#xff0c;这些进程就可以构成一个进程组。例如&#xff0c; liyongj…

UE4架构初识(四)

目录 UE4仿真引擎学习 一、架构基础 1. GameMode 2. GameState 3. GameSession UE4仿真引擎学习 一、架构基础 1. GameMode 即使最开放的游戏也拥有基础规则&#xff0c;而这些规则构成了 Game Mode。在最基础的层面上&#xff0c;这些规则包括&#xff1a; 出现的玩家和…

深度赋能产业数字化转型,蚂蚁集团数字化三件套亮相中国国际金融展

“十四五”规划纲要指出&#xff1a;加快推动数字产业化&#xff0c;推进产业数字化转型&#xff0c;实施“上云用数赋智”行动&#xff0c;推动数据赋能全产业链协同转型。明确提出了通过科技创新&#xff0c;加快产业数字化转型的要求。 4月25日&#xff0c;以“荟萃金融科技…

Flowable打印调用原生API查询接口的SQL日志

一.简介 建议在 Spring Boot 的 application.properties 中添加如下配置&#xff0c;开启 flowable 日志&#xff1a; logging.level.org.flowabledebug这个配置表示开启 flowable 的日志&#xff0c;开启日志的好处是可以看到底层的 SQL语句。 二.查询部署信息 例如查询流…

【python中的魔法方法有哪些?】

__init__(self, ...): 类的构造函数&#xff0c;用于创建一个类的实例并初始化它的属性。__str__(self): 返回对象的字符串表示形式&#xff0c;可以用于打印对象或者转化成字符串。__repr__(self): 返回对象的字符串表示形式&#xff0c;通常是用于开发者调试和查看对象信息。…

4.24~25(总结)

第一周任务 - Virtual Judge 分析&#xff1a;这道题开始想错了&#xff0c;所以错了一次。后来又仔细读了一遍题&#xff0c;才发现&#xff0c;要是最长的那个排序子数组&#xff0c;所以第二次就做出来了&#xff0c;它其实应该分为两大块&#xff0c;第一块找左边的起点&a…

HTTPS (HTTP+SSL) 对称/非对称加密 中间人攻击 证书加密

&#x1f496; 欢迎来阅读子豪的博客&#xff08;JavaEE篇 &#x1f934;&#xff09; &#x1f449; 有宝贵的意见或建议可以在留言区留言 &#x1f4bb; 欢迎 素质三连 点赞 关注 收藏 &#x1f9d1;‍&#x1f680;码云仓库&#xff1a;补集王子的代码仓库 不要偷走我小火…

“源擎”云原生分布式核心业务系统有什么产品优势?

“源擎”核心系统利用云原生、分布式、微服务技术&#xff0c;基于企业架构设计思想&#xff0c;构建了基础服务、业务服务、交易中心以及系列支撑组件&#xff0c;包含业务架构和多个微服务应用。 业务架构中&#xff0c;交易中心为银行提供了更灵活的选择&#xff0c;支持产…