我需要确定在画布上移动的对象的交集(不一定在画布上,其他任何面板上)。
我正在尝试确定与FillContainsWithDetail的交点。似乎相交会忽略对象的相对位置。
XAML:
<Window x:Class="WpfCollisionTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfCollisionTest"
Title="Collisions" Height="400" Width="500">
<Window.DataContext>
<local:CProvider x:Name="Provider"/>
</Window.DataContext>
<Window.Resources>
<PathGeometry x:Key="geoPoly">
<PathGeometry.Figures>
<PathFigure StartPoint="0,0" IsClosed="True">
<PolyLineSegment Points="0,0 50,0 50,50 0,50"/>
</PathFigure>
</PathGeometry.Figures>
</PathGeometry>
</Window.Resources>
<Grid>
<Canvas Background="White" MouseMove="Canvas_OnMouseMove">
<Path Name="rectangle1" Data="{StaticResource geoPoly}" Stroke="Black"
Canvas.Left="175" Canvas.Top="100"/>
<Path Name="rectangle2" Data="{StaticResource geoPoly}" Stroke="Black"
Canvas.Left="{Binding rectLeft}" Canvas.Top="{Binding rectTop}"/>
</Canvas>
<TextBlock Text="{Binding intersectionDetail}" VerticalAlignment="Bottom"/>
</Grid>
CS:
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
namespace WpfCollisionTest
{
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
}
private void Canvas_OnMouseMove(object sender, MouseEventArgs e)
{
var pos = e.GetPosition(sender as FrameworkElement);
Provider.rectLeft = pos.X;
Provider.rectTop = pos.Y;
var g1 = rectangle1.RenderedGeometry.GetFlattenedPathGeometry();
var g2 = rectangle2.RenderedGeometry.GetFlattenedPathGeometry();
var intersect = g1.FillContainsWithDetail(g2);
Provider.intersectionDetail = intersect.ToString();
}
}
}
在此示例中,结果始终是:相交。
我想念什么?
最近,我不得不处理相同的问题。因此,
我们需要一种从源对象提取所有转换的方法。在我的应用程序中,我仅在Canvas中使用RenderTransform。另外,请确保在使用Canvas.Top和Canvas.Left参数进行TranslateTransform之前应用此变换:
private static Transform GetFullTransform(UIElement e)
{
// The order in which transforms are applied is important!
var transforms = new TransformGroup();
if(e.RenderTransform != null)
transforms.Children.Add(e.RenderTransform);
var xTranslate = (double)e.GetValue(Canvas.LeftProperty);
if (double.IsNaN(xTranslate))
xTranslate = 0D;
var yTranslate = (double)e.GetValue(Canvas.TopProperty);
if (double.IsNaN(yTranslate))
yTranslate = 0D;
var translateTransform = new TranslateTransform(xTranslate, yTranslate);
transforms.Children.Add(translateTransform);
return transforms;
}
介绍一种将给定对象转换为Geometry的方法。在此出于演示目的,我转换了Shape对象:
public Geometry GetGeometry(Shape s)
{
var g = s.RenderedGeometry.Clone();
g.Transform = GetFullTransform(s);
return g;
}
最后,使用FillContainsWithDetail方法。在以下两种情况下,以下条件返回True:当存在相交时,或者其中一个几何完全在另一个几何内部时:
private static bool HasIntersection(Geometry g1, Geometry g2) =>
g1.FillContainsWithDetail(g2) != IntersectionDetail.Empty;