题目描述:

如何判断一个点是否在一个三角形内。

测试样例:

自定义的POINT类:

class POINT{

int x;

int y;

public POINT(int x,int y){

this.x = x;

this.y = y;

}

}

思路一:

面积法:

如果一个点在三角形内,其与三角形的三个点构成的三个子三角形的面积等于大三角形的面积。否则,大于大三角形的面积。

所以,这个问题就转化成如何在知道三角形的三个点的情况下,求这个三角形的面积的问题了。

因为所有点的坐标已知,我们有几种方式计算面积:

1)首先可以计算出每条边的长度及周长,我们就可以利用海伦公式计算面积,然后进行比较。

S=p(p−a)(p−b)(p−c)−−−−−−−−−−−−−−−−−√ S = sqrt{p(p-a)(p-b)(p-c)}

S=

p(p−a)(p−b)(p−c)

p=(a+b+c)2 p = frac{(a+b+c)}{2}

p=

2

(a+b+c)

2)向量法:先求出这个三角形的对应的平行四边形的面积。然后这个面积的1/2就是三角形的面积了。

先随意选择两个点,如B、C通过其坐标相减得向量(B,C)。记得谁减另一个就是指向谁。然后求出其中一个点和剩下一个点的向量。这两个向量的叉乘的便是平行四边形的面积。除以2就是三角形的面积。(注意这里是叉乘 (cross product),而非点乘(dot product))。

(补充)向量之间的积分为两种:叉乘和点乘。叉乘求面积,点乘求投影。这是两者的意义。而且,叉乘理论得到的是一个向量,而点乘得到的是一个标量。

代码:

private static final double ABS_DOUBLE_0 = 0.0001;

public static boolean isInTriangle(POINT A, POINT B, POINT C, POINT P) {

double ABC = triAngleArea(A, B, C);

double ABp = triAngleArea(A, B, P);

double ACp = triAngleArea(A, C, P);

double BCp = triAngleArea(B, C, P);

double sumOther = ABp + ACp + BCp;

if (-ABS_DOUBLE_0 < (ABC - sumOther) && (ABC - sumOther) < ABS_DOUBLE_0) { // 若面积之和等于原三角形面积,证明点在三角形内

return true;

} else {

return false;

}

}

private static double triAngleArea(POINT A, POINT B, POINT C) { // 由三个点计算这三个点组成三角形面积

POINT ab,bc;

ab = new POINT(B.x - A.x,B.y - A.y);//

bc = new POINT(C.x - B.x,C.y - B.y);

return Math.abs((ab.x * bc.y - ab.y * bc.x) / 2.0);

}

思路二:

同向法:

假设点P位于三角形内,会有这样一个规律,当我们沿着ABCA的方向在三条边上行走时,你会发现点P始终位于边AB,BC和CA的右侧。我们就利用这一点,但是如何判断一个点在线段的左侧还是右侧呢?我们可以从另一个角度来思考,当选定线段AB时,点C位于AB的右侧,同理选定BC时,点A位于BC的右侧,最后选定CA时,点B位于CA的右侧,所以当选择某一条边时,我们只需验证点P与该边所对的点在同一侧即可。问题又来了,如何判断两个点在某条线段的同一侧呢?可以通过叉积来实现,连接PA,将PA和AB做叉积,再将CA和AB做叉积,如果两个叉积的结果方向一致,那么两个点在同一测。

代码:

public static boolean isInTriangle(POINT A, POINT B, POINT C, POINT P) {

/*利用叉乘法进行判断,假设P点就是M点*/

int a = 0, b = 0, c = 0;

POINT MA = new POINT(P.x - A.x,P.y - A.y);

POINT MB = new POINT(P.x - B.x,P.y - B.y);

POINT MC = new POINT(P.x - C.x,P.y - C.y);

/*向量叉乘*/

a = MA.x * MB.y - MA.y * MB.x;

b = MB.x * MC.y - MB.y * MC.x;

c = MC.x * MA.y - MC.y * MA.x;

if((a <= 0 && b <= 0 && c <= 0)||

(a > 0 && b > 0 && c > 0))

return true;

return false;

}

思路三:

重心法:

我们都知道,三角形的三个点在同一个平面上,如果选中其中一个点,其他两个点不过是相对该点的位移而已,比如选择点A作为起点,那么点B相当于在AB方向移动一段距离得到,而点C相当于在AC方向移动一段距离得到。

所以对于平面内任意一点,都可以由如下方程来表示。

P=A+u∗(C−A)+v∗(B−A) P = A + u * (C-A) + v * (B-A)

P=A+u∗(C−A)+v∗(B−A)

如果系数u或v为负值,那么相当于朝相反的方向移动,即BA或CA方向。那么如果想让P位于三角形ABC内部,u和v必须满足什么条件呢?有如下三个条件:

u >= 0

v >= 0

u + v <= 1

几个边界情况:

当u = 0,v = 0 时,就是点A;

当u = 0,v = 1 时,就是点B;

当u = 1,v = 0 时,就是点C。

整理方程1得到:

P−A=u(C−A)+v(B−A) P-A = u(C-A) + v(B-A)

P−A=u(C−A)+v(B−A)

令 v0 = C – A, v1 = B – A, v2 = P – A,则

v2=u∗v0+v∗v1 v2 = u * v0 + v * v1

v2=u∗v0+v∗v1

现在是一个方程,两个未知数,无法解出u和v,所以将等式两边分别点乘v0和v1的到两个等式:(ps.下面公式中的·符号代表“点乘”)

(v2)⋅v0=(u∗v0+v∗v1)⋅v0 (v2)·v0 = (u * v0 + v * v1)·v0

(v2)⋅v0=(u∗v0+v∗v1)⋅v0

(v2)⋅v1=(u∗v0+v∗v1)⋅v1 (v2)·v1 = (u * v0 + v * v1)·v1

(v2)⋅v1=(u∗v0+v∗v1)⋅v1

注意到这里u和v是数,而v0,v1和v2是向量,所以可以将点积展开得到下面的式子。

v2⋅v0=u∗(v0⋅v0)+v∗(v1⋅v0) v2·v0 = u * (v0·v0) + v * (v1·v0)

v2⋅v0=u∗(v0⋅v0)+v∗(v1⋅v0)

v2⋅v1=u∗(v0⋅v1)+v∗(v1⋅v1) v2·v1 = u * (v0·v1) + v * (v1·v1)

v2⋅v1=u∗(v0⋅v1)+v∗(v1⋅v1)

解这个方程得到:

u=((v1⋅v1)(v2⋅v0)−(v1⋅v0)(v2⋅v1))/((v0⋅v0)(v1⋅v1)−(v0⋅v1)(v1⋅v0)) u = ((v1·v1)(v2·v0)-(v1·v0)(v2·v1)) / ((v0·v0)(v1·v1) - (v0·v1)(v1·v0))

u=((v1⋅v1)(v2⋅v0)−(v1⋅v0)(v2⋅v1))/((v0⋅v0)(v1⋅v1)−(v0⋅v1)(v1⋅v0))

v=((v0⋅v0)(v2⋅v1)−(v0⋅v1)(v2⋅v0))/((v0⋅v0)(v1⋅v1)−(v0⋅v1)(v1⋅v0)) v = ((v0·v0)(v2·v1)-(v0·v1)(v2·v0)) / ((v0·v0)(v1·v1) - (v0·v1)(v1·v0))

v=((v0⋅v0)(v2⋅v1)−(v0⋅v1)(v2⋅v0))/((v0⋅v0)(v1⋅v1)−(v0⋅v1)(v1⋅v0))

代码

private static boolean isInTriangle(POINT p, POINT a, POINT b, POINT c) {

POINT AB, AC, AP;

AB = new POINT(b.x - a.x, b.y - a.y);

AC = new POINT(c.x - a.x, c.y - a.y);

AP = new POINT(p.x - a.x, p.y - a.y);

float dot00 = dotProduct(AC, AC);

float dot01 = dotProduct(AC, AB);

float dot02 = dotProduct(AC, AP);

float dot11 = dotProduct(AB, AB);

float dot12 = dotProduct(AB, AP);

float inverDeno = 1 / (dot00 * dot11 - dot01 * dot01);

// 计算重心坐标

float u = (dot11 * dot02 - dot01 * dot12) * inverDeno;

float v = (dot00 * dot12 - dot01 * dot02) * inverDeno;

return (u >= 0) && (v >= 0) && (u + v < 1);

}

private static float dotProduct(POINT p1, POINT p2) {

return p1.x * p2.x + p1.y * p2.y;

}

点击“java架构”

能否构成三角形的条件代码_Java 如何判断一个点是否在一个三角形内相关推荐

  1. Java 判断一个点是否在一个三角形内

    题目描述:   如何判断一个点是否在一个三角形内. 测试样例: 自定义的POINT类: class POINT{int x;int y;public POINT(int x,int y){this.x ...

  2. Algorithm: 如何判断一个点是否在一个三角形内

    昨日因为机缘巧合,做了一道阿里的实习生编程题.题目很有趣,其中涉及到了如何判断一个点是否在一个三角形内. 其中,判断这个问题最简单的方法是面积法.(图片来源:http://www.cnblogs.co ...

  3. 【c++】判断一个点是否在三角形内部

    判断一个点是否在三角形内部 基础知识 整体代码 之前做笔试题的时候,忘了怎么计算点是否在三角形的内部,写个博客记录一下. 基础知识 使用结构体保存点的坐标 // 用一个结构体去表示点 struct p ...

  4. 面试高频算法题补充系列:如何判断一个点是否在三角形内?

    前言 了解更多常考高频算法题可以关注 公众号:一个搬砖的胖子 企业面试题库:https://codetop.cc/ 小程序:CodeTop 该题曾出现在字节跳动.腾讯.网易.美团.小马智行等公司的面试 ...

  5. 如何判断一个点是否在三角形内部

    如何判断一个点是否在三角形内部 昨天学到一个方法,虽然是数学上的问题,而且也没找到具体严格的证明,但觉得知道下其用法还是很好的. 问题:如何判断一个点是否在三角形内部 方法:比如三角型外有点P,三角型 ...

  6. 能否构成三角形的条件代码_三角形基础知识

    提要 三角形基础知识是研究三角形的基础,要知道三条线段只有满足三边关系才能组成三角形,要知道三角形的高,中线,角平分线是三条线段,要知道它们的有关性质,特别要注意三角形的高的位置与三角形的形状有关,因 ...

  7. 能否构成三角形的条件代码_平面几何之三角形篇

    平面几何是高考的必考点,其中,三角形又是备受出题人喜爱的一中图形.对三角形的考察方式有很多,许多体型都可以与三角形相结合,比如向量.三角函数.圆锥曲线等. 本文总结了高中三角形相关的知识点,其中涉及了 ...

  8. 能否构成三角形的条件代码_初中数学几何题汇编 三角形

    初中数学几何题汇编 三角形 知识考点: 理解三角形三边的关系及三角形的主要线段(中线.高线.角平分线)和三角形的内角和定理.关键是正确理解有关概念,学会概念和定理的运用.应用方程知识求解几何题是这部分 ...

  9. 能否构成三角形的条件代码_人教版初中数学三角形全等的判定教案

    三角形全等的判定教案 一.教学目标 [知识与技能] 掌握三角形全等的判定方法"边边边",能运用"边边边"证明两个三角形全等. [过程与方法] 通过推理论证及&q ...

最新文章

  1. 回顾2018,正在改变未来游戏规则的技术
  2. linux下安装mysql5.7.25详细教程
  3. 3.游戏优化(CCSpriteBatchNode)
  4. 《凡人修仙传》中打斗场景(c++多态实现)
  5. 前端学习(1763):前端调试值之性能分析的方法一
  6. 10以内的分解与组成怎么教_【一年级数学】(上)10以内的分与合技巧及练习题...
  7. this(C# 参考)
  8. Visual Studio Code远程开发配置
  9. 2015.10.7第一篇
  10. 安装ORK功能包踩坑之路和解决方案
  11. 华为荣耀10电路原理图
  12. 开发APP软件需要哪些编程语言和开发环境
  13. 数学分析 隐函数定理及其应用(第18章)
  14. 一次完整的软件工程课程设计
  15. Mac怎么看剩余空间,Mac怎么看硬盘空间
  16. 关于两种运行sh的方式: ./myscript.ksh and . ./myscript.ksh
  17. 回首向来萧瑟处 也无风雨也无晴
  18. 计算机界面视频录制软件,电脑版的录视频软件如何使用?录屏精灵为大家介绍基本操作...
  19. 解决报错npm ERR request to https://registry.cnpmjs.org/wangeditor failed, reason: Hostname/
  20. shen_tian_hao的C++快快编程AC代码库(每周更新)

热门文章

  1. 用电脑将图片转为excel表格有几种方法?怎么操作?
  2. Python网络爬虫之基本项目:爬取网易新闻排行榜
  3. USB-C接口功能有多强大?[USB-C台式显示器方案介绍]
  4. 大数据架构、大数据开发与数据分析的区别
  5. 【探索 Kubernetes|作业管理篇 系列 8】探究 Pod 的 API 对象属性级别与重要字段用法
  6. 详解Android 7.0带来的新工具类:DiffUtil
  7. [Java基础]-- 为何java一些方法会有横线?
  8. Ant design Pro of vue 实战一
  9. java图片添加水印文字
  10. Linux内核:kmalloc()和SLOB、SLAB、SLUB内存分配器