score:6

Accepted answer

OK, so I was able to at least simulate the images hiding around the back of the globe, by calculating the great circle distance between the projection center and the point in question. If the distance was greater than π/2, the point would be beyond the horizon:

        .attr("opacity", function(d) {
            var geoangle = d3.geo.distance(
                    d.geometry.coordinates,
                    [
                        -projection.rotate()[0],
                        projection.rotate()[1]
                    ]);
            if (geoangle > 1.57079632679490)
            {
                return "0";
            } else {
                return "1.0";
            }
        })

I'm sure I can get a bit fancier by fading them out as they approach the edge, disabling clicks, etc. but now I can move on...

score:1

I know this is an old question but would like to add a new solution. You can use projection.stream to filter, parse, and then return the projected x,y in pixels. This method also works on filtering out points that outside of current (zoomed) extent.

Note this will filter (clip) out all points that are invisible under current projection. Add another loop to compare two arrays if you really want to retain all points. But this works very well in my case of using reactive properties.

let newStream = []
let stream = youCurrentProjection.stream({
  point: function (x, y) {
    newStream.push([x, y])
  }
})

arrayOfPoints.forEach(point => {
  stream.point(point.x, point.y)
})

Or build a closure to pass the index

let streamWrapper = function (x, y, index) {
  let stream = youCurrentProjection.stream({
    point: function (x, y) {
      arrayOfPoints[index].isVisible = true
    }
  })
  stream.point(x, y)
}

arrayOfPoints.forEach((point, index) => {
  streamWrapper(point.x, point.y, index)
})

score:8

Calculate if the point is visible

If you have your projection:

const chartProjection = d3.geo.orthographic();

You can turn it into a path function:

const path = d3.geo.path()
  .projection(chartProjection);

Then you can evaluate each point for visibility. path will return undefined for values behind the projection.

function getVisibility(d) {
  const visible = path(
    {type: 'Point', coordinates: [d.longitude, d.latitude]});

  return visible ? 'visible' : 'hidden';
}

// Update all text elements.
svg.selectAll('text')
  .attr('visibility', getVisibility);

Related Query

More Query from same tag