1

I am working in Processing making contour maps from height maps using the blobDetection library. My end goal is to laser cut the blobs to make sort of architectural landscape maquettes.

enter image description here

Currently I can obtain the contours and export the contour map as SVG which is great, but I want to be able to identify each blob (or contour, or ring) and to then be able to manipulate each contour separately. Namely I want to reposition them on the window so that they are not on top of each other and do not overlap. I also want to assign coordinates to each individual blob so they would be easy to know where each blob goes once it has been laser cut.

Here is the code (from an example provided by author v3ga):

import processing.svg.*;
import blobDetection.*;
import peasy.*;
import processing.pdf.*;

PeasyCam cam;
PImage img;

float levels = 10;
float factor = 10;
float elevation = 125;

float colorStart = 0;
float colorRange = 160;

BlobDetection[] contours = new BlobDetection[int(levels)];

boolean recording = false;
void keyPressed(){
  if (key == 'r' || key == 'R'){
    recording = !recording;
  }
}

void setup() {

  size(1000,800,P3D);
  surface.setResizable(true);

  img = loadImage("map1.gif");
  surface.setSize(img.width, img.height);

  cam = new PeasyCam(this, img.width, img.height, 0, 500);
  colorMode(HSB, 360, 100, 100);

  for (int i=0; i<levels; i++){
    contours[i] = new BlobDetection(img.width, img.height);
    contours[i].setThreshold(i/levels);
    contours[i].computeBlobs(img.pixels);
  }

}

void draw(){

  if (recording){
    beginRecord(SVG, "frame_####.svg");
  }

  for (int i=0; i<levels; i++){
    drawContours(i);
  }

  if (recording) {
    endRecord();
  recording = false;
  }

}

void drawContours(int i) {
  Blob b;
  EdgeVertex eA,eB;
  for (int n=0 ; n<contours[i].getBlobNb() ; n++) {
    b=contours[i].getBlob(n);
    if (b!=null) {
      stroke(250,75,90);
      for (int m=0;m<b.getEdgeNb();m++) {
        eA = b.getEdgeVertexA(m);
        eB = b.getEdgeVertexB(m);
        if (eA !=null && eB !=null)
          line(
          eA.x*img.width, eA.y*img.height, 
          eB.x*img.width, eB.y*img.height 
            ); 
      }
    }
  }
}

After testing a few things I think the best is to create and array of objects that contain information for each blob (x and y coordinates, level) and to fill this array in the drawContours method. However I am having a lot of trouble obtaining the right information to store in this array.

So my questions are:

  • How to identify x,y coordinates of complex shapes such as these blobs
  • How to reposition the blobs once I have their info store in an array

Any suggestion, even using other techniques (i.e. not Processing) would be greatly appreciated.

samzmann
  • 2,286
  • 3
  • 20
  • 47
  • You want to see them stacked in 3D? The blob object has x and y properties you can access, and I would imagine the level would just be equal to the blob's index in the array. – Patrick Murphy Jan 10 '17 at 22:52

1 Answers1

0

To display the blobs in 3D add the height_scale constant at the top and modify the drawContours function to the following:

final int HEIGHT_SCALE = 10; // amount of z space between each blob

void drawContours(int i) {
  Blob b;
  EdgeVertex eA,eB;
  for (int n=0 ; n<contours[i].getBlobNb() ; n++) {
    b=contours[i].getBlob(n);
    if (b!=null) {
      stroke(250,75,90);
      beginShape();
      for (int m=0;m<b.getEdgeNb();m++) {
        eA = b.getEdgeVertexA(m);
        eB = b.getEdgeVertexB(m);
        if (eA !=null && eB !=null)
          vertex(eA.x*img.width, eA.y*img.height, i*HEIGHT_SCALE);
          vertex(eB.x*img.width, eB.y*img.height, i*HEIGHT_SCALE);
      }
      endShape(CLOSE);
    }
  }
}

Keep in mind I have not run this code, and I haven't used the framework that you are using however the beginShape(), vertex(), and endShape() functions should allow you to create the same lines between edges, and I added a z coordinate to the vertex's so that they are separated in height.

Just realized you could also just go with the following because line(x1,y1,x2,y2) can also take line(x1,y1,z1,x2,y2,z2):

final int HEIGHT_SCALE = 10; // amount of z space between each blob

void drawContours(int i) {
  Blob b;
  EdgeVertex eA,eB;
  for (int n=0 ; n<contours[i].getBlobNb() ; n++) {
    b=contours[i].getBlob(n);
    if (b!=null) {
      stroke(250,75,90);
      for (int m=0;m<b.getEdgeNb();m++) {
        eA = b.getEdgeVertexA(m);
        eB = b.getEdgeVertexB(m);
        if (eA !=null && eB !=null)
          line(eA.x*img.width, eA.y*img.height, i*HEIGHT_SCALE, eB.x*img.width, eB.y*img.height, i*HEIGHT_SCALE);
      }
    }
  }
}
Patrick Murphy
  • 2,311
  • 14
  • 17
  • I omitted some parts of the original example because I don't need them for this project, but yes it is possible to render the map in 3D, by translating the contours `translate(0,0,elevation/levels);` in the loop that calls `drawContours()` (using the variables declared at the beginning of the program). – samzmann Jan 11 '17 at 06:08
  • So you just want to know how to create a custom object that holds your blob? and store those in the array? – Patrick Murphy Jan 11 '17 at 17:07
  • Yes. I don't have a problem with creating objects, but I do with getting the right data to give properties to the object. The properties I want to get are x and y coordinates of the blob, most importantly, and then its level, as in its height relative to the total height of the maquette. – samzmann Jan 11 '17 at 21:50