基本思路

如图,点P在三角形ABC内部,可以通过以下三个条件判断:

  1. 点P和点C在直线AB同侧
  2. 点P和点B在直线AC同侧
  3. 点P和点A在直线BC同侧

如果以上三个条件同时满足,则点P在三角形ABC内部。

下面将会用到叉乘这个数学工具来确定一个点在直线的哪一侧。

判断点在直线的哪一侧

叉乘是一个判断点在直线哪一侧的数学工具。先看一下叉乘的定义:

a⃗ ×b⃗ =∥a⃗ ∥∥b⃗ ∥sinθn⃗ 

其中,θ为向量夹角,n⃗ 是一个向量,与a⃗ 和b⃗ 都垂直,方向满足右手螺旋法则,即下图所示:

于是,从第一个向量的方向看,如果第二个向量在左边,那个叉乘是正的,在右边,则是负的,在同一个方向上,则是0.叉乘的大小,则是两个向量组成的平行四边形的面积。

那么叉乘具体如何计算呢?先将x、y、z轴方向的单位向量分别记为i⃗ 、j⃗ 和k⃗ ,则如果有两个向量,分别为:

u⃗ =u1i⃗ +u2j⃗ +u3k⃗ =(u1,u2,u3)v⃗ =v1i⃗ +v2j⃗ +v3k⃗ =(v1,v2,v3)

则有:

u⃗ ×v⃗ =(u2v3−u3v2)i⃗ +(u3v1−u1v3)j⃗ +(u1v2−u2v1)k⃗ 

可以用以下行列式来简记:

u⃗ ×v⃗ =∣∣∣∣∣i⃗ u1v1j⃗ u2v2k⃗ u3v3∣∣∣∣∣

如果叉乘的两个向量都是平面向量,则可以看作是第三个分量为0的三维向量。

以下Processing程序可以验证叉乘用于点在直线哪一侧的判断的正确性:

PVector a = new PVector(100, 200);
PVector b = new PVector(300, 300);
PVector c = PVector.sub(b, a);void setup() {size(400, 400);fill(0);
}void draw() {background(255);line(a.x, a.y, b.x, b.y);PVector d = new PVector(mouseX - a.x, mouseY - a.y);String side;if (c.cross(d).z > 0)side = "left";else if (c.cross(d).z < 0)side = "right";elseside = "on";text(side, 40, 40);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

有兴趣的读者也可以把cross方法展开试试。

算法实现

现在算法已经很明显啦!其中有一点小技巧,三角形的三个顶点是转着来的,算一次就行了。比如,在上图中,点C在直线AB左侧,点B在直线CA的左侧,点A在直接BC的左侧。所以,第一步是先计算三角形的方向:

float signOfTrig = (b.x - a.x)*(c.y - a.y) - (b.y - a.y)*(c.x - a.x);
  • 1

注意这样一下子写出来不太容易看明白,但是如果看成向量AB和向量AC叉乘之后的Z坐标就好懂的多了。

再分别计算P在AB、CA、BC的哪一侧:

float signOfAB = (b.x - a.x)*(p.y - a.y) - (b.y - a.y)*(p.x - a.x);
float signOfCA = (a.x - c.x)*(p.y - c.y) - (a.y - c.y)*(p.x - c.x);
float signOfBC = (c.x - b.x)*(p.y - c.y) - (c.y - b.y)*(p.x - c.x);
  • 1
  • 2
  • 3

最后判断它们是否在同一侧:

boolean d1 = (signOfAB * signOfTrig > 0);
boolean d2 = (signOfCA * signOfTrig > 0);
boolean d3 = (signOfBC * signOfTrig > 0);
println(d1 && d1 && d3);
  • 1
  • 2
  • 3
  • 4

这就是所有的算法了!最后来个程序验证一下。

验证程序

PVector[] trig;
float r = 150;
float t = 0;
float interval = 30;void setup() {size(500, 500);trig = new PVector[3];ellipseMode(CENTER);
}void draw() {translate(width/2, height/2);updateTrig();background(0);stroke(255);line(trig[0].x, trig[0].y, trig[1].x, trig[1].y);line(trig[1].x, trig[1].y, trig[2].x, trig[2].y);line(trig[0].x, trig[0].y, trig[2].x, trig[2].y);noStroke();for (float i = -width/2 + interval/2; i < width/2; i += interval) {for (float j = -height/2 + interval/2; j < height/2; j += interval) {if (inTrig(i, j)) {fill(255, 0, 0);} else {fill(255);}ellipse(i, j, 2, 2);}}t += 0.5;
}void updateTrig() {for (int i = 0; i < 3; i++)trig[i] = new PVector(r * cos(radians(i * 120 + t)), r * sin(radians(i * 120 + t)));
}boolean inTrig(float x, float y) {PVector a = trig[0];PVector b = trig[1];PVector c = trig[2];PVector p = new PVector(x, y);float signOfTrig = (b.x - a.x)*(c.y - a.y) - (b.y - a.y)*(c.x - a.x);float signOfAB = (b.x - a.x)*(p.y - a.y) - (b.y - a.y)*(p.x - a.x);float signOfCA = (a.x - c.x)*(p.y - c.y) - (a.y - c.y)*(p.x - c.x);float signOfBC = (c.x - b.x)*(p.y - c.y) - (c.y - b.y)*(p.x - c.x);boolean d1 = (signOfAB * signOfTrig > 0);boolean d2 = (signOfCA * signOfTrig > 0);boolean d3 = (signOfBC * signOfTrig > 0);return d1 && d2 && d3;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

效果如下:

如何判断一个点在三角形内部相关推荐

  1. 判断点是否在三角形内部

    判断点是否在三角形内部 给定三角形ABC和一点P(x,y,z),判断点P是否在ABC内.这是游戏设计中一个常见的问题.需要注意的是,这里假定点和三角形位于同一个平面内. 内角和法 连接点P和三角形的三 ...

  2. 判断一个点在三角形内

    http://www.gimoo.net/t/1505/5557e812d7390.html 判断点是否在三角形内 本文只是翻译和整理,原文在此http://www.blackpawn.com/tex ...

  3. c语言判断一个点在长方体内部_21个入门练手项目,让你轻松玩转C语言

    C 语言作为大学理工科专业的必修,是很多同学走进编程世界的第一课.那么怎样才能更好的入门 C 语言呢? 下面整理了 21 个 C 语言练手项目,从基础语法开始,逐步深入,通过一个个练手项目,让你轻松驰 ...

  4. [转]如何判断一个点是否在一个多边形内部

    原文地址:http://hi.baidu.com/wayright/item/ad18e4c0c5446b2dee4665c9 在多边性的存储中,每一个多边形都是由一系列连续的点组成,例如保存为数组P ...

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

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

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

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

  7. 如何判断一个点在多边形内

    一.从三角形开始说起---怎么判断一个点在三角形内 三角形是最简单的多边形了.先说说三角形有哪些判断方法. 参考自:判断一个点是否在三角形内部 - 知乎 几种方法判断平面点在三角形内_独L无二的博客- ...

  8. 判断一个点是否在三角形内部

    题目:在二维坐标系中,所有的值都是double型,那么一个三角形可以由三个点来代表,给定三个点代表的三角形,再给定一个点(x, y),判断(x, y)是否在三角形中 基本思路: 如果一个点O在三角形的 ...

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

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

  10. Qt 判断一个点是否落在三角形内(算法)

    利用重心法判断一个点是否落在三角形面积内,三角形的三个点在同一个平面上,如果选中其中一个点,其他两个点不过是相对该点的位移而已,比如选择点A作为起点,那么点B相当于在AB方向移动一段距离得到,而点C相 ...

最新文章

  1. python使用箱图法和业务规则进行异常数据处理并检查预测使用的数据特征是否有字段缺失的情况并补齐
  2. RMAN干掉热备份#OCP试验1#
  3. java高级之Io流
  4. PTA-1022——Digital Library
  5. Python常见的一些面试题,太有用啦!
  6. java学习体会论文_Java I/O学习心得一
  7. (转)Arcgis for JS实现台风运动路径与影像范围的显示
  8. mysql cluster安装配置_mysqlcluster安装与配置_MySQL
  9. myeclipse9.1 安装svn(图)
  10. 453. Minimum Moves to Equal Array Elements 一次改2个数,变成统一的
  11. python对文件的读取
  12. poj 1815(最小割、割集)
  13. 安卓游戏源码-android游戏源码开发-android游戏开发
  14. python彩虹蛇_贪吃蛇还能这么玩?绝对是你从未体验过的全新版本(上)
  15. Filtered off site request to
  16. 如何制作打首板的量化策略
  17. 7-108 三角形判断
  18. docker webdav_【技术分享】利用WebDAV特性建立隐蔽后门
  19. IAP 促销优惠(promotional offer)后端接入指南
  20. WINDOWS下文件夾里到底有什麼,各個文件夾都代表的什麼?

热门文章

  1. winAUTOPWN2.8更新下载
  2. 诺奖经济大师,数学天才赌徒,和“神秘的股市财富公式”
  3. Linux下和编译器、程序的运行、环境变量等相关的常见问题
  4. 我在CSDN参与的3000个帖子
  5. 云知声临门一脚不敢踹:科大讯飞指其数据造假,业绩持续增长存疑
  6. 拼图软件——texturepacker
  7. java编程语言怎么学习,详细说明
  8. Pickers应用程序
  9. gitter 卸载_最佳Gitter渠道:Node.js
  10. MYSQL简单题目和知识点