简体   繁体   English

PointF []数组中的最大值和最小值

[英]Maximum and Minimum values in a PointF[] array

I have an array of PointF's that I want to use it for drawing a curve with Graphics.DrawCurve method. 我有一个PointF数组,我想用它来绘制一个使用Graphics.DrawCurve方法的曲线。

For doing this, I need to now max and min of both X and Y so I can scale my bitmap imagebox correctly. 为此,我需要现在X和Y的最大值和最小值,以便我可以正确地缩放我的位图图像框。

How is it possible to find the max and min for X & Y in an array of PointF's ? 如何在PointF数组中找到X和Y的最大值和最小值?

I came up with this idea but I am not sure if this is the best way! 我想出了这个想法,但我不确定这是不是最好的方法!

    //Find the max value on X axis (Time) and Y axis (Current)
    float xMax = 0;
    float yMax = 0;

    foreach (PointF point in points)
    {
        if (point.X > xMax)
        {
            xMax = point.X;
        }

        if (point.Y > yMax)
        {
            yMax = point.Y;
        }
    }

You need to iterate over all the elements in the array and test each one against a bounding box, increasing the bounding box when the current item is outside it. 您需要迭代数组中的所有元素并针对边界框测试每个元素,在当前项目位于其外时增加边界框。 Like this: 像这样:

Point 
  min = first item in array, 
  max = first item in array;

foreach (item in array of points)
{
  min.x = Math.Min (min.x, item.x)
  min.y = Math.Min (min.y, item.y)
  max.x = Math.Max (max.x, item.x)
  max.y = Math.Max (max.y, item.y)
}


(min,max) are now the opposite corners of an axis aligned bounding box

EDIT: You've got the right idea, but there is a .Net framework API to do the min/max test: Math.Min and Math.Max. 编辑:你有正确的想法,但有一个.Net框架API来进行最小/最大测试:Math.Min和Math.Max。 Unless there's some other information about the array of points that can be used to reduce the number of tests, you are going to have to test every point in the array. 除非有关于可用于减少测试数量的点数组的其他信息,否则您将不得不测试数组中的每个点。 No short cuts there unfortunately. 不幸的是,那里没有捷径。 I wonder if the JIT compiler is smart enough to use SIMD for this? 我想知道JIT编译器是否足够聪明,可以使用SIMD吗?

Also, initialising with the value 0 could cause an error if all the points in the array are less than zero. 此外,如果数组中的所有点都小于零,则使用值0初始化可能会导致错误。

If you find the minumum (top left point) and maximum (bottom right point) you can calculate the size of the graph. 如果找到最小值(左上角)和最大值(右下角),则可以计算图形的大小。

First you need a way to compare Point values - if the Point class (struct?) implements IComparable you're already good to go, otherwise you might need to write a custom IComparer class. 首先,您需要一种比较Point值的方法 - 如果Point类(struct?)实现IComparable,您已经很好了,否则您可能需要编写自定义IComparer类。

Next you can write a simple extension method on IEnumerable to get the minimum or maximum values out of a collection: 接下来,您可以在IEnumerable上编写一个简单的扩展方法,以从集合中获取最小值或最大值:

static class ExtensionsClass
{
    /// <summary>
    /// Returns the mimimum value within the collection.
    /// </summary>
    static public T Min(this IEnumerable<T> values) where T : IComparable<T>
    {
        T min = values.First();

        foreach(T item in values)
        {
            if (item.CompareTo(min) < 0)
                min = item;
        }

        return min;
    }

    /// <summary>
    /// Returns the maximum value within the collection.
    /// </summary>
    static public T Max(this IEnumerable<T> values) where T : IComparable<T>
    {
        T max= values.First();

        foreach(T item in values)
        {
            if (item.CompareTo(min) > 0)
                max= item;
        }

        return max;
    }
}

Using these extension methods it would be much easier to find the minimum/maximum points and therefore and size of the graph. 使用这些扩展方法,可以更容易地找到最小/最大点,从而找到图形的大小。

var minX = points.Min().x;
var minY = points.Min().y;
var maxX = points.Max().x;
var maxY = points.Max().y;

Using RyuJIT and SIMD , these operations can be massively accelerated. 使用RyuJIT和SIMD ,可以大大加速这些操作。

  void MinMax(int[] a, out int minimum, out int maximum) {
  int simdLength = Vector<int>.Length;
  Vector<int> vmin = new Vector<int>(int.MaxValue);
  Vector<int> vmax = new Vector<int>(int.MinValue);
  for (int i = 0; i < a.Length; i += simdLength) {
      Vector<int> va = new Vector<int>(a, i);
      Vector<int> vLessThan = Vector.LessThan(va, vmin);
      vmin = Vector.ConditionalSelect(vLessThan, va, vmin);
      Vector<int> vGreaterThan = Vector.GreaterThan(va, vmax);
      vmax = Vector.ConditionalSelect(vGreaterThan, va, vmax);
  }
  int min = int.MaxValue, max = int.MinValue;
  for (int i = 0; i < simdLength; ++i) {
      min = Math.Min(min, vmin[i]);
      max = Math.Max(max, vmax[i]);
  }
  minimum = min;
  maximum = max;
}

Obviously replace the int array with the PointF array. 显然用PointF数组替换int数组。 Essentially what goes on here is that SIMD is able to process the Min and Max values 4-8 items per loop iteration. 基本上,这里发生的是SIMD能够在每次循环迭代中处理最小值和最大值4-8个项目。 This would theoretically provide a 4-8x speedup depending on your CPU. 从理论上讲,这将提供4-8倍的加速,具体取决于您的CPU。 Using CPUs that support AVX2 provides the fastest performance boost. 使用支持AVX2的CPU可以提供最快的性能提升。

Source: http://blogs.microsoft.co.il/sasha/2014/04/22/c-vectorization-microsoft-bcl-simd/ 资料来源: http//blogs.microsoft.co.il/sasha/2014/04/22/c-vectorization-microsoft-bcl-simd/

Your code isn't good. 你的代码不好。 If you have points (2, 4) and (3, 1), then xMax will be 3, and yMax will be 4, which isn't one point. 如果你有点(2,4)和(3,1),那么xMax将是3,而yMax将是4,这不是一个点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM