I've been working on an application where I am building a 3d terrain, using three.js. The part I have working so far is building the 3d terrain mesh from standard 30m elevation data, and then draping NAIP imagery on top. The elevation and imagery are projected to UTM Zone 13 N. This part works beautifully. Where I am stuck is with adding vector data, specifically lines. I can't for the life of me project the line coordinates into the scene space properly.

I am using d3 to help with projecting the line coordinates (also in utm zone 13 N coordinate space) to the three.js coordinates. I have searched the internet far & wide, and this post is the closest I have found to the answer. This is how the author creates a d3 projection:

var projection = d3.geo.transverseMercator()
    .translate([terrainSize / 2, terrainSize / 2])
    .scale(terrainSize * 106.4)
    .rotate([-9, 0, 0])
    .center([-0.714, 61.512]);  

Per the linked post, translate, rotate, and center are all self-explanatory, and I make the updates based on UTM Zone 13. Its the scale that I have no idea about. The author himself says "The scale factor corresponds linearly to the distance between projected points. I figured out that this was terrainSize multiplied by 106.4 for my example, but I don't know why exactly 106.4..."

I have played with the scale factor ad nauseam - and just cant get it to work. I am hoping someone can help me understand how to compute the proper scale factor. If there is an easier way to go from UTM to three.js without d3 - I am open to any suggestions.

  • in a nutshell: three.js works on a hierarchical cartesian object coordinate system with the scene coordinates as the global scope; you have a projected, equal spaced raster in cartesian coordinates, which doesn't get any better with reprojecting. three.js (or rather webgl) doesn't care for units or size of the systems. in short: just assign the UTM coordinates to the planebuffergeometry's position array and the line's vertices array and you are set. the real issue will be that your line will not be drawn over the terrain (-> straight lines between vertices). – geozelot Apr 23 '18 at 9:01

Shame on me for not reading the excellent d3 documentation... By using a combination of rotate and fitExtent, I did not need to fuss with scale or translate.

This is what I used:

var projection = d3.geoTransverseMercator()
      .rotate([105 + 30 / 60, -37 - 50 / 60])
      .fitExtent([[0,0], this.terrain['planeSize']], this.geojsonTrailFeature);

I ended up switching to CO State Plane Central for projection. The first element in the array passed into rotate is central meridian, the second argument is latitude of origin.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.