I use openlayers 6.
I have an issue with displaying a layer on the map.
I load the layer as XML in GML format and try to display, but the layer doesn't show on the map.
Here is the vector definition:
function createLayer(layer, strategy, extent, projection) {
if (!strategy) strategy = allStrategy;
let vsource = createSourceLayer(strategy, layer, extent, projection);
var vector = new VectorLayer({
source: vsource,
visible: true,
style: new Style({
image: new Icon({
src: '/images/icon-alert-blue.png',
size: [30, 30],
})
})
});
return vector;
}
Here is the vector source definition:
function createSourceLayer(strategy, layer, extent, projection) {
let url = "url resources";
let vectorSource = new VectorSource({
format: new WFS({
gmlFormat: new GML({
featureType: "WW_MONITOR",
featureNS: "http://www.opengis.net/wfs",
srsName: "EPSG:2039"
})
}),
loader: function (extent, resolution, projection) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onload = function () {
if (xhr.status === 200) {
vectorSource.addFeatures(
vectorSource.getFormat().readFeatures(xhr.responseText, {
dataProjection: projection,
extent: [195380.430213, 739554.42288, 207900.538587, 750611.382494]
})
);
} else {
console.log("loader fail");
}
},
xhr.send();
},
strategy: strategy
});
return vectorSource;
}
Here is the map definition:
map = new Map({
layers: [baseLayer,layer],
view: view,
target: 'map',
});
Here is view definition:
view = new View({
extent: [195380.430213, 739554.42288, 207900.538587, 750611.382494],
maxResolution: 80000,
center: [201640.48440000002, 745082.902687],
projection: israeliTM,
zoom: 0
});
UPDATE:
Here is example of single featuere in GML that I get from server:
<?xml version="1.0" encoding="UTF-8"?>
<wfs:FeatureCollection xsi:schemaLocation="http://www.opengis.net/gml http://schemas.opengis.net/gml/2.1.2/feature.xsd http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/WFS-basic.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ns216630453="http://fdo.osgeo.org/schemas/feature/ns216630453"
xmlns:wfs="http://www.opengis.net/wfs"
xmlns:gml="http://www.opengis.net/gml">
<!-- Feature 1 -->
<gml:featureMember>
<ns216630453:WW_MONITOR>
<ns216630453:FeatId>1</ns216630453:FeatId>
<ns216630453:Name>Donald garage</ns216630453:Name>
<ns216630453:Street>Dundas str </ns216630453:Street>
<ns216630453:Building>128</ns216630453:Building>
<ns216630453:StreetCode>354</ns216630453:StreetCode>
<ns216630453:FK_Category>11</ns216630453:FK_Category>
<ns216630453:WaterUsing>27</ns216630453:WaterUsing>
<ns216630453:Exceptions>0</ns216630453:Exceptions>
<ns216630453:Geometry>
<gml:Point>
<gml:coordinates>199480.000000,747711.000000</gml:coordinates>
</gml:Point>
</ns216630453:Geometry>
</ns216630453:WW_MONITOR>
</gml:featureMember>
<!-- Feature 2 -->
.
.
.
</wfs:FeatureCollection>
And here how it looks after parsing:
0: Feature
dispatching_: {}
disposed_: false
geometryChangeKey_: null
geometryName_: "geometry"
id_: undefined
listeners_: {change: geometry: Array(1)}
ol_uid: "130"
pendingRemovals_: {}
revision_: 0
styleFunction_: undefined
style_: null
target_: undefined
values_:
Building: "128"
Exceptions: "0"
FK_Category: "11"
FeatId: "1"
Geometry:
Point:
coordinates: "199480.000000,747711.000000"
__proto__: Object
__proto__: Object
Name: "Donald garage"
Street: "Dundas str"
StreetCode: "354"
WaterUsing: "27"
__proto__: Object
__proto__: BaseObject
The projection that I use in vector layer is the same projection that I use in view.
Here the defenition of the projection:
proj4.defs("EPSG:2039", "+proj=tmerc +lat_0=31.73439361111111 +lon_0=35.20451694444445 +k=1.0000067 +x_0=219529.584 +y_0=626907.39 +ellps=GRS80 +towgs84=-48,55,52,0,0,0,0 +units=m +no_defs");
register(proj4);
let israeliTM = getProjection('EPSG:2039');
Any idea why the map doesn't show?
The source is WFS 1.0.0 which uses GML 2.1.2
<wfs:FeatureCollection xsi:schemaLocation="http://www.opengis.net/gml http://schemas.opengis.net/gml/2.1.2/feature.xsd http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/WFS-basic.xsd"
So the parser format must be specified as GML2
format: new WFS({
gmlFormat: new GML2({
featureType: "WW_MONITOR",
featureNS: "http://www.opengis.net/wfs",
srsName: "EPSG:2039"
})
}),
Related
Hi I'm new with Vue and I bump to this problem where when I update the location it doesn't reflect on the child component. I've used computed and watch but still not updating. forgive me as I don't have a strong knowledge about VueJS.
so in my code I have location(computed) which listen to localLocation(data) that is bind to the project.location. I update the location using the method setPlace()
hope anyone can help. here's my code below:
<template lang="pug">
.google-maps-wrapper
template(v-if="!location")
f7-list.no-margin-top
f7-list-button(title='Add Location' #click="isAutocompleteOpen = true")
template(v-if="location")
f7-list.no-margin(inline-labels no-hairlines-md)
f7-list-item.short-text Address: {{ location.formattedAddress }}
div
gmap-map.main-map(ref="googleMap" :options="mapOptions" :center="location.position" :zoom="16" :map-type-id="mapTypeId")
gmap-marker(:position="location.position" :clickable="false")
f7-actions(ref='mapsAction')
f7-actions-group
f7-actions-group
f7-actions-button(#click="copyToClipboard()") Copy to Clipboard
f7-actions-button(#click="isAutocompleteOpen = true") Change Address
f7-actions-button(v-if="$root.$device.ios || $root.$device.macos" #click="$refs.navigateActions.f7Actions.open()") Navigate
f7-actions-button(v-else #click="googleMapsNavigate()") Navigate
f7-actions-group
f7-actions-button
b Cancel
f7-actions(ref='navigateActions')
f7-actions-group
f7-actions-group
f7-actions-button(#click="googleMapsNavigate()") Google Maps
f7-actions-button(#click="appleMapsNavigation()") Apple Maps
f7-actions-group
f7-actions-button
b Cancel
f7-popup.locate-project(:opened='isAutocompleteOpen' #popup:closed='closeAutocomplete()')
f7-page
f7-navbar
f7-nav-title Search Location
f7-nav-right
f7-link(#click="closeAutocomplete()") Close
f7-searchbar.searchbar(search-container=".search-list" search-in=".item-title" #input="searchLocation($event)" placeholder="Enter Location" clear-button)
f7-list.not-found(v-if="!pendingSearch && !suggestedLocations.length && searchedLocation")
f7-list-item(title="Nothing found")
f7-block-title.gmap-preloader(v-if="pendingSearch")
f7-preloader(size="16")
f7-list.search-list.searchbar-found.gmap-search-list(v-if="!pendingSearch && suggestedLocations.length" media-list)
f7-list-item.item-button(v-for='(location, index) in suggestedLocations' :title="location.structured_formatting.main_text" :subtitle="location.structured_formatting.secondary_text" #click="updateLocation(location)")
</template>
<script>
import { debounce } from 'lodash-es'
import { Plugins } from '#capacitor/core'
const { Clipboard } = Plugins
const { Browser } = Plugins
const debounceSearch = debounce(run => {
run()
}, 500)
import defaultMixin from '#/mixins/default'
import {
f7Actions,
f7ActionsLabel,
f7ActionsGroup,
f7ActionsButton,
f7Popup,
f7Page,
f7NavRight,
f7NavTitle,
f7Navbar,
f7Block,
f7BlockTitle,
f7Label,
f7Link,
f7Preloader,
f7List,
f7ListButton,
f7ListItem,
f7ListInput,
f7Icon,
f7Searchbar
} from 'framework7-vue'
import { gmapApi } from 'vue2-google-maps'
export default {
name: "google-maps",
mixins: [defaultMixin],
props: ['project'],
components: {
f7Actions,
f7ActionsLabel,
f7ActionsGroup,
f7ActionsButton,
f7Popup,
f7Page,
f7NavRight,
f7NavTitle,
f7Navbar,
f7Block,
f7BlockTitle,
f7Label,
f7Link,
f7Preloader,
f7List,
f7ListButton,
f7ListItem,
f7ListInput,
f7Icon,
f7Searchbar
},
data() {
return {
mapTypeId: "terrain",
directionsService: undefined,
directionsDisplay: undefined,
autocompleteService: undefined,
autocompleteRequest: undefined,
navigate: false,
localLocation: this.project.location,
mapOptions: {
disableDefaultUI: true,
backgroundColor: '#d3d3d3',
draggable: false,
zoomControl: false,
fullscreenControl: false,
streetViewControl: false,
clickableIcons: false
},
isAutocompleteOpen: false,
suggestedLocations: [],
pendingSearch: false,
origin: '',
searchedLocation: ''
}
},
computed: {
location() {
return this.localLocation
},
google: gmapApi
},
methods: {
appleMapsNavigation(){
window.open(`http://maps.apple.com/?daddr=${encodeURI(this.project.location.formattedAddress)}`)
},
googleMapsNavigate(){
if(this.$root.$device.ios){
window.open(`comgooglemaps://?daddr=${encodeURI(this.project.location.formattedAddress)}`)
}else{
window.open(`https://www.google.com/maps/dir//${encodeURI(this.project.location.formattedAddress)}`)
}
},
closeAutocomplete() {
this.isAutocompleteOpen = false
this.searchedLocation = ''
this.suggestedLocations = []
this.$f7.searchbar.clear('.searchbar')
},
updateLocation( location ){
this.getGeocode(location.place_id, output => {
this.suggestedLocations = []
this.setPlace(output[0])
})
},
getGeocode( placeId, callback ){
const geocoder = new google.maps.Geocoder()
this.$f7.dialog.preloader()
geocoder.geocode({placeId}, output => {
callback(output)
this.closeAutocomplete()
this.$f7.dialog.close()
})
},
searchLocation( event ) {
this.pendingSearch = true
this.searchedLocation = event.target.value
debounceSearch(() => {
if(!this.searchedLocation) {
this.pendingSearch = false
this.suggestedLocations = []
return
}
const autocompleteService = new google.maps.places.AutocompleteService()
autocompleteService.getPlacePredictions({input: this.searchedLocation}, output => {
if(this.pendingSearch){
this.suggestedLocations = output || []
this.pendingSearch = false
}
})
})
},
setPlace( selectedLocation ) {
if(!selectedLocation.formatted_address) return;
const data = {
location: {
formattedAddress: selectedLocation.formatted_address,
position: {
lat: selectedLocation.geometry.location.lat(),
lng: selectedLocation.geometry.location.lng()
}
}
};
this.$f7.popup.close('.add-location')
if(this.$refs.autocomplete) this.$refs.autocomplete.$el.disabled = true
this.localLocation = data.location
db.collection("projects")
.doc(this.project.id)
.set(data, {
merge: true
})
.then()
},
copyToClipboard() {
Clipboard.write({
string: this.project.location.formattedAddress
});
}
}
}
</script>
Code Summary (just the summary of the whole code above)
Template that displays the address and map
.google-maps-wrapper
template(v-if="!location")
f7-list.no-margin-top
f7-list-button(title='Add Location' #click="isAutocompleteOpen = true")
template(v-if="location")
f7-list.no-margin(inline-labels no-hairlines-md)
f7-list-item.short-text Address: {{ location.formattedAddress }}
div
gmap-map.main-map(ref="googleMap" :options="mapOptions" :center="location.position" :zoom="16" :map-type-id="mapTypeId")
gmap-marker(:position="location.position" :clickable="false")
Last line of the template where it updates the location
f7-list-item.item-button(v-for='(location, index) in suggestedLocations' :title="location.structured_formatting.main_text" :subtitle="location.structured_formatting.secondary_text" #click="updateLocation(location)")
Script that updates the location
updateLocation( location ){
this.getGeocode(location.place_id, output => {
this.suggestedLocations = []
this.setPlace(output[0])
})
},
setPlace( selectedLocation ) {
if(!selectedLocation.formatted_address) return;
const data = {
location: {
formattedAddress: selectedLocation.formatted_address,
position: {
lat: selectedLocation.geometry.location.lat(),
lng: selectedLocation.geometry.location.lng()
}
}
};
this.$f7.popup.close('.add-location')
if(this.$refs.autocomplete) this.$refs.autocomplete.$el.disabled = true
this.localLocation = data.location
db.collection("projects")
.doc(this.project.id)
.set(data, {
merge: true
})
.then()
},
Initial Page No Address yet
Actual Output after adding location
Expected Output
So I've been using the google-maps-react example for converting GeoJSON data to polygons. The problem I've run into is that the example doesn't support converting GeoJSON features of the 'MultiPolygon' type. (Multiple polygons grouped together).
Is there anything I could change in the example to support that? Thinking I might be able to just add a case to the following function:
function geometryToComponentWithLatLng(geometry) {
const typeFromThis = Array.isArray(geometry);
const type = typeFromThis ? this.type : geometry.type;
let coordinates = typeFromThis ? geometry : geometry.coordinates;
switch (type) {
case 'Polygon':
return {
ElementClass: Polygon,
paths: coordinates.map(
geometryToComponentWithLatLng, {
type: 'LineString'
}
)[0],
};
case 'LineString':
coordinates = coordinates.map(
geometryToComponentWithLatLng, {
type: 'Point'
}
);
return typeFromThis ? coordinates : {
ElementClass: Polyline,
path: coordinates,
};
case 'Point':
coordinates = {
lat: coordinates[1],
lng: coordinates[0]
}
return typeFromThis ? coordinates : {
ElementClass: Marker,
ChildElementClass: InfoWindow,
position: coordinates,
};
default:
throw new TypeError('Unknown geometry type: ${ type }');
}
}
Managed to fix this one myself by adding a case to the switch for 'MultiPolygon', and making some slight changes to the case for 'Polygon', like so:
switch (type) {
case 'MultiPolygon':
return {
ElementClass: Polygon,
paths: coordinates.map(
geometryToComponentWithLatLng, {
type: 'Polygon'
}
),
};
case 'Polygon':
coordinates = coordinates.map(
geometryToComponentWithLatLng, {
type: 'LineString'
}
)[0];
return typeFromThis ? coordinates : {
ElementClass: Polygon,
path: coordinates,
};
case 'LineString':
coordinates = coordinates.map(
geometryToComponentWithLatLng, {
type: 'Point'
}
);
return typeFromThis ? coordinates : {
ElementClass: Polyline,
path: coordinates,
};
case 'Point':
coordinates = {
lat: coordinates[1],
lng: coordinates[0]
}
return typeFromThis ? coordinates : {
ElementClass: Marker,
ChildElementClass: InfoWindow,
position: coordinates,
};
default:
throw new TypeError('Unknown geometry type: ${ type }');
}
I have a Google maps component in a React/Redux app. When you click an item from a list, it passes down an array of coordinates to render as directions from the user's current location. The props are being passed fine through react-redux mapStateToProps. I'm calling a function to generate the the polyline, this is where my problem is. The marker is generated fine inside of render, but the directions do not render until another entry is clicked. Basically it's always one step behind the current markers. So, for 2 stops, I'll have directions from current location to stop 1, but not stop 2. For 3 stops, current location to stop 1 to stop 2 will be generated, but not stop 3.
When I log out the length of the array of stops inside of render I get the expected amount, a length of 1 for 1 stop. I have tried putting the method inside of componentWillWillReceiveProps and componentWillUpdate, and both methods will log a 0 for 1 stop.
Here's the component, if relevant:
const GoogleMapComponent = React.createClass({
mixin: [PureRenderMixin],
getInitialState: function() {
return {
map: null,
maps: null,
color: 0
}
},
componentWillUpdate: function() {
console.log('LOGS ZERO HERE', this.props.tourList.length)
if (this.state.maps) {
this.calculateAndDisplayRoute(this.state.directionsService, this.state.directionsDisplay, this.props.tourList);
}
},
saveMapReferences: function(map, maps) {
let directionsDisplay = new maps.DirectionsRenderer({map, polylineOptions: {strokeColor: '#76FF03'}, suppressMarkers: true});
let directionsService = new maps.DirectionsService();
this.setState({ map, maps, directionsService, directionsDisplay });
},
generateWaypoints: function(coords) {
return coords.map((coord) => {
return { location: new this.state.maps.LatLng(coord.lat, coord.lng) };
});
},
calculateAndDisplayRoute: function(directionsService, directionsDisplay, tourStops) {
let origin = this.props.userLocation || { lat: 37.77, lng: -122.447 };
let destination = tourStops[tourStops.length - 1];
let directions = { origin, destination, travelMode: this.state.maps.TravelMode.DRIVING };
if (this.props.tourList.length > 1) {
directions.waypoints = this.generateWaypoints(tourStops);
}
if (tourStops.length > 0) {
directionsService.route(directions, (response, status) => {
if (status === this.state.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
} else {
console.log('Directions request failed due to ' + status);
}
});
} else {
directionsDisplay.set('directions', null);
}
},
render: function() {
console.log('LOGS 1 HERE', this.props.tourList.length)
let markers = this.props.tourList.map((marker, idx) => {
let loc = marker.prevLoc ? marker.prevLoc : 'your current location.';
return <Marker className='point' key={idx} image={marker.poster} lat={marker.lat} lng={marker.lng} location={marker.location} price={marker.price} loc={loc} />
});
let defaultCenter = {lat: 37.762, lng: -122.4394};
let defaultZoom = 12
if (this.props.userLocation !== null) {
return (
<div className='map'>
<GoogleMap defaultCenter={defaultCenter} defaultZoom={defaultZoom} yesIWantToUseGoogleMapApiInternals={true}
onGoogleApiLoaded={({map, maps}) => {
map.setOptions({styles: mapStyles});
this.saveMapReferences(map, maps);
}} >
{markers}
<UserMarker lat={this.props.userLocation.lat} lng= {this.props.userLocation.lng} />
</GoogleMap>
</div>
);
}
return (
<div className='map'>
<GoogleMap defaultCenter={defaultCenter} defaultZoom={defaultZoom} yesIWantToUseGoogleMapApiInternals={true}
onGoogleApiLoaded={({map, maps}) => {
map.setOptions({styles: mapStyles});
this.saveMapReferences(map, maps);
}} >
{markers}
</GoogleMap>
</div>
);
}
});
function mapStateToProps(state) {
return {
tourList: state.sidebar.tourList,
userLocation: state.home.userLocation
}
}
export default connect(mapStateToProps)(GoogleMapComponent);
Figured it out, I was not passing nextProps to componentWillUpdate, so the function was always being called with the old props.
componentWillUpdate is called prior to this.props being updated. Change componentWillUpdate as follows:
componentWillUpdate: function(nextProps) {
console.log('SHOULD LOG ONE HERE', nextProps.tourList.length)
if (this.state.maps) {
this.calculateAndDisplayRoute(this.state.directionsService, this.state.directionsDisplay, nextProps.tourList);
}
}
Hello guys i have a problem with displaying my pie chart, when i try to add more data into the pie chart this error occurs, i need your expertise on this matter
this is my controller code. and the error message is
[50053] - Incomplete dimensions binding
onInit: function() {
this._setupSelectionList();
// 2.Create a JSON Model and set the data
var oModel = new sap.ui.model.json.JSONModel("http://lssinh000.sin3.sap.corp:8000/SAP_LE/lionExpress/Volunteer/Services/request.xsjs");
var oVizFrame = this.getView().byId("idpiechart");
// 3. Create Viz dataset to feed to the data to the graph
var oDataset = new sap.viz.ui5.data.FlattenedDataset({
dimensions : [{
name : 'Status',
value : "{Status}",
name : 'StartDate',
value : '{StartDate}'
}],
measures : [{
name : 'reqID',
value : '{reqID}',
},],
data : {
path : "/Status"
}
});
oVizFrame.setDataset(oDataset);
oVizFrame.setModel(oModel);
// 4.Set Viz properties
oVizFrame.setVizProperties({
title:{
text : "Delivery Summary"
},
plotArea: {
colorPalette : d3.scale.category20().range(),
drawingEffect: "glossy"
}});
var feedSize = new sap.viz.ui5.controls.common.feeds.FeedItem({
'uid': "size",
'type': "Measure",
'values': ["reqID"]
}),
feedColor = new sap.viz.ui5.controls.common.feeds.FeedItem({
'uid': "color",
'type': "Dimension",
'values': ["Status"]
}),
feedValue = new sap.viz.ui5.controls.common.feeds.FeedItem({
'uid': "value",
'type': "Dimension",
'values': ["StartDate"]
});
oVizFrame.addFeed(feedSize);
oVizFrame.addFeed(feedColor);
oVizFrame.addFeed(feedValue);
//this.getView().byId("idPopOver").connect(oVizFrame.getVizUid());
},
In the dataset, the name attribute has to be same as in the values arrays of the feeds.
I have this code
dojo.ready(function(){
inventoryStore = new dojo.store.JsonRest({
target: "http://localhost:9080/driver/dojoMVC",
idProperty: "name",
put: function(object, options){
if(object.quantity < 0){
throw new Error("quantity must not be negative");
}
}
});
results = inventoryStore.query("");
var storeData = new dojo.data.ItemFileWriteStore({
data:dojo.fromJson(results)
});
gridLayout = [
{ name: 'Name', field: 'name', editable: true},
{ name: 'Quantity', field: 'quantity'},
{ name: 'Category', field: 'category'}];
var grid = new dojox.grid.DataGrid({
store: storeData,
clientSort: true,
structure: gridLayout
}, dojo.byId("gridElement"));
grid.startup();
When i run it i receive this strange error in FF console
SyntaxError: missing ] after element list
[Break On This Error]
([object Object])
json.js (line 26, col 9)
Can anyone help me with this?
Thanks
maybe you must setup your Layout like this :
var layout = [[
{name:"Id", field: "ident", width:"30%"},
{name:"Name", field: "name", width:"70%"}
]];
In Ev'ry Example i find in dojo the layout is in double brackets.
This would explain why the Error says " missing ]".
Look:
http://dojotoolkit.org/reference-guide/1.9/dojo/data/ItemFileWriteStore.html?highlight=itemfilewritestore#itemfilewritestore-changes-reflected-in-dojox-data-datagrid
Update1
so the Error lies in the store. Have you tried to fill in the data like:
results = inventoryStore.query( name : "*"); // to query all items
Have you checked it there are any results in "results"?
var storeData = new dojo.data.ItemFileWriteStore({
data:results
});
After all i would try to fill in the data without dojo.fromJson.
Give it a try.
Regards, Miriam
The problem is inside the code you posted, which has a syntax error at the very end around line 26. You started with dojo.ready({ but didn't finish it with });
Here, reformatted to make it more obvious:
dojo.ready(function(){
inventoryStore = new dojo.store.JsonRest({
target: "http://localhost:9080/driver/dojoMVC",
idProperty: "name",
put: function(object, options){
if(object.quantity < 0){
throw new Error("quantity must not be negative");
}
}
});
results = inventoryStore.query("");
var storeData = new dojo.data.ItemFileWriteStore({
data:dojo.fromJson(results)
});
gridLayout = [
{ name: 'Name', field: 'name', editable: true},
{ name: 'Quantity', field: 'quantity'},
{ name: 'Category', field: 'category'}
];
var grid = new dojox.grid.DataGrid({
store: storeData,
clientSort: true,
structure: gridLayout
}, dojo.byId("gridElement"));
grid.startup();
Try adding:
});
Also, you're missing some var keywords in there.