1

I'm working on a modification to vis.js's Graph3d to do a filled line graph, like this:

filled line graph

The hard part - unsurprisingly - is working out the rendering order for the polygons. I think I can do this by checking whether a ray from the viewer to a given line B crosses line A:

enter image description here

In this example, since line A is "in the way" of line B, we should draw line A first. I'll use a snippet of code from How do you detect where two line segments intersect? to check whether the lines cross.

However, I haven't figured how to find the position of the user's view. I kind of assumed this would be the camera object, so wrote a little bit of debug code to draw the camera on the graph:

var camera = this._convert3Dto2D(this.camera.getCameraLocation());
ctx.strokeStyle = Math.random()>0.5 ? 'ff0000' : '00ff00';
ctx.beginPath();
ctx.moveTo(camera.x, camera.y);
ctx.lineTo(camera.x, camera.y+5);
ctx.stroke();

In fact, the camera co-ordinates as measured by this are always at 0,0,0 on the graph (which would be the far top right on the above screengrab). What I need, I think, is effectively the bottom of the screen.

How can I find this? Or is there a better way to achieve what I'm trying to do?

Community
  • 1
  • 1
Richard Fairhurst
  • 816
  • 1
  • 7
  • 15

1 Answers1

1

I don't know if this is still an active issue, but FWIW, Graph3D has internal handling of the sort ordering.

All graph points are sorted with respect to the viewpoint, using a representative coordinate called point.bottom. The rendering is then done using this ordering, with the most distant elements drawn first. This works fine as long as none of the elements intersect; in that case, you can expect artefacts.

Basically, all you need to do, is define point.bottom per graph polygon, and Graph3D will then pick it up from there.

If you are still interested in working on this:

This happens in Graph3d.js, method Graph3d.prototype._calcTranslations(). For an example, have a look at how the Grid and Surface graph elements are initialized in Graph3d.prototype._getDataPoints(). The relevant code is:

obj = {};
obj.point = point3d;
obj.trans = undefined;
obj.screen = undefined;
obj.bottom = new Point3d(x, y, this.zRange.min);
Wim Rijnders
  • 116
  • 15
  • Thanks! I ended up using three.js for the graph rather than vis.js because of this issue, but hopefully it'll be useful to someone else. (If you're interested, you can see the finished graph at http://cycle.travel/map; plan a route, click the elevation icon, then click '3D'.) – Richard Fairhurst Mar 25 '17 at 11:28
  • Not a problem! I'm happy that you found something that works for you. I think this graph type is a cool idea; it's on my TODO as of now. – Wim Rijnders Mar 25 '17 at 15:43