WPFのRectの重なり判定、RectangleGeometryにしてからFillContainsWithDetailメソッドでできた
2つのRectの重なり判定を、GeometryクラスのFillContainsWithDetailメソッドで行ってみた
FillContainsWithDetailはIntersectionDetailを返すので、それを見て判定
IntersectionDetail 列挙型(System.Windows.Media) | Microsoft
Docs
//https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.media.intersectiondetail
IntersectionDetail列挙型 | 状態 |
---|---|
Empty | 全く重なっていない |
FullyContains | r2はr1の領域に完全に収まっている |
FullyInside | r1はr2の領域に完全に収まっている |
Intersects | 一部が重なっている |
NotCalculated | 計算されません(よくわからん) |
こんな便利なのがあったのね
それぞれの重なりの状態
これを基準にしたとして
一部が重なっている
全く重なっているところがない
すべて覆っているか、全て覆われているか
キワキワ部分のx4倍表示もいっしょに載せてみた
実行環境
- Visual Studio Community 2019
- Windows 10 Home
- WPF
- .NET Core 5
- C#
2つのRectの一部でも重なっていたらtrueを返す
MainWindow.xaml.cs
using System.Windows; using System.Windows.Media; //IntersectionDetail 列挙型(System.Windows.Media) | Microsoft Docs //https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.media.intersectiondetail namespace _20210127_Rect同士の重なり判定 { /// <summary> /// RectからRectangleGeometryを作って、FillContainsWithDetailメソッドを使って判定できる /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); Rect r1 = new(0, 0, 100, 100);//座標0,0 サイズ100,100 //true Intersects var r1r2 = IsOverlapping(r1, new(10, 10, 100, 100)); //true FullyContains var r1r3 = IsOverlapping(r1, new(10, 10, 50, 50)); //false Empty var r1r4 = IsOverlapping(r1, new(100, 100, 100, 100)); //true intersects var r1r5 = IsOverlapping(r1, new(99, 99, 100, 100)); //false Empty var r1r6 = IsOverlapping(r1, new(110, 50, 100, 100)); //true FullyInside var r1r7 = IsOverlapping(r1, new(-10, -10, 200, 200)); } /// <summary> /// 2つのRectが一部でも重なっていたらtrueを返す /// </summary> /// <param name="r1"></param> /// <param name="r2"></param> /// <returns></returns> private (bool, IntersectionDetail) IsOverlapping(Rect r1, Rect r2) { RectangleGeometry geo1 = new(r1); IntersectionDetail detail = geo1.FillContainsWithDetail(new RectangleGeometry(r2)); return (detail != IntersectionDetail.Empty, detail); //return (detail != IntersectionDetail.Empty || detail != IntersectionDetail.NotCalculated, detail); } //IntersectionDetail列挙型 //Empty 全く重なっていない //FullyContains r2はr1の領域に完全に収まっている //FullyInside r1はr2の領域に完全に収まっている //Intersects 一部が重なっている //NotCalculated 計算されません(よくわからん) } }
実行結果
IntersectionDetailのNotCalculatedってのはよくわからない(計算されませんってなんなん)ので、Empty以外なら重なっていると判定することにした
判定だけなら1行でもできる
return IntersectionDetail.Empty != new RectangleGeometry(r1).FillContainsWithDetail(new RectangleGeometry(r2));
new Rectしてないよ
37行目の
new(-10, -10, 200, 200);
Rectを作っているので、ホントなら
new Rect(-10, -10, 200, 200));
こう書くんだけど、書いてなくてもRect扱いになっているのは、このメソッドの引数の型がRectってわかっているからこうなるんかなあ
Core 5.0以前は
List
Core 5.0からは
List
関連記事
次回のWPF記事は5日後
前回のWPFは4日前
5年前
gogowaten.hatenablog.com
今回の記事と同じことしてた…この記事のことは憶えているけど、FillContainsWithDetailを使っていたことは全く憶えていない、すごい記憶力だ!