I'm trying to make a map from an image using the projection of Robinson. The idea is to give the image the same behaviors of a normal map, so the user should be able to zoom and pan on the map, it should be also able to mark the localisation that he want using a pushpin.
To do this I create a class that manage the zoom and pan behaviors, and a user control that manage the projection.
Th problem that i have now is that i can't fix the pushpin on the image, and it lose it's position when i'm zooming. Also when the map scale is over 1, the push pin is not placed on the right position.
If anyone has an idea of how can I fix this problem, please help.
Here is the code of the class and of the user control.
ZoomPan.cs
#region PropertiesprivateCanvas m_Map;privateUIElement m_Pin;privatePoint m_Origin;privatePoint m_Start;public bool IsMouseWheel=false;#endregion#region Method/// <summary>/// Initialize child Events./// </summary>publicvoidInitialize(){
m_Map =this.Children[0]asCanvas;
m_Pin =this.Children[1];if(this.Children.Count>=0){TransformGroup aMapGroup =newTransformGroup();ScaleTransform aMapScale =newScaleTransform();
aMapGroup.Children.Add(aMapScale);TranslateTransform aMapTranslate =newTranslateTransform();
aMapGroup.Children.Add(aMapTranslate);
m_Map.RenderTransform= aMapGroup;
m_Map.RenderTransformOrigin=newPoint(0.0,0.0);TransformGroup aPinGroup =newTransformGroup();ScaleTransform aPinScale =newScaleTransform();
aPinGroup.Children.Add(aPinScale);TranslateTransform aPinTranslate =newTranslateTransform();
aPinGroup.Children.Add(aPinTranslate);
m_Pin.RenderTransform= aPinGroup;
m_Pin.RenderTransformOrigin=newPoint(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>privateTranslateTransformGetTranslateTransform(UIElement element){return(TranslateTransform)((TransformGroup)element.RenderTransform).Children.First(tr => tr isTranslateTransform);}/// <summary>/// Get Scale Transform./// </summary>privateScaleTransformGetScaleTransform(UIElement element){return(ScaleTransform)((TransformGroup)element.RenderTransform).Children.First(tr => tr isScaleTransform);}/// <summary>/// Set Translation./// </summary>privatedoubleSetTranslation(double p_Max,double p_Vector){if(p_Vector <-p_Max){return-p_Max;}else{return p_Vector;}}/// <summary>/// Pan Child/// </summary>privatevoidPanChild(double p_TranslateX,double p_TranslateY){var transform = m_Pin.TransformToVisual(m_Map);Point p = transform.Transform(newPoint(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>privatevoid 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>privatevoid 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 =newPoint(aMapTranslation.X, aMapTranslation.Y);this.Cursor=Cursors.CCursors.CursorHand;
m_Map.CaptureMouse();}}/// <summary>/// Mouse Left Button Up./// </summary>privatevoid 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>privatevoid 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}
The code of MapControl.cs
#region Properties/// <summary> Latitude</summary>publicfloatLatitude=0;/// <summary> Longitude</summary>publicfloatLongitude=0;/// <summary> Longitude in Pixels</summary>privatestaticdouble s_kLongitudeInPixel =0.81;/// <summary> Latitude in Pixels</summary>privatestaticdouble s_kLatitudeInPixel =0.71;/// <summary> Middle of the map</summary>privatestaticdouble s_KMiddle =206;/// <summary> Pin Image</summary>privateImage m_Pin =newImage();publicstaticdouble m_Zoom =0;#endregion#region Constructor/// <summary>/// Constructor/// </summary>publicCUserControlMap(){InitializeComponent();
m_Pin.Source=Application.Current.TryFindResource("Pin")asBitmapImage;
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>publicvoidSetCurrentLocalization(float p_latitude,float p_longitude){double pointX =GetXFromLongitude(p_longitude);double pointY =GetYFromLatitude(p_latitude);
m_Pin.Margin=newThickness(pointX +97, pointY -22,0,0);}/// <summary>/// Get X from longitude/// </summary>privatedoubleGetXFromLongitude(float p_longitude){return(p_longitude / s_kLongitudeInPixel)+(s_KMiddle /2);}/// <summary>/// Get Y from latitude/// </summary>privatedoubleGetYFromLatitude(float p_latitude){return(m_Image.Height/2)-(p_latitude / s_kLatitudeInPixel);}#endregion#region Events/// <summary>/// Image Mouse Right Button Down/// </summary>privatevoidImage_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