How to calculate the rotated coordinates of a line in UWP - c#

I have rotated a line based using Transform Group in UWP. Once after rotation I need to get the new bounds of line using the transform matrix value .Whether it is possible to get the current points of line using the matrix value? Can anyone help me out on this ?
RotateTransform rotate = new RotateTransform();
rotate.Angle = -angle;
var translate = new TranslateTransform
{
X = offset,
Y = offset
};
var group = new TransformGroup
{
Children = { (Transform)translate.Inverse, rotate,translate }
};
line.RenderTransform = group;
var matrix = ((line.RenderTransform as TransformGroup).Value);

if you know and access the Parent of the Line, then I think you can do this:
var line_bound = line.TransformToVisual(parent).TransformBounds(new Rect(0, 0, Math.Abs(line.X2 - line.X1), Math.Abs(line.Y2 - line.Y1)));
Here the parent may be a Grid or a Canvas that you attach the line to.
Read more about TransformBounds(Rect) Method here.

Related

How to make a circle type buffer around NetTopologySuite Point with radius in N meters?

I have to draw a circle with N meters diameter around some geolocation.
I could able to generate coordinates for vertically oriented ellipse only.
C#
using NetTopologySuite;
//
const int SRID = 4326;
var fact = new GeometryFactory(new PrecisionModel(), SRID);
var point = fact.CreatePoint(new Coordinate(lat, long));
var bufferParameters = new BufferParameters();
var poly = point.Buffer(0.0005, bufferParameters) as NetTopologySuite.Geometries.Polygon;
var coords = new List<BasicGeoposition>();
foreach (var cItem in poly.Coordinates)
{
coords.Add(new BasicGeoposition() { Latitude = cItem.X, Longitude = cItem.Y });
}
Please help me to understand how to set the radius and make circle instead of an ellipse.

How to get the combined bounds of multiple UI image in a canvas?

I'm trying to get the bounds of multiple ui images inside a canvas. I'm using this code:
Bounds bounds = new Bounds(imageList[0].transform.position, Vector3.zero);
for (int i = 0; i < imageList.Count; i++)
{
bounds.Encapsulate(imageList[i].transform.position);
}
But if I have two images, the bound will start and ends in the middle of each image. This code is working when using a gameobject cube, sphere etc. but different result when using UI.
You can use RectTransform.GetWorldCorners in order to get the 4 corners of each Image in word coordinates.
Then you can iterate over them and use Vector3.Min and Vector3.Max to calculate the minimum and maximum of all corners of all images.
And finally use Bounds.SetMinMax in order to create a bounding box using this minimum and maximum.
public class Example : MonoBehaviour
{
public List<Image> imageList = new List<Image>();
private void OnDrawGizmos()
{
var min = Vector3.positiveInfinity;
var max = Vector3.negativeInfinity;
foreach (var image in imageList)
{
if(!image) continue;
// Get the 4 corners in world coordinates
var v = new Vector3[4];
image.rectTransform.GetWorldCorners(v);
// update min and max
foreach (var vector3 in v)
{
min = Vector3.Min(min, vector3);
max = Vector3.Max(max, vector3);
}
}
// create the bounds
var bounds = new Bounds();
bounds.SetMinMax(min, max);
Gizmos.color = Color.red;
Gizmos.DrawWireCube(bounds.center, bounds.size);
}
}
Note: This bounding box will be world aligned with the global XYZ axis (as was your original attempt).
Use RectTransform.GetWorldCorners to get all corners of the images.
Find the minimal and maximal points.
Use Bounds.SetMinMax to get the bounds.

Extra lines appear when EdgeMode.Aliased option is used in WPF

I have encountered a very odd problem today using WPF. Here is the code I have used to draw 10000 LineGeometry objects.
// Draw 10000 lines
var g = new GeometryGroup();
var x = 0;
var y = 0;
var n = 1;
while (n < 10000)
{
x = x + 20;
if (x > 600)
{
x = 0;
y = y + 20;
}
var l = new LineGeometry
{
StartPoint = new Point(x, y),
EndPoint = new Point(x, y + 15)
};
g.Children.Add(l);
n++;
}
var drawing = new GeometryDrawing {Geometry = g};
var drawingGroup = new DrawingGroup();
drawingGroup.Children.Add(drawing);
var myPen = new Pen {Thickness = 1, Brush = Brushes.Yellow};
drawing.Pen = myPen;
var myImage = new Image {Stretch = Stretch.None, Margin = new Thickness(10)};
var myDrawingImage = new DrawingImage {Drawing = drawingGroup};
myImage.Source = myDrawingImage;
canvas.Children.Add(myImage);
Now as you can see the result is not crisp and I used the code below to achieve better results.
RenderOptions.SetEdgeMode(myImage, EdgeMode.Aliased);
The image gets crisp but has another side effects as you can see in the image below.
Some lines are now shown.
Some extra odd lines are shown.
I have included the full code so you can experiment this for yourself.
Note:
I'm using ZoomBorder class around the Canvas canvas.
Pan & Zoom Image
Have you tried using
RenderOptions.SetBitmapScalingMode(myImage, BitmapScalingMode.HighQuality);
instead?
You can also set it on your Canvas control as well..
<Canvas RenderOptions.BitmapScalingMode="HighQuality"> ...
This is not a real answer but I want add something to that odd behavior of WPF in hope somebody can come up with a real explanation.
I added a single line from (0,0)-(20000,20000). Creating 8000 line objects (n < 8000) produces the expected result like this:
Now, creating 9000 line objects will totally mess it up, but see for yourself:
Without setting EdgeMode.Aliased it looks fine, even with high counts of objects.

How to keep shape in ILCube

I want to plot some 3d surfaces with ILNumerics. I noticed that ILCube does not keep the shape of surface if I rotate it and it is because it tries to fit the cube in the ILPanel. If I use ILCamera, however, it will keep the shape but there is no cube around it. Here is an example,
private void ilPanel1_Load(object sender, EventArgs e)
{
var scene = new ILScene();
ILArray<float> A = ILSpecialData.torus(0.75f, 0.25f);
var sf = new ILSurface(A);
var pc = new ILPlotCube();
pc.TwoDMode = false;
scene.Add(pc);
pc.Add(sf);
sf.Colormap = Colormaps.Jet;
var cb = new ILColorbar();
cb.Location = new PointF(1, .1f);
sf.Children.Add(cb);
ilPanel1.Scene = scene;
}
and the result is
and for ILCamera
private void ilPanel1_Load(object sender, EventArgs e)
{
var scene = new ILScene();
ILArray<float> A = ILSpecialData.torus(0.75f, 0.25f);
var sf = new ILSurface(A);
var cam = scene.Camera;
cam.Add(sf);
sf.Colormap = Colormaps.Jet;
var cb = new ILColorbar();
cb.Location = new PointF(1, .1f);
sf.Children.Add(cb);
ilPanel1.Scene = scene;
}
and the result is
Is there any way to make the ILCube to keep the shape of the surface? Or add a cube around the surface to the ILCamera? Thanks.
Plot cubes currently do not support equal axis aspect ratios. But it is fairly simple to add this yourself.
For your example, the content of the plot cube (torus) is stretched along the Z axis, because the extend of the torus along Z is smaller than in X or Y direction. Hence, the plot cube chooses to stretch the content to give better details.
In order to show the torus without distortion, make sure the axis range of the plot cube equals in all directions:
pc.Limits.Set(new Vector3(-1,-1,-1), new Vector3(1,1,1));
See an interactive example here: http://ilnumerics.net/ilcc.php?ilc=i63fb4c
Drawback: you will have to adjust the Limits setting everytime the content of the plot cube is modified (ie. data is added / removed / altered).

WPF 3D - Apply a transformation, change the underlying object values

I've got a method that transforms a number of cylinders. If I run the method a second time it transforms the cylinders from their original position rather than their new position.
Is there anyway of 'applying' the transformation so that it changes the underlying values of the cylinders so that I can re-transform from the new values?
Can anyone assist?
Cheers,
Andy
void TransformCylinders(double angle)
{
var rotateTransform3D = new RotateTransform3D { CenterX = 0, CenterY = 0, CenterZ = 0 };
var axisAngleRotation3D = new AxisAngleRotation3D { Axis = new Vector3D(1, 1, 1), Angle = angle };
rotateTransform3D.Rotation = axisAngleRotation3D;
var myTransform3DGroup = new Transform3DGroup();
myTransform3DGroup.Children.Add(rotateTransform3D);
_cylinders.ForEach(x => x.Transform = myTransform3DGroup);
}
You are remaking the Transform3DGroup every time the method is called:
var myTransform3DGroup = new Transform3DGroup();
Transforms are essentially a stack of matrices that get multiplied together. You are clearing that stack every time you make a new group. You need to add consecutive transforms to the existing group rather than remake it.

Categories

Resources