ofEvent with a million gazillion objects

#1

Hey guys,

I’ve been using OpenFrameworks for about a month now. Really amazing how simple it makes things specially 3D graphics.

Right now I’m working on sort of a graph class which draws curves with a lot of data points with ofPolyline as its main tool.

This graph will have an array storing the points in it with its size expected to be anywhere between 150,000 to 500,000.

Each data point is an instance of a point class which contains an ofEvent. I add each point as a listener to the OF mouse events so that when it is clicked, dragged, etc. I can record its new coordinates and then use ofNotifyEvent to let the graph know. The graph then updates the ofPolyline coordinates as well.

I wanted to run this by you guys and see what you thought of the implementation. Is the OF event system designed to handle so many objects or am I going about this the wrong way? Instead of having so many points listening to the mouse events and each doing some calculations I could have the graph listen to mouse events and then decide which point is to be changed.

Thanks a bunch!

#2

My gut feeling is that anything than involves a search in a 500k elements array is going to be slow unless you organize the data in some special way. I would think about getting the mousedown coordinates in a single event and then searching the points data with a specialized algorithm (may be a tree-like object based on position on screen zones or some kind of hash).

But then may be your proposed implementation is fast enough on a modern machine, it should not take long to build a mockup to test this. I am curious to know what happens.

ciao
Davide

#3

Thanks for the reply David. What I noticed was that adding each point as a mouse event listener caused my program to hang. It could be a flaw with my code but it seems its ok for data of around 5,000. It actually seems ok with that number of points.

But I would agree with you on having a single mouse event and doing a search. I actually don’t think I need to do a search because if I know the coordinates of the point clicked / dragged and also know how many points I’m currently displaying, I could find the array index of the point (although this may not be reliable, I will have to test).

I’m going to try this method and see what happens.

#4

Ok guys, so the sane solution seems to be what we discussed. The graph class will contain the following ingredients:

  • std::vector or data
  • ofPolyline displaying the data

Cooking instructions:

As you add information to your std::vector, you also use the lineTo() method of the ofPolyline to push either the exact same data or a scaled version of it as needed. The size of both containers will match exactly. Keep in mind that if you use curveTo() your ofPolyline will have ~ x20 times more points because of the nature of this call.

Once the graph is clicked or the mouse is dragged or whatever mouse event occurs, you take the coordinates of the mouse and scale it accordingly. Key thing to note here is to scale the x coordinate of the mouse to the number of points you have in your ofPolyline / std::vector. This way, you can directly access the exact point you need to modify in both containers.

A note on how to access the ofPolyline points:

std::vector<glm::vec3>& tmp = polyline.getVertices();

tmp[index].x = newX;
tmp[index].y = newY;

So far this is very fast and simple. Works seamlessly with data of size ~150,000. I don’t expect there to be any issues with higher numbers since you aren’t using any events other than the single set of mouse events.

Although I would be curious to know how other implementation work out with ofEvents if any one ever goes that route (please post your recipe); in this case it simply wouldn’t make sense to do that.

Thanks!

1 Like