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     @Override
129     public void dispose() {
130         // TODO Auto-generated method stub
131         super.dispose();
132     }
133     
134     
135     InputAdapter adapter = new InputAdapter(){
136         @Override
137         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         @Override
144         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         @Override
151         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 }

运行结果:

 

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

 

posted @ 2014-10-22 20:39  丛林小阁楼  阅读(401)  评论(0编辑  收藏  举报