首页 > 代码库 > libgdx学习记录27——线段与线段相交检测

libgdx学习记录27——线段与线段相交检测

给定p1, p2, p3, p4四个点,p1,p2为一条线段,p3,p4为一条线段,检测其是否有交点。

可分为三种情况:

1. L2与x轴平行

2. L2与y轴平行

3. L2与坐标轴不平行。

(L1与坐标轴平行,类似处理)

 

基本思路,求出交点坐标,并检测其是否在两个线段内即可。

检测代码:

 1     public static float min(float x, float y) { return x<y? x: y; } 2     public static float max(float x, float y) { return x>y? x: y; } 3      4     public static boolean isSegmentOverlap(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4){ 5         if(p3.x == p4.x){ 6             float x = p3.x; 7             float y = p1.y + (p3.x-p1.x)*(p2.y-p1.y)/(p2.x-p1.x); 8             //System.out.println(y); 9             if( x>min(p1.x, p2.x) && x<max(p1.x, p2.x)  &&  y>min(p1.y, p2.y) && y<max(p1.y, p2.y)  && 10                 x>=min(p3.x, p4.x) && x<=max(p3.x, p4.x)  &&  y>min(p3.y, p4.y) && y<max(p3.y, p4.y)    ){11                 return true;12             }13         }14         else if(p3.y == p4.y){15             float x = p1.x + (p3.y-p1.y)*(p2.x-p1.x)/(p2.y-p1.y);16             float y = p3.y;            17             if( x>min(p1.x, p2.x) && x<max(p1.x, p2.x)  &&  y>min(p1.y, p2.y) && y<max(p1.y, p2.y)  && 18                 x>min(p3.x, p4.x) && x<max(p3.x, p4.x)  &&  y>=min(p3.y, p4.y) && y<=max(p3.y, p4.y) ){19                 return true;20             }21         }22         else if(p1.x==p2.x || p1.y==p2.y){23             return isSegmentOverlap(p3, p4, p1, p2);24         }25         else{26             float k1 = (p2.y-p1.y)/(p2.x-p1.x);27             float k2 = (p4.y-p3.y)/(p4.x-p3.x);28             float x = (k2*p3.x-k1*p1.x+p1.y-p3.y)/(k2-k1);29             float y = k1*(x-p1.x) + p1.y;            30             //System.out.println( k1 + "," + k2 + "," + x + "," + y );            31             if( x>min(p1.x, p2.x) && x<max(p1.x, p2.x)  &&  y>min(p1.y, p2.y) && y<max(p1.y, p2.y)  && 32                 x>min(p3.x, p4.x) && x<max(p3.x, p4.x)  &&  y>min(p3.y, p4.y) && y<max(p3.y, p4.y) ){33                 return true;34             }            35         }36         37         return false;38     }

 

实例代码:

  1 package com.fxb.Gam003;  2   3 import com.badlogic.gdx.ApplicationAdapter;  4 import com.badlogic.gdx.Gdx;  5 import com.badlogic.gdx.InputAdapter;  6 import com.badlogic.gdx.graphics.Color;  7 import com.badlogic.gdx.graphics.GL10;  8 import com.badlogic.gdx.graphics.glutils.ShapeRenderer;  9 import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType; 10 import com.badlogic.gdx.math.Rectangle; 11 import com.badlogic.gdx.math.Vector2; 12 import com.badlogic.gdx.scenes.scene2d.InputListener; 13  14  15 public class Lib054_SegmentOverlap extends ApplicationAdapter{ 16  17     ShapeRenderer rend; 18      19     Vector2 p1 = new Vector2(300, 100); 20     Vector2 p2 = new Vector2(500, 200); 21     Vector2 p3 = new Vector2(300, 200); 22     Vector2 p4 = new Vector2(400, 300); 23      24     Rectangle rect = new Rectangle( 100, 100, 200, 200 ); 25      26     @Override 27     public void create() { 28         // TODO Auto-generated method stub 29         super.create(); 30          31         rend = new ShapeRenderer(); 32         Gdx.input.setInputProcessor(adapter); 33     } 34  35      36     public static float min(float x, float y) { return x<y? x: y; } 37     public static float max(float x, float y) { return x>y? x: y; } 38      39     public static boolean isSegmentOverlap(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4){ 40         if(p3.x == p4.x){ 41             float x = p3.x; 42             float y = p1.y + (p3.x-p1.x)*(p2.y-p1.y)/(p2.x-p1.x); 43             //System.out.println(y); 44             if( x>min(p1.x, p2.x) && x<max(p1.x, p2.x)  &&  y>min(p1.y, p2.y) && y<max(p1.y, p2.y)  &&  45                 x>=min(p3.x, p4.x) && x<=max(p3.x, p4.x)  &&  y>min(p3.y, p4.y) && y<max(p3.y, p4.y)    ){ 46                 return true; 47             } 48         } 49         else if(p3.y == p4.y){ 50             float x = p1.x + (p3.y-p1.y)*(p2.x-p1.x)/(p2.y-p1.y); 51             float y = p3.y;             52             if( x>min(p1.x, p2.x) && x<max(p1.x, p2.x)  &&  y>min(p1.y, p2.y) && y<max(p1.y, p2.y)  &&  53                 x>min(p3.x, p4.x) && x<max(p3.x, p4.x)  &&  y>=min(p3.y, p4.y) && y<=max(p3.y, p4.y) ){ 54                 return true; 55             } 56         } 57         else if(p1.x==p2.x || p1.y==p2.y){ 58             return isSegmentOverlap(p3, p4, p1, p2); 59         } 60         else{ 61             float k1 = (p2.y-p1.y)/(p2.x-p1.x); 62             float k2 = (p4.y-p3.y)/(p4.x-p3.x); 63             float x = (k2*p3.x-k1*p1.x+p1.y-p3.y)/(k2-k1); 64             float y = k1*(x-p1.x) + p1.y;             65             //System.out.println( k1 + "," + k2 + "," + x + "," + y );             66             if( x>min(p1.x, p2.x) && x<max(p1.x, p2.x)  &&  y>min(p1.y, p2.y) && y<max(p1.y, p2.y)  &&  67                 x>min(p3.x, p4.x) && x<max(p3.x, p4.x)  &&  y>min(p3.y, p4.y) && y<max(p3.y, p4.y) ){ 68                 return true; 69             }             70         } 71          72         return false; 73     } 74      75      76     public static boolean isSegRectOverlap(Vector2 p1, Vector2 p2, Rectangle rect){ 77         float x = rect.x, y = rect.y, w = rect.width, h = rect.height; 78         Vector2 rp1 = new Vector2(x, y); 79         Vector2 rp2 = new Vector2(x+w, y); 80         Vector2 rp3 = new Vector2(x+w, y+h); 81         Vector2 rp4 = new Vector2(x, y+h); 82         //return isSegmentOverlap(p1, p2, rp1, rp2) || isSegmentOverlap(p1, p2, rp2, rp3) ||  83         //        isSegmentOverlap(p1, p2, rp3, rp4) || isSegmentOverlap(p1, p2, rp4, rp1); 84          85         if( rect.contains(p1) || rect.contains(p2) ){ 86             return true; 87         } 88          89         return isSegmentOverlap(p1, p2, rp1, rp2) || isSegmentOverlap(p1, p2, rp2, rp3) ||  90                 isSegmentOverlap(p1, p2, rp3, rp4) || isSegmentOverlap(p1, p2, rp4, rp1); 91     } 92      93      94      95     @Override 96     public void render() { 97         // TODO Auto-generated method stub 98         super.render(); 99         Gdx.gl.glClearColor(1, 1, 1, 1);100         Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);101         102         rend.begin(ShapeType.Line);103         104         if(isSegmentOverlap(p1, p2, p3, p4)){            105             rend.setColor(Color.RED);106         }107         else{108             rend.setColor(Color.BLUE);109         }110         rend.line(p1, p2);111         rend.line(p3, p4);112         113         114 //        if(isSegRectOverlap(p1, p2, rect)){115 //            rend.setColor(Color.RED);116 //        }117 //        else{118 //            rend.setColor(Color.BLUE);119 //        }    120 //        rend.line(p1, p2);121 //        rend.rect(rect.x, rect.y, rect.width, rect.height);122         123         124         rend.end();125         126     }127 128     @Override129     public void dispose() {130         // TODO Auto-generated method stub131         super.dispose();132     }133     134     135     InputAdapter adapter = new InputAdapter(){136         @Override137         public boolean touchDown(int screenX, int screenY, int pointer, int button) {        138             p1.set(screenX, 480-screenY);            139             return super.touchDown(screenX, screenY, pointer, button);140         }141         142         143         @Override144         public boolean touchDragged(int screenX, int screenY, int pointer) {145             p2.set(screenX, 480-screenY);146             return super.touchDragged(screenX, screenY, pointer);147         }148 149 150         @Override151         public boolean touchUp(int screenX, int screenY, int pointer, int button) {152             p2.set(screenX, 480-screenY);153             return super.touchUp(screenX, screenY, pointer, button);154         }155         156         157         158     };159 160 }

运行结果:

 

显示两种状态,相交红色,不相交蓝色。

 

libgdx学习记录27——线段与线段相交检测