Максимальное и минимальное значения в массиве PointF [] - PullRequest
1 голос
/ 01 ноября 2011

У меня есть массив PointF, которые я хочу использовать для рисования кривой с помощью метода Graphics.DrawCurve.

Для этого мне нужно теперь установить max и min как X, так и Y, чтобы я могправильно масштабировать мое растровое изображение.

Как можно найти максимальные и минимальные значения для X & Y в массиве PointF?

Я пришел к этой идее, но не уверен, чтоэто лучший способ!

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

Ответы [ 4 ]

3 голосов
/ 01 ноября 2011

Вам нужно перебрать все элементы в массиве и проверить каждый из них на ограничивающем прямоугольнике, увеличивая ограничивающий прямоугольник, когда текущий элемент находится за его пределами. Как это:

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 Framework API для выполнения теста min / max: Math.Min и Math.Max. Если нет какой-либо другой информации о массиве точек, которую можно использовать для сокращения количества тестов, вам придется тестировать каждую точку в массиве. К сожалению, нет коротких путей. Интересно, достаточно ли умен JIT-компилятор, чтобы использовать SIMD для этого?

Кроме того, инициализация со значением 0 может вызвать ошибку, если все точки в массиве меньше нуля.

1 голос
/ 01 ноября 2011

Если вы найдете минимум (верхняя левая точка) и максимум (нижняя правая точка), вы можете рассчитать размер графика.

Сначала вам нужен способ сравнения значений точек - если класс 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;
0 голосов
/ 22 июля 2014

Используя 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;
}

Очевидно, заменить массив int на массив PointF. По сути, здесь происходит то, что SIMD может обрабатывать значения Min и Max 4-8 элементов за цикл. Это теоретически обеспечит ускорение в 4-8 раз в зависимости от вашего процессора. Использование процессоров, поддерживающих AVX2, обеспечивает самое быстрое повышение производительности.

Источник: http://blogs.microsoft.co.il/sasha/2014/04/22/c-vectorization-microsoft-bcl-simd/

0 голосов
/ 01 ноября 2011

Ваш код не очень хороший.Если у вас есть точки (2, 4) и (3, 1), то xMax будет равен 3, а yMax - 4, что не является одной точкой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...