簡體   English   中英

PointF []數組中的最大值和最小值

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

我有一個PointF數組,我想用它來繪制一個使用Graphics.DrawCurve方法的曲線。

為此,我需要現在X和Y的最大值和最小值,以便我可以正確地縮放我的位圖圖像框。

如何在PointF數組中找到X和Y的最大值和最小值?

我想出了這個想法,但我不確定這是不是最好的方法!

    //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;
        }
    }

您需要迭代數組中的所有元素並針對邊界框測試每個元素,在當前項目位於其外時增加邊界框。 像這樣:

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

編輯:你有正確的想法,但有一個.Net框架API來進行最小/最大測試:Math.Min和Math.Max。 除非有關於可用於減少測試數量的點數組的其他信息,否則您將不得不測試數組中的每個點。 不幸的是,那里沒有捷徑。 我想知道JIT編譯器是否足夠聰明,可以使用SIMD嗎?

此外,如果數組中的所有點都小於零,則使用值0初始化可能會導致錯誤。

如果找到最小值(左上角)和最大值(右下角),則可以計算圖形的大小。

首先,您需要一種比較Point值的方法 - 如果Point類(struct?)實現IComparable,您已經很好了,否則您可能需要編寫自定義IComparer類。

接下來,您可以在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;
    }
}

使用這些擴展方法,可以更容易地找到最小/最大點,從而找到圖形的大小。

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

使用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;
}

顯然用PointF數組替換int數組。 基本上,這里發生的是SIMD能夠在每次循環迭代中處理最小值和最大值4-8個項目。 從理論上講,這將提供4-8倍的加速,具體取決於您的CPU。 使用支持AVX2的CPU可以提供最快的性能提升。

資料來源: http//blogs.microsoft.co.il/sasha/2014/04/22/c-vectorization-microsoft-bcl-simd/

你的代碼不好。 如果你有點(2,4)和(3,1),那么xMax將是3,而yMax將是4,這不是一個點。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM