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

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

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

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值