C#のFormで、FormにはPictureBoxを親コンテナにドッキングして配置する。またPictureBoxのClickイベントを使用する。
青い斜めの線は固定となり、もう一方の線はマウスで二箇所をクリックすることにより、それらを接続する線を引くことができる。2本の線が交差している場合は赤で、交差していない場合は緑で表示する。
アルゴリズムは 線分交差判定 - juntkの日記 に書いてある物をそのまま使用させてもらった。
線分同士の当たり判定は、例えば現在位置と未来位置で線を作り、進入禁止エリアを囲うラインと当たり判定を行い、衝突が発生した場合は移動させない というような使い方ができると思う。ただし線分同士の衝突範囲では、万が一線で囲ったエリアの中に入り込んでしまった場合には、外にでることができなくなるという問題がある。また、今いる場所が進入禁止エリアの中なのか、それとも稼働可能範囲なのかを判定することは出来ない。
それと、線分同士の当たり判定では始点と終点を使用するため、線のどの部分で衝突しているかを判定することは出来ない。もしもどの場所で衝突しているかを調べる必要があるなら、二分探索等で十分に線が短くなるまで探していくか、他の方法を考える必要がある。
using System;
using System.Drawing;
using System.Windows.Forms;
namespace LineCollisionDetection {
public partial class Form1 : Form {
LinePoint Line1, Line2;
Point? Start;
Pen Pen1, Pen2, Pen3;
public Form1() {
InitializeComponent();
Pen1 = new Pen(Color.Red, 3);
Pen2 = new Pen(Color.Green, 3);
Pen3 = new Pen(Color.Blue, 3);
Line1 = new LinePoint(new Point(100, 100), new Point(300, 300));
Line2 = new LinePoint(new Point(300, 100), new Point(100, 300));
Size += new Size(400, 400) - pictureBox1.Size;
MaximumSize = MinimumSize = Size;
Draw();
}
~Form1() {
Pen1.Dispose();
Pen2.Dispose();
Pen3.Dispose();
if (pictureBox1.Image != null) {
pictureBox1.Image.Dispose();
}
}
private void pictureBox1_Click(object sender, EventArgs e) {
Point mouse = pictureBox1.PointToClient(Cursor.Position);
if (Start == null) {
Start = mouse;
} else {
Line1 = new LinePoint(Start ?? new Point(), mouse);
Start = null;
Draw();
}
}
public void Draw() {
Bitmap bmp = new Bitmap(pictureBox1.Width, pictureBox1.Height);
using (Graphics gra = Graphics.FromImage(bmp)) {
bool Collision = LinePoint.IsCollision(Line1, Line2);
gra.DrawLine(Pen3, Line2.S, Line2.E);
gra.DrawLine(Collision ? Pen1 : Pen2, Line1.S, Line1.E);
}
if (pictureBox1.Image != null) {
pictureBox1.Image.Dispose();
}
pictureBox1.Image = bmp;
}
class LinePoint {
public Point S;
public Point E;
public LinePoint() {
S = new Point();
E = new Point();
}
public LinePoint(Point S, Point E) {
this.S = S;
this.E = E;
}
public LinePoint(LinePoint Line) {
S = Line.S;
E = Line.E;
}
static public bool IsCollision(LinePoint Line1, LinePoint Line2) {
return ((
((Line2.S.X - Line2.E.X) * (Line1.S.Y - Line2.S.Y) + (Line2.S.Y - Line2.E.Y) * (Line2.S.X - Line1.S.X)) *
((Line2.S.X - Line2.E.X) * (Line1.E.Y - Line2.S.Y) + (Line2.S.Y - Line2.E.Y) * (Line2.S.X - Line1.E.X)) <= 0) && (
((Line1.S.X - Line1.E.X) * (Line2.S.Y - Line1.S.Y) + (Line1.S.Y - Line1.E.Y) * (Line1.S.X - Line2.S.X)) *
((Line1.S.X - Line1.E.X) * (Line2.E.Y - Line1.S.Y) + (Line1.S.Y - Line1.E.Y) * (Line1.S.X - Line2.E.X)) <= 0));
}
}
}
}
0 件のコメント:
コメントを投稿