У меня есть тревожная сетка, заполненная фотографиями.Как я могу убедиться, что фотографии не отображаются вместе в C # - PullRequest
8 голосов
/ 10 марта 2011

У меня в основном есть сетка, скажем, 100 х 100, которая заполнена URL-адресами коллекции фотографий.Некоторые из них являются дубликатами, поскольку у меня может быть только 50 фотографий, но я хочу скопировать их, чтобы убедиться, что сетка 100 х 100 заполнена.Я случайным образом заполняю сетку URL-адресами, а затем отображаю их, что нормально.У меня проблема в том, что, очевидно, иногда фотографии с одним и тем же URL-адресом случайным образом размещаются вместе либо по оси x, либо по оси y, либо иногда одновременно.

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

Любая помощь приветствуется

Майк

Ответы [ 4 ]

4 голосов
/ 10 марта 2011

Если вы действительно хотите «как можно дальше друг от друга», то (1) держу пари, что вам не повезло, и (2) если бы это было достижимо, это, вероятно, привело бы к не очень случайным результатам.Но если все, что вы хотите, это «несколько далеко друг от друга», это не так уж плохо.Вот несколько вещей, которые вы можете сделать:

(1) Классифицировать позиции сетки в соответствии с четностью их координат x, y: то есть, являются ли они нечетными и четными.Разделите фотографии на четыре партии примерно одинакового размера.Теперь выберите из разных партий в соответствии с соотношением координат.Следующий код (который немного «умный»; извините) делает это, по модулю ошибок и опечаток.

System.Random rng = new System.Random();
for (int x=0; x<nx; ++x) {
  for (int y=0; y<ny; ++y) {
    k = ((x&1)<<1) + (y&1); // 0..3
    int n_photos_in_batch = (n_photos+3-k) >> 2;
    int photo_number = (rng.Next(0,n_photos_in_batch-1) << 2) + k;
    // use this photo
  }
}

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

Вариации: мы в основном покрываем сетку плитками 2х2 и ограничиваем диапазон фотографий, которые могут появляться в каждой плитке.Вы можете использовать большие плитки, или плитки различной формы, или расположить их по-другому.Например, если вы скажете k = ((x&1)<<1) ^ (y&3), вы получите плитки 2х2, расположенные в виде своего рода шестиугольника, что на самом деле, вероятно, лучше, чем в приведенной выше версии.

(2) Зацикливание позиций в вашей сетке (порядок растра будетсделайте, хотя могут быть и более лучшие альтернативы) и для каждой выберите фотографию, которая (а) уже не появляется слишком близко к позиции, на которую вы смотрите, и (б) в противном случае является случайной.Следующий код (опять же, по модулю ошибок и опечаток) делает что-то подобное, хотя для больших сеток вы можете захотеть сделать его более эффективным.

System.Random rng = new System.Random();
radius = MAX_RADIUS; // preferably not too big, so that the search isn't too slow
while ((2*radius+1)*(2*radius+1) >= n_photos) --radius; // gratuitously inefficient!
for (int x=0; x<nx; ++x) {
  for (int y=0; y<ny; ++y) {
    // which photos already appear too near to here?
    System.Collections.BitArray unseen = new System.Collections.BitArray(n_photos,True);
    for (x1=x-radius; x1<=x+radius; ++x1) {
      for (int y1=y-radius; y1<=y+radius; ++y1) {
        if (0 <= x1 && x1 < nx && 0 <= y1 && y1 < nx && (y1<y || (y1==y && x1<x))) {
          unseen[photos[x1,y1]] = False;
        }
      }
    }
    // now choose a random one of them
    int n_unseen = 0;
    for (int i=0; i<n_photos; ++i) if (unseen[i]) ++n_unseen;
    System.Debug.Assert(n_unseen>0, "no photos available");
    int j = rng.Next(0,n_unseen-1);
    for (int i=0; i<n_photos; ++i) {
      if (unseen[i]) {
        if (j==0) { photos[x,y] = i; break; }
        --j;
      }
    }
  }
}

Примечания: это намного дороже, чем вариант 1.проверка достоверности на x1, y1, конечно, здесь совершенно неэффективна.Так же и выбор радиуса.Однако очевидные, более эффективные их версии могут сломаться, если вы примете некоторые из вариантов, которые я собираюсь перечислить.Этот код, в его нынешнем виде, не будет ничего делать для разделения фотографий, если их меньше 9. Выбор радиуса на самом деле полностью поддельный, для порядка обхода сетки, который я использовал, потому что никогда не бывает больше 2r.^ 2 + 2r «исключенных» позиций;опять же, это может измениться, если вы пересекаете сетку в другом порядке.И т. Д.

Вариации: нет реальной причины, по которой регион, по которому вы ведете поиск, должен быть квадратным.Циркуляр вполне может быть лучше, например.Вы можете, проделав дополнительную работу, построить регион, в котором всегда будет ровно столько точек, сколько у вас фотографий (хотя, если вы это сделаете, вы получите в основном периодический шаблон фотографий, так что лучше быть немного менее агрессивным).Возможно, было бы лучше обрабатывать элементы сетки в другом положении - например, по спирали от центра.

(3) Вариант 2 выше сохранит фотографии уникальными в определенном диапазоне (примерно настолько большом, насколько это возможно).учитывая, сколько у вас есть разных фотографий), но вам не нужно хранить копии подальше от этого.Вместо этого вы могли бы решить, насколько плохо иметь две одинаковые фотографии на любом заданном расстоянии, а затем выбрать фотографии, чтобы минимизировать общее количество ошибок.Это будет даже дороже, чем вариант 2. Я не буду давать пример кода;Вы, вероятно, можете понять, как это сделать.

[ИЗМЕНЕНО, чтобы добавить ...]

(4) Вот милая вариация на тему (1).Он будет работать лучше всего, когда сетка квадратная, а ее размер равен степени 2, но вы можете адаптировать ее для более общей работы.Это занимает время, пропорциональное размеру вашей сетки, сколько бы фотографий у вас ни было.Для каждой позиции (x, y): выбросить все, кроме нижних k битов координат, для некоторого k.Обращайте их по битам и чередуйте биты, задавая число m от 0 до 2 ^ (2k) -1.Выберите k так, чтобы это было где-то порядка, скажем, n_photos / 4.Теперь в позиции (x, y) вы поместите номер фотографии вокруг (n_photos * m / 2 ^ (2k) + smallish_random_number).Я оставлю вам несколько деталей для заполнения: -).

0 голосов
/ 11 марта 2011

Самый быстрый способ что-то вроде этого:

  1. У вас есть массив из n imgs URL & grid x * y
  2. Найдите центральную ячейку сетки.
  3. Случайным образом извлекает URL-адрес imgs из массива и помещает каждый URL вокруг центральной ячейки (первый URL-адрес помещается в центр)
  4. Делайте это, пока не заполните все ячейки сетки или пока у вас нет URL-адресов в массиве.
  5. Если используется каждый URL, то вы должны брать URL из концентрических окружностей, которые вы сделали. Сверните из центральной ячейки в круг с наибольшим радиусом.
  6. URL-адреса, полученные этим методом, вы должны произвольно поместить вокруг самого большого круга.

Этот алгоритм будет работать, если у вас достаточно URL для рисования менее 2 дисков в сетке.

Вы можете успешно изменить его, если будете следовать правилу, согласно которому URL из одного набора должны заполнять как можно больший круг.

0 голосов
/ 10 марта 2011

То, что вы хотите, это кривая заполнения пространства, например кривая Гильберта. Он заполняет вашу сетку непрерывной линией, разделяющей каждый квадрат только на 1 бит. Поскольку природа sfc заключается в рекурсивном заполнении пространства и поддержании окрестности, вы можете использовать это и разместить картинку вдоль линии. Если вы не хотите размещать одно и то же изображение в непосредственном соседстве, вы можете использовать глубинный поиск в sfc на каждом узле, исключая копии.

0 голосов
/ 10 марта 2011

Предупреждение, мозговой штурм:

Я бы собрал коллекцию доступных URL-адресов и случайно выбрал бы ее. Как только я использую URL, я бы либо удалил его из коллекции, либо пометил его как использованный. Я остановлюсь, когда исчерпаю коллекцию или нажму 100.

Если бы я исчерпал коллекцию до достижения 100, я бы отметил последние использованные URL-адреса X и снова начал цикл, убедившись, что следующий выбранный URL-адрес не был одним из последних использованных X.

Извините за отсутствие кода, надеюсь, это полезно.

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