Проверьте, находится ли точка рядом с преобразованным прямоугольником - PullRequest
0 голосов
/ 25 сентября 2019

У меня есть Rectangle, который преобразуется, если установить для его свойства RenderTransform значение TransformGroup.Группа преобразований содержит следующие преобразования: SkewTransform, RotateTransform, TranslateTransform.

Теперь я хотел бы создать метод, который определяет, находится ли Point рядом с прямоугольником.Таким образом, не только когда точка равна в (преобразованном) прямоугольнике, но также и когда она очень близка к нему.Без использования воображаемого круга / радиуса от центральной точки прямоугольника.

Порог, который определяет, достаточно ли близка точка и может рассматриваться как находящаяся рядом, всегда находится на одинаковом расстоянии от силуэтапреобразованный прямоугольник.Вы можете видеть это, как будто прямоугольник имеет границу, скажем, 30 пикселей.Когда точка находится в этой границе (или в самом прямоугольнике), результат будет true .В противном случае результат будет false .

Имея всю доступную помощь .NET Framework, это кажется простым.Он попробовал несколько подходов, например, используя Visual.pointFromScreen().Обратное преобразование и т. Д. Но я продолжаю делать что-то не так.

И чтобы сделать вещи более сложными, я также ищу быстрое и эффективное решение.

Код, который я пробовал:

public bool IsInHitArea(Point pt)
{
    // _transformedRect = my rectangle
    // HitRectangleMargin = proximity treshold.
    // _offsetX, _offsetY = x and y position of rectangle
    // _areaWidth, _areaHeight = width/height of rectangle

    Point p = _transformedRect.PointFromScreen(pt);

    return (p.X >= _offsetX - HitRectangleMargin
        && p.X <= _offsetX + _areaWidth + HitRectangleMargin
        && p.Y >= _offsetY - HitRectangleMargin
        && p.Y <= _offsetY + _areaHeight + HitRectangleMargin);
}

// Or another try

public bool IsInHitArea(Point pt)
{
    // TransformGroup is a property containing the transform group.

    Point p = TransformGroup.Inverse.Transform(pt);

    // I actually don't really undersand if it's maybe naive to use just the following
    // equations:
    return (p.X >= _offsetX - HitRectangleMargin
        && p.X <= _offsetX + _areaWidth + HitRectangleMargin
        && p.Y >= _offsetY - HitRectangleMargin
        && p.Y <= _offsetY + _areaHeight + HitRectangleMargin);
}

1 Ответ

0 голосов
/ 25 сентября 2019

Вместо использования прямоугольника, преобразованного с помощью RenderTransform, лучше использовать путь с преобразованным RectangleGeometry.

Вы можете наложить отображаемый путь на другой, имеющий прозрачный Stroke и Fill и достаточно широкая StrokeThickness для захвата ввода мыши в непосредственной близости от отображаемого прямоугольника.

<Window.DataContext>
    <local:ViewModel/>
</Window.DataContext>
<Canvas>
    <Path Data="{Binding TransformedRectangle}"
          StrokeThickness="3" Stroke="Black"/>

    <Path Data="{Binding TransformedRectangle}"
          StrokeThickness="60" StrokeLineJoin="Round"
          Stroke="Transparent" Fill="Transparent"
          MouseLeftButtonDown="PathMouseLeftButtonDown"/>
</Canvas>

Пример модели представления, которая обеспечивает преобразованную геометрию:

public class ViewModel
{
    public RectangleGeometry TransformedRectangle { get; } = new RectangleGeometry();

    public ViewModel()
    {
        var transform = new TransformGroup();
        transform.Children.Add(new ScaleTransform(2, 1));
        transform.Children.Add(new SkewTransform(30, 0));
        transform.Children.Add(new RotateTransform(45, 250, 150));

        TransformedRectangle.Rect = new Rect(100, 100, 100, 100);
        TransformedRectangle.Transform = transform;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...