D3.js - Изчертаването на точки на картата е неуспешно поради грешна проекция

В момента работя върху проект, който чертае карта въз основа на географски данни от JSON файл, използвайки D3.js.

Сега имам друг JSON файл с местоположения в него и искам да начертая тези местоположения като точки на моята карта.

Правя това по следния начин:

svg.selectAll('circle')
.data(redCrossLocations.features)
.enter()
.append('circle')
.attr('cx', function(d) {
  var x = d.geometry.x
  var y = d.geometry.y
  return projection([x.toString(), y.toString()])[0]
})
.attr('cy', function(d) {
  var x = d.geometry.x
  var y = d.geometry.y
  return projection([x.toString(), y.toString()])[1]
})
.attr('r', 10)
.attr('text',function(d) {
  return d.attributes.DienstSt
})
.style('fill', 'yellow')

Но когато погледна кръговете с Firebug, тези кръгове имат много високи cx и cy стойности, които изобщо не отговарят на координатите на картата. В резултат на това точките не са позиционирани и не се виждат на картата.

Ето как изглежда, когато изследвате html с Firebug:

<svg id="chart-330a29bc-10a6-422f-b7a4-b79213e63a0f" viewBox="0 0 1700 850">
<g transform="">
<svg width="425" height="425">
<rect width="850" height="850" style="stroke: black; fill: none;">
<path d="M406.7479670817884,199.90340867304621L407.06008919224314,199.57933852526912L407.7100188308723,198.8568991193315L408.1015443102342,198.34893921523326L408.14613950961393,198.29087863446694L408.68509042962614,197.6062181990019L408.79620200385034,197.4452283080136L409.08485295673836,197.0327872268681L409.31646456821454,196.6144688478962L409.62291817269215,195.96797874850017L409.78145919928556,195.49428734522007L409.912011977608,194.9738064907906L409.986809685407,194.39973754590756L410.0058080374765,193.7122278...00837217,205.1538807821671L401.9104729365481,204.65327053784495L402.62461611946765,203.79979531967183L403.17787116003547,203.1799602826395L403.20639083074093,203.1993550356201L403.308689649577,203.08799997778988L403.42697542668066,202.95942665539405L403.5903878256004,202.78322302641755L405.8101836239257,200.80217267343687L405.8688615178462,200.74629337105216L405.89149125655877,200.7271611214237L405.95836191302715,200.66712537209605L406.1133158381808,200.52594198620864L406.3833670058257,200.28190447086672Z" style="fill: red; stroke-width: 1; stroke: black;">
<circle cx="189993884.995462" cy="-29942.633406634715" r="10" text="Salzburg Stadt" style="fill: yellow;">
<circle cx="186702567.5263016" cy="6214.613271863014" r="10" text="Lamprechtshausen" style="fill: yellow;">
<circle cx="191422937.49531066" cy="NaN" r="10" text="Mattsee" style="fill: yellow;">
<circle cx="196518708.70128453" cy="NaN" r="10" text="Straßwalchen" style="fill: yellow;">

С надеждата, че ще помогне за намирането на решение, ето кода за генериране на карта:

const svg = d3.select(`#${chartId}`)
    svg
    .append("svg")
    .attr("width", width / 2).attr("height", height / 2)

  var center = d3.geo.centroid(salzburg)
  var scale  = 1;
  var offset = [width / 2, height / 2];
  var projection =
    d3.geo.mercator()
      .scale(scale)
      .center(center)
      .translate(offset);

  // create the path
  var path = d3.geo.path().projection(projection);

  // using the path determine the bounds of the current map and use
  // these to determine better values for the scale and translation
  var bounds  = path.bounds(salzburg);
  var hscale  = scale * width  / (bounds[1][0] - bounds[0][0]);
  var vscale  = scale * height / (bounds[1][1] - bounds[0][1]);
  var scale   = (hscale < vscale) ? hscale : vscale;
  var offset  = [width - (bounds[0][0] + bounds[1][0]) / 2.1,
    height - (bounds[0][1] + bounds[1][1]) / 2.4];

  projection = d3.geo.mercator().center(center)
    .scale(scale).translate(offset);
  path = path.projection(projection);

  svg.append("rect").attr('width', width).attr('height', height)
    .style('stroke', 'black').style('fill', 'none');

  svg.selectAll("path").data(salzburg.features).enter().append("path")
    .attr("d", path)
    .style("fill", "red")
    .style("stroke-width", "1")
    .style("stroke", "black")

redCrossLocations изглежда така:

"features": [{
    "attributes": {
      "OBJECTID": 1,
      "DienstSt": "Salzburg Stadt",
      "Art": "Bezirksstelle",
      "Ort": "Salzburg",
      "Strasse": "Sterneckstraße",
      "Hnr": "32",
      "Bezirk": "Stadt Salzburg und Flachgau",
      "Typ": null
    },
    "geometry": {
      "x": 429395.48199999984,
      "y": 296716.59500000067
    }
  }, {
    "attributes": {
      "OBJECTID": 2,
      "DienstSt": "Lamprechtshausen",
      "Art": "Ortsstelle",
      "Ort": "Lamprechtshausen",
      "Strasse": "Schulstraße",
      "Hnr": "1",
      "Bezirk": "Stadt Salzburg und Flachgau",
      "Typ": null
    },
    "geometry": {
      "x": 421963.38900000043,
      "y": 317197.9179999996
    }
  },
...

Някой знае ли защо получавам тези абсолютно грешни координати на точка?


person Michael Andorfer    schedule 28.12.2015    source източник
comment
Как изглежда вашето redCrossLocations.features? Защо извиквате .toString() на вашите x и y стойности?   -  person altocumulus    schedule 28.12.2015
comment
Не е свързано с действителния ви проблем, но както за cx, така и за cy имате достъп до първия елемент на проектираната точка, т.е. имате достъп до първата стойност [0] на върнатия масив, поради което cx и cy имат идентични стойности.   -  person altocumulus    schedule 28.12.2015
comment
@altocumulus Добавих json сега; тъй като местоположението се доставя е число и съм чел, че трябва да е низ, но е възможно да няма ефект както в положителна, така и в отрицателна посока.   -  person Michael Andorfer    schedule 28.12.2015
comment
@altocumulus благодаря ти, че ми го каза, но това прави още по-лошо, защото сега имам не само високи стойности, но и NaN стойности   -  person Michael Andorfer    schedule 28.12.2015
comment
Вашият JSON е JSON формат на Esri, който не е съвместим с GeoJSON, който се изисква от D3. Разгледайте следния въпрос относно конвертирането между формати: Как да конвертирате ArcGIS Server JSON в GeoJSON?   -  person altocumulus    schedule 28.12.2015
comment
@altocumulus Сега направих трансформацията, но за съжаление няма никакъв ефект   -  person Michael Andorfer    schedule 28.12.2015
comment
@altocumulus да, сега работи, преди съм вземал грешен EPSG   -  person Michael Andorfer    schedule 28.12.2015
comment
Защо направихте толкова драстични промени във вашия JSON? Текущата версия (въведена от версия 4) е GeoJSON, която вече не прилича на оригиналния Esri JSON. Усещането е като да поставите една част от отговора във въпроса. Бих искал да предложа да отмените тази промяна.   -  person altocumulus    schedule 29.12.2015
comment
@altocumulus Направих връщането назад, както беше предложено сега   -  person Michael Andorfer    schedule 29.12.2015


Отговори (1)


Първо, когато търсите подробности, взети от вашия redCrossLocations, изглежда, че са изтеглени от този източник. Проверката на пълния файл разкрива два проблема с вашите гео входни данни:

  1. Вашият JSON изглежда е JSON формат на Esri, докато D3 очаква GeoJSON като свой вход. Тъй като вашият JSON не е съвместим с GeoJSON, ще трябва да го конвертирате.

  2. Файлът има дефиниция на "spatialReference":{"wkid":31258,"latestWkid":31258}, която се отнася до проектираната координатна система < em>MGI_Austria_GK_M31 (EPSG::31258), което също не е правилното за използване, когато става въпрос за D3. За да го направите използваем за D3, трябва да го трансформирате в географската координатна система WGS 84 (EPSG::4326).

За щастие, можете да използвате инструмента ogr2ogr, за да направите и двете преобразувания в едно изпълнение:

ogr2ogr -f "GeoJSON" -t_srs "EPSG::4326" "RotesKreuz_Dienststellen.json"

Освен това има налична опция -s_srs за изрично указване на изходната координатна система (-s_srs "EPSG:31258"), която не е необходима във вашия случай, защото ще бъде получена от входния файл.

Има и ogr2ogr уеб клиент, наличен за извършване на конвертирането и трансформацията онлайн. С помощта на този формуляр можете да качите вашия файл и да посочите „Target SRS“ да бъде EPSG:4326, което ще трансформира координатната система и ще я преобразува в GeoJSON.

person altocumulus    schedule 29.12.2015