<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
    不過樓主的方法相對容易理解,這一點必須承認。  回復  更多評論
      

    主站蜘蛛池模板: 中文字幕永久免费| 中文字幕手机在线免费看电影| 日本最新免费网站| 亚洲日本中文字幕区| 最近免费字幕中文大全| 亚洲无码在线播放| 大地资源在线资源免费观看| 午夜亚洲国产理论秋霞| 在线a免费观看最新网站| 国产精品亚洲片在线va| 天天干在线免费视频| 大桥未久亚洲无av码在线 | 亚洲精品视频专区| 免费观看激色视频网站(性色)| 中文字幕亚洲情99在线| 四虎国产精品免费视| 一道本在线免费视频| 亚洲av无码国产精品夜色午夜| 98精品全国免费观看视频| 国产精品亚洲片在线va| 午夜国产羞羞视频免费网站| aa级女人大片喷水视频免费| 亚洲永久永久永久永久永久精品| 久视频精品免费观看99| 亚洲aⅴ天堂av天堂无码麻豆| 内射无码专区久久亚洲| 国产精品视频白浆免费视频| 亚洲人成77777在线播放网站不卡| 女人18毛片a级毛片免费| 在线免费视频你懂的| 亚洲精品中文字幕麻豆| 免费人成网站在线高清| 久久久久久AV无码免费网站下载| 亚洲中文字幕一二三四区苍井空| 无码国产亚洲日韩国精品视频一区二区三区 | 亚洲s色大片在线观看| 性感美女视频在线观看免费精品 | 免费福利电影在线观看| 亚洲国产精品18久久久久久| 亚洲精品成人无限看| 性感美女视频在线观看免费精品|