判定一个点是否在三角形内

时间:2022-08-18 10:26:18
原文链接:http://blog.csdn.net/xyylchq/article/details/7015026




判定一个点是否在三角形内
如何判定一个点P是否存在于指定的三角形ABC内,这肯定是一个简单的问题,本文仅用一个图形界面程序展示了该问题,有兴趣的朋友可以看看。(2008.07.24最后更新)


在此处使用一种常见且简便的方法:如果三角形PAB,PAC和PBC的面积之和与三角形ABC的面积相等,即可判定点P在三角形ABC内(包括在三条边上)。
可知,该方法的关键在于如何计算三角形的面积。幸运地是,当知道三角形顶点(A,B和C)的坐标((Ax, Ay),(Bx, By)和(Cx, Cy))之后,即可计算出其面积:
S = |(Ax * By + Bx * Cy + Cx * Zy - Ay * Bx - By * Cx - Cy * Ax) / 2|


关键的代码如下,
// 由给定的三个顶点的坐标,计算三角形面积。
// Point(java.awt.Point)代表点的坐标。
private static double triangleArea(Point pos1, Point pos2, Point pos3) {
    double result = Math.abs((pos1.x * pos2.y + pos2.x * pos3.y + pos3.x * pos1.y
            - pos2.x * pos1.y - pos3.x * pos2.y - pos1.x * pos3.y) / 2.0D);
    return result;
}


// 判断点pos是否在指定的三角形内。
private static boolean inTriangle(Point pos, Point posA, Point posB,
        Point posC) {
    double triangleArea = triangleArea(posA, posB, posC);
    double area = triangleArea(pos, posA, posB);
    area += triangleArea(pos, posA, posC);
    area += triangleArea(pos, posB, posC);
    double epsilon = 0.0001;  // 由于浮点数的计算存在着误差,故指定一个足够小的数,用于判定两个面积是否(近似)相等。
    if (Math.abs(triangleArea - area) < epsilon) {
        return true;
    }
    return false;
}


执行该应用程序,用鼠标在其中点击三次,即可绘制一个三角形,如下组图所示:


然后仅需移动鼠标,就会出现一个空心圆圈。如果圆圈的中心在三角内(包含在三条边上),则圆圈显示为红色;否则,显示为蓝色。如下组图所示:




完整代码如下:
public class CanvasPanel extends JPanel {


    private static final long serialVersionUID = -6665936180725885346L;


    private Point firstPoint = null;


    private Point secondPoint = null;


    private Point thirdPoint = null;


    public CanvasPanel() {
        setBackground(Color.WHITE);
        addMouseListener(mouseAdapter);
        addMouseMotionListener(mouseAdapter);
    }


    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        drawTriangel(g);
    }


    private void drawTriangel(Graphics g) {
        if (firstPoint != null && secondPoint != null) {
            g.drawLine(firstPoint.x, firstPoint.y, secondPoint.x, secondPoint.y);
            if (thirdPoint != null) {
                g.drawLine(firstPoint.x, firstPoint.y, thirdPoint.x, thirdPoint.y);
                g.drawLine(secondPoint.x, secondPoint.y, thirdPoint.x, thirdPoint.y);
            }
        }
    }


    private static boolean inTriangle(Point pos, Point posA, Point posB,
            Point posC) {
        double triangeArea = triangleArea(posA, posB, posC);
        double area = triangleArea(pos, posA, posB);
        area += triangleArea(pos, posA, posC);
        area += triangleArea(pos, posB, posC);
        double epsilon = 0.0001;
        if (Math.abs(triangeArea - area) < epsilon) {
            return true;
        }
        return false;
    }


    private static double triangleArea(Point pos1, Point pos2, Point pos3) {
        double result = Math.abs((pos1.x * pos2.y + pos2.x * pos3.y + pos3.x * pos1.y
                            - pos2.x * pos1.y - pos3.x * pos2.y - pos1.x * pos3.y) / 2.0D);
        return result;
    }


    private MouseInputAdapter mouseAdapter = new MouseInputAdapter() {


        public void mouseReleased(MouseEvent e) {
            Point pos = e.getPoint();
            if (firstPoint == null) {
                firstPoint = pos;
            } else if (secondPoint == null) {
                secondPoint = pos;
                Graphics g = CanvasPanel.this.getGraphics();
                CanvasPanel.this.paintComponent(g);
                g.drawLine(firstPoint.x, firstPoint.y, secondPoint.x, secondPoint.y);
            } else if (thirdPoint == null) {
                thirdPoint = pos;
                Graphics g = CanvasPanel.this.getGraphics();
                CanvasPanel.this.paintComponent(g);
                g.drawLine(firstPoint.x, firstPoint.y, secondPoint.x, secondPoint.y);
                g.drawLine(firstPoint.x, firstPoint.y, thirdPoint.x, thirdPoint.y);
                g.drawLine(secondPoint.x, secondPoint.y, thirdPoint.x, thirdPoint.y);
            }
        }


        public void mouseMoved(MouseEvent e) {
            Point pos = e.getPoint();
            Graphics2D g2 = (Graphics2D) CanvasPanel.this.getGraphics();
            CanvasPanel.this.paintComponent(g2);
            if (firstPoint != null && secondPoint == null) {
                g2.drawLine(firstPoint.x, firstPoint.y, pos.x, pos.y);
            } else if (firstPoint != null && secondPoint != null&& thirdPoint == null) {
                g2.drawLine(firstPoint.x, firstPoint.y, pos.x, pos.y);
                g2.drawLine(secondPoint.x, secondPoint.y, pos.x, pos.y);
            } else if (firstPoint != null && secondPoint != null&& thirdPoint != null) {
                if (inTriangle(pos, firstPoint, secondPoint, thirdPoint)) {
                    g2.setColor(Color.RED);
                } else {
                    g2.setColor(Color.BLUE);
                }
                int radius = 4;
                g2.drawOval(pos.x - radius, pos.y - radius, radius * 2, radius * 2);
            }
        }
    };
}


public class Triangle extends JFrame {


    private static final long serialVersionUID = 1L;


    private CanvasPanel mainPanel = null;


    public Triangle() {
        setTitle("Triangle");
        setSize(new Dimension(300, 200));
        setResizable(false);


        init();


        Container container = getContentPane();
        container.add(mainPanel);


        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }


    private void init() {
        mainPanel = new CanvasPanel();
    }


    public static void main(String[] args) {
        new Triangle();
    }
}