Geomerative - fitting text inside arbitrary shapes?

I’m trying to fit text into shapes, so as to get an effect like so:

I’m using the Geomerative library, but the RShape.contains(RShape) doesn’t seem to be working for me. It always seems to return false, no matter what. Heres a sketch that accurately describes the problem - the small rectangle should turn red when inside the larger one, but it never does, despite intersecting with it, and then not intersecting with it after it goes inside.

import geomerative.*;

RShape shape;
RShape rect;

void setup(){
  size(600, 600, OPENGL);
  smooth();

  RG.init(this);
  RG.setPolygonizer(RG.ADAPTATIVE);

  RG.ignoreStyles();
  
  shape = RG.getRect(100,100,100,50);
}

void draw(){
  rect = RShape.createRectangle(mouseX, mouseY, 10, 10);
  shape.draw(this);
  if (shape.contains(rect))
    rect.setFill(color(255, 0, 0));
  rect.draw(this);
  RPoint[] ps = shape.getIntersections(rect);
  if (ps != null) {
    for (int i=0; i<ps.length; i++) {
      ellipse(ps[i].x, ps[i].y, 10, 10);
    }
  }
}
1 Like

The geomerative tutorial example on contains finds whether a RPoint is contained within an RShape, and works OK for me, may’be you could get that to work for you?

1 Like

OK I explored a bit more would something like this be acceptable?

import geomerative.*;

RShape shape;
RShape rect;

void setup(){
  size(600, 600, P2D);
  RG.init(this);
  RG.setPolygonizer(RG.ADAPTATIVE);
  shape = RG.getRect(100,100,100,50);
}

void draw(){
  fill(255);
  rect = RShape.createRectangle(mouseX, mouseY, 10, 10);
  shape.draw(this);
  if (shape.contains(rect.getCentroid())){
    fill(255, 0, 0);
  }
  else{
    fill(255);
  }
  rect.draw(this);
}

OR

import geomerative.*;

RShape bounds;
RShape my_rect;

void setup() {
  size(600, 600);
  RG.init(this);
  RG.setPolygonizer(RG.ADAPTATIVE);
  bounds = RG.getRect(105, 105, 95, 45);
}

void draw() {
  fill(255);
  my_rect = RShape.createRectangle(mouseX, mouseY, 10, 10);
  rect(100, 100, 100, 50);
  if (inBounds(my_rect)){
    fill(255, 0, 0);
  } else {
    fill(255);
  }
  my_rect.draw(this);
}

boolean inBounds(RShape shp) {
  RPoint[] pts = shp.getPoints();
  for (int i = 0; i < pts.length; i++) {
    if (!bounds.contains(pts[i]))
    { 
      return false;
    }
  }
  return true;
}

For something a bit more sophisticated.

2 Likes

Hey, that looks really good, thank you!! I tried the RShape.contains(RPoint[]) and it didn’t work. I didn’t think to just check each of them manually in my own function. Dumb of me, in retrospect. XD

Hmm. This is only vaguely related, but how would you suggest I put a buffer zone between the shapes? Should I just make a bounding box with the increased space and text against that? Or is there a better way?

Is how it looks now, and you can see the problem in question in the upper left.

Actually, now that I think about it, maybe I should just make a smaller version of the bounding shape to check against.

Also, here’s the code if anyone’s curious. XD

1 Like

I’m quite fond of the geomerative library which is why I answered your original question. It seems that there a few glitches unfinished things as you found with not working contains(RPoint[] pts). I have come up with neater workaround for your original boundary test see this gist.

2 Likes

Here’s BoundaryTest.java converted to “BoundaryTest.pde”: :smile_cat:

import geomerative.*;

Boundary bounds;
RShape my_rect;

void setup() {
  size(600, 600, P2D);
  RG.init(this);
  RG.setPolygonizer(RG.ADAPTATIVE);
  bounds = Boundary.createBoundingRectangle(100, 100, 100, 50);
}

void draw() {
  fill(255);
  my_rect = RShape.createRectangle(mouseX, mouseY, 10, 10);
  bounds.draw();
  drawMyRect(bounds.inside(my_rect));
}

void drawMyRect(boolean inside) {
  if (inside) {
    noStroke();
    fill(255, 0, 0);
  } else {
    stroke(0);
    fill(255);
  }
  my_rect.draw(this);
}
1 Like

That actually seems less sophisticated though. It only checks against the bounding rectangle, which means that if you’re dealing with fitting things inside a hexagon, for example, you will occasionally have cases where symbols get invalidated by their corners when they shouldn’t be. Fitting an o against a sloped wall, for example. It’s probably more efficient, but as I only need to run this code when generating graphics, I’m not super concerned about that.

Yeah but there’s no reason why you couldn’t implement createShape(RShape shp) in a custom Boundary.

Here is how I did it with test!

Again, it loses precision. I decided to just scale the characters appropriately to account for the border and leave it at that. You can see my code here: https://gitlab.com/AngularAngel/Crovasshun/blob/master/src/processingdisplay/ASCIIShape.java

And a screenshot:

2 Likes