WPF:如何检测画布上的几何相交?

问题描述 投票:0回答:1

我需要确定在画布上移动的对象的交集(不一定在画布上,其他任何面板上)。

我正在尝试确定与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();
        }
    }
}

在此示例中,结果始终是:相交。

我想念什么?

enter image description here

c# wpf geometry intersection
1个回答
0
投票

最近,我不得不处理相同的问题。因此,

  1. 我们需要一种从源对象提取所有转换的方法。在我的应用程序中,我仅在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;
    }
    
  2. 介绍一种将给定对象转换为Geometry的方法。在此出于演示目的,我转换了Shape对象:

    public Geometry GetGeometry(Shape s)
    {
        var g = s.RenderedGeometry.Clone();
        g.Transform = GetFullTransform(s);
        return g;
    }
    
  3. 最后,使用FillContainsWithDetail方法。在以下两种情况下,以下条件返回True:当存在相交时,或者其中一个几何完全在另一个几何内部时:

    private static bool HasIntersection(Geometry g1, Geometry g2) =>
        g1.FillContainsWithDetail(g2) != IntersectionDetail.Empty;
    
© www.soinside.com 2019 - 2024. All rights reserved.