判断某点是否在三角形内(Python)

news2024/11/27 8:36:26

已知三角形的三个顶点坐标,判断某个点是否在三角形中(在三角形的边上,我们也视作在三角形中),我们提供不同的方法。

image

方法1:内角和等于360°

方法2:等面积法

即对于△ABC内的某一点P,连接PA、PB、PC得到三条线段,当且仅当三条线段组成的三个夹角和为360°的时候,该点才位于三角形内部。但此种方法的计算涉及到平方根、反正(余)弦,效率低。

类似的还有,P与ABC三个顶点组成的三个三角形,面积之和等于△ABC的面积,同样可以证明点P位于三角形内部,但效率也很低。

知道三个点,如何求该三个点为顶点的三角形的面积?使用海伦公式:

,其中,a,b,c表示三个边长,p表示半周长

#面积法判断点是否在三角形内
def isInside(x1, y1, x2, y2, x3, y3, x, y):
    def getSideLength(x1, y1, x2, y2):
        a = abs(x2 - x1)
        b = abs(y2 - y1)
        return math.sqrt(a*a + b*b)
 
    def getArea(x1, y1, x2, y2, x3, y3):
        a = getSideLength(x1, y1, x2, y2)
        b = getSideLength(x1, y1, x3, y3)
        c = getSideLength(x2, y2, x3, y3)
        p = (a + b + c) / 2
        return math.sqrt(p * (p-a) * (p-b) * (p-c))
 
    area1 = getArea(x1, y1, x2, y2, x, y)
    print(area1)
    area2 = getArea(x1, y1, x3, y3, x, y)
    print(area2)
    area3 = getArea(x2, y2, x3, y3, x, y)
    print(area3)
    allArea = getArea(x1, y1, x2, y2, x3, y3)
    print(allArea)
    return (area1 + area2 + area3) <= allArea
 
 
# -*- coding: utf-8 -*-
# author: Yufeng Song
import numpy as np
import random
 
 
# 定义点
class Vertex(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y
 
    def __str__(self):
        return ("x坐标:%s,y坐标:%s" % (self.x, self.y))
        # "Freind : %s" %self.name 返回多个参数啊
 
 
# 定义三角形
class Triangle(object):
    def __init__(self, A, B, C):
        self.A = A
        self.B = B
        self.C = C
 
    def __str__(self):
        return ("A点:%s B点:%s C点:%s" % (self.A, self.B, self.C))
 
    # 判断构建的三角形是否满足三角形条件,即面积是否为零
    def isTriangle(self):
        arr = np.array([[self.A.x, self.A.y, 1], [self.B.x, self.B.y, 1], [self.C.x, self.C.y, 1]])
        s = abs(0.5 * np.linalg.det(arr))
        return False if s == 0 else True
 
    # 判断一个点是否在三角形内,即该点与三角形任意两点构成的面积不为0且面积和为外部大三角形面积之和
    def isInTriangle(self, D):
        arr1 = np.array([[self.A.x, self.A.y, 1], [self.B.x, self.B.y, 1], [self.C.x, self.C.y, 1]])
        sumAera = 0.5 * np.linalg.det(arr1)
        arr2 = np.array([[self.A.x, self.A.y, 1], [self.B.x, self.B.y, 1], [D.x, D.y, 1]])
        s1 = 0.5 * np.linalg.det(arr2)
        arr3 = np.array([[self.A.x, self.A.y, 1], [D.x, D.y, 1], [self.C.x, self.C.y, 1]])
        s2 = 0.5 * np.linalg.det(arr3)
        arr4 = np.array([[D.x, D.y, 1], [self.B.x, self.B.y, 1], [self.C.x, self.C.y, 1]])
        s3 = 0.5 * np.linalg.det(arr4)
        if s1 != 0 and s2 != 0 and s3 != 0 and abs(s1 + s2 + s3 - sumAera) < 0.000001:
            return True
        else:
            return False
 
 
if __name__ == '__main__':
    # 产生1000个点且存储起来
    arrOfVertex = []
    for i in range(1000):
        tempx = random.randint(1, 100)
        tempy = random.randint(1, 100)
        tempVertex = Vertex(tempx, tempy)
        arrOfVertex.append(tempVertex)
    # 在这1000个点中随机选取3个点且保证这三个点构成一个三角形
    k, j, m = random.randint(0, 999), random.randint(0, 999), random.randint(0, 999)
    selectedTriangle = Triangle(arrOfVertex[k], arrOfVertex[j], arrOfVertex[m])
    while not selectedTriangle.isTriangle():
        k, j, m = random.randint(0, 999), random.randint(0, 999), random.randint(0, 999)
 
        selectedTriangle = Triangle(arrOfVertex[k], arrOfVertex[j], arrOfVertex[m])
    # 判断点是否在三角形中,且用一个数组存储起来
    arrOfJudge = []
    sum = 0
    for i in range(1000):
        temp = selectedTriangle.isInTriangle(arrOfVertex[i])
        print(arrOfVertex[i], end="  ")
        if temp: sum += 1
        arrOfJudge.append(temp)
    print("选取的是否为三角形:%s" % selectedTriangle.isTriangle())
    print(arrOfJudge)
    print("在三角形内部的比例为:%s %%" % (sum / 10))
 
# a = Vertex(1, 1)
# b = Vertex(2, 2)
# c = Vertex(3, 3)
# print(a)
# tri = Triangle(a, b, c)
# print(tri)
# print(tri.isTriangle())

方法3:向量法(同边法)

向量法:如果点(x, y)在三角形内部,那么从某个点逆时针出发,点(x, y)都在每条边的左侧。

首先看一下这个问题,如何判断某两个点在某条直线的同一侧?

image

根据向量的叉乘以及右手螺旋定则,AB^AM (^表示叉乘,这里向量省略了字母上面的箭头符号)的方向为向外指出屏幕,AB^AN也是向外指出屏幕,但AB^AO的方向是向内指向屏幕,因此M,N在直线AB的同侧,M ,O在直线AB的两侧。实际计算时,只需要考虑叉积的数值正负

假设以上各点坐标为A(0,0), B(4,0), M(1,2), N(3,4), O(3,-4), 则:

AB^AM = (4,0)^(1,2) = 4*2 - 0*1 = 8

AB^AN = (4,0)^(3,4) = 4*4 – 0*3 = 16

AB^AO = (4,0)^(3,-4) = 4*-4 – 0*3 = –16

由上面的数值可知,可以根据数值的正负判断叉乘后向量的方向。即,如果叉积AB^AM 和 AB^AN的结果同号,那么M,N两点就在直线的同侧,否则不在同一侧。特殊地,如果点M在直线AB上,则AB^AM的值为0。(如果是在三维坐标系中,求出的叉积是一个向量,可以根据两个向量的点积结果正负来判断两个向量的是否指向同一侧)                                    

以上的问题解决了,就很容易的用来判断某个点是否在三角形内,如果P在三角形ABC内部,则满足以下三个条件:P,A在BC的同侧、P,B在AC的同侧、PC在AB的同侧。某一个不满足则表示P不在三角形内部。

def isInside(x1, y1, x2, y2, x3, y3, x, y):
    def crossProduct(x1, y1, x2, y2):
        return x1 * y2 - x2 * y1

    if crossProduct(x3-x1, y3-y1, x2-x1, y2-y1) >= 0:
        x2, x3 = x3, x2
        y2, y3 = y3, y2
    if crossProduct(x2-x1, y2-y1, x-x1, y-y1) < 0:
        return False
    if crossProduct(x3-x2, y3-y2, x-x2, y-y2) < 0:
        return False
    if crossProduct(x1-x3, y1-y3, x-x3, y-y3) < 0:
        return False
    return True

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

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

相关文章

LInux文件权限相关知识介绍

LInux文件权限相关知识分享&#x1f60e; 前言&#x1f64c;Linux相关权限的概念&#xff1a;文件类型基本权限文件访问权限的相关设置方法chmod① 用户表示符/-权限字符②三位8进制数字 总结撒花&#x1f49e; &#x1f60e;博客昵称&#xff1a;博客小梦 &#x1f60a;最喜欢…

java+springboot+vue高校毕业生就业统计管理系统022xr

系统的设计与实现采用Spring、SpringMVC和MyBatis作为主体框架,系统设计遵循界面层、业务逻辑层和数据访问层的Web开发三层架构。采用B/S结构,使得系统更加容易维护。系统的设计与实现主要实现角色有管理员和用户,管理员在后台管理用户表模块、token表模块、生源信息模块、招聘…

代码随想录Day19 LeetCode T669修剪二叉搜索树 LeetCode T108将有序数组转化为二叉搜索树 T538 把二叉搜索树转化为累加树

LeetCode T669 修剪二叉搜索树 题目链接:669. 修剪二叉搜索树 - 力扣&#xff08;LeetCode&#xff09; 题目思路 这题我们有几个思路需要避坑,首先我们不能这样想,比如遇见比low值还小的节点值,不能直接返回null,而是考虑该节点的右子树有没有符合题目需求的节点值存在,同理删…

Java学习之TreeSet

Java TreeSet 底层是红黑树实现 将元素插入TreeSet add() - 将指定的元素插入集合 addAll() - 将指定集合的所有元素插入集合 import java.util.TreeSet;class Main {public static void main(String[] args) {TreeSet<Integer> evenNumbers new TreeSet<>();/…

二十三、【五种图层】

文章目录 像素图层智能图层文字图层形状图层调整图层 像素图层 像素图层由空白像素图层组成&#xff0c;上边没有任何颜色&#xff0c;如下图&#xff0c;我们可以使用画笔工具在空白相处图层上进行修改&#xff1a; 智能图层 智能图层可以记录该图层当前的数据在被编辑后可…

ShareX使用说明——优秀的录屏软件

ShareX初识 ShareX 是一个自由及开放源代码的截图录像软件&#xff0c;目前仅支持Windows系统。 项目源代码在GitHub平台上发布&#xff0c; 软件可以在Microsoft商店和Steam上下载。 ShareX is a free and open source program that lets you capture or record any area of y…

VPN的不同种类及现网应用场景

学习目标&#xff1a; 1. 企业为什么要部署VPN&#xff1f; 2. 常见的VPN有哪些种类&#xff1f; 3. VPN如何保障数据传输安全&#xff1f; -- VPN - 虚拟私有网络 - 企业最常用的功能之一 - 增值型业务 -- 需求&#xff1a;大一些公司 分公司 - 管理问题 --…

通过jsoup抓取谷歌商店评分

文章目录 背景实现是否下架预警评分 总的工具类,测试 背景 在谷歌上面发布包,有时候要看看评分,有时候会因为总总原因被下架,希望后台能够对评分进行预警,和下架预警 实现 测试地址: https://play.google.com/store/apps/details?idcom.tencent.mm 通过jsoup解析页面,然后获…

项目管理之六大目标及成功方程式

项目管理的六大目标分别是范围、质量、时间、成本、收益和风险。在项目开始之前&#xff0c;需要明确了解项目的范围&#xff0c;并在项目执行过程中对范围进行严格控制&#xff0c;确保项目不偏离既定的范围。同时&#xff0c;需要明确项目的质量标准和预期成果&#xff0c;然…

采用 guidance 提高大模型输出的可靠性和稳定性

本文首发于博客 LLM 应用开发实践 在复杂的 LLM 应用开发中&#xff0c;特别涉及流程编排和多次 LLM 调用时&#xff0c;每次的 Prompt 设计都取决于前一个步骤的大模型输出。如何避免大语言模型的"胡说八道"&#xff0c;以提高大语言模型输出的可靠性和稳定性&#…

1.13.C++项目:仿muduo库实现并发服务器之TcpServer模块的设计

文章目录 一、LoopThreadPool模块二、实现思想&#xff08;一&#xff09;管理&#xff08;二&#xff09;流程&#xff08;三&#xff09;功能设计 三、代码 一、LoopThreadPool模块 TcpServer模块&#xff1a; 对所有模块的整合&#xff0c;通过 tcpserver 模块实例化的对象&…

C++指针解读(3)-- 指针变量作为函数参数

函数执行是通过系统栈来实现的&#xff0c;系统栈分为若干个栈帧。栈帧就是函数运行的环境&#xff0c;每个函数在被调用时都会在系统栈区形成一个叫栈帧的结构。一次函数调用相关的数据保存在栈帧中&#xff0c;比如函数参数、函数的局部变量、函数执行完后的返回地址等数据。…

【LeetCode刷题(数据结构)】:另一颗树的子树

给你两棵二叉树 root 和 subRoot 检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子…

PCL点云处理之基于强度特征的SIFT关键点提取法 (二百一十五)

PCL点云处理之基于强度特征的SIFT关键点提取法 (二百一十五) 一、算法介绍二、具体实现1.代码2.效果一、算法介绍 继续SIFT关键点的提取介绍,之前已经基于高程和颜色分别提取了关键点,这里是基于强度信息,若遇到文件无法读取强度问题,请参考上一篇博文,下面是具体的实现…

SQL语句-中级

一、Mysql软件使用 1.启动/停止Mysql服务器 任务管理器 cmd命令&#xff1a;以管理员的身份打开cmd命令行 net start mysql80//开启net stop mysql80//停止 2.连接与断开Mysql服务器 注意要在bin目录下执行:-u用户名root&#xff0c;-p密码 mysql -u root -p 可能出现的…

物联网AI MicroPython传感器学习 之 TEA5767 FM收音机模块

学物联网&#xff0c;来万物简单IoT物联网&#xff01;&#xff01; 一、产品简介 TEA5767 FM收音机模块是工作频率在76MHz&#xff5e;108MHz的自动数字调谐收音机。其特点高灵敏度、高稳定、低噪声&#xff0c;内部集成了中频选频和解调网络。 引脚定义 GND&#xff1a;接…

School‘s Java test

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;那个传说中的man的主页 &#x1f3e0;个人专栏&#xff1a;题目解析 &#x1f30e;推荐文章&#xff1a;题目大解析&#xff08;3&#xff09; 目录 &#x1f449;&#x1f3fb;第四周素数和念整数 &#…

SSM+springboot+vue+java企业公寓员工宿舍后勤管理网站

论文主要是对后勤管理系统进行了介绍&#xff0c;包括研究的现状&#xff0c;还有涉及的开发背景&#xff0c;然后还对系统的设计目标进行了论述&#xff0c;还有系统的需求&#xff0c;以及整个的设计方案&#xff0c;对系统的设计以及实现&#xff0c;也都论述的比较细致&…

24字符串-kmp寻找重复子串

目录 字符串匹配——kmp算法 LeetCode之路——459. 重复的子字符串 分析&#xff1a; 字符串匹配——kmp算法 强烈建议参考Carl的讲解&#xff1a; 视频讲解版&#xff1a;帮你把KMP算法学个通透&#xff01;&#xff08;理论篇&#xff09;(opens new window) 视频讲解版&…

使用Plotly可视化

显示项目受欢迎程度 改进图表 设置颜色&#xff0c;字体