I am needing to transform GeoJSON vector data from EPSG:4326 to EPSG:3857...
I have a map...
var olMapDiv = document.getElementById('olmap');
control.map = new ol.Map({
target: olMapDiv,
renderer: 'canvas',
layers: layers,
interactions: ol.interaction.defaults({
altShiftDragRotate: false,
dragPan: false,
rotate: false
}).extend([new ol.interaction.DragPan({ kinetic: null })]),
pixelRatio: 1,
loadTilesWhileAnimating: true,
loadTilesWhileInteracting: true,
view: view
});
and a view...
var view = new ol.View({
// make sure the view doesn't go beyond the 22 zoom levels of Google Maps
maxZoom: 21,
projection: 'EPSG:3857',
center: [0, 0],
zoom: 0
});
I define my geoJson Object...
var geoJsonObj = {
'type': 'Feature',
'geometry': JSON.parse(shape),
'name': 'V',
'id': V.vID
}
I try to read the features into a open layers Vector object and provide projection parameters...
var vectorSource = new ol.source.Vector({
features: (new ol.format.GeoJSON()).readFeatures(geoJsonObj, {defaultDataProjection:"EPSG:4326",featureProjection:"EPSG:3857"})
});
Then I use the "vectorSource" above in a new Vector layer...
vectors = new ol.layer.Vector({
title: V.vID,
source: vectorSource,
id: V.vID,
name: 'V',
label: response.VList[key].Acres,
fill: response.VList[key].Shade,
stroke: defaultStrokeHex,
style: function (feature, resolution) {
var text = resolution * 100000 < 10 ? response.VList[key].Acres : '';
if (text != "") {
styleCache[text] = [new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#319FD3',
width: 1
}),
text: new ol.style.Text({
font: '12px Calibri,sans-serif',
text: text,
fill: new ol.style.Fill({
color: '#000'
}),
stroke: new ol.style.Stroke({
color: '#fff',
width: 3
})
}),
fill: new ol.style.Fill({
color: rcisWebMapUtilities.convertHex(response.VList[key].Shade, '0.5')
})
})];
}
else if (text == "") {
styleCache[text] = [new ol.style.Style({
fill: new ol.style.Fill({
color: rcisWebMapUtilities.convertHex(response.VList[key].Shade, '0.5')
})
})
]
} return styleCache[text];
}
});
No matter what I do I either see the vector drawn...but in EPSG:4326 or nothing loads...
I've spent way too much time trying to figure out how to get OpenLayers3 to do this...Any help is greatly appreciated!!
If you use EPSG:4326 in your view then your geojson vector declaration should be
var vectorSource = new ol.source.Vector({
features: (new ol.format.GeoJSON()).readFeatures(geojsonObject, {
dataProjection: 'EPSG:4326',
featureProjection:'EPSG:4326' })
});
If you use EPSG:3857 in your view use this:
var vectorSource = new ol.source.Vector({
features: (new ol.format.GeoJSON()).readFeatures(geojsonObject, {
dataProjection: 'EPSG:4326',
featureProjection:'EPSG:3857' })
});
Just to explain dataProjection is the source coords. Means the epsg of your coordinates within the geojson file. While featureProjection is the EPSG of your view and thus the EPSG of your map. Means is the EPSG original coords should be trasformed.
So try to remember this rule: featureProjection and ol.View projection declaration should be equal.
Note that I am assuming your geojson coords are projected in EPSG:4326.
Related
I have a doubt. In openlayers, how should I know if a layer or map was added or not? For example, I have a layer control, to see if that layer is visible on the map.
In Leaflet I use it like this
my_layer_leaflet.on("add",function(){
);
And in openlayers?
var my_layer_openlayers = new ol.layer.Vector({
title: 'MyLayer',
visible: false,
style: new ol.style.Style({
image: new ol.style.Icon( ({
anchor: [0.5, 26],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: 'legend/image.png'
}))
}),
source: new ol.source.Vector({
format: new ol.format.GeoJSON(),
url: function(extent) {
return layer_geoserver;
},
strategy: ol.loadingstrategy.all,
})
});
Place a single layer in a layerGroup an add a listener to the "change:layergroup" event:
var baseLayerGroup = new ol.layer.Group({layers: [layer_geoserver]});
map.on("change:layergroup", function() {console.log("LayerGroup changed.")});
map.setLayerGroup(baseLayerGroup);
I'm using ArcGIS JS 4.16 to allow users to draw a polygon on the map. The idea is that there will only be one polygon at any given time and when you connect two dots, it makes sense that it would complete the polygon. Double clicking or pressing "C" seems a bit more complex for the average use case.
const drawLayer = new GraphicsLayer();
const map = new Map({
basemap: 'streets-vector',
layers: [drawLayer],
});
const view = new MapView({
container: mapRef.current,
map: map,
center: [-73.93, 40.73],
zoom: 10,
});
const draw = new Draw({ view: view });
document
.getElementById('enableCreatePolygon')
.addEventListener('click', () => {
enableCreatePolygon(draw, view);
});
const enableCreatePolygon = (draw, view) => {
const action = draw.create('polygon');
action.on('vertex-add', (evt) => {
createPolygonGraphic(evt.vertices);
});
action.on('vertex-remove', (evt) => {
createPolygonGraphic(evt.vertices);
});
action.on('cursor-update', (evt) => {
createPolygonGraphic(evt.vertices);
});
action.on('draw-complete', (evt) => {
createPolygonGraphic(evt.vertices);
});
};
const createPolygonGraphic = (vertices) => {
view.graphics.removeAll();
const polygon = {
type: 'polygon',
rings: vertices,
spatialReference: view.spatialReference,
};
const graphic = new Graphic({
geometry: polygon,
symbol: {
type: 'simple-fill',
color: [51, 51, 204, 0.15],
style: 'solid',
outline: {
color: [51, 51, 204, 0.8],
width: 2,
},
},
});
I see two options, implement the "logic" or use SketchViewModel where is it already implemented. Btw, with the "logic" I mean complete polygon when the last vertex is equal (with a tolerance) to the first vertex.
Take a look at this links,
ArcGIS JS API Docs - SketchViewModel
You can implement your own UI to interact with the model or use the SketchWidget.
ArcGIS JS API Examples - Using custom UI or interaction
ArcGIS JS API Examples - Using SketchWidget
I need to draw outline to the polygon primitive drawn with following code :
scene.primitives.add( new Cesium.ClassificationPrimitive({
geometryInstances : new Cesium.GeometryInstance({
geometry : new Cesium.PolygonGeometry({
polygonHierarchy : new Cesium.PolygonHierarchy(
Cesium.Cartesian3.fromDegreesArray(coords)
),
height : height
}),
attributes : {
color: color,
},
id : id,
description : "Highlight Object",
})
}));
Is there any way to draw outline to a polygon primitive? I am aware that it can be added with Entities but the requirement is to use primitives.
Any help is much appreciated.
You can use PolylineCollection as a separate primitive for outline.
I created a demo in Sandcastle showing this use case:
var viewer = new Cesium.Viewer('cesiumContainer');
var coords = [
-72.0, 40.0,
-70.0, 35.0,
-75.0, 30.0,
-70.0, 30.0,
-68.0, 40.0
];
var cartesian = Cesium.Cartesian3.fromDegreesArray(coords);
var color = Cesium.Color.DARKRED;
var outlineColor = Cesium.Color.GOLD;
var polygonPrimitive = new Cesium.Primitive({
geometryInstances: new Cesium.GeometryInstance({
id: 'polygon',
geometry: Cesium.PolygonGeometry.createGeometry(
new Cesium.PolygonGeometry({
polygonHierarchy: new Cesium.PolygonHierarchy(cartesian)
})
)
}),
appearance: new Cesium.MaterialAppearance({
material: new Cesium.Material.fromType('Color', {
color: color
})
}),
asynchronous: false
});
var polylinePrimitive = new Cesium.PolylineCollection();
polylinePrimitive.add({
positions: cartesian,
width: 3.0,
loop: true,
material: new Cesium.Material.fromType('Color', {
color: outlineColor
})
});
var primitives = viewer.scene.primitives;
primitives.add(polygonPrimitive);
primitives.add(polylinePrimitive);
In Google Vr (Web View) it is possible to define hotspots by providing the following information:
vrView.addHotspot('hotspot_name', {
pitch: 30, // In degrees. Up is positive.
yaw: 20, // In degrees. To the right is positive.
radius: 0.05, // Radius of the circular target in meters.
distance: 2 // Distance of target from camera in meters.
});
However I see no way to set the shape or colour of the hotspots. So all hotspots are the same.
I would like to define hotspots that allow navigation (e.g. within a list of images/videos), either by providing controls similar to the VR view in YouTube (where the video control appear if you gaze at them and you move to the next or previous video), or simply by inserting hotspots that are different in shape and/or colour (e.g. with right and left arrow to indicate direction as in StreetView).
However I have not found any way to do it.
I see that in the underlying library, hotspots are defined as three's Object3D. I am not familiar with three but I suppose there should be a way to change the shape?
You have to change the embed.js code. There you can set color for the hotspot.
var innerMaterial = new THREE.MeshBasicMaterial({
color: 0x93c01f, side: THREE.DoubleSide, transparent: true,
opacity: MAX_INNER_OPACITY, depthTest: false
});
var outerMaterial = new THREE.MeshBasicMaterial({
color: 0xffffff, side: THREE.DoubleSide, transparent: true,
opacity: MAX_OUTER_OPACITY, depthTest: false
});
To change shape you have to edit three.js and include function BoxGeometry and dependencies from:
https://threejs.org/build/three.js
In order to apply different colors within the same scene, you can change these following lines of code in embed.js:
HotspotRenderer.prototype.add = function(pitch, yaw, radius, distance, id, color) {
var hotspot = this.createHotspot_(radius, distance, color);
}
HotspotRenderer.prototype.createHotspot_ = function(radius, distance, givenColor) {
if (!givenColor) {
givenColor = 0xffffff;
}
var innerMaterial = new THREE.MeshBasicMaterial({
color: givenColor, side: THREE.DoubleSide, transparent: true,
opacity: MAX_INNER_OPACITY, depthTest: false
});
var outerMaterial = new THREE.MeshBasicMaterial({
color: givenColor, side: THREE.DoubleSide, transparent: true,
opacity: MAX_OUTER_OPACITY, depthTest: false
});
}
function onAddHotspot(e) {
var id = e.id;
var color = e.color;
worldRenderer.hotspotRenderer.add(pitch, yaw, radius, distance, id, color);
}
… in vrview.js:
Player.prototype.addHotspot = function(hotspotId, params) {
var data = {
pitch: params.pitch,
yaw: params.yaw,
radius: params.radius,
distance: params.distance,
id: hotspotId,
color: params.color
};
this.sender.send({type: Message.ADD_HOTSPOT, data: data});
};
… and in your upper-level JavaScript for the player:
vrView.addHotspot('hotspot-1', {
pitch: 1,
yaw: 10,
radius: 0.2,
distance: 1,
color: 0xffaa00
});
vrView.addHotspot('hotspot-2', {
pitch: -1,
yaw: -20,
radius: 0.2,
distance: 1,
color: 0x22fefe
});
I'm quite new to sencha touch. The goal is to create an app which has a TabPanel containing four Tabs, one of them should be a map (the others are a NestedList and two Panels working like a charm). I've tried to make the map card like
NPApp.views.Mapcard = Ext.extend(Ext.Map, { ...
where I ended up with getting really strange results like some views are overlapping and no map is shown.
The second try was to creating a Panel, embed it into the TabPanel and add a map to the panel, where I get this error:
Uncaught TypeError: Cannot read property 'ROADMAP' of undefined;
sencha-touch-debug.js:24840
I've already tried to change the mapType to google.map.MapTypeID like mentioned in the Google Map API V3, no success there.
I just can't get the hang on it, hope you can give me some hints!
The App:
NPApp = new Ext.Application({
name: "NPApp",
title: "NextPuff",
icon: 'images/icon.png',
tabletStartupScreen: 'images/index_default.jpg',
phoneStartupScreen: 'images/index_default.jpg',
launch: function() {
this.views.viewport = new this.views.Viewport();
this.views.homecard = this.views.viewport.getComponent('navi');
}
});
The Viewport:
NPApp.views.Viewport = Ext.extend(Ext.TabPanel, {
fullscreen: true,
store: NPApp.npstore,
initComponent: function() {
Ext.apply(this, {
tabBar: {
dock: 'bottom',
layout: {
pack: 'center'
}
},
items: [
{ xtype: 'homecard', stretch: true},
{ xtype: 'searchcard', id: 'navi' },
{ xtype: 'mapcard' },
{ xtype: 'morecard' }
]
});
NPApp.views.Viewport.superclass.initComponent.apply(this, arguments);
}
});
The Mapcard:
NPApp.views.Mapcard = Ext.extend(Ext.Panel, {
title: "Map",
iconCls: "map",
initComponent: function() {
var npMap = new Ext.Map({
title: 'Map',
useCurrentLocation: true,
listeners: {
centerchange : function(comp, map){
// refreshMap(map);
}
},
mapOptions : {
mapTypeControl : false,
navigationControl : false,
streetViewControl : false,
backgroundColor: 'transparent',
disableDoubleClickZoom: true,
zoom: 17,
draggable: false,
keyboardShortcuts: false,
scrollwheel: false
}
});
Ext.apply(this, {
defaults: {
styleHtmlContent: true
},
items: [npMap]
});
NPApp.views.Homecard.superclass.initComponent.apply(this, arguments);
}
});
Ext.reg('mapcard', NPApp.views.Mapcard);
Sencha 1.1.0; Google JavaScript Maps API V3; Safari 5.1
I have a similar application running. Your tabpanel is perfect. All you need to alter is your map code.... Try this instead :
var map = new Ext.Map({
mapOptions : {
center : center,
zoom : 20,
mapTypeId : google.maps.MapTypeId.HYBRID,
navigationControl: true,
navigationControlOptions: {
style: google.maps.NavigationControlStyle.DEFAULT
}
},
listeners : {
maprender : function(comp, map){
var marker = new google.maps.Marker({
position: center,
//title : 'Sencha HQ',
map: map
});
setTimeout( function(){map.panTo (center);} , 1000);
}
},
geo:new Ext.util.GeoLocation({
autoUpdate:true,
maximumAge: 0,
timeout:2000,
listeners:{
locationupdate: function(geo) {
center = new google.maps.LatLng(geo.latitude, geo.longitude);
if (map.rendered)
map.update(center)
else
map.on('activate', map.onUpdate, map, {single: true, data: center});
},
locationerror: function ( geo,
bTimeout,
bPermissionDenied,
bLocationUnavailable,
message) {
if(bLocationUnavailable){
alert('Your Current Location is Unavailable on this device');
}
else{
alert('Error occurred.');
}
}
}
})
});
This creates the map object and sets the center to ur current location. Now you need to dock this object inside an Ext.extend(Ext.Panel({}) object. Ive tried directly creating the map object but it needs a panel to display on.
So you're panel code should go something like so:
NPApp.views.Mapcard = new Ext.extend(Ext.Panel({
iconCls : 'map',
title : 'Map',
layout: 'card',
ui: 'light',
items: [map],
listeners:{
}
});
)
It took me ages of going thru a dozen or more examples to make the current location work. This is a combination of several codes and a bunch of stuff in the Google API.
Lemme know if you have any more questions about Google Maps or directions.
Cheers :)
Sasha