2015-03-17 6 views
0

Я пытаюсь улучшить свой способ выкладки позиции тысяч фигур с равной площадью над поверхностью сетки из центральной точки (у нее более органичный вид). Поверхность сетки означает, что между соседями существует равное расстояние, но я не хочу создавать патч-работу, подобную шаблону, путем выбора случайной координаты x и y (или x и z в этом случае, когда я работаю в трех измерениях). То, что у меня сейчас работает, но невероятно медленное, когда я начинаю двигаться с 2000 объектов. Есть ли более быстрый метод? Я избегаю эффекта патч-работы, как я уже сказал, равно как и кругового распространения. Распределение прямо сейчас очень похоже на город и идеально, но слишком медленно.Распределение фигур из центральной точки

Я прокомментировал функцию на протяжении так что надеюсь, это объясняет все тщательно:

ArrayList buildingCoords; // stores the co-ordinates of occupied spaces 
int w = 50 // Footprint dimensions. Width and depth. 

PVector generateNewBuildingPosition(PVector coord) { 
    float sW = 30; // gap between shapes 
    // Starting at a coordinate of 0,0 if this is our 1st go 
    // (PVector coord initially feeds 0,0) 
    // or the last coordinate that was already taken 
    // (this loops with the last coordinate if it fails) 
    // we check one of the four spaces next to us with 
    // the roll of a dice (in a way...) 
    float randomX = random(0,15); 
    float randomZ = random(0,15); 
    if (randomX >= 10) { 
     randomX = w + sW; 
    } else if (randomX >= 5) { 
     randomX = (w + sW) * -1; 
    } else { 
     randomX = 0; 
    } 
     if (randomZ >= 10) { 
     randomZ = w + sW; 
    } else if (randomX >= 5) { 
     randomZ = (w + sW) * -1; 
    } else { 
     randomZ = 0; 
    } 

    // We've picked our direction. 
    // We have a PVector that acts as a marker for where we're 
    // placing. Adding or subtracting the movement of each 
    // attempt, one at a time, means the shapes spreads out 
    // more organically from the centre rather than trying 
    // to distribute each shape as a random patch. 
    PVector newDirection = new PVector(randomX, 0, randomZ); 
    coord.add(newDirection); 
    // Our marker moves to the new spot, we check if it exists. 
    // If it doesn't, we confirm it as this shape's anchor spot. 
    // If it does, we loop this function again, feeding it where our 
    // marker is. 
    if(buildingCoords.contains(coord)) { 
     generateNewBuildingPosition(coord); 
    } else { 
     // add this PVector to the arrayList 
     buildingCoords.add(coord); 
    } 
    // Return the coordinates that just succeeded. 
    return coord; 
    } 
+0

Что такое var w? –

+0

Извинения, я пропустил, что была одна внешняя переменная. Теперь я включил его в оригинал, но это ширина и глубина отпечатка каждой фигуры. – biscuitstack

+0

Я полагаю, что это замедляется, потому что вы делаете рекурсивный вызов, если 'buildingCoords' содержит вычисленную' coord'. Что вы можете сделать, так это изменить свой алгоритм, поэтому он учитывает только пробелы в его вычислении, поэтому вам никогда не придется проверять, используется ли подсчитанная координата. Ergo: создайте пространство поиска «доступных» мест (это может динамически увеличиваться, чтобы ограничить количество вещей) и выберите один из них, используя некоторую логику, чтобы сделать его «полуслучайным», обновить доступные места и перейти к следующему объекту. – Warkst

ответ

1

Этот код обрабатывает 200,000 в основном мгновенно. Я должен был угадать несколько деталей, но он должен быть близок к тому, что вы ищете.

public class Test { 

    static Map<Integer, Vector3> buildingCoords; 
    public static void main(String[] args) { 
     buildingCoords = new HashMap(); 

     Vector3 start = new Vector3(0,0,0); 

     for (int i = 0; i < 200000; i++) 
      start = generateNewBuildingPosition(start); 

     System.out.print("Done"); 

    } 

    static Vector3 generateNewBuildingPosition(Vector3 coord) { 
     int w = 50; // Footprint dimensions. Width and depth. 
     float sW = 30; // gap between shapes 
     // Starting at a coordinate of 0,0 if this is our 1st go 
     // (PVector coord initially feeds 0,0) 
     // or the last coordinate that was already taken 
     // (this loops with the last coordinate if it fails) 
     // we check one of the four spaces next to us with 
     // the roll of a dice (in a way...) 
     float randomX = (float)random() * 15; 
     float randomZ = (float)random() * 15; 
     if (randomX >= 10) randomX = w + sW; 
     else if (randomX >= 5) randomX = (w + sW) * -1; 
     else randomX = 0; 

     if (randomZ >= 10) randomZ = w + sW; 
     else if (randomX >= 5) randomZ = (w + sW) * -1; 
     else randomZ = 0; 


     // We've picked our direction. 
     // We have a PVector that acts as a marker for where we're 
     // placing. Adding or subtracting the movement of each 
     // attempt, one at a time, means the shapes spreads out 
     // more organically from the centre rather than trying 
     // to distribute each shape as a random patch. 
     Vector3 newDirection = new Vector3(randomX, 0, randomZ); 
     coord.add(newDirection); 
     // Our marker moves to the new spot, we check if it exists. 
     // If it doesn't, we confirm it as this shape's anchor spot. 
     // If it does, we loop this function again, feeding it where our 
     // marker is. 
     if(buildingCoords.containsKey(coord.hashCode())) { 
      generateNewBuildingPosition(coord); 
     } else { 
      // add this PVector to the arrayList 
      buildingCoords.put(coord.hashCode(), coord); 
     } 
     // Return the coordinates that just succeeded. 
     return coord; 
    } 
} 

class Vector3 { 

    float x, y, z; // package-private variables; nice encapsulation if you place this in a maths package of something 

    Vector3(float x, float y, float z) { 
     this.x = x; 
     this.y = y; 
     this.z = z; 
    } 

    public Vector3 add(Vector3 vector) { 
     x += vector.x; 
     y += vector.y; 
     z += vector.z; 
     return this; // method chaining would be very useful 
    } 

    @Override 
    public int hashCode(){ 
     return Float.hashCode(x + y + z); 
    } 

} 

Редактировать: hashCode, как показано на рисунке, не очень звучит и может вызвать проблемы. Вы должны прочитать: Hashing 2D, 3D and nD vectors

+0

Спасибо, Майкл, это выглядит фантастически. Пожалуйста, со мной, я не особенно разбираюсь в этом и должен адаптировать то, что вы написали. Особенно «Карта», которой у меня пока нет. – biscuitstack

+0

Np, если вам нужна помощь, дайте мне знать. Я буду около 30 минут или около того. На стороне примечания я обеспокоен хэш-функцией, которую я предоставил. Как только я поеду, я проведу несколько тестов. –

+0

Я собираюсь предположить, что вы не слишком хорошо знакомы с инфраструктурой java «Обработка» (судя по вашему вопросу о «содержит») раньше? Это делает такие вещи, как «Карта» сложным, поскольку это не часть структуры. В java можно сделать вызовы более низкого уровня, но они немного выше моего понимания. – biscuitstack