<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    John Jiang

    a cup of Java, cheers!
    https://github.com/johnshajiang/blog

       :: 首頁 ::  :: 聯(lián)系 :: 聚合  :: 管理 ::
      131 隨筆 :: 1 文章 :: 530 評論 :: 0 Trackbacks
    判定一個點是否在三角形內(nèi)
    如何判定一個點P是否存在于指定的三角形ABC內(nèi),這肯定是一個簡單的問題,本文僅用一個圖形界面程序展示了該問題,有興趣的朋友可以看看。(2008.07.24最后更新)

    在此處使用一種常見且簡便的方法:如果三角形PAB,PAC和PBC的面積之和與三角形ABC的面積相等,即可判定點P在三角形ABC內(nèi)(包括在三條邊上)
    可知,該方法的關(guān)鍵在于如何計算三角形的面積。幸運地是,當(dāng)知道三角形頂點(A,B和C)的坐標(biāo)((Ax, Ay),(Bx, By)和(Cx, Cy))之后,即可計算出其面積:
    = |(Ax * By + Bx * Cy + Cx * Zy - Ay * Bx - By * Cx - Cy * Ax) / 2|

    關(guān)鍵的代碼如下,
    // 由給定的三個頂點的坐標(biāo),計算三角形面積。
    // Point(java.awt.Point)代表點的坐標(biāo)。
    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是否在指定的三角形內(nèi)。
    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;  // 由于浮點數(shù)的計算存在著誤差,故指定一個足夠小的數(shù),用于判定兩個面積是否(近似)相等。
        if (Math.abs(triangleArea - area) < epsilon) {
            
    return true;
        }
        
    return false;
    }

    執(zhí)行該應(yīng)用程序,用鼠標(biāo)在其中點擊三次,即可繪制一個三角形,如下組圖所示:

    然后僅需移動鼠標(biāo),就會出現(xiàn)一個空心圓圈。如果圓圈的中心在三角內(nèi)(包含在三條邊上),則圓圈顯示為紅色;否則,顯示為藍(lán)色。如下組圖所示:


    完整代碼如下:
    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(300200));
            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();
        }
    }

    posted on 2008-07-24 17:02 John Jiang 閱讀(7882) 評論(13)  編輯  收藏 所屬分類: JavaSEJavaSwingGUIAlgorithm原創(chuàng)

    評論

    # re: 判定一個點是否在三角形內(nèi)(原) 2008-07-24 22:09 qiyadeng
    似乎有更好的方法。  回復(fù)  更多評論
      

    # re: 判定一個點是否在三角形內(nèi)(原) 2008-07-25 13:59 長老
    學(xué)過計算機圖形學(xué)的都知道, 計算機圖形中判斷一個點是否在一條直線上, 或三角內(nèi), 根本不必要像幾何數(shù)學(xué)中這么精確. 最典型的, 一般都是把點用小正方形表示, 而不是圓, 這樣算法大大簡化了. 所以上面的情況, 也有更簡單好用的算法.  回復(fù)  更多評論
      

    # re: 判定一個點是否在三角形內(nèi)(原)[未登錄] 2008-07-27 10:27 nile black
    樓主至少提出了一種方法  回復(fù)  更多評論
      

    # re: 判定一個點是否在三角形內(nèi)(原) 2008-07-27 20:40 Sha Jiang
    > 學(xué)過計算機圖形學(xué)的都知道, 計算機圖形中判斷一個點是否在一條直線上,
    > 或三角內(nèi), 根本不必要像幾何數(shù)學(xué)中這么精確.
    我這里就是把它當(dāng)幾何問題來處理的。

    此處使用的面積法,原理容易理解,也很容易用程序?qū)崿F(xiàn)。
    還可利用線段PA,PB和PC的"走勢"來做判斷。當(dāng)然,仍然是基于幾何學(xué) :-)  回復(fù)  更多評論
      

    # re: 判定一個點是否在三角形內(nèi)(原) 2008-10-16 01:08 Fu
    如果已經(jīng)知道三角形三個頂點的坐標(biāo),如何判斷另一點是否在這個三角形內(nèi)呢?
    謝謝!  回復(fù)  更多評論
      

    # re: 判定一個點是否在三角形內(nèi)(原) 2008-10-16 07:52 Sha Jiang
    > 如果已經(jīng)知道三角形三個頂點的坐標(biāo),如何判斷另一點是否在這個三角形內(nèi)呢?
    這不正是我的這篇Blog所涉及的內(nèi)容嘛 :-  回復(fù)  更多評論
      

    # re: 判定一個點是否在三角形內(nèi)(原)[未登錄] 2009-08-21 11:50 zhang
    當(dāng)一個點與一條邊的距離十分近的時候,該方法不成立!我在實際應(yīng)用中使用過  回復(fù)  更多評論
      

    # re: 判定一個點是否在三角形內(nèi)(原) 2009-08-21 18:13 Sha Jiang
    > 當(dāng)一個點與一條邊的距離十分近的時候,該方法不成立!我在實際應(yīng)用中使用過
    就算移動的點在某條邊上,該方法仍然沒有問題啊。  回復(fù)  更多評論
      

    # re: 判定一個點是否在三角形內(nèi)(原) 2009-11-08 04:49 ucdavis
    http://www.blackpawn.com/texts/pointinpoly/default.html  回復(fù)  更多評論
      

    # re: 判定一個點是否在三角形內(nèi)(原) 2010-01-28 22:54 eee
    三角形ABC,點P。用AB表示從A到B的矢量,用<AB>表示AB/|AB|, 用(X,Y)表示矢量X和矢量Y的內(nèi)積。如果(<BP>,<BC>)*(<BC>,<BA>)<=(<BP>,<BA>),且(<CP>,<CB>)*(<CB>,<CA>)<=(<CP>,<CA>),則P在三角形ABC內(nèi)部或在其邊上。  回復(fù)  更多評論
      

    # re: 判定一個點是否在三角形內(nèi)(原) 2010-01-29 01:36 eee
    三角形ABC,點P。用AB表示從A到B的矢量,用<AB>表示AB/|AB|, 用(X,Y)表示矢量X和矢量Y的內(nèi)積。如果(<BP>,<BC>)*(<BC>,<BA>)<(<BP>,<BA>),且(<BP>,<BA>)*(<BA>,<BC>)<(<BP>,<BC>),且(<CP>,<CA>)*(<CA>,<CB>)<(<CP>,<CB>),則P在三角形ABC內(nèi)部。【【更正】】  回復(fù)  更多評論
      

    # re: 判定一個點是否在三角形內(nèi)(原) 2011-04-21 15:39 Patronum
    ucdavis給的那個鏈接上的方法只需要12次浮點數(shù)乘法,而樓主的方法需要24次浮點數(shù)乘法,加法次數(shù)也是樓主的方法比較多,所以相對而言,還是采取連接中給的方法比較好,叉積判定法。  回復(fù)  更多評論
      

    # re: 判定一個點是否在三角形內(nèi)(原) 2011-04-21 15:40 Patronum
    不過樓主的方法相對容易理解,這一點必須承認(rèn)。  回復(fù)  更多評論
      

    主站蜘蛛池模板: 亚洲大尺度无码无码专线一区| 国产成人A在线观看视频免费| 亚洲AV日韩AV无码污污网站 | 亚洲日韩AV一区二区三区中文| 日本亚洲视频在线| 亚洲A∨午夜成人片精品网站| 无码人妻精品一二三区免费| 一级毛片免费播放| 91视频免费网站| 乱人伦中文视频在线观看免费| 中文字幕亚洲精品无码| 亚洲视频在线观看不卡| 亚洲av中文无码乱人伦在线咪咕| 亚洲AV中文无码乱人伦在线视色| 在线观着免费观看国产黄| 免费黄色网址入口| 在线a毛片免费视频观看| 免费观看AV片在线播放| 久久午夜夜伦鲁鲁片免费无码影视| 久久美女网站免费| 在线观看特色大片免费网站| 中国一级全黄的免费观看| 久久久久久久国产免费看| 一级毛片免费播放男男| 男女作爱免费网站| 添bbb免费观看高清视频| 国产精品免费播放| 日本一道综合久久aⅴ免费| 国产极品粉嫩泬免费观看| 精品剧情v国产在免费线观看| 成全视频免费高清| 成人免费看黄20分钟| 影音先锋在线免费观看| 免费无码又爽又刺激高潮| 免费国产成人午夜私人影视| 国产一级理论免费版| 亚洲国产激情一区二区三区| 精品国产亚洲一区二区在线观看 | 男人j进女人p免费视频| 成年网在线观看免费观看网址| 国产精品偷伦视频免费观看了|