/*-------------------------------------------------*/
/* Random Walk Generator                           */
/* Made with Processing                            */
/* Andreas Pirchner, 2019                          */
/*-------------------------------------------------*/


import processing.pdf.*;

PointCloud cloudy;
PVector cloudOrigin;
float spacing;
int pathLength = 500;

ArrayList<PVector> neighbours;
ArrayList<PVector> randomWalk;

void setup(){
   size(1000,1000,P2D);
   background(255);
   cloudOrigin = new PVector(0,0,0);
   spacing = width / 100;
   cloudy = new PointCloud(80,80, cloudOrigin, spacing);
   randomWalk = new ArrayList<PVector>();
   randomWalk = cloudy.makeRandomWalk(300);
   //neighbours = new ArrayList<PVector>();
   //neighbours = cloudy.getAdjacentPoints(21); 
   fill(0);
   ellipseMode(RADIUS);
   stroke(0, 50);
   
   for(int i = 0; i < randomWalk.size()-1; i++){
    strokeWeight(1);
    line(randomWalk.get(i).x, randomWalk.get(i).y, randomWalk.get(i+1).x, randomWalk.get(i+1).y);
  }
   stroke(0);
   strokeWeight(1);
   cloudy.drawCloud();
}


void draw(){

}

void mousePressed(){
    background(255); 
    pathLength += 0;
    cloudy = new PointCloud(80,80, cloudOrigin, spacing);
   randomWalk = new ArrayList<PVector>();
   randomWalk = cloudy.makeRandomWalk(pathLength);
   //neighbours = new ArrayList<PVector>();
   //neighbours = cloudy.getAdjacentPoints(21); 
   beginRecord(PDF, "filename-"+random(10000)+".pdf"); 
   fill(0);
   ellipseMode(RADIUS);
   stroke(0);
   
   for(int i = 0; i < randomWalk.size()-1; i++){
    strokeWeight(1);
    line(randomWalk.get(i).x, randomWalk.get(i).y, randomWalk.get(i+1).x, randomWalk.get(i+1).y);
    }
   stroke(0);
   strokeWeight(1);
   //cloudy.drawCloud();
   endRecord();
  
}
				
			
				
					/*-------------------------------------------------*/
/* Class PointCloud Random Walk                    */
/* Made with Processing                            */
/* Andreas Pirchner, 2019                          */
/*-------------------------------------------------*/


class PointCloud{
  ArrayList<PVector> cloudPoints;
  int totalPoints;
  PVector cloudOrigin;
  int xResolution, yResolution;
  
  PointCloud(int xDepth, int yDepth, PVector origin, float spacing){
    cloudPoints = new ArrayList<PVector>();
    xResolution = xDepth;
    yResolution = yDepth;
    totalPoints = xResolution * yResolution; 
    cloudOrigin = origin; 
    int counter = 0;
    //for(float iZ = 0; iZ < zDepth; iZ++){
      for(float iY = 0; iY < yResolution; iY++){
        for(float iX = 0; iX < xResolution; iX++){
          cloudPoints.add(new PVector((iX*spacing)+cloudOrigin.x, (iY*spacing)+cloudOrigin.y));
          counter ++;
        }
      }
    //}
    drawCloud();
  }
  
  void drawCloud(){
    for(int i = 0; i < cloudPoints.size(); i++){
     PVector pt = cloudPoints.get(i);
     point(pt.x, pt.y);
    }
  }
  
  ArrayList<PVector> makeRandomWalk(int walkLength) {
    ArrayList<PVector> randomWalkVectors;
    randomWalkVectors = new ArrayList<PVector>();
    int[] walkPointNumbers = makeRandomWalkNumbers(walkLength);
    for(int i = 0; i < walkPointNumbers.length; i++){
      randomWalkVectors.add(cloudPoints.get(walkPointNumbers[i]));
    }
    return randomWalkVectors;
  }
  
  
  int[] makeRandomWalkNumbers(int walkLength){
   ArrayList<PVector> randomWalk;
   randomWalk = new ArrayList<PVector>();
   int[] randomWalkNumbers; 
   randomWalkNumbers = new int[walkLength];
   int startPoint = int(random(totalPoints));
   PVector startVector = cloudPoints.get(startPoint);
   
   for(int i = 0; i < walkLength; i++){
      //ArrayList<int> nextCandidates;
      //nextCandidates = new ArrayList<int>();
      IntList nextCandidates = getAdjacentPointNumbers(startPoint);
      int next = nextCandidates.get(int(random(nextCandidates.size())));
      randomWalkNumbers[i] = next;
      startPoint = next;
   }
   return randomWalkNumbers;
  }
  
  PVector getRandomPoint(){
    PVector randomPoint = cloudPoints.get(int(random(totalPoints)));
    return randomPoint;
  }
  
IntList getAdjacentPointNumbers(int pointNumber){
    IntList adjacentList;
    adjacentList = new IntList();
    int xPos = pointNumber % xResolution;
    //int yPos = ceil(pointNumber / xResolution); 
    if (pointNumber>xResolution){
      adjacentList.append(pointNumber-xResolution);
    }
    if (pointNumber< totalPoints-xResolution){
      adjacentList.append(pointNumber+xResolution);
    }
    if (xPos < xResolution-1){
      adjacentList.append(pointNumber+1);
    }
    if (xPos > 0){
      adjacentList.append(pointNumber-1);
    }
    /*adjacentList[0] = pointNumber-xResolution;
    adjacentList[1] = pointNumber+xResolution;
    adjacentList[2] = pointNumber-1;
    adjacentList[3] = pointNumber+1;*/
    println(adjacentList);
    return adjacentList;
  }
  /*
  ArrayList<PVector> getAdjacentPoints(int pointNumber){
    ArrayList<PVector> adjacentList;
    adjacentList = new ArrayList<PVector>();
    int xPos = pointNumber % xResolution;
    int yPos = ceil(pointNumber / xResolution); 
    adjacentList.add(cloudPoints.get(pointNumber));
    adjacentList.add(cloudPoints.get(pointNumber-xResolution));
    adjacentList.add(cloudPoints.get(pointNumber+xResolution));
    adjacentList.add(cloudPoints.get(pointNumber-1));
    adjacentList.add(cloudPoints.get(pointNumber+1));
    return adjacentList;
  }*/
  
}