Camera.pixel(Height/Width) doesnt match the Canvas size Unity - c#

I am making an app that has a custom viewport Rect like so:
When i check the sizes of this viewport rect in pixels with the following function in c#: Camera.pixelHeight; Camera.pixelWidth i get the following values: 743px, 770px.
This looks correct.
Now when i check my canvas in the Editor i see the following values for the width and hight.. See img below
No i have a script that gets the width and hight of the Canvas.. This is correct i get again the 743px and 770px. But when i position my UI element it is outside because the positioning refers back the the incorrect values displayed in the Canvas Rect Transform properties.
Edit:
Maybe it has something to do with how i position the element. I do it in the following way atm:
sl.position = new Vector3(200, -200, 0);
this position should be relative to the anchor point of this element in the Canvas.
What is happening here and how do it make the canvas use the correct values?

Related

Canvas and Image Share Zoom and Offset for Grid Overlay

This is in reference to the following answer: c# pan and zoom image
I want to add a grid that scales along with the image. I've tried adding a canvas with IsHitTestVisible = "False" and use border.RenderTransforms.Value.OffsetX which gives a value, but doesn't update. I also tried ((TransformGroup)border.RenderTransform).Children.First(tr => tr is ScaleTransform)) but it provides a MatrixTransform instead of a Scale.
Basically, I'm looking to share the ScaleTransform and TranslateTransform values from the ZoomBorder class object and place them into a canvas.
After some trials, I found that a simple canvas.RenderTransform = image.RenderTransform works well.

Confused about drawing a rectangle in WPF

I want to draw a rectangle on a canvas in WPF. For drawing a line I can do this:
line.X1 = ls.P0.X;
line.Y1 = ls.P0.Y;
line.X2 = ls.P1.X;
line.Y2 = ls.P1.Y;
MyCanvas.Children.Add(line);
...in other words the location is a property of the line itself. I want to draw a rectangle the same way, i.e., assign its coordinates and add it to my canvas. But the examples I've seen online so far seem to look like this:
rect = new Rectangle
{
Stroke = Brushes.LightBlue,
StrokeThickness = 2
};
Canvas.SetLeft(rect,startPoint.X);
Canvas.SetTop(rect,startPoint.X);
canvas.Children.Add(rect);
...in other words it doesn't look like the rectangle has an inherent location, but instead its location is set by calling a method of Canvas. Is this true - Lines have inherent coordinates but Rectangles do not? Is there any way to have a rectangle in WPF with an inherent location, like a line, or do I have to roll my own (using lines)?
You could use a Path control with a RectangleGeometry like this:
var rect = new Path
{
Data = new RectangleGeometry(new Rect(x, y, width, height)),
Stroke = Brushes.LightBlue,
StrokeThickness = 2
};
canvas.Children.Add(rect);
...in other words it doesn't look like the rectangle has an inherent location, but instead its location is set by calling a method of Canvas. Is this true - Lines have inherent coordinates but Rectangles do not?
Locations in WPF are relative, which begs the question: coordinates relative to what?
Line, Rectangle, and Path all inherit from Shape, and in the case of any Shape object, the coordinates of the defining geometry are relative to the top-left corner of the Shape itself. Thus, when you create a Line object from (100, 300) to (300, 100), the resulting element is 300x300 points in size, even though the visible line has bounds of 200x200:
In this case, it is unnecessary to place the Line within a Canvas, as you are not using the coordinate system of the Canvas.
Some shapes like Line and Path allow you to place geometry at any "internal" coordinates you like. Others, like Rectangle and Ellipse, always position their defining geometry at (0, 0) internally, forcing you to use other layout properties to position the shapes within the greater scene (e.g., Canvas.Top/Left, Margin, etc.).
In your example, if you were to define a Rectangle of 200x200 points, and use the Canvas attached properties to position the rectangle at (100, 100), the resulting Rectangle element would measure 200x200, while the parent Canvas would measure itself to be at least 300x300, which is arguably more intuitive:
(shading added for clarity)
You are correct in that this is rather inconsistent. You may find it useful to always use layout properties (e.g., Canvas.Left/Top) to position shapes within a scene such that all elements are using the same coordinate system.

Canvas has Width of 0 after adding children. How to cause canvas to recalculate width?

I'm creating a custom canvas which has dynamically added shapes (lines) which are added as children. Unfortunately, after adding the children, the canvas has a width of 0, which is not expected.
Ideally, the canvas should update its width by using its children's dimensions.
How can I modify my canvas to account for the dimensions of its children, and then update its width?
As I said, I changed the shapes on the canvas dynamically. I do this every time one of its dependency properties is changed using a callback function.
Generally, this is what that callback function looks like:
This is not my algorithm, but it should demonstrate the point.
public void UpdateLines()
{
for(int i = 0; i < NUM_BARS; i++)
{
Line bar = new Line();
bar.Stroke = Brushes.Black;
bar.StrokeThickness = 4;
bar.X1 = 0;
bar.X2 = ActualWidth;
bar.Y1 = i * (bar.StrokeThickness + 2);
bar.Y1 = bar.Y2;
this.Children.Add(bar);
}
//[Inserted here]
}
The next thing I noticed is that I could add a line with a large length, and that line would appear, but the canvas width would still remain 0.
At the "Inserted Here" mark, I put this line of code to test:
Children.Add(new Line() { Stroke=Brushes.Black,
StrokeThickness = 4, X1 = 0, X2 = 200, Y1 = 10, Y2 = 10 });
So, why the canvas width is not updating properly? I need to use it for calculating the size of my lines.
Your help is greatly appreciated. Thanks.
Please refer to the Panels Overview page on MSDN for further help with WPF Panels, but in short, the Canvas Panel does not resize itself when child items are added (or at any time). From the linked page:
Canvas is not affected by the size of its children. As a result, it is possible for a child element to overdraw other elements outside the bounding rectangle of the parent Canvas.
Therefore, you will either need to manually update the size of the Canvas, or use a different type of layout Panel that does resize itself when child items are added, although the Canvas is the only Panel that enables users to place child controls at absolute positions within it.
Again, from the linked page:
Canvas provides the most flexible layout support of any Panel. Height and Width properties are used to define the area of the canvas, and elements inside are assigned absolute coordinates relative to the area of the parent Canvas. Four attached properties, Canvas.Left, Canvas.Top, Canvas.Right and Canvas.Bottom, allow fine control of object placement within a Canvas, allowing the developer to position and arrange elements precisely on the screen.

Windows Phone: Can't get ViewportControl to align

I've been trying to implement pinch-and-zoom using the ViewportControl class in a Windows Phone 8 Silverlight app for quite some time without any success. There are some great samples out there, such as this one, but I haven't been able to map the examples that I found to my scenario.
Pinching and zooming works fine, the problem I'm having is with the alignment of the viewport with the content, after the manipulation has completed.
The main problem I'm facing is that after my manipulation has completed, I've been unable to align the scaled content (a XAML canvas and sub tree which is the child of the ViewportControl) to the viewport. This results in the effective bounds of the viewport (the scrollable area) being offset from my content, resulting in part of my content being unreachable/unscrollable.
Here is my algorithm for the manipulation:
Pinch manipulation starts.
Apply render transform to canvas' sub tree during pinch.
Manipulation completes.
Scale main canvas to the effective size of
the render-transformed sub tree (this works as expected and the canvas is aligned with the render-transformed sub tree).
Obtain a transform between the canvas inside the ViewportControl and the viewport control itself.
Use the transform to obtain a bounding rect which (I expect) should represent a rect which overlays the content I want to scroll inside the ViewportControl,
but in the coordinate space of the hosting ViewportControl.
Apply this rect as the viewport bounds of the ViewportControl.
Set the origin of the viewport to the translated top-left coordinates of the canvas
Here is where I calculate and apply the new bounds, after the manipulation has completed:
// Obtain transform between canvas and ViewportControl
GeneralTransform gt = m_MainCanvas.TransformToVisual(m_ViewportControl);
Rect newBounds = gt.TransformBounds(new Rect(0, 0, m_MainCanvas.Width, m_MainCanvas.Height));
m_ViewportControl.Bounds = newBounds;
// set the origin of the viewport again
m_ViewportControl.SetViewportOrigin(gt.Transform(new Point(0, 0)));
This is resulting in my content being misaligned with the viewport.
Try, try as I might, I haven't been able to figure out what I'm doing wrong here... even after looking at tutorials that show how to solve this... :|
I figure that what is happening is that my rect that I'm setting the bounds to is sized correctly, but it's X and Y coordinates are off. I was hoping that this would be addressed by using the transform between the canvas and the ViewportControl itself, but apparently not.
Question: How do I go about setting the origin of the ViewportControl correctly (how do I calculate the point to pass to the SetViewportOrigin method? Can someone please explain this ratio that people are using between the scaled contents and the viewport that I see in other examples of how to crack this?
7/8/2014 Update
I made some headway here. My approach of getting a transform between the content in the ViewportControl and the control itself, then using this to obtain a rect in the control's space to use as the bounds for the viewport wasn't working. My workaround was to simply wrap the render-transformed content in a canvas which I resized the effective (render transformed) size. Then I set the bounds to that size and I finally had the nice bounce-back effect working.
The problem I'm facing now is that when I resize the canvas and reset the bounds for the viewport, the content snaps to the top-left corner of the viewport, and is no longer centered around the pinch area that the user provided.
Can anyone help me understand how the SetViewportOrigin method works on ViewportControl? I'm seeing some really odd data for the Viewport vs. the canvas after a pinch manipulation:
Canvas Size = 1025.69, 1641.11
Bounds = 0,0,1025.69,1641.11
viewport = -56,41.00,480,698
Why is the viewport offset with non-zero values (x,y = -56,41) when I don't even call SetViewportOrigin(Point)?
Here is how I'm thinking the SetViewportOrigin(Point) method works: let's say my Viewport control itself was sized to 400 x 400 pixels, and my content was 800 x 800 pixels. If I set the origin of the viewport to 100, 100 the content would be scrolled such that the first 100 vertical and 100 horizontal pixels would be clipped/masked/offscreen. Is this not how the ViewportControl works?
I figured this out and am a happy camper now. It turned out that I was setting the viewport origin to a point using the wrong coordinate space. I was thinking that if I wanted to move the content to a certain place, that I would provide that point in the coordinate space of the viewport and the content would scroll (setting the upper-left point of the content). What I figured out is that the Point data that the SetViewportOrigin method takes is in the coordinate space of the content. For example: if your content is 500 x 500 pixels wide, your viewport is 400 x 400 pixels wide, and you'd like the first 100 vertical and 100 horizontal pixels to be masked by the viewport (showing the bottom-right corner of the content), you would set the origin to be 100,100, not -100,100.
I was doing a bunch of useless conversion between coordinate spaces, trying to pass the viewport a point in its coordinate system.

WinRT Bing.Maps - how add a image with a lat/lon bounding box?

I am able to add an image to my map just fine via code.
However when I zoom in/out, the image stays the same. I would like it scale relative to the map.
In the WPF version of the Map, you could use an ImageBrush for a MapPolygon and it would be constrained to the bounding box.
I tried the solution from this SO question, but it seems to have no effect on the Image.
imageLayer.Children.Clear();
MapLayer.SetPosition(_vm.RadarImage, new Location(_vm.Overlay.LatN, _vm.Overlay.LonW));
imageLayer.Children.Add(_vm.RadarImage);
shapeLayer.Shapes.Clear();
var rect = new MapPolygon();
rect.Locations.Add(new Location(_vm.Overlay.LatN, _vm.Overlay.LonW));
rect.Locations.Add(new Location(_vm.Overlay.LatS, _vm.Overlay.LonW));
rect.Locations.Add(new Location(_vm.Overlay.LatS, _vm.Overlay.LonE));
rect.Locations.Add(new Location(_vm.Overlay.LatN, _vm.Overlay.LonE));
rect.FillColor = Colors.Green;
shapeLayer.Shapes.Add(rect);
mappy.SetView(new LocationRect(new Location(_vm.Overlay.LatN + 0.0001, _vm.Overlay.LonW + 0.0001), new Location(_vm.Overlay.LatS - 0.0001, _vm.Overlay.LonE - 0.0001)));
This is the correct scaling.
When you zoom once via the Navigation, you can see the image is now larger than the Polygon
There isn't a simple solution for this. I have put together a sample app that shows one approach to do this. You can find it here: http://code.msdn.microsoft.com/Binding-and-Image-to-a-01a56e48 What I did was add a Canvas to the map, and then use the map to calculate the pixel coordinates of the bounding box for the image. I then used these pixel coordinates to scale and position the image on the canvas overtop the map. I've done something similar to create custom polygons that support image brushes in the past but haven't uploaded that code sample yet.

Categories

Resources