I'm trying to draw US state outlines with the D3 framework (http://mbostock.github.com/d3/) but am having issues generating the actual SVG data. I've written my code to follow the Chloropleth example (as it most closely resembles what this project needs), made sure the supplied data is in geoJSON format, and AFAIK have the backend half of this working fine.
The problem is that when I view the DOM, the <svg> object contains only one <g> element (which I created manually, per the example), and none of the child <path> elements that should under it. My code seems fairly identical to the example, and my data appears to look correct, though I am outputting MultiPolygons instead of the Polygon object that the example uses.
Our app is a RoR project with jQuery (we're only using D3 for the SVG and geography features). The test page tries to create an <svg> element under a div called theArea, based upon the selection from a dropdown select of U.S. states:
$(document).ready( function() {
$("#chooser_state").change( function() {
var status = "#status";
var statebox = "#chooser_state";
var theArea = "#theArea"
var url = "/test/get_state_geom";
var data = { state: $(statebox).val() };
$(status).text("Request sent...");
$.post(url, jQuery.param(data), function(resp) {
$(status).text("Received response: " + resp["message"]);
$(theArea).empty();
var path = d3.geo.path();
var svg = d3.select(theArea).append("svg");
var state = svg.append("g").attr("id", "state_view");
var features = resp.payload.features;
$(status).text("Created SVG object");
state.selectAll("path")
.data(features)
.enter()
.append("path")
.attr("d", path );
});
});
});
The data we're feeding D3 looks like this:
{
'type' => 'Feature',
'id' => '01',
'properties' => {
'name' => 'Colorado'
},
'geometry' => {
'type' => 'MultiPolygon',
'coordinates' => [
[
[
[
-106.190553863626,
40.9976070173843
],
[
-106.061181,
40.996998999999995
],
< -- and so on -- >
]
]
]
}
}
Can someone clue me in to what we're doing wrong? I am new to geo and GIS stuff. I suspect the problem lies with the data() function, as it looks like it should be creating the blank <path> objects for each Feature (though we have only one, at the moment), but the D3 documentation seems unclear (and difficult to understand).
EDIT: Just wanted to add that the geoJSON we generate was created by the geoJSON extension for the GeoRuby gem. The actual map lines were sourced from the consolidated data that US Census Bureau's cartographic boundary files, which were converted to SQL and saved with postGIS. Part of me suspects the geoJSON extension is doing something wrong, so that is my next avenue of attack.
After giving up on this and then coming back, I noticed that my FeaturesCollection was not, in fact, a collection. There's a small detail that is easy to overlook when examining geoJSON samples: the contents of the FeaturesCollection is an array of hashes, not a single hash.
Related
I am trying to achieve dynamic 3D model of a building which i choose during search criteria, so far the code i have done is below.
map.on('load', function () {
// Listen for the `geocoder.input` event that is triggered when a user
// makes a selection
geocoder.on('result', function (ev) {
debugger;
var layers = map.getStyle().layers;
var styleSpec = ev.result;
var styleSpecBox = document.getElementById('json-response');
var styleSpecText = JSON.stringify(styleSpec, null, 2);
var syntaxStyleSpecText = syntaxHighlight(styleSpecText);
styleSpecBox.innerHTML = syntaxStyleSpecText;
map.addSource('floorplan', {
// GeoJSON Data source used in vector tiles, documented at
// https://gist.github.com/ryanbaumann/a7d970386ce59d11c16278b90dde094d
'type': 'geojson',
'data': 'https://docs.mapbox.com/mapbox-gl-js/assets/indoor-3d-map.geojson'
});
map.addLayer({
'id': 'room-extrusion',
'type': 'fill-extrusion',
'source': 'floorplan',
'paint': {
// See the Mapbox Style Specification for details on data expressions.
// https://docs.mapbox.com/mapbox-gl-js/style-spec/#expressions
// Get the fill-extrusion-color from the source 'color' property.
'fill-extrusion-color': ['get', 'color'],
// Get fill-extrusion-height from the source 'height' property.
'fill-extrusion-height': ['get', 'height'],
// Get fill-extrusion-base from the source 'base_height' property.
'fill-extrusion-base': ['get', 'base_height'],
// Make extrusions slightly opaque for see through indoor walls.
'fill-extrusion-opacity': 0.5
}
});
});
});
As i have tried to add this json URL (https://docs.mapbox.com/mapbox-gl-js/assets/indoor-3d-map.geojson) which i have found on this link: https://docs.mapbox.com/mapbox-gl-js/example/3d-extrusion-floorplan/
It only shows a fixed location in 3D of a building which is given on the second URL.
Now actually I want to achieve a specific 3D building on the map as only dynamic when i use search criteria.
The GeoJSON data at this file which you are using contains polygon features along with coordinates representing where in the geographic space these polygons are located. The extrude polygons for 3D indoor mapping example which you are referencing creates the "3D model" being display by taking the two-dimensional geometries specified by the polygon features in the GeoJSON used as a source, and then adding a corresponding layer which makes use of fill extrusions to visually extrude these two-dimensional polygons into three dimensions.
So, unless you change the contents of the GeoJSON file used as the source, it is expected behavior that the "3D model" of the building will continue to display at the same geographic location. If the geocoder returns the location of a particular building based on the input search criteria, you will still need to specify which GeoJSON polygons should be extruded to create the extruded model of the building. The Geocoding API response body for an address search itself likely won't be enough for this, since only a coordinate will be returned representing the location of this POI. As such, you would need to integrate some custom building data or another custom workflow to generate the polygons needed to extrude a variety of building polygon geometries.
I need to creat a Tunisia map using Amcharts with my json data
Code in my json / id in tunisiaLow
nbre in my json / value in tunisialow
i change in tunisiaLow like my json data but not work
i need samthink like this
pic
pleas help me
this is my code in plunker plnkr.co/edit/6aDJREhcFYSfM5JW99mX?p=preview
The biggest issue with your code is that you modified the AmCharts map JS file in such a way that it completely breaks with the library. The JS files should not be modified unless you know what you're doing and follow the directions on creating your own map files tutorial. Your modified file removes the required id attribute that makes the map function.
Ideally you should modify your data to match the map format, not the other way around. Going by your last ticket, you seem to be unable to change your data, so the solution is the same as the last - remap your data to conform with AmCharts' format.
The original JS/SVG map has a list of IDs for each province. Since your dataset's titles don't exactly match the titles within the original map, you'll want to create a lookup object that uses your titles to link up to the internal map IDs, for example, using your French titles:
var areaDataMapping = {
"TUNIS": "TN-11",
"ARIANA": "TN-12",
"BEN AROUS": "TN-13",
"MANOUBA": "TN-14",
"NABEUL": "TN-21",
"ZAGHOUAN": "TN-22",
"BIZERTE": "TN-23",
"BEJA": "TN-31",
"JENDOUBA": "TN-32",
"KEF": "TN-33",
"SILIANA": "TN-34",
"KAIROUAN": "TN-41",
"KASSERINE": "TN-42",
"SIDI BOUZID": "TN-43",
"SOUSSE": "TN-51",
"MONASTIR": "TN-52",
"MAHDIA": "TN-53",
"SFAX": "TN-61",
"GAFSA": "TN-71",
"TOZEUR": "TN-72",
"KEBILI": "TN-73",
"GABES": "TN-81",
"MEDENINE": "TN-82",
"TATAOUINE": "TN-83"
};
From there, you can remap your parsed JSON file to create the correct area object array with the required properties such as id, title and value and then assign the result to your code:
var remappedAreas = AmCharts.parseJSON( areas ).map(function(area) {
return {
id: areaDataMapping[area.libelleFr],
title: area.libelleAr,
code: area.code,
value: area.nbre
}
});
var map = AmCharts.makeChart("...", {
// ...
"dataProvider": {
// ...
"areas": remappedAreas,
// ...
},
// ...
});
Here's an updated plunkr, which uses the official AmCharts JS for Tunisia instead of your version.
I'm trying to build a webmap using Leaflet. My data are stored in a zipped shapefile, so I'm using the shapefile-js, which allows me to load and use the data. My program loads the zipped shapfile and adds the content to a geoJson object.
The next big thing: I want to grap the geoJson object to visualize the data in a table view using for example datatables.net or json Table.
Firstly find some code below:
var m = L.map('map', {
center : [51.3, 10.3],
zoom : 6,
minZoom : 6,
maxZoom : 10
});
var geo = L.geoJson({
features : []
}, {
onEachFeature : function (feature, layer) {
layer.on({
click : displayInfos
});
layer.bindLabel(layer.feature.properties.GEN, {
direction : 'auto'
});
},
style : style,
}).addTo(m);
// add the shapefile to the geojson object `geo`
shp('zipped_shapefile.zip').then(function (data) {
geo.addData(data);
});
Now I have some questions about it:
1.) As already said, now I want to access the data as a (geo)json object. Using Chrome's developer tools, I ask for the 'geo'object and I get the following output:
e {options: Object, _layers: Object, _initHooksCalled: true, _leaflet_id: 22, _map: e…}
Here is the question of why: Why is this not already a FeatureCollection type? This is only the case, if I use geo.toGeoJSON(); , where geo is the L.geoJson object (check code above).
2.) I've tried to solve the problem with a workaround. So...using the developer console I type
> geo2 = geo.toGeoJSON();
and I get the following result:
Object {type: "FeatureCollection", features: Array[412]}
This is exactly, what I want to have, isn't it? It's a json object... In my opinion, I only have to add this line at the end of my code (see the big code-block), but by doing it, I only get an empty FeatureCollection object.
> geo2
Object {type: "FeatureCollection", features: Array[0]}
I need to know, how I can store the geo-object (from whatever reason the geo-object is not accessible as a json object (question 1)) as a json object (question 2). As previously mentioned: it works by using the console, but not by placing the lines in my code :-/
Any help is mich appreciated :)
I am trying to transition between two GeoJSON objects, but have been unable to find any information on how to include more than one GeoJSON file. I am happy with the final transformation, but cannot find anything on multiple GeoJSON files.
I can currently plot one map like so:
d3.json("goldatt2.json", function (data) {
var group = canvas.selectAll("g")
.data(data.features)
.enter()
.append("g")
var path = d3.geo.path().projection(d3.geo.equirectangular());
var areas = group.append("path")
.attr("d", path)
How would I change this so that two GeoJSON files are called and can be transformed?
I found this example, http://bl.ocks.org/mbostock/3081153 but in this example there is only GeoJSON object that is then transformed to a circle.
Getting the Data is separate task with respect to transforming it.
So you could, in theory, have multiple ajax calls to fetch the data you need before you decide to do whatever with that data.
Mike Bostock has a Queue implementation for this purpose.
If you are using JQuery with D3, you could look into Deferred an example of which is posted here.
Once you have the data-sets that you need, you can now decide how you want to transform the data or provide transitions between them.
Pseudo-code:
var files = ["file1.json", "file2.json"];
//Fetch Data for both files and create a data set object of this format
var dataset = {
"file1.json": {/*geojson data for file1*/},
"file2.json": {/*geojson data for file2*/}
}
for(var item in dataset) {
var data = dataset[item];
//Do whatever transformation you need
}
I believe what I am trying to accomplish should be a fairly common task, yet I'm having difficulty getting it to work. I simply wish to create a multi-series plot from a data set containing (for each record) an ISO8601 timestamp along with multiple data points. The data is in JSON format and I'm using dojox.charting.chart "Lines" type.
I'm already aware that the Dojo charts cannot directly handle time-based axis data, let alone ISO8601. So I've already dealt with converting the x-axis to milliseconds-since-T0 server-side.
Here is a distilled example excerpt of my JSON:
[{"Offset_ms":0,"CP":250.58368,"TP":181.88211},
{"Offset_ms":360000,"CP":233.18443,"TP":119.94824},
{"Offset_ms":540000,"CP":227.15465,"TP":117.99422},
{"Offset_ms":720000,"CP":222.87495,"TP":117.55895},
{"Offset_ms":896000,"CP":218.19876,"TP":117.64221},
{"Offset_ms":900000,"CP":219.77487,"TP":117.93475}]
And the distilled JavaScript (assume the above JSON is in the variable 'sequenceData'):
var chart = new dojox.charting.Chart("sequenceDataGraph");
chart.addPlot("default", {
type: "Lines",
tension: "X"
});
chart.addAxis("x", { labelFunc: labelTimeAxis });
chart.addAxis("y", { vertical: true });
var sequenceDataStore = new dojo.store.Observable(new dojo.store.Memory({
data: {
label: "Sequence",
items: sequenceData
}
}));
addSequenceDataSeries(chart, sequenceDataStore, "TP");
addSequenceDataSeries(chart, sequenceDataStore, "CP");
chart.render();
function addSequenceDataSeries(chart, sequenceDataStore, sColumnName) {
chart.addSeries(sColumnName, new dojox.charting.StoreSeries(sequenceDataStore, { query: {} },
sColumnName));
}
What appears to be happening, is that Dojo Chart is not using the x-axis data at all, but instead plotting each point at a fixed interval based on the number of data points. That is, each data point seems to be assigned an ordinal, such as if Offset_ms was merely 1, 2, 3... Since my data points are not always at fixed intervals, the resulting graph is distorted.
How do I instruct Dojo Chart to use the "Offset_ms" field in the JSON data for the x-axis component?
I've scoured the tutorials, the API docs and performed numerous Google & SO searches to no avail. I've even browsed portions of the Dojo source, particularly StoreSeries.js.uncompressed.js, but I'm not finding any answers. Surely this is possible, and hopefully trivial!
Unfortunately, the official dojo documentation is seriously lacking, and I only figured out how to do something similar by browsing the dojo source. Specifically, line 135 of the StoreSeries test, http://archive.dojotoolkit.org/nightly/dojotoolkit/dojox/charting/tests/test_StoreSeries.html
The StoreSeries constructor's third argument accepts an object that maps the X and Y axis to specific fields in your data store.
Change the following line in your code from this:
chart.addSeries(sColumnName, new dojox.charting.StoreSeries(sequenceDataStore, { query: {} },
sColumnName));
to this:
chart.addSeries(sColumnName, new dojox.charting.StoreSeries(sequenceDataStore, { query: {} },
{ x: "Offset_ms", y: sColumnName }));
sColumnName becomes { x: "Offset_ms", y: sColumnName }