从c#中的操纵事件计算位置

时间:2014-11-23 07:11:12

标签: c# windows-phone-8 gesture

我已经创建了一个帮助应用来证明我的问题。

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

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

以下是如何使用下面附带的帮助应用程序重现我的问题: 运行应用程序,只需移动(不压缩)图像,直到获得位置值为(0,0),即可同时获取图像和矩形的左上角。 下一步捏合并移动图像并一起返回左上角,现在您可以看到该值不是(0,0)。

Download here

这是我的操纵三角洲事件:

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;
    }

1 个答案:

答案 0 :(得分:0)

首先,找到相对于变换中心的初始左上角的位置。这是相当简单的减法。这些可以预先计算,因为变换前帧不会改变。您不希望通过在_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);

然后将gestureTransform应用于角点:       Point transCorner = gestureTransform.Transform(origCorner);

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

这将使事情变得非常接近准确,除非通过改变位置然后应用变换来跟踪翻译的方式存在一些舍入误差和一些奇怪之处。通常你只会做后者。我会留下追踪作为读者的练习:)

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