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 }
运行结果:
显示两种状态,相交红色,不相交蓝色。