Change the coordinate system of a Canvas in WPF?

Here's an all-XAML solution. Well, mostly XAML, because you have to have the IValueConverter in code. So: Create a new WPF project and add a class to it.

The class is MultiplyConverter: namespace YourProject { public class MultiplyConverter : System.Windows.Data. IValueConverter { public object Convert(object value, System. Type targetType, object parameter, System.Globalization.

CultureInfo culture) { return AsDouble(value)* AsDouble(parameter); } double AsDouble(object value) { var valueText = value as string; if (valueText! = null) return double. Parse(valueText); else return (double)value; } public object ConvertBack(object value, System.

Type targetType, object parameter, System.Globalization. CultureInfo culture) { throw new System. NotSupportedException(); } } } Then use this XAML for your Window.

Now you should see the results right in your XAML preview window EDIT : You can fix the Background problem by putting your Canvas inside another Canvas. Kind of weird, but it works. In addition, I've added a ScaleTransform which flips the Y-axis so that positive Y is up and negative is down.

Note carefully which Names go where: Canvas Name="canvas" Background="Moccasin".

Here's an all-XAML solution. Well, mostly XAML, because you have to have the IValueConverter in code. So: Create a new WPF project and add a class to it.

The class is MultiplyConverter: namespace YourProject { public class MultiplyConverter : System.Windows.Data. IValueConverter { public object Convert(object value, System. Type targetType, object parameter, System.Globalization.

CultureInfo culture) { return AsDouble(value)* AsDouble(parameter); } double AsDouble(object value) { var valueText = value as string; if (valueText! = null) return double. Parse(valueText); else return (double)value; } public object ConvertBack(object value, System.

Type targetType, object parameter, System.Globalization. CultureInfo culture) { throw new System. NotSupportedException(); } } } Then use this XAML for your Window.

Now you should see the results right in your XAML preview window. EDIT: You can fix the Background problem by putting your Canvas inside another Canvas. Kind of weird, but it works.In addition, I've added a ScaleTransform which flips the Y-axis so that positive Y is up and negative is down.

Note carefully which Names go where: As for your new requirements that you need varying ranges, a more complex ValueConverter would probably do the trick.

This solution also works with a PathGeometry, by the way. – Kyralessa Oct 31 '08 at 20:05 This is pretty close to what I need, but I don't think that this scales well enough. If either the coordinate system was Lat=(2, -74) Lon=(-180, -175) or if the size of the Canvas changes (h=50,w=100) it will not work.

Also, the Background property is unusable. – Dylan Oct 31 '08 at 21:17 The various Transforms are what you want, but finding the exact right combination and order of them is kind of a pain. – Kyralessa Nov 1 '08 at 5:27 ...and it's not made any easier by the fact that the XAML preview window often doesn't show things to scale.

If something that should be correct looks off in the preview window, you may have to run the app to see that it's not really off. – Kyralessa Nov 1 '08 at 5:30.

I'm pretty sure you can't do that exactly, but it would be pretty trivial to have a method which translated from lat/long to Canvas coordinates. Point ToCanvas(double lat, double lon) { double x = ((lon * myCanvas. ActualWidth) / 360.0) - 180.0; double y = ((lat * myCanvas.

ActualHeight) / 180.0) - 90.0; return new Point(x,y); } (Or something along those lines).

I have that function, I was just hoping to not need to convert points to and from the canvas all the time. – Dylan Oct 31 '08 at 16:48 Doing it that way does have the added benefit of making your canvas nice and scalable. – MojoFilter Oct 31 '08 at 17:13.

I guess another option would be to extend canvas and override the measure / arrange to make it behave the way you want.

That's more along the lines I was thinking, but I'm not sure how to implement it. – Dylan Oct 31 '08 at 16:51 It's not really tooooo simple. The idea is that you override ArrangeOverride() and MeasureOverride().

– MojoFilter Oct 31 '08 at 17:11.

I was able to get it to by creating my own custom canvas and overriding the ArrangeOverride function like so: public class CustomCanvas : Canvas { protected override Size ArrangeOverride(Size arrangeSize) { foreach (UIElement child in InternalChildren) { double left = Canvas. GetLeft(child); double top = Canvas. GetTop(child); Point canvasPoint = ToCanvas(top, left); child.

Arrange(new Rect(canvasPoint, child. DesiredSize)); } return arrangeSize; } Point ToCanvas(double lat, double lon) { double x = this. Width / 360; x *= (lon - -180); double y = this.

Height / 180; y *= -(lat + -90); return new Point(x, y); } } Which works for my described problem, but it probably would not work for another need I have, which is a PathGeometry. It wouldn't work because the points are not defined as Top and Left, but as actual points.

You can use transform to translate between the coordinate systems, maybe a TransformGroup with a TranslateTranform to move (0,0) to the center of the canvas and a ScaleTransform to get the coordinates to the right range. With data binding and maybe a value converter or two you can get the transforms to update automatically based on the canvas size. The advantage of this is that it will work for any element (including a PathGeometry), a possible disadvantage is that it will scale everything and not just points - so it will change the size of icons and text on the map.

Another possible solution: Embed a custom canvas (the draw-to canvas) in another canvas (the background canvas) and set the draw-to canvas so that it is transparent and does not clip to bounds. Transform the draw-to canvas with a matrix that makes y flip (M22 = -1) and translates/scales the canvas inside the parent canvas to view the extend of the world you're looking at. In effect, if you draw at -115, 42 in the draw-to canvas, the item you are drawing is "off" the canvas, but shows up anyway because the canvas is not clipping to bounds.

You then transform the draw-to canvas so that the point shows up in the right spot on the background canvas. This is something I'll be trying myself soon. Hope it helps.

Note: I tried this out, but found one oddity. If you scale in until a meter is roughly a few tens of pixels and you are NOT near the actual 0,0 point of the draw-to canvas, moving the draw-to canvas (via transform OR via Canvas. SetTop/SetLeft) seems to be quantized.

Even though you change either top/left or M11/M22 by small values, the visual drawing doesn't move except at "quantized" values (not sure what those values are). I'm wondering if it's making calculations in double but passing them to some lower-level routine that converts to floats, thus "quantizing" large numbers. – FTLPhysicsGuy Jun 23 '10 at 19:31.

Embed a custom canvas (the draw-to canvas) in another canvas (the background canvas) and set the draw-to canvas so that it is transparent and does not clip to bounds. Transform the draw-to canvas with a matrix that makes y flip (M22 = -1) and translates/scales the canvas inside the parent canvas to view the extend of the world you're looking at. In effect, if you draw at -115, 42 in the draw-to canvas, the item you are drawing is "off" the canvas, but shows up anyway because the canvas is not clipping to bounds.

You then transform the draw-to canvas so that the point shows up in the right spot on the background canvas. This is something I'll be trying myself soon. Hope it helps.

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions