0

I'm trying to plot some cordinates on an image using d3 v4 following this Link.When i'm trying to pass my co-ordinates to the projection function it returns NAN for some of the data points. I got some help from here that javascript follows the following latitude and longitude convention but not sure how it exacty works.

This is the format of my data:

{coordinates: [60, 84],coordinates: [204, 92.4],coordinates: [117, 132.72]}

D3 code :

var el = d3.select('.js-map'),
  // 150 DPI image
  width = 300,
  // 150 DPI image
  height = 300;
  var thisObj = this;
var projection = d3.geoMercator()
  .scale(1)
  .translate([0, 0])
console.log('projection', projection);
var path = d3.geoPath()
  .projection(projection);

var map = el.append('svg')
  .attr('width', width)
  .attr('height', height);

map.append('image')
  .attr('xlink:href', this.floorMaps[0])
  .attr('width', width)
  .attr('height', height);

this.floorSensorInfo.forEach((data, index) => {
  var lonlat = projection(data.coordinates);

  console.log('Longitude Latitude', lonlat);

I can see my data output like [2.0420352248333655, NaN]and not sure what happened exactly.

and moreover if someone can explain following the first link which i realy don't understand it would be really helpful

Exported bounds of raster image
rasterBounds = [[-122.7895, 45.4394], [-122.5015, 45.6039]]

Update:

@Andrew suggested to plot normal co-ordinates because latitude and longitude apply only to world maps. So i had pasted my below working code version now which is plotting the points on the image now.

  var svg = d3.select("body")
    .append("svg")
    .attr("width",960) 
    .attr("height",500) 

  // image width and height in pixels, we don't want to skew this or scale this (then image units aren't straight pixels)
  var imageWidth = 300;
  var imageHeight = 168;
     var color_hash = {  0 : ["apple", "green"],
              1 : ["mango", "orange"],
              2 : ["cherry", "red"]
            } 

  function scale(coords) {
    return [coords[0] * imageWidth / 100, coords[1] * imageHeight / 100];
  }


  svg.append("image")
       .attr("width",imageWidth)  
       .attr("height",imageHeight)
       .attr("x", 0) // could be non-zero, but we would have to shift each circle that many pixels.
       .attr("y", 0)     
     .attr("xlink:href", this.floorMaps[0])


  var data = this.floorSensorInfo

          // var dataNest = d3.nest()
          // .key(function (d) { return d['sensor_name']; })
          // .entries(data)
    data.forEach(function (d, i) {
   svg.selectAll("circle")
    .data(data)
    .enter()

    .append("circle")
    .attr("cx", function(d) { return (d.value)[0]; })
      .attr("cy", function(d) { return (d.value)[1]; })
    .attr("r", 5)
   .style("fill", function(d) { 
         var color = color_hash[data.indexOf(d)][1]
         return color;
      })
         svg.append('text')

            .attr("x", 20+(i)*100)  // space legend
             .attr("y", imageHeight+20)  
                  // style the legend

       .style("stroke", function () { // Add the colours dynamically
                  return d['color'] = color_hash[data.indexOf(d)][1];
              })
        //.attr("dy", ".35em")
        .text( d.sensor_name);
//.text("jjjjjjj")
      })}
user7422128
  • 902
  • 4
  • 17
  • 41
  • You are using invalid latitudes - there are two values over 90: 92.4, 132.72 – Andrew Reid Jun 19 '18 at 18:30
  • but i have my co-ordinates like this only . I'm getting an image from a REST response and computing my cordinates(x,y) values from a percentage value of the image size. So suppose image is 300*300 then 50% of it will be {150,150} which will be my co-ordinate to plot. So i will have such values can i get some workaround for it? I know this may sound weird but this is the thing i need to do @AndrewReid – user7422128 Jun 19 '18 at 18:37
  • If you are scaling your latitudes and longitudes prior to the projection you are skewing features (changing their shapes, areas, lengths, and/or map direction etc). And no matter what you can't feed a latitude of more than 90 to the d3 projection - the work around for this wraps coordinates around the world - this won't produce the desired effects. But, It sounds like you are asking about how to scale and translate the projection output to match an image. If so you'll need to describe the image (is it the whole world? what projection is it? what are its extents?) – Andrew Reid Jun 19 '18 at 18:43
  • No it's not the whole world. It's a floor plan image of a store where co-ordinates are the sensors location so we need to plot colour circles at such points. As much as i know we need to decide the co-ordinates from the image resolution by the percentage method i explained above. What about longitude?what is it's range? is there any range for latitude as well @AndrewReid – user7422128 Jun 19 '18 at 18:49
  • Ah, longitude has a range of +180 to -180, latitude +90 through -90. But, are you actually getting longitude/latitude pairs from the service (as if they came from a GPS device?) or are you getting Cartesian x,y coordinates measured in something like meters on a grid that covers your facility? – Andrew Reid Jun 19 '18 at 18:51
  • Those are x and y coordinates – user7422128 Jun 19 '18 at 18:52
  • 1
    Then a d3 projection is not needed. These take spherical coordinates (points on a three dimensional globe represented by longitude and latitude) and project them to a two dimensional plane. Not what you need. Instead you need to translate and/or scale the x,y values. For this you should be able to provide the extent of the image's x,y values in this coordinate system and indicate the size of the image in pixels as well (which I understand is 300x300). I'd update the question to reflect the problem as it now stands (otherwise the question will be buried in the comments) – Andrew Reid Jun 19 '18 at 18:57
  • You could just apply your scale method (the percentages) if the only difference between the image's units (pixels) and the xy units of the locations (meters maybe) is a scale factor. No need for anything else. – Andrew Reid Jun 19 '18 at 19:08
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/173422/discussion-between-codaholic-and-andrew-reid). – user7422128 Jun 19 '18 at 19:08
  • @AndrewReid i had updated the question with the ans you suggested and don't find any option to upvote which one of your comment – user7422128 Jun 21 '18 at 17:21
  • No problem - you can add the solution as an answer - this way you can accept it as the answer and others will see that your question has an answer. But either way, I'm glad if everything is working. – Andrew Reid Jun 22 '18 at 00:41
  • Do you have anything to suggest for this @Andrew Reid https://stackoverflow.com/questions/50974257/slider-not-updating-the-svg-view-in-d3 – user7422128 Jun 22 '18 at 05:29

1 Answers1

1
 var svg = d3.select("body")
    .append("svg")
    .attr("width",960) 
    .attr("height",500) 

  // image width and height in pixels, we don't want to skew this or scale this (then image units aren't straight pixels)
  var imageWidth = 300;
  var imageHeight = 168;
     var color_hash = {  0 : ["apple", "green"],
              1 : ["mango", "orange"],
              2 : ["cherry", "red"]
            } 

  function scale(coords) {
    return [coords[0] * imageWidth / 100, coords[1] * imageHeight / 100];
  }


  svg.append("image")
       .attr("width",imageWidth)  
       .attr("height",imageHeight)
       .attr("x", 0) // could be non-zero, but we would have to shift each circle that many pixels.
       .attr("y", 0)     
     .attr("xlink:href", this.floorMaps[0])


  var data = this.floorSensorInfo

          // var dataNest = d3.nest()
          // .key(function (d) { return d['sensor_name']; })
          // .entries(data)
    data.forEach(function (d, i) {
   svg.selectAll("circle")
    .data(data)
    .enter()

    .append("circle")
    .attr("cx", function(d) { return (d.value)[0]; })
      .attr("cy", function(d) { return (d.value)[1]; })
    .attr("r", 5)
   .style("fill", function(d) { 
         var color = color_hash[data.indexOf(d)][1]
         return color;
      })
         svg.append('text')

            .attr("x", 20+(i)*100)  // space legend
             .attr("y", imageHeight+20)  
                  // style the legend

       .style("stroke", function () { // Add the colours dynamically
                  return d['color'] = color_hash[data.indexOf(d)][1];
              })
        //.attr("dy", ".35em")
        .text( d.sensor_name);
//.text("jjjjjjj")
      })}
javascript d3.js
user7422128
  • 902
  • 4
  • 17
  • 41