UWP:如何在旋转后获得新的形状尺寸?

UWP:如何在旋转后获得新的形状尺寸?,uwp,geometry,windows-10-universal,Uwp,Geometry,Windows 10 Universal,如何在UWP中测量旋转后的宽度和高度?它可以是任何形状,例如多边形或椭圆。 只需计算极值点的坐标即可 对于多边形 left = min(p[i].x) right = max(p[i].x) top = min(p[i].y) bottom = max(p[i].y) 对于椭圆或其他解析曲线,解析地获得极值坐标 solve X'(t) = 0 for t=tz (there are some subtle moments for min/max finding through deriv

如何在UWP中测量旋转后的宽度和高度?它可以是任何形状,例如多边形或椭圆。
只需计算极值点的坐标即可

对于多边形

left = min(p[i].x)
right = max(p[i].x)
top = min(p[i].y)
bottom = max(p[i].y)
对于椭圆或其他解析曲线,解析地获得极值坐标

solve X'(t) = 0 for t=tz   
(there are some subtle moments for min/max finding through derivatives)
find min and max from X(tz) and curve ends and so on

不幸的是,我找不到从XAML可视化树计算边界框的方法。我通常使用Win2D进行这些类型的操作。看一看它计算边界框的能力

如果您没有Win2D的访问权限,或者您只需要快速解决此问题,这里有一个帮助器类,可以处理任何形状、椭圆、路径等:

警告:这是一个使用暴力命中测试的糟糕实现。我添加了一个计时器来证明它有多慢

public static class BoundsHelper
{
    /// <summary>Computes the axis-aligned minimum bounding box of the given <paramref name="element"/>.</summary>
    /// <param name="element">The element to test.</param>
    /// <param name="tolerance">The precision tolerance expressed in pixels. The lower the value the higher the precision, but the slower the operation.</param>
    public static Rect ComputeBounds(FrameworkElement element, float tolerance = .5f)
    {
        var sw = Stopwatch.StartNew();
        var transform = element.TransformToVisual(null);
        var bounds = new Rect(0, 0, element.ActualWidth, element.ActualHeight);

        bounds = transform.TransformBounds(bounds);

        var minX = TestX(element, bounds, tolerance);
        var minY = TestY(element, bounds, tolerance);
        var maxX = TestX(element, bounds, -tolerance);
        var maxY = TestY(element, bounds, -tolerance);

        sw.Stop();

        Debug.WriteLine($"{sw.Elapsed.TotalMilliseconds} ms to compute bounds with tolerance = {tolerance}");


        return new Rect(new Point(minX, minY), new Point(maxX, maxY));
    }

    private static double TestX(UIElement element, Rect bounds, float tolerance)
    {
        bounds = tolerance > 0
            ? new Rect(bounds.Left, bounds.Top, tolerance, bounds.Height)
            : new Rect(bounds.Right + tolerance, bounds.Top, -tolerance, bounds.Height);

        while (!VisualTreeHelper.FindElementsInHostCoordinates(bounds, element).Any())
        {
            bounds.X += tolerance;
        }

        return bounds.X;
    }

    private static double TestY(UIElement element, Rect bounds, float tolerance)
    {
        bounds = tolerance > 0
            ? new Rect(bounds.Left, bounds.Top, bounds.Width, tolerance)
            : new Rect(bounds.Left, bounds.Bottom + tolerance, bounds.Width, -tolerance);

        while (!VisualTreeHelper.FindElementsInHostCoordinates(bounds, element).Any())
        {
            bounds.Y += tolerance;
        }

        return bounds.Y;
    }
}
公共静态类BoundsHelper
{
///计算给定对象的轴对齐最小边界框。
///要测试的元素。
///以像素表示的精度公差。值越低,精度越高,但操作越慢。
公共静态Rect计算边界(FrameworkElement元素,浮点公差=.5f)
{
var sw=Stopwatch.StartNew();
var transform=element.TransformToVisual(null);
var bounds=new Rect(0,0,element.ActualWidth,element.ActualHeight);
边界=变换。变换边界(边界);
var minX=TestX(元素、边界、公差);
var minY=TestY(元素、边界、公差);
var maxX=TestX(元素、边界、公差);
var maxY=TestY(元素、边界、公差);
sw.Stop();
Debug.WriteLine($“{sw.appeased.totalmillizes}ms,用于计算公差为{tolerance}的边界);
返回新的Rect(新点(minX,minY),新点(maxX,maxY));
}
私有静态双TestX(UIElement元素、Rect边界、浮点公差)
{
边界=公差>0
?新矩形(边界.左侧,边界.顶部,公差,边界.高度)
:新矩形(bounds.Right+公差,bounds.Top,-公差,bounds.Height);
而(!VisualTreeHelper.FindElementsInHostCoordinates(bounds,element).Any())
{
边界X+=公差;
}
返回边界.X;
}
私有静态双测试(UIElement元素、Rect边界、浮点公差)
{
边界=公差>0
?新矩形(边界、左侧、边界、顶部、边界、宽度、公差)
:新矩形(bounds.Left,bounds.Bottom+公差,bounds.Width,-公差);
而(!VisualTreeHelper.FindElementsInHostCoordinates(bounds,element).Any())
{
边界Y+=公差;
}
返回边界.Y;
}
}