How can I programmatically add 3-D shapes to Bing Maps (Virtual Earth)?
Here's some code that should help you:
var map = new VEMap('map_div_id');
// Put you points together and into an array, the 10.0 below is meters above the ground
var point1 = new VELatLong(45.01188,-111.06687, 10.0);
var point2 = new VELatLong(45.01534,-104.06324, 10.0)
var point3 = new VELatLong(41.01929,-104.06, 10.0);
var point4 = new VELatLong(41.003,-111.05878, 10.0);
var points = [point1, point2, point3, point4, point1];
var shape = new VEShape(VEShapeType.Polygon, points);
map.AddShape(shape);
See the following for more information:
VELatLong Class
VEShape Class
AddShape Method
Related
I would like to have an option to export my drawings as geoJSON files. So far I've managed perfectly with all of them except for the circle, which comes admittedly with no geometries at all!
I know, that GeoJSON format can render a pure circle, and we need to model it as the points as per this thread:
How to define a circle using GeoJson?
https://docs.mongodb.com/manual/tutorial/query-a-2dsphere-index/
I am fully aware of it, that's why I started to modify my code in order to make the circle physically visible.
My problem is very similar to this one:
Can't save features of drawn Circle to JSON in Openlayers 3
and similar to the solution below:
http://geoadmin.github.io/ol3/apidoc/sphere.js.html
After amending the code:
var wgs84Sphere = new ol.sphere(6378137);
var circleInteraction = new ol.interaction.Draw({
geometryFunction: function(coordinates, geometry) {
if (!geometry) {
geometry = new ol.geom.Polygon(null);
}
var center = coordinates[0];
var last = coordinates[1];
var dx = center[0] - last[0];
var dy = center[1] - last[1];
var radius = Math.sqrt(dx * dx + dy * dy);
var circle = ol.geom.Polygon.circular(wgs84Sphere, ol.proj.toLonLat(center), radius);
circle.transform('EPSG:4326', 'EPSG:3857');
geometry.setCoordinates(circle.getCoordinates());
return geometry;
},
type: 'Circle',
source: vectorLayer.getSource()
});
circleInteraction.setActive(false);
circleInteraction.on('drawend', onDrawend );
I have received an error:
Uncaught TypeError: ol.sphere is not a constructor
which is caused by the OpenLayers library upgrade and is not been valid anymore since version 5.0.0.
https://github.com/openlayers/openlayers/issues/9046
regarding this situation, I've tried to change the wgs84Sphere variable
var polygon_geometry = new ol.geom.Polygon;
var wgs84Sphere = ol.sphere.getArea(polygon_geometry, projection='EPSG:4326', radius=6378137)
but it didn't work either
Uncaught TypeError: Cannot read properties of undefined (reading SimpleGeometry.js:170
pointing the line
if (coordinates.length === 0) {
Is it possible to generate the .geoJSON geometries for circle then?
My full JSFiddle is here:
https://jsfiddle.net/pet6h30d/
The parameters for ol.geom.Polygon.circular have also changed so you do not need to construct a sphere, see https://openlayers.org/en/latest/examples/draw-and-modify-geodesic.html If you are not need to modify you only need a polygon
geometryFunction: function(coordinates, geometry, projection) {
if (!geometry) {
geometry = new ol.geom.Polygon([]);
}
var center = ol.proj.transform(coordinates[0], projection, 'EPSG:4326');
var last = ol.proj.transform(coordinates[1], projection, 'EPSG:4326');
var radius = ol.sphere.getDistance(center, last);
var circle = ol.geom.Polygon.circular(center, radius);
circle.transform('EPSG:4326', projection);
geometry.setCoordinates(circle.getCoordinates());
return geometry;
},
In a three.js rendering, I have a small texture which I want to repeat multiple times. For this texture there is the map, a displacement map, a normal map, an ambient occlusion map and a specular map. As long as the repeating pattern is 1 in the x and 1 in the y direction, the image looks as expected. There is displacement where expected.
If the repeat values are greater than 1, all of the maps appear to scaled correctly except for the displacement map. The displacement map does not appear to be repeated. The displace is the same as shown in the previous image.
A code snippet for applying these maps to a plane follows:
///////////////////////////////////////////////
// add texture plane for a test
xRep = 1;
yRep = 1;
var loader = new THREE.TextureLoader();
var tex = loader.load('images/img.png');
tex.wrapS = tex.wrapT = THREE.RepeatWrapping;
tex.repeat.set(xRep, yRep);
var nloader = new THREE.TextureLoader();
var ntex = loader.load('images/img-normal.png');
ntex.wrapS = ntex.wrapT = THREE.RepeatWrapping;
ntex.repeat.set(xRep, yRep);
var aloader = new THREE.TextureLoader();
var atex = aloader.load('images/img-ao.png');
atex.wrapS = atex.wrapT = THREE.RepeatWrapping;
atex.repeat.set(xRep, yRep);
var dloader = new THREE.TextureLoader();
var dtex = dloader.load('images/img-v003-disp.png');
dtex.wrapS = dtex.wrapT = THREE.RepeatWrapping;
dtex.repeat.set(xRep, yRep);
var sloader = new THREE.TextureLoader();
var stex = sloader.load('images/img-v003-spec.png');
stex.wrapS = stex.wrapT = THREE.RepeatWrapping;
stex.repeat.set(xRep, yRep);
var faceMaterial = new THREE.MeshPhongMaterial({
color: 0xa0a0a0,
shininess: 30,
//map : tex,
//bumpMap : tex,
//bumpScale : 1,
displacementMap: dtex,
displacementScale: 10,
normalMap: ntex,
//normalScale : (1,1),
aoMap: atex,
//aoMapIntensity : 1,
specularMap: stex
//_last: 0
});
face = new THREE.Mesh(new THREE.PlaneGeometry(50, 50, 256, 256),
faceMaterial);
face.position.z = 50;
face.receiveShadow = true;
face.castShadow = true;
scene.add(face);
How can this snippet be modified so the displacement map is repeated the same as the other maps?
Note: This issue appear to be related to the discussion at issue #7826 on Git hub.
You want your displacement map to repeat, but the displacement map does not honor the offset repeat value in the current version of three.js.
A work-around is to modify the UVs of your geometry.
Suppose you want the displacement map to be repeated 3 times. Then, multiply your UVs by 3.
Using PlaneBufferGeometry, follow this pattern to do so:
var uvs = geometry.attributes.uv.array;
for ( var i = 0; i < uvs.length; i ++ ) uvs[ i ] *= 3;
For the other textures, if you wanted to, you could compensate by scaling their repeat values accordingly:
texture.repeat.set( 1 / 3, 1 / 3 );
If you are changing the buffer geometry UVs after rendering at least once, you will need to set:
mesh.geometry.attributes.uv.needsUpdate = true;
Also, be sure to read this post.
three.js r.79
I have an IcosahedronGeometry defined like this (with all the code about colors and non-position stuff omitted):
var radius = 200;
geometry = new THREE.IcosahedronGeometry(radius, 2);
var materials = [
new THREE.MeshPhongMaterial({}),
new THREE.MeshBasicMaterial({})
];
group1 = THREE.SceneUtils.createMultiMaterialObject(geometry, materials);
group1.position.x = 0;
// rotate a bit just so it spins off-axis
group1.rotation.x = -1.87;
Which creates an almost spherical, many-sided shape.
I want to place little spheres at just a few of the vertices of this shape. Let's say 10 spheres. I do this by copying 10 vertices into an array, like this:
var vertexArray = [];
for (var i = 0; i < 10; i++) {
vertexArray.push(geometry4.vertices[i])
}
then, I use the Vectors copied into vertexArray to set the positions off Sprites:
for (var i = 0; i < vertexArray.length; i++) {
var loader = new THREE.TextureLoader()
var spriteMaterial = new THREE.SpriteMaterial(
{
map: loader.load('/glow.png'),
blending: THREE.AdditiveBlending,
side: THREE.BackSide
})
var sprite = new THREE.Sprite(spriteMaterial)
sprite.position.set(vertexArray[i].x, vertexArray[i].y, vertexArray[i].z)
// do i need rotate these by the same amount?
sprite.rotation.x = -1.87
scene.add(sprite)
}
This all works fine, except that the Sprites don't line up with the actual vertices on the Icosahedron, they just sit randomly (seemingly) somewhere on the faces. Occasionally a Sprite will sit exactly on a vertex.
Am I copying the vertices wrong, or missing a step in here?
Add an object as a child of a parent object, and the child object will rotate with the parent.
Use this pattern, instead:
var sprite = new THREE.Sprite( spriteMaterial );
sprite.position.copy( vertexArray[i] );
group1.add( sprite );
three.js r.76
On Leaflet I can create a new circle easily given the centre and the radius:
// Circle
var radius = 500; // [metres]
var circleLocation = new L.LatLng(centreLat, centreLon);
var circleOptions = {
color: 'red',
fillColor: '#f03',
fillOpacity: 0.5
};
var circle = new L.Circle(circleLocation, radius, circleOptions);
map.addLayer(circle);
The circle above is created and drawn without problems, so it is all.
However, if I wanted now to create and draw a rectangle that which bounds the circle, it does not work. Here is what I did:
// Rectangle
var halfside = radius; // It was 500 metres as reported above
// convert from latlng to a point (<-- I think the problem is here!)
var centre_point = map.latLngToContainerPoint([newCentreLat, newCentreLon]);
// Compute SouthWest and NorthEast points
var sw_point = L.point([centre_point.x - halfside, centre_point.y - halfside]);
var ne_point = L.point([centre_point.x + halfside, centre_point.y + halfside]);
// Convert the obtained points to latlng
var sw_LatLng = map.containerPointToLatLng(sw_point);
var ne_LatLng = map.containerPointToLatLng(ne_point);
// Create bound
var bounds = [sw_LatLng, ne_LatLng];
var rectangleOptions = {
color: 'red',
fillColor: '#f03',
fillOpacity: 0.5
};
var rectangle = L.rectangle(bounds, rectangleOptions);
map.addLayer(rectangle);
The size of the rectangle that I obtain has nothing to do with 500 metres. Also, it looks like the size of the rectangle depends on the zoom level the map is. None of these problems arose for the circle.
I suspect the way I transform the latitude/longitude to point and viceversa is wrong.
Just use the getBounds method that L.Circle inherits from L.Path:
Returns the LatLngBounds of the path.
http://leafletjs.com/reference.html#path-getbounds
var circle = new L.Circle([0,0], 500).addTo(map);
var rectangle = new L.Rectangle(circle.getBounds()).addTo(map);
Working example on Plunker: http://plnkr.co/edit/n55xLOIohNMY6sVA3GLT?p=preview
I was getting "Cannot read property 'layerPointToLatLng' of undefined" error, So I made some changes to iH8's answer.
var grp=L.featureGroup().addTo(map);
var circle=L.circle([0,0],{radius:<circle radius>}).addTo(grp);
L.rectangle(circle.getBounds()).addTo(this.bufferMap);
map.removeLayer(grp);
Three.js has function called THREE.Triangle() and I would like to know how to use it.
I suspect the Triangle class may not be what you are expecting it to be; it is not a class to be used directly for drawing simple 2D Triangles.
The Triangle class is a math utility function for encapsulating triangles and doing calculations, which is useful when drawing surfaces.
A good more detailed explanation for usage of triangles in drawing surfaces: Why do 3D engines primarily use triangles to draw surfaces?
If you are just trying to draw a simple 2D triangle:
var geom = new THREE.Geometry();
var v1 = new THREE.Vector3(0,0,0);
var v2 = new THREE.Vector3(30,0,0);
var v3 = new THREE.Vector3(30,30,0);
geom.vertices.push(v1);
geom.vertices.push(v2);
geom.vertices.push(v3);
geom.faces.push( new THREE.Face3( 0, 1, 2 ) );
geom.computeFaceNormals();
var mesh= new THREE.Mesh( geom, new THREE.MeshNormalMaterial() );
Another StackOverflow answer for this: Basic 2D colored triangle using three.js
Equivalent code using the Triangle class:
var geom = new THREE.Geometry();
var v1 = new THREE.Vector3(0,0,0);
var v2 = new THREE.Vector3(30,0,0);
var v3 = new THREE.Vector3(30,30,0);
var triangle = new THREE.Triangle( v1, v2, v3 );
var normal = triangle.normal();
// An example of getting the area from the Triangle class
console.log( 'Area of triangle is: '+ triangle.area() );
geom.vertices.push(triangle.a);
geom.vertices.push(triangle.b);
geom.vertices.push(triangle.c);
geom.faces.push( new THREE.Face3( 0, 1, 2, normal ) );
jsbin link to play with: http://jsbin.com/zatejelika/1/edit?html,css,js,output
Triangle class documentation link: http://threejs.org/docs/#Reference/Math/Triangle