其他题目---判断一个点是否在三角形内部

【题目】

  在二维坐标系中,所有的值都是double型,那么一个三角形可以由三个点来代表,给定三个点代表的三角形,再给定一个点(x, y),判断(x, y)是否在三角形中。

【基本思路】

  方法一。
  等面积法。如果一个点在三角形内部,那么以该点为顶的三个小三角形的面积和应该等于大三角形的面积。如果这个点在三角形的外部,那么三个小三角形的面积和要大于大三角形的面积。知道三个点,如何求该三个点为顶点的三角形的面积?使用海伦公式 S=p(pa)(pb)(pc) ,其中,a,b,c表示三个边长,p表示半周长,即 p=a+b+c2 。实现代码参见isInside1。

  虽然该方法的逻辑是正确的,但是并不推荐使用该方法。因为double类型的值在计算时会出现一定程度的偏差。所以经常会出现一个点明明在三角形内部,面积却对不准的情况,最终导致判断出错。方法二则没有此顾虑。

  方法二。
  如果一个点O在三角形的内部,那么从三角形的一个点出发,逆时针走过所有边的过程中,点O始终在走过边的左边。如果点O在外侧,则不满足这一条件。

  如果要逆时针走过一遍三角形,那么三个点的位置是重要的,假设输入的三个点依次是a,b,c,如果b在边ac的左边,按照a -> b -> c的顺序遍历是顺时针遍历,如果b在边ac的右边,按照a -> b -> c的顺序遍历就是逆时针遍历。如果出现前者情况,我们需要先调整一下三个点输入的顺序。

  接下来的重点就是判断一个点是在一条边的左侧还是右侧。该问题可以使用几何上的向量积(叉积)解决。

  设线段端点为从A(x1, y1)到B(x2, y2),线外一点p(x, y)。
   a⃗ =(x2x1,y2y1)
   b⃗ =(xx1,yy1)
   a⃗ ×b⃗ =|a⃗ ||b⃗ |sinθ
   a⃗ ×b⃗  决定p的位置,如果 a⃗ ×b⃗  大于0,p在线段左侧;小于0,在右侧;等于0,共线。所以有如下结论:
       xaybxbya>0   p在左侧
       xaybxbya<0   p在右侧
       xaybxbya=0   共线
  一个简单的确定满足“右手定则”的结果向量的方向的方法是这样的:若坐标系是满足右手定则的,当右手的四指从a以不超过180度的转角转向b时,竖起的大拇指指向是c的方向。

  实现代码参见isInside2。

【代码实现】

#python3.5
def isInside1(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


def isInside2(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
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这道题目需要先定义一下正方形和三角形面片的数据结构,然后使用循环嵌套的方法遍历每个正方形的三角形面片并填充,最后检查每个正方形的三角形面片连接处是否填充完整。 以下是一个示例代码: ```c #include <stdio.h> #define N 10 // 正方形数量 // 定义三角形面片数据结构 typedef struct { int x1, y1; int x2, y2; int x3, y3; } Triangle; // 定义正方形数据结构 typedef struct { Triangle t1; // 第一个三角形面片 Triangle t2; // 第二个三角形面片 int isFilled; // 是否已填充 } Square; // 判断一个点是否三角形内部 int isInsideTriangle(int x, int y, Triangle t) { int a = (t.x1 - x) * (t.y2 - t.y1) - (t.x2 - t.x1) * (t.y1 - y); int b = (t.x2 - x) * (t.y3 - t.y2) - (t.x3 - t.x2) * (t.y2 - y); int c = (t.x3 - x) * (t.y1 - t.y3) - (t.x1 - t.x3) * (t.y3 - y); return (a >= 0 && b >= 0 && c >= 0) || (a <= 0 && b <= 0 && c <= 0); } // 填充一个三角形面片 void fillTriangle(Triangle t) { // 填充代码 } int main() { // 构造正方形数组 Square squares[N]; for (int i = 0; i < N; i++) { // 构造第一个三角形面片 squares[i].t1.x1 = i * 10; squares[i].t1.y1 = i * 10; squares[i].t1.x2 = i * 10 + 5; squares[i].t1.y2 = i * 10 + 10; squares[i].t1.x3 = i * 10 + 10; squares[i].t1.y3 = i * 10; // 构造第二个三角形面片 squares[i].t2.x1 = i * 10; squares[i].t2.y1 = i * 10; squares[i].t2.x2 = i * 10 + 10; squares[i].t2.y2 = i * 10 + 5; squares[i].t2.x3 = i * 10; squares[i].t2.y3 = i * 10 + 10; squares[i].isFilled = 0; // 初始化为未填充状态 } // 遍历每个正方形的三角形面片并填充 for (int i = 0; i < N; i++) { fillTriangle(squares[i].t1); fillTriangle(squares[i].t2); } // 检查每个正方形的三角形面片连接处是否填充完整 for (int i = 0; i < N; i++) { int isFilled1 = isInsideTriangle(squares[i].t1.x1, squares[i].t1.y1, squares[i].t2); int isFilled2 = isInsideTriangle(squares[i].t2.x1, squares[i].t2.y1, squares[i].t1); if (isFilled1 && isFilled2) { squares[i].isFilled = 1; } } // 输出每个正方形的填充状态 for (int i = 0; i < N; i++) { printf("Square %d is %sfilled.\n", i+1, squares[i].isFilled ? "" : "not "); } return 0; } ``` 在这个示例代码中,我们使用了两个结构体分别表示三角形面片和正方形,并实现了一个判断是否三角形内部的函数和一个填充三角形面片的函数。在主函数中,我们构造了一个包含10个正方形的数组,并遍历每个正方形的三角形面片进行填充,最后检查每个正方形的三角形面片连接处是否填充完整,并输出每个正方形的填充状态。 需要注意的是,这个示例代码中的填充代码和判断代码都只是占位符,需要根据实际情况进行替换。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值