根据 c# 中的操作事件计算仓位

本文关键字:计算 事件 操作 根据 | 更新日期: 2023-09-27 18:31:39

我创建了一个辅助应用程序来演示我的问题。

我有一个填充有图像画笔的矩形,这个画笔可以使用手势操作在矩形内转换。

我正在从矩形的左上角确定图像左上角的位置。我在(仅)翻译图像时获得了正确的值,但在使用捏合手势时获得了错误的值。如果放大太多并平移图像,则画笔会向相反方向移动。

以下是您可以使用下面附加的帮助程序应用程序重现我的问题的方法:运行应用程序,只需移动(不捏合)图像,直到获得位置值为 (0,0),即可将图像和矩形的左上角放在一起。接下来捏合并移动图像并一起返回左上角,现在您可以看到该值不是 (0,0)。

在此下载

这是我的操作增量事件:

public virtual void Brush_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
    {
        if (e.PinchManipulation != null)
        {
            // Rotate
            _currentAngle = previousAngle + AngleOf(e.PinchManipulation.Original) - AngleOf(e.PinchManipulation.Current);
            // Scale
            _currentScale *= e.PinchManipulation.DeltaScale;
            // Translate according to pinch center
            double deltaX = (e.PinchManipulation.Current.SecondaryContact.X + e.PinchManipulation.Current.PrimaryContact.X) / 2 -
                (e.PinchManipulation.Original.SecondaryContact.X + e.PinchManipulation.Original.PrimaryContact.X) / 2;
            double deltaY = (e.PinchManipulation.Current.SecondaryContact.Y + e.PinchManipulation.Current.PrimaryContact.Y) / 2 -
                (e.PinchManipulation.Original.SecondaryContact.Y + e.PinchManipulation.Original.PrimaryContact.Y) / 2;
            _currentPos.X = previousPos.X + deltaX;
            _currentPos.Y = previousPos.Y + deltaY;
        }
        else
        {
            // Translate
            previousAngle = _currentAngle;
            _currentPos.X += e.DeltaManipulation.Translation.X;
            _currentPos.Y += e.DeltaManipulation.Translation.Y;
            previousPos.X = _currentPos.X;
            previousPos.Y = _currentPos.Y;
        }
        e.Handled = true;
        ProcesstTransform();
    }
    void ProcesstTransform()
    {
        CompositeTransform gestureTransform = new CompositeTransform();
        gestureTransform.CenterX = _currentPos.X;
        gestureTransform.CenterY = _currentPos.Y;
        gestureTransform.TranslateX = _currentPos.X - outputSize.Width / 2.0;
        gestureTransform.TranslateY = _currentPos.Y - outputSize.Height / 2.0;
        gestureTransform.Rotation = _currentAngle;
        gestureTransform.ScaleX = gestureTransform.ScaleY = _currentScale;
        brush.Transform = gestureTransform;
    }

根据 c# 中的操作事件计算仓位

首先,找到初始左上角相对于变换中心的位置。这几乎是直接的减法。这些可以预先计算,因为转换前的框架不会更改。您不希望通过乘以_scale来预先缩放_brushSize。这将最终缩放画笔两次。

  Point origCentre = new Point(ManipulationArea.ActualWidth / 2, ManipulationArea.ActualHeight / 2);
  Point origCorner = new Point(origCentre.X - _brushSize.Width / 2, origCentre.Y - _brushSize.Height /2);

然后将手势变换应用到角点: Point transCorner = gestureTransform.Transform(origCorner);

  XValue.Text = transCorner.X.ToString();
  YValue.Text = transCorner.Y.ToString();

这将使事情非常接近准确,除非通过更改位置和应用转换来跟踪翻译的方式会出现一些舍入错误和一些奇怪之处。通常,您只会执行后者。我将把追踪它作为读者的练习:)

Microsoft的Rob Caplan帮助我解决了这个问题。