1

I have an old project which involves using Unfolding Maps and Processing to draw, well...maps haha. The project works fine, but I was checking something out to help a colleague and encountered something I don't quite understand.

My question is as follows: if I call Unfolding Map's draw() method (map.draw()) in Processing's draw() method, everything works fine, everything gets redrawn continuously and I can properly interact with the app and whatnot. However, if I do map.draw() in Processing's setup() method and then avoid Processing's draw() method from ever running, shouldn't the map get drawn once and then everything get shut down?

Instead, when I run map.draw() in setup() and then force everything to stop, it doesn't draw anything, not even once.

Also, I've tried running Processing's draw() method just once and calling map.draw() just once in Processing's draw() method, by using noLoop() at the end of setup(). My project is really long, so I'll just post a bit of code only meant to test this small question of mine.

private static final boolean offline = false;
public static String mbTilesString = "/Users/roy/IdeaProjects/UnfoldingMaps/data/blankLight-1-3.mbtiles"
private UnfoldingMap map;

public void setup() {
    size(900, 700, OPENGL);

    if (offline) {
        this.map = new UnfoldingMap(this, 200, 50, 650, 600, new MBTilesMapProvider(mbTilesString));
    } else {
        this.map = new UnfoldingMap(this, 200, 50, 650, 600, new Microsoft.RoadProvider());
    }

    MapUtils.createDefaultEventDispatcher(this, this.map);

    noLoop(); // draw() gets called only once
}

public void draw() {
    this.map.draw();
}

I expect the map to be drawn once and then everything to stop. Instead I get the following:

blank window

Kevin Workman
  • 41,537
  • 9
  • 68
  • 107
Roy
  • 27
  • 1
  • 6

1 Answers1

2

Everything you've said makes sense, and your expectations are valid. You can confirm the behavior by drawing a rectangle instead of a map.

My best guess is that Unfolding Maps is not compatible with the noLoop() function. I would assume that Unfolding Maps has some internal logic that relies on the draw loop: loading map tiles asynchronously, responding to user input, etc.

You can explore the behavior by doing something like this in your setup() function:

noLoop();

for(int i = 0; i < 100; i++){
  draw();
}

This is a hack meant to explore the behavior. I'm not recommending this is a fix. If I do this, I see that the map gets partially loaded:

partially loaded map

This tells me that Unfolding Maps somehow relies on draw() being called multiple times to handle the loading. This makes sense, as the loading is asynchronous and happens in the background over time. It probably has something to do with needing to draw on Processing's main thread after the images are loaded. If you want to be sure, you could look at the source of Unfolding Maps to understand its internal behaviors.

If you really really need to use noLoop() with Unfolding Maps, you might use a hack with the delay() function. Or you could look at the documentation for Unfolding Maps; maybe there's a useful function that we've missed. Or you could modify the source to get the behavior your want. Or maybe you could put something together using a PGraphics or something.

But mostly, I think you should avoid using noLoop() with Unfolding Maps.

Kevin Workman
  • 41,537
  • 9
  • 68
  • 107
  • Oh wow, how silly of me not to consider that. This was really helpful :) – Roy Jan 11 '19 at 19:01
  • Nope, I don't need to use noLoop(), I just added that to test my assumptions as to how it worked in the background, since I wasn't sure why the map didn't get drawn at least once. My mistake in testing this was that for some reason I was convinced from the beginning that the reason lied in the logic of Processing, and I didn't once consider that it might be Unfolding Maps that acted out. I'm just intrigued so I'll check Unfolding Map's code later to understand better how it functions as it draws along. Thanks very much !! – Roy Jan 11 '19 at 19:22