我正在尝试改进从中心点开始在网格表面上具有相同覆盖区的数千个形状的位置的布局方法(它具有更自然的外观)。网格表面意味着邻居之间的间距相等,但是我不想通过选择随机的x和y坐标(或者在这种情况下是x和z,因为我使用的是3维)来创建类似补丁的图案)。我现在可以使用,但是当我从2,000个对象开始向上移动时,速度却非常慢。有没有更快的方法?我正在避免像我所说的拼凑效果,以及均匀的圆形扩展。现在的发行非常像城市,而且很完美,但是速度太慢了。

我在整个函数中都评论了此函数,因此希望它能彻底解释所有内容:

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

最佳答案

此代码基本上立即处理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

08-18 11:03