Adding random rotation to a program which clusters/organises randomly distributed objects
in
Programming Questions
•
11 months ago
Hi,
I am currently trying to get to grips with processing as part of my dissertation for my Masters Degree.
I am hoping to write a piece of code which will be able to randomly distribute houses (represented by rectangles) within a given area, with a minimum distance between each house (i.e no overlapping), and possibly arranged around a road structure (probably just represented by some lines- but this part is only if i have time/is even possible). Then use genetic algorithm to test the fitness function (based around the number of houses achieved) to reach the optimal solution in terms of density.
I have been looking at a number of examples for the initial part of my study (most of which involve circles):
// i was interested in the way that the answer to this problem tests for overlapping
// i have mainly been looking at this one - though i think a few of the details (the square spiral, the mouse/keyboard inputs etc) are unnecessary for what i am trying to achieve. I just cant figure out what to take out!
// this one seems closest to what i am looking for but i don't understand it at all
Where I am currently at:
// This is very basic, but it reflects my competency levels! It simply randomly generates rectangles within a specified area. I would like to add:
1. A random rotation factor for the rectangles
2. The ability to calculate and avoid collisions (though i think this requires the rectangles to be objects??)
3. The ability to calculate collisions with the boundary line (as currently i am just specifying a field within which to place the rectangles)
- void setup(){
- size(1000,1000);
- }
- int amount = 40;
- float w = 500;
- float h = 250;
- float lhs = ((w/2)-width);
- float rhs = lhs + w;
- float t = (h/2)+h;
- float b = t + h;
- void draw(){
- background(0);
- stroke(255);
- noFill();
- rect(((width-w)/2),((height-h)/2),w,h);
- fill(30,60);
- for (int i=0; i < amount; i++){
- float x = random(lhs, rhs-20);
- float y = random(t, b-40);
- rect(x,y,20,40);
- }
- noLoop();
- }
// This example is basically just a very simple tweak of the 2nd link above, i am struggling with it
- int numHouses = 20;
- int spacing = 1;
- int minSep = 0;
- int maxSep = 0;
- Object[] objects = new Object[1];
- void setup(){
- size(1000,1000);
- objects[0] = new Object(0);
- for(int i= 1; i <numHouses; i++){
- Object objectInstance = new Object(i);
- objects = (Object[]) append(objects, objectInstance);
- }
- }
- void draw()
- {
- background(255);
- pushMatrix();
- translate(width/2, height/2);
- for(int i=0; i <objects.length; i++){
- objects[i].display();
- }
- popMatrix();
- }
- class Object {
- int id;
- float x;
- float y;
- int w;
- int h;
- int spiralPhase = 1;
- float spiralMaxDistance = 1;
- Object(int _id){
- id = _id;
- x = int(random(-width/2, width/2));
- y = int(random(-height/2, height/2));
- w = 20;
- h = 40;
- }
- void display() {
- pushMatrix();
- translate(x, y);
- fill(150, 50);
- rect(0, 0, w,h);
- fill(0);
- text(id, 5, 25);
- popMatrix();
- }
- void resetObject() {
- x = 0;
- y = 0;
- spiralPhase = 1;
- spiralMaxDistance = 1;
- }
- void moveInSpiral() {
- switch(spiralPhase) {
- case 1:
- x++; //Move right
- if(x >= spiralMaxDistance) {
- spiralPhase = 2; //Switch to next phase
- }
- break;
- case 2:
- y++; //Move down
- if(y >= spiralMaxDistance) {
- spiralPhase = 3; //Switch to next phase
- }
- break;
- case 3:
- x--; //Move left
- if(abs(x) >= spiralMaxDistance) {
- spiralPhase = 4; //Switch to next phase
- }
- break;
- case 4:
- y--; //Move up
- if(abs(y) >= spiralMaxDistance) {
- spiralPhase = 1; //Switch to next phase
- spiralMaxDistance++;
- }
- break;
- }
- }
- void newRandomPositionAndSize() {
- x = int(random(-width/2, width/2));
- y = int(random(-height/2, height/2));
- }
- }
- //
- // Checks for collisions between any two objects
- //
- boolean isCollision(Object object1, Object object2) {
- float minDistance = object1.w + object2.w + spacing;
- float actualDistance = dist(object1.x, object1.y, object2.x, object2.y);
- boolean isCollision;
- if (actualDistance < minDistance) {
- isCollision = true;
- }
- else {
- isCollision = false;
- }
- return isCollision;
- }
- void clusterObjects() {
- //First reset all positions to 0,0
- for(int i = 0; i < objects.length; i++) {
- objects[i].resetObject();
- }
- //Then resolve collisions --- test current object (i) against all prior objects (j)
- //i starts at 1, though, in order to skip over the first object, which will just remain at 0,0
- for(int i = 1; i < objects.length; i++) {
- boolean collisionsOccurring = true;
- int collisionTally = 0;
- while(collisionsOccurring) {
- for(int j = 0; j < i; j++) { //Test i vs. all prior j's
- if(isCollision(objects[i], objects[j])) {
- collisionTally++; //If there is a collision, then increment the tally.
- }
- }
- if(collisionTally > 0) { //If any collisions happened,
- objects[i].moveInSpiral(); //then move object i to a new position
- collisionTally = 0; //and start the loop over again.
- }
- else { //But if no collsions happened,
- collisionsOccurring = false; //then this loop is done, and we can move on to the next object i.
- }
- }
- }
- }
- void mousePressed() {
- clusterObjects();
- }
- void keyPressed() {
- if (key == 'r') { //Randomize positions and sizes
- for (int i = 0; i < objects.length; i++) {
- objects[i].newRandomPositionAndSize();
- }
- }
- else if (key == ']') { //Increase spacing
- spacing++;
- clusterObjects();
- }
- else if (key == '[') { //Decrease spacing
- spacing--;
- clusterObjects();
- }
- else if (key == '+' || key == '=') { //Create a new object
- numHouses++;
- Object objectInstance = new Object(objects.length);
- objects = (Object[]) append(objects, objectInstance);
- }
- else if (key == '-' || key == '_') { //Remove the newest object
- if(numHouses > 0) {
- numHouses--;
- objects = (Object[]) shorten(objects);
- }
- }
- }
Many thanks,
Adam
1