Is my geojson data file created correclty? - javascript

I'm using this code to map power transformers on a leaflet map, but unfortunately when the map loads I don't find my data displayed. Can you please help me identify some problems(if any) in my code. I must admit that I'm new to web mapping so I just need some help here.
Here is the javascript code I'm using:
//global variables
var map,
fields = ["tx_id", "owner", "kva_rating", "prim_voltage", "sec_voltage", "serial_no", "area_name"],
autocomplete = [];
$(document).ready(initialize);
function initialize(){
$("#map").height($(window).height());
map = L.map("map", {
center: L.latLng(-0.7166700, 36.4359100),
zoom: 10
});
var tileLayer = L.tileLayer('https://api.tiles.mapbox.com/v4/mapbox.streets/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoicmFqYWJueWFtYnUiLCJhIjoiY2lqbTB4cnpiMDA4bnZhbHh3Znl2aDAwZiJ9.YC_iahav7t9GPl-7XgB-yQ', {
attribution: 'Network Design © Rajab Inc., Map data © OpenStreetMap contributors, | Map Tiles: CC-BY-SA, Imagery © Mapbox',
maxZoom: 19,
minZoom: 1,
id: 'rajabnyambu.oo91e3ga',
accessToken: 'pk.eyJ1IjoicmFqYWJueWFtYnUiLCJhIjoiY2lqbTB4cnpiMDA4bnZhbHh3Znl2aDAwZiJ9.YC_iahav7t9GPl-7XgB-yQ'
}).addTo(map);
//next: add features to map
getData();
};
function getData(){
$.ajax("getData.php", {
data: {
table: "transformer",
fields: fields
},
success: function(data){
mapData(data);
}
})
};
function mapData(data){
//remove existing map layers
map.eachLayer(function(layer){
//if not the tile layer
if (typeof layer._url === "undefined"){
map.removeLayer(layer);
}
});
//create geojson container object
var geojson = {
"type": "FeatureCollection",
"features": []
};
//split data into features
var dataArray = data.split(", ;");
dataArray.pop();
//console.log(dataArray);
//build geojson features
dataArray.forEach(function(d){
d = d.split(", "); //split the data up into individual attribute values and the geometry
//feature object container
var feature = {
"type": "Feature",
"properties": {}, //properties object container
"geometry": JSON.parse(d[fields.length]) //parse geometry
};
for (var i=0; i<fields.length; i++){
feature.properties[fields[i]] = d[i];
};
//add feature names to autocomplete list
if ($.inArray(feature.properties.featname, autocomplete) == -1){
autocomplete.push(feature.properties.featname);
};
geojson.features.push(feature);
});
//console.log(geojson);
//activate autocomplete on featname input
$("input[name=area_name]").autocomplete({
source: autocomplete
});
var mapDataLayer = L.geoJson(geojson, {
pointToLayer: function (feature, latlng) {
var markerStyle = {
fillColor: "#CC5600",
color: "#CAF",
fillOpacity: 0.5,
opacity: 0.8,
weight: 1,
radius: 8
};
return L.circleMarker(latlng, markerStyle);
},
onEachFeature: function (feature, layer) {
var html = "";
for (prop in feature.properties){
html += prop+": "+feature.properties[prop]+"<br>";
};
layer.bindPopup(html);
}
}).addTo(map);
};
my getData.php file works well so I guess the problem lies within the javascript file. Here is the getData.php:
require ('networkdbinfo.php');
$dbc = pg_connect( "$host $port $dbname $credentials" );
if(!$dbc) {
echo "Not connected : " . pg_error();
exit;
}
// Get the table and fields data
$table= 'transformer';
$fields = ["tx_id", "owner", "kva_rating", "prim_voltage", "sec_voltage", "serial_no", "area_name"];
// Turn fields array into formatted string
$fieldstr="";
foreach ($fields as $i=> $field) {
$fieldstr=$fieldstr . "l.$field,";
}
// Get the geometry as geojson in EPSG:900913
$fieldstr=$fieldstr . "ST_AsGeoJSON(ST_Transform(l.geom, 900913))";
// Create basic SQL statement
$sql="SELECT $fieldstr FROM $table l";
//if a query, add those to the sql statement
if (isset($_GET['area_name'])){
$area_name = $_GET['area_name'];
$distance = $_GET['distance'] * 1000; //change km to meters
//join for spatial query - table geom is in EPSG:900913
$sql = $sql . " LEFT JOIN $table r ON ST_DWithin(l.geom, r.geom, $distance) WHERE r.area_name = '$area_name';";
}
// echo $sql;
// Send the query
if (!$response=pg_query($dbc, $sql)) {
echo "A query error occurred.\n";
exit;
}
// Echo the data back to the DOM
while ($row=pg_fetch_row($response)) {
foreach ($row as $i=> $attr) {
echo $attr.", ";
}
echo ";";
}
?>

You probably have the same issue as there:
Json file dosen't show up in google chrome
I.e. opening your page from File System in Chrome browser.
The solutions proposed in that post are to set up a local server or to open Chrome with specific parameters.
But you should be able to test it directly with Firefox instead.

Related

Wfs layer registration failed

I can't solve this problem:
We have developed a webmapping application.
We use OpenLayers version 6 and Geoserver 2.18, and PostGis 3.0.2
Loading a WFS layer on openlayers is no problem.
On Openlayers, I tried to edit (add new vector) this layer (wfs-t) but save failed.
Editing this layer (wfs-t) on Qgis is going well.
here are the code blocks:
//variables
var its_typeName ='reception:fak_test';
var url_NS = 'http://localhost:8080/geoserver';
var url_wfs ='http://localhost:8080/geoserver/reception/ows?service=WFS&version=1.0.0';
var fak_draw;
var formatWFS = new ol.format.WFS();
var formatGML = new ol.format.GML3({
featureNS: url_NS,
featureType: its_typeName,
srsName: 'EPSG:4326'
//srsName: "EPSG:3857"
});
var transactWFS = function(p,f) {
f.unset('bbox', true);
switch(p) {
case 'insert':
node = formatWFS.writeTransaction([f],null,null,formatGML);
break;
case 'update':
node = formatWFS.writeTransaction(null,[f],null,formatGML);
break;
case 'delete':
node = formatWFS.writeTransaction(null,null,[f],formatGML);
break;
}
s = new XMLSerializer();
str = s.serializeToString(node);
console.log(str);
// send data
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (request.readyState == 4 && request.status == 200) {
alert(request.responseText);
}
}
request.open("POST", url_wfs, true);
request.send(str);
}
// parameter of layer
var PolygonStyle = [
new ol.style.Style({
stroke: new ol.style.Stroke({ color: '#EC1B0C', width: 3,}),
fill: new ol.style.Fill({ color: 'rgba(0, 0, 255, 0.1)',}),
})
];
// to load wfs on OpenLayers
function test_wfs_t(){
var url = url_wfs
+ '&request=GetFeature'
+ '&typeName=' + its_typeName
+ '&outputFormat=application/json';
fetch(url)
.then((response) => response.text())
.then((data) => {
//console.log(data);
getItsAttributs_db(data);
});
}
function getItsAttributs_db(xData)
{
//get its infos to post in the new feature
var JSON_received = JSON.parse(xData);
var len_draw = JSON_received.features.length;
var xid = len_draw + 1;
var nom = "xxx";
var custom_lab = "next";
var descriptio = "bla bla";
var xcouleur= "#FF0000";
// convert to GeoJSON
const vectorSource = new ol.source.Vector({
features: new ol.format.GeoJSON().readFeatures(xData, {
dataProjection: 'EPSG:4326',
featureProjection: 'EPSG:3857'
}),
});
// init vector to load on map
var fak_Vector = new ol.layer.Vector({
source: vectorSource,
style: PolygonStyle
});
var its_source = fak_Vector.getSource();
// load on map
map.addLayer(fak_Vector);
//remove old draw
map.removeInteraction(fak_draw);
//add new draw
draw_boo_wfst = true;
fak_draw = new ol.interaction.Draw({
type: 'MultiPolygon',
source: its_source
});
map.addInteraction(fak_draw);
// on end of draw
fak_draw.on('drawend', function(e) {
//add its properties
var draw_wfst = e.feature;
draw_wfst.setProperties(create_gfc_Attributs_view(xid, nom, descriptio, custom_lab, xcouleur));
// try to send to database
transactWFS('insert', draw_wfst);
});
}
// to create attributs of the new feature
function create_gfc_Attributs_view(xid, nom, descriptio, custom_lab, xcouleur){
var xTable = {};
xTable.id = xid;
xTable.name = nom;
xTable.descriptio = descriptio;
xTable.custom_lab = custom_lab;
xTable.color = xcouleur;
// callback
return xTable;
}
PostgreSQL syntax :
-- Structure of postgis
CREATE TABLE public.fak_test
(
id integer NOT NULL DEFAULT nextval('track_store.fak_test_id_seq'::regclass),
geom geometry(MultiPolygon,4326),
name character varying(254) COLLATE pg_catalog."default",
descriptio character varying(254) COLLATE pg_catalog."default",
custom_lab character varying(254) COLLATE pg_catalog."default",
color character varying(254) COLLATE pg_catalog."default",
CONSTRAINT fak_test_pkey PRIMARY KEY (id)
)
GRANT ALL ON TABLE public.fak_test TO myuser;
CREATE INDEX sidx_fak_test_geom
ON public.fak_test USING gist
(geom)
TABLESPACE pg_default;
Output of GML
<Transaction xmlns="http://www.opengis.net/wfs" service="WFS" version="1.1.0"
xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Insert>
<reception:fak_test xmlns:reception="http://localhost:8080/geoserver">
<reception:geometry>
<MultiPolygon xmlns="http://www.opengis.net/gml" srsName="EPSG:4326">
<polygonMember>
<Polygon srsName="EPSG:4326">
<exterior>
<LinearRing srsName="EPSG:4326">
<posList srsDimension="2">
-2144007.8418341065 5288167.744512376 -2144040.7892421824 5289040.850826394 -2145259.8433409994 5288645.48192948 -2144007.8418341065 5288167.744512376
</posList>
</LinearRing>
</exterior>
</Polygon>
</polygonMember>
</MultiPolygon>
</reception:geometry>
<reception:id>5</reception:id>
<reception:name>xxx</reception:name>
<reception:descriptio>bla blax</reception:descriptio>
<reception:custom_lab>suite</reception:custom_lab>
<reception:color>#FF0000</reception:color>
</reception:fak_test>
</Insert>
</Transaction>
Response from server:
<?xml version="1.0" encoding="UTF-8"?>
<ows:ExceptionReport xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ows="http://www.opengis.net/ows"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0.0"
xsi:schemaLocation="http://www.opengis.net/ows http://localhost:8080/geoserver/schemas/ows/1.0.0/owsExceptionReport.xsd">
<ows:Exception exceptionCode="InvalidParameterValue">
<ows:ExceptionText>org.geotools.referencing.operation.projection.PointOutsideEnvelopeException: -2144007.8418341065 outside of (-180.0,180.0)
Parsing failed for LinearRing: org.geoserver.wfs.WFSException: org.geotools.referencing.operation.projection.PointOutsideEnvelopeException: -2144007.8418341065 outside of (-180.0,180.0)
org.geotools.referencing.operation.projection.PointOutsideEnvelopeException: -2144007.8418341065 outside of (-180.0,180.0)
-2144007.8418341065 outside of (-180.0,180.0)</ows:ExceptionText>
</ows:Exception>
</ows:ExceptionReport>
Where is the problem?
Thank you
You are lying to GeoServer and it doesn't like it. You are sending coordinates that are not in lat/lon but claiming that they are.
<Polygon srsName="EPSG:4326">
<exterior>
<LinearRing srsName="EPSG:4326">
<posList srsDimension="2">
-2144007.8418341065 5288167.744512376 -2144040.7892421824 5289040.850826394 -2145259.8433409994 5288645.48192948 -2144007.8418341065 5288167.744512376
</posList>
</LinearRing>
</exterior>
</Polygon>
I don't know what projection your map is in, but I'd guess it is Web Mercator (EPSG:3857) so you should either set that in the data you send or reproject the polygon to ESPG:4326 before you send it.

Php $var in Javascript function Laravel

I pass php $var into Javascript from controller. $var has fetched addresses from DB. And i put it in Javascript. Now i can see the addresses in the console. No problem with that, I don't know why syntax error pop up too.
This is how I insert it into JS.
function initMap(){
var options = {
zoom:8,
center:
'{!! $estates[0]->address !!}'
}
var map = new google.maps.Map(document.getElementById("map"), options);
var marker = new google.maps.Marker({
position:
#foreach($estates as $addr)
'{!! $addr->address !!}',
#endforeach
map:map
});
var infoWindow = new google.maps.InfoWindow({
content:'content here'
});
marker.addListener('click', function () {
infoWindow.open(map, marker);
});
}
my foreach running without a problem I can see the addreses in the console but also at this line: '{!! $estates[0]->address !!}' error pops up too. Actually I am seeing the address not this line.
error is this:
Uncaught SyntaxError: Invalid or unexpected token
Do you have any idea? am I making syntax mistake. But if do that then how can I retrieving the addresses at the console?
Also having this error too at the same line:
Undefined variable: estates (View:
/var/www/html/laravel/resources/views/layouts/app.blade.php) (View:
/var/www/html/laravel/resources/views/layouts/app.blade.php)
Controller
public function index()
{
$estates = DB::table("allestates")
->get();
return view("home", compact('estates'));
}
the topic is different the duplicated ones. it's not pure JS i am working with Laravel.
I think one of the addresses contains the ' character. To avoid it use the addslashes function. You could do that in the controller:
public function index()
{
$estates = DB::table("allestates")->get()->map(function($estate) {
$estate->address = addslashes($estate->address);
return $estate;
});
return view("home", compact('estates'));
}
And the according js would be:
var options = {
zoom:8,
center: new google.maps.LatLng({{$estates[0]->lat}}, {{$estates[0]->long}});
}
Because you have multiple addresses, it means you will have multiple markers too. That being said your code should look something like:
function initMap(){
var options = {
zoom:8,
center: new google.maps.LatLng({{$estates[0]->lat}}, {{$estates[0]->long}});
}
var map = new google.maps.Map(document.getElementById("map"), options);
var infoWindow = new google.maps.InfoWindow({
content:'content here'
});
var markers = [];
#foreach ($estates as $key => $estate)
markers[{{$key}}] = new google.maps.Marker({
position: new google.maps.LatLng({{$estate->lat}}, {{$estate->long}});
map: map
});
markers[{{$key}}].addListener('click', function () {
infoWindow.open(map, markers[{{$key}}]);
});
#endforeach
}
You can use php variables inside laravel blade files as
var options = {
zoom:8,
center:
'{{$estates[0]->address}}'
}

merge many polygon from json map api v3

I'm trying to find method to merge many polygon ( >100 ) in order to have only 1 polygon to have just the border of the merged polygon, not border for all "little" polygon
I import coordinates from JSON file and I use this code to render each polygon:
var thisUcVar<?php echo $nb_fichier ?>;
var thisAgencyVar<?php echo $nb_fichier ?>;
var thisListAgencyVar;
var thisUcColor;
$.getJSON("<?php echo("test/". $fichier); ?>", function(json1) {
var i=0;
var coordUc = [];
var thisUc = json1;
thisUcVar<?php echo $nb_fichier ?> = thisUc[0].name;
thisAgencyVar<?php echo $nb_fichier ?> = thisUc[0].agency;
thisUcColor = thisUc[0].color;
$.each(json1, function(key, data){
i = 0;
$.each(data.coordinates, function(key, data){
coordUc.length = 0;
$.each(data, function(key, data){
var innerCoordUc = {"lat": data[1], "lng": data[0] };
coordUc[i] = innerCoordUc;
i++;
});
var uc = new google.maps.Polygon({
title: i,
strokeWeight: 1,
fillColor: thisUcColor,
paths: coordUc,
zIndex: 10
});
uc.setMap(map);
map.addListener('zoom_changed',function(){
if(map.getZoom()>=10){
uc.set('zIndex', 90);
}else{
uc.set('zIndex', 10);
}
});
uc.addListener('click', function() {
$(".layer").html("<h1>" + thisUcVar<?php echo $nb_fichier ?> + "</h1><ul></ul>");
$.each(thisAgencyVar<?php echo $nb_fichier ?>, function(key, data){
listThisAgencyVar = data.name;
$(".layer").append("<li>" + uc.title + listThisAgencyVar + "</li>");
});
if(map.getZoom() >= 10){
map.setZoom(11);
map.setCenter(uc.getBounds().getCenter());
}
});
if (!google.maps.Polygon.prototype.getBounds) {
google.maps.Polygon.prototype.getBounds=function(){
var bounds = new google.maps.LatLngBounds()
this.getPath().forEach(function(element,index){bounds.extend(element)})
return bounds;
}
}
});
});//fin de boucle json1
});
Result is like image below:
And here one of the JSON files that I'm using to generate each polygons.
JSON used to generate polygons group
I search everywhere and I didn't find any way to merge many polygons in one big ...
Thanks a lot
A solution that might work is using the Turf library. In particular, it has a union method that does exactly what you want (merge multiple polygons into one that corresponds to the union of the polygons).
However, this library uses the Geojson standard format so you will need to convert your data into this standard.
If you can use this format, it will also help you to display the data on the map using a DataLayer and the loadGeoJson method from Google Maps API.

Dynamic downloadURL( ) call

I'm building a website that has, among the others, a photo gallery feature. In the gallery page, there's a map (google) with several markers and every marker is related to a specific photo.
I've got a 'markers' table in my database:
markers:
id | name | address | lat | lng | gallery_id
_______________________________________________________
1 | .. | .... |.. | .. | 2
2 | .. | .... |.. | .. | 2
3 | .. | .... |.. | .. | 3
4 | .. | .... |.. | .. | 3
5 | .. | .... |.. | .. | 10
......................
All the fields are populated with geolocated data and every row represents a specific photo uploaded by the user, all but gallery_id, that holds the id of the gallery that owns the photo.
In the gallery page there's the javascript to build up the google map:
<script type="text/javascript">
function load() {
var map = new google.maps.Map(document.getElementById("map"), {
disableDefaultUI: true,
scrollwheel: false,
navigationControl: false,
mapTypeControl: false,
scaleControl: false,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var infoWindow = new google.maps.InfoWindow;
var bounds = new google.maps.LatLngBounds();
//phpsqlajax-xmlgenerator.php, get the data from database
downloadUrl("phpsqlajax-xmlgenerator.php", function(data) {
var xml = data.responseXML;
var markers = xml.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
var name = markers[i].getAttribute("name");
var address = markers[i].getAttribute("address");
var type = markers[i].getAttribute("type");
var point = new google.maps.LatLng(
parseFloat(markers[i].getAttribute("lat")),
parseFloat(markers[i].getAttribute("lng")));
var html = "<b>" + name + "</b> <br/>" + address;
var marker = new google.maps.Marker({
map: map,
position: point,
icon: icon.icon,
animation: google.maps.Animation.BOUNCE
});
bindInfoWindow(marker, map, infoWindow, html);
bounds.extend(marker.position);
}
map.fitBounds(bounds);
});
}
function bindInfoWindow(marker, map, infoWindow, html) {
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(html);
infoWindow.open(map, marker);
});
}
function downloadUrl(url, callback) {
var request = window.ActiveXObject ?
new ActiveXObject('Microsoft.XMLHTTP') :
new XMLHttpRequest;
request.onreadystatechange = function() {
if (request.readyState == 4) {
request.onreadystatechange = doNothing;
callback(request, request.status);
}
};
request.open('GET', url, true);
request.send(null);
}
function doNothing() {}
</script>
I provide to downloadURL the phpsqlajax-xmlgenerator.php file, with which I build the xml file holding the markers table data:
<?php
//Start xml file, create parent node
$dom = new DOMDocument("1.0");
$node = $dom->createElement("markers");
$parnode = $dom->appendChild($node);
// Opens a connection to a MySQL server
$conn = mysqli_connect('localhost', 'root', 'password', 'database');
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
//Select rows in the markers table
$query = "
SELECT * FROM `markers` WHERE 1;
";
$result = mysqli_query($conn, $query);
header("Content-type: text/xml");
// Iterate through the rows
while ($row = mysqli_fetch_assoc($result)){
// ADD TO XML DOCUMENT NODE
$node = $dom->createElement("marker");
$newnode = $parnode->appendChild($node);
$newnode->setAttribute("name",$row['name']);
$newnode->setAttribute("address", $row['address']);
$newnode->setAttribute("lat", $row['lat']);
$newnode->setAttribute("lng", $row['lng']);
$newnode->setAttribute("type", $row['type']);
}
echo $dom->saveXML();
?>
Everything works just fine so far and, as long there's only one gallery in the database, the map and the markers are correct.
Now comes my problem: I need a way to provide to phpsqlajax-xmlgenerator.php the gallery_id, in order to perform the right query since the old one just returns every rows of markers, no matter the gallery. I was thinking to put phpsqlajax-xmlgenerator.php code right on the top of the gallery.php page and generate the xml file directly on the page, but then what should I provide to the downloadURL function? gallery.php?. Another way I was thinking about is to put some sort of $_GET request in the downloadURL parameter, but I can't find a way to perform that properly.
Pass the gallery_id with the URL,e.g.:
downloadUrl("phpsqlajax-xmlgenerator.php?id=3", function(data) {
And build the sql based on the get-parameter:
$id=#intval($_GET['id']);
if($id<1){
exit();
}
$query = 'SELECT * FROM `markers` WHERE gallery_id='.$id;

jVectorMap Issue while loading ajax data

I'm trying to show data from visitors inside a map created using jvectormap plugin.
This is driving me crazy, i can not load the data through ajax, if i put the data manually it works.
So far i have this:
map.php
$datos = array();
$link->set_charset("utf8");
$sql = $link->query("SELECT SUM(ID) as visitors, state FROM visitors WHERE state != '' GROUP BY state");
while($row = $sql->fetch_row()){
$ss = $link->query("SELECT * FROM states WHERE state = '".$row[1]."'");
$rr = $ss->fetch_row();
$datos[] = array("ccode" => $rr[2], "visits" => $row[0]);
}
$data = array("countries" => $datos);
echo json_encode($data,JSON_NUMERIC_CHECK);
This returns the following data:
{"countries":[{"ccode":"VE-A","visits":81},{"ccode":"VE-L","visits":24}]}
Now the function to load the map:
function cargaMapa(){
//jvectormap data
$.post("ajax/map.php",{},function(mapa){
var dataC = eval(mapa);
//var dataC = {"countries":[{"ccode":"VE-A","visits":81},{"ccode":"VE-L","visits":24}]};
var countryData = [];
//for each country, set the code and value
$.each(dataC.countries, function() {
countryData[this.ccode] = this.visits;
console.log("Estado: "+this.ccode+" Visitas: "+this.visits);
});
//World map by jvectormap
$('#world-map').vectorMap({
map: 've_mill_en',
backgroundColor: "#fff",
regionStyle: {
initial: {
fill: '#e4e4e4',
"fill-opacity": 1,
stroke: 'none',
"stroke-width": 0,
"stroke-opacity": 1
}
},
series: {
regions: [{
values: countryData,
scale: ["#3c8dbc", "#2D79A6"], //['#3E5E6B', '#A6BAC2'],
normalizeFunction: 'polynomial'
}]
},
onRegionLabelShow: function(e, el, code) {
//search through dataC to find the selected country by it's code
var country = $.grep(dataC.countries, function(obj, index) {
return obj.ccode == code;
})[0]; //snag the first one
//only if selected country was found in dataC
if (country != undefined) {
el.html(el.html() + ': ' + country.ccode + country.visits + ' visitas');
}
}
});
});
}
As you can see in the function i have the var dataC, if i load in there the array coming from map.php it gives me Uncaught SyntaxError: Unexpected token : but if copy and paste the result of map.php into the var dataC it works pretty good.
How can i solve this?
I appreciate any help
Thanks
I figured it out, just changed $.post for $.getJSON and the magic began

Categories