(资料图)
判定一个点是否在三角形内如何判定一个点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(); } }
还可参见一篇英文文章: http://www.blackpawn.com/texts/pointinpoly/default.html 好文章 ;-)