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 件のコメント:
コメントを投稿