0
点赞
收藏
分享

微信扫一扫

4.4 给定的点是否在三角形之内


1. 前言

本文的一些图片, 资料 截取自编程之美

2. 问题描述

4.4 给定的点是否在三角形之内_编程之美

3. 问题分析

假设给定的三角形为ABC, 给定的点为D, 使用S(ABC) 表示ABC三个点构成的三角形的面积
解法一 : 连接AD, BD, CD, 然后求解S(ABC); S(DBC), S(ADC), S(ABD), 如果S(ABC) == S(DBC) + S(ADC) + S(ABD), 则说明给定的点D是在三角形ABC内部, 否则后者的面积是会大于ABC的面积的

解法二 : 逆时针遍历ABC的三个边, AB, BC, CA, 如果相对于这三个边, D**均**在左边, 则说明D在三角形ABC的内部

可能上面的描述比较抽象, 特别是第二种解法, 下面是一些图解

解法一 :

1 D在ABC内部

4.4 给定的点是否在三角形之内_编程之美_02


2 D在ABC外部

4.4 给定的点是否在三角形之内_Math_03

解法二 :

1 D在ABC内部

4.4 给定的点是否在三角形之内_Math_04


2 D在ABC外部

4.4 给定的点是否在三角形之内_编程之美_05

4. 代码

/**
 * file name : Test13IsPointInTriangle.java
 * created at : 9:34:57 AM May 30, 2015
 * created by 970655147
 */

package com.hx.test04;

public class Test13IsPointInTriangle {

    // 判断给定的点是否在三角形内部
    public static void main(String []args) {

        Point point = new Point(0, 6);
        Triangle tri = new Triangle(new Point(0, 0), new Point(5, 0), new Point(0, 7) );

        isPointInTriangle01(point, tri);
        isPointInTriangle02(point, tri);

    }

    // 思路 : 将tri的三个顶点和point连接起来, 然后判断(abd + acd + bcd) 是否大于abc
    // 如果大于   则说明d在abc之外, 否则说明d在abc之内
    public static void isPointInTriangle01(Point point, Triangle tri) {
        double offset = 0.001;
        Triangle abd = new Triangle(tri.vertex01, tri.vertex02, point);
        Triangle acd = new Triangle(tri.vertex01, tri.vertex03, point);
        Triangle bcd = new Triangle(tri.vertex02, tri.vertex03, point);

        if(abd.getArea() + acd.getArea() + bcd.getArea() > (tri.getArea() + offset) ) {
            Log.log(false);
        } else {
            Log.log(true);
        }
    }

    // 从d开始逆时针旋转   可以发现  点d在边ab, bc, ca的左边   于是便有了下面的方法
    // 如果点d 在ab, bc, ca的左边   则说明点d存在于该三角形内
    // 否则  点d在三角形内
    public static void isPointInTriangle02(Point point, Triangle tri) {
        if(crossProduct(tri.vertex01, tri.vertex02, point) >= 0.0d && crossProduct(tri.vertex02, tri.vertex03, point) >= 0.0d && crossProduct(tri.vertex03, tri.vertex01, point) >= 0.0d) {
            Log.log(true);
        } else {
            Log.log(false);
        }
    }

    // 表示向量 ab x ad
    // 如果ab x ad > 0,  则说明d在ab的左边
    // 如果ab x ad < 0,  则说明d在ab的右边
    // 如果ab x ad == 0,  则说明d在ab的上
    private static double crossProduct(Point a, Point b, Point d) {
        return (b.x - a.x) * (d.y - a.y) - (d.x - a.x) * (b.y - a.y);
    }

    // 三角形
    static class Triangle {
        // 三个顶点  三个边长
        Point vertex01, vertex02, vertex03;
        double edge12, edge23, edge31;

        // 初始化
        public Triangle() {

        }
        public Triangle(Point vertex01, Point vertex02, Point vertex03) {
            this.vertex01 = vertex01;
            this.vertex02 = vertex02;
            this.vertex03 = vertex03;

            edge12 = calcEdge(vertex01, vertex02);
            edge23 = calcEdge(vertex02, vertex03);
            edge31 = calcEdge(vertex03, vertex01);
        }

        // 给定两个顶点  计算他们之间的距离
        private double calcEdge(Point vertex01, Point vertex02) {
            return Math.sqrt(Math.pow((vertex01.x - vertex02.x ), 2) + Math.pow((vertex01.y - vertex02.y ), 2) );
        }

        // 利用海伦公式求面积
        public double getArea() {
            double p = (edge12 + edge23 + edge31) / 2;
            return Math.sqrt((p - edge12) * (p - edge23) * (p - edge31) * p );
        }
    }

}

5. 运行结果

4.4 给定的点是否在三角形之内_编程之美_06

6. 总结

这个问题不仅让我了解到了这两种方法, 还有一个收获就是, 了解到了海伦公式, 以及勾股定理的证明

注 : 因为作者的水平有限,必然可能出现一些bug, 所以请大家指出!


举报

相关推荐

0 条评论