使用C#WPF缩放和平移地图图像

时间:2013-09-24 14:24:27

标签: c# wpf zoom pan

我正在尝试使用罗宾逊的投影从图像制作地图。 我们的想法是为图像提供与普通地图相同的行为,因此用户应该能够在地图上进行缩放和平移,它还应该能够使用图钉标记他想要的本地化。

为此,我创建了一个管理缩放和平移行为的类,以及一个管理投影的用户控件。

我现在遇到的问题是我无法修复图像上的图钉,当我缩放时它会失去它的位置。 此外,当地图比例超过1时,推针不会放在正确的位置。

如果有人知道如何解决此问题,请提供帮助。

这是类和用户控件的代码。

ZoomPan.cs

    #region Properties

    private Canvas m_Map;
    private UIElement m_Pin;

    private Point m_Origin;
    private Point m_Start;
    public bool IsMouseWheel = false;

    #endregion

    #region Method

    /// <summary>
    /// Initialize child Events.
    /// </summary>
    public void Initialize()
    {
        m_Map = this.Children[0] as Canvas;
        m_Pin = this.Children[1];

        if (this.Children.Count >= 0)
        {
            TransformGroup aMapGroup = new TransformGroup();
            ScaleTransform aMapScale = new ScaleTransform();
            aMapGroup.Children.Add(aMapScale);
            TranslateTransform aMapTranslate = new TranslateTransform();
            aMapGroup.Children.Add(aMapTranslate);

            m_Map.RenderTransform = aMapGroup;
            m_Map.RenderTransformOrigin = new Point(0.0, 0.0);

            TransformGroup aPinGroup = new TransformGroup();
            ScaleTransform aPinScale = new ScaleTransform();
            aPinGroup.Children.Add(aPinScale);
            TranslateTransform aPinTranslate = new TranslateTransform();
            aPinGroup.Children.Add(aPinTranslate);

            m_Pin.RenderTransform = aPinGroup;
            m_Pin.RenderTransformOrigin = new Point(0.0, 0.0);

            this.MouseWheel += child_MouseWheel;
            this.MouseLeftButtonDown += child_MouseLeftButtonDown;
            this.MouseLeftButtonUp += child_MouseLeftButtonUp;
            this.MouseMove += child_MouseMove;
        }
    }

    /// <summary>
    /// Get Translate Transform.
    /// </summary>
    private TranslateTransform GetTranslateTransform(UIElement element)
    {
        return (TranslateTransform)((TransformGroup)element.RenderTransform)
          .Children.First(tr => tr is TranslateTransform);
    }

    /// <summary>
    /// Get Scale Transform.
    /// </summary>
    private ScaleTransform GetScaleTransform(UIElement element)
    {
        return (ScaleTransform)((TransformGroup)element.RenderTransform)
          .Children.First(tr => tr is ScaleTransform);
    }

    /// <summary>
    /// Set Translation.
    /// </summary>
    private double SetTranslation(double p_Max, double p_Vector)
    {
        if (p_Vector < -p_Max)
        {
            return -p_Max;
        }
        else
        {
            return p_Vector;
        }
    }

    /// <summary>
    /// Pan Child
    /// </summary>
    private void PanChild(double p_TranslateX, double p_TranslateY)
    {
        var transform = m_Pin.TransformToVisual(m_Map);
        Point p = transform.Transform(new Point(0, 0));

        p.ToString();

        var aMapScale = GetScaleTransform(m_Map);
        var aMapTranslation = GetTranslateTransform(m_Map);

        var aPinScale = GetScaleTransform(m_Pin);
        var aPinTranslation = GetTranslateTransform(m_Pin);

        if (p_TranslateX < 0)
        {
            aMapTranslation.X = SetTranslation(this.ActualWidth * (aMapScale.ScaleX - 1), p_TranslateX);
            aPinTranslation.X = SetTranslation(this.ActualWidth * (aMapScale.ScaleX - 1), p_TranslateX);
        }
        else
        {
            aMapTranslation.X = 0;
            aPinTranslation.X = 0;
        }

        if (p_TranslateY < 0)
        {
            aMapTranslation.Y = SetTranslation(this.ActualHeight * (aMapScale.ScaleY - 1), p_TranslateY);
            aPinTranslation.Y = SetTranslation(this.ActualWidth * (aMapScale.ScaleY - 1), p_TranslateY);
        }
        else
        {
            aMapTranslation.Y = 0;
            aPinTranslation.Y = 0;
        }
    }

    #endregion

    #region Child Events

    /// <summary>
    /// On Mouse Wheele (Zoom).
    /// </summary>
    private void child_MouseWheel(object sender, MouseWheelEventArgs e)
    {
        if (m_Map != null && m_Pin !=null)
        {
            IsMouseWheel = true;

            var aMapScale = GetScaleTransform(m_Map);
            var aMapTranslation = GetTranslateTransform(m_Map);

            var aPinScale = GetScaleTransform(m_Pin);
            var aPinTranslation = GetTranslateTransform(m_Pin);

            double zoom = e.Delta > 0 ? .5 : -.5;

            if (!(e.Delta > 0) && (aMapScale.ScaleX <= 1 || aMapScale.ScaleY <= 1))
            {
                return;
            }

            Point relative = e.GetPosition(m_Map);

            double abosuluteX;
            double abosuluteY;

            abosuluteX = relative.X * aMapScale.ScaleX + aMapTranslation.X;
            abosuluteY = relative.Y * aMapScale.ScaleY + aMapTranslation.Y;

            if (aMapScale.ScaleX >= 7 || aMapScale.ScaleY >= 7)
            {
                if (e.Delta > 0)
                {
                    return;
                }
            }

            aMapScale.ScaleX += zoom;
            aMapScale.ScaleY += zoom;

            CUserControlMap.m_Zoom = (int)(aMapScale.ScaleX - 1) * 2;

            double X = abosuluteX - relative.X * aMapScale.ScaleX;
            double Y = abosuluteY - relative.Y * aMapScale.ScaleY;

            PanChild(X, Y);
        }
    }

    /// <summary>
    /// Mouse Left Button Down (Translate).
    /// </summary>
    private void child_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        if (m_Map != null && m_Pin !=null)
        {
            var aMapScale = GetScaleTransform(m_Map);

            if (aMapScale.ScaleX == 1 || aMapScale.ScaleY == 1)
            {
                return;
            }

            var aMapTranslation = GetTranslateTransform(m_Map);
            m_Start = e.GetPosition(this);
            m_Origin = new Point(aMapTranslation.X, aMapTranslation.Y);
            this.Cursor = Cursors.CCursors.CursorHand;
            m_Map.CaptureMouse();
        }
    }


    /// <summary>
    /// Mouse Left Button Up.
    /// </summary>
    private void child_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        if (m_Map != null && m_Pin !=null)
        {
            m_Map.ReleaseMouseCapture();
            this.Cursor = Cursors.CCursors.CursorArrow;
        }
    }

    /// <summary>
    /// Mouse Move
    /// </summary>
    private void child_MouseMove(object sender, MouseEventArgs e)
    {
        if (m_Map != null && m_Pin != null)
        {
            if (m_Map.IsMouseCaptured)
            {
                var aMapScale = GetScaleTransform(m_Map);
                var aMapTranslation = GetTranslateTransform(m_Map);

                var aPinScale = GetScaleTransform(m_Pin);
                var aPinTranslation = GetTranslateTransform(m_Pin);

                Vector v = m_Start - e.GetPosition(this);

                double X = m_Origin.X - v.X;
                double Y = m_Origin.Y - v.Y;

                PanChild(X, Y);
            }
        }
    }
    #endregion
}

MapControl.cs的代码

    #region Properties

    /// <summary> Latitude</summary>
    public float Latitude = 0;

    /// <summary> Longitude</summary>
    public float Longitude = 0;

    /// <summary> Longitude in Pixels</summary>
    private static double s_kLongitudeInPixel = 0.81;

    /// <summary> Latitude in Pixels</summary>
    private static double s_kLatitudeInPixel = 0.71;

    /// <summary> Middle of the map</summary>
    private static double s_KMiddle = 206;

    /// <summary> Pin Image</summary>
    private Image m_Pin = new Image();

    public static double m_Zoom = 0;

    #endregion

    #region Constructor

    /// <summary>
    /// Constructor
    /// </summary>
    public CUserControlMap()
    {
        InitializeComponent();

        m_Pin.Source = Application.Current.TryFindResource("Pin") as BitmapImage;
        m_Pin.Height = 24;
        m_Pin.Width = 30;

        m_Canvas.Children.Add(m_Pin);
        m_Canvas.Initialize();
    }

    #endregion

    #region Methods

    /// <summary>
    /// Add a pin to the current Localization
    /// </summary>
    public void SetCurrentLocalization(float p_latitude, float p_longitude)
    {
        double pointX = GetXFromLongitude(p_longitude);
        double pointY = GetYFromLatitude(p_latitude);

        m_Pin.Margin = new Thickness(pointX + 97 , pointY - 22, 0, 0);
    }

    /// <summary>
    /// Get X from longitude
    /// </summary>
    private double GetXFromLongitude(float p_longitude)
    {
        return (p_longitude / s_kLongitudeInPixel) + (s_KMiddle / 2);
    }

    /// <summary>
    /// Get Y from latitude
    /// </summary>
    private double GetYFromLatitude(float p_latitude)
    {
        return (m_Image.Height / 2) - (p_latitude / s_kLatitudeInPixel);
    }

    #endregion

    #region Events

    /// <summary>
    /// Image Mouse Right Button Down
    /// </summary>
    private void Image_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
    {
        Point point = e.GetPosition(m_Image);

        Longitude = (float)(point.X - s_KMiddle) * (float)s_kLongitudeInPixel;
        Latitude = (float)(m_Image.Height / 2 - point.Y) * (float)s_kLatitudeInPixel;

        SetCurrentLocalization((float)Latitude, (float)Longitude);
    }

    #endregion

1 个答案:

答案 0 :(得分:0)

使用LayoutTransform而不是RenderTransform。 更多详情:http://msdn.microsoft.com/en-us/library/ms750596.aspx#layoutTransformsAndRenderTransformsSection