<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

       :: 首頁 ::  :: 聯系 :: 聚合  :: 管理 ::
      131 隨筆 :: 1 文章 :: 530 評論 :: 0 Trackbacks
    判定一個點是否在三角形內
    如何判定一個點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(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 閱讀(7878) 評論(13)  編輯  收藏 所屬分類: JavaSEJavaSwingGUIAlgorithm原創

    評論

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

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

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

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

    此處使用的面積法,原理容易理解,也很容易用程序實現。
    還可利用線段PA,PB和PC的"走勢"來做判斷。當然,仍然是基于幾何學 :-)  回復  更多評論
      

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

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

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

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

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

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

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

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

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

    主站蜘蛛池模板: 亚洲fuli在线观看| 亚洲丁香色婷婷综合欲色啪| 亚洲免费视频播放| 99在线观看精品免费99| 亚洲国产第一页www| 免费A级毛片在线播放| 中文字幕亚洲色图| 波多野结衣中文字幕免费视频| 亚洲成人在线免费观看| 91九色老熟女免费资源站| 亚洲欧洲另类春色校园小说| 一二三四在线播放免费观看中文版视频| 亚洲综合久久久久久中文字幕| av无码久久久久不卡免费网站| 国产成人亚洲合集青青草原精品| 成人五级毛片免费播放| 杨幂最新免费特级毛片| 亚洲精品无码久久久久去q| 日韩视频在线观看免费| 18亚洲男同志videos网站| 大学生一级毛片免费看| 综合偷自拍亚洲乱中文字幕| 亚洲日本va午夜中文字幕久久| 免费萌白酱国产一区二区三区| 91亚洲导航深夜福利| 最近中文字幕mv手机免费高清| 亚洲AV无码成人精品区日韩 | 美女被羞羞网站免费下载| 免费人妻无码不卡中文字幕18禁| 国产va免费观看| 亚洲理论片在线观看| 国产午夜无码视频免费网站 | 久草免费福利资源站| 亚洲 日韩经典 中文字幕 | 亚洲AV无码国产精品麻豆天美 | 久久亚洲AV午夜福利精品一区| 在线观看免费人成视频色9 | a视频免费在线观看| 亚洲日本国产综合高清| 久久久亚洲精品蜜桃臀| 免费在线看v网址|