Openylayers 2 - Draw a circle or a point with radius - geometry

I have a position (lon, lat) and a radius. The radius is a float value and is in the km (kilometer) unit.
For example: Lat=46.92, Lon=7.95 and radius 5km.
Now my goal is to draw a circle or point at this position with this radius.
I'm using the follow transformation:
function GetLonLatObj(lat, lon) {
var lonLat = new OpenLayers.LonLat( lon ,lat )
.transform(
new OpenLayers.Projection("EPSG:4326"), // Transformation aus dem Koordinatensystem WGS 1984
map.getProjectionObject() // in das Koordinatensystem 'Spherical Mercator Projection'
);
return lonLat
}
To draw the circle on the right position is no problem. Unfortunately the circle is to small and has no radius of 5 km on the map.
Here is my code:
var map = new OpenLayers.Map("mapdiv");
map.addLayer(new OpenLayers.Layer.OSM('OpenStreetMap',
"https://a.tile.openstreetmap.org/${z}/${x}/${y}.png",
"https://b.tile.openstreetmap.org/${z}/${x}/${y}.png",
"https://c.tile.openstreetmap.org/${z}/${x}/${y}.png"
));
map.addLayer(vectorNotamLayer);
zoom = 12;
var vectorNotamLayer = new OpenLayers.Layer.Vector("Simple Geometry", {
styleMap: new OpenLayers.StyleMap({
'default': {
pointRadius: "${Radius}",
label : "${Title}",
fontSize: "20px",
fontWeight: "bold",
labelAlign: "cm",
labelYOffset: -10,
fillOpacity: 0.4,
labelOutlineWidth: 3
}
}),
});
var lon = 7.95;
var lat = 46.92;
var radius = 5;
var upper = item.upper;
var lower = item.lower;
var number = item.number;
var title = series + number + " " + lower + "-" + upper;
var latLonObj = GetLonLatObj(lat, lon);
var point = new OpenLayers.Geometry.Point(latLonObj.lon, latLonObj.lat);
var pointFeature = new OpenLayers.Feature.Vector(point);
pointFeature.attributes = {
Title: title,
Radius: radius,
};
vectorNotamLayer.addFeatures([pointFeature]);
Can sombody help me here please?
Edit:
I changed the code from:
var pointFeature = new OpenLayers.Feature.Vector(point);
pointFeature.attributes = {
Title: title,
Radius: radius,
};
To
var poly = OpenLayers.Geometry.Polygon.createRegularPolygon
(
point,
radius,
36,
0
);

Related

How to measure the distance from center of a circle to the edge in openlayers

I want to give users the ability to find out how far they are from a Point of Interest to the edge of a radius on a map. I would also like to convert that unit to kilometers, meter or nautical mile.
I understand that all polygons are drawn in meters.
I am using fromCircle to convert a circle to a geometer polygon. Please help me. I remember there was a getbound() function in openlayers 2 but i can not find it anymore to use to calculate the distance form the the point of interest or center of the map to the edge. I have searched through stackoverflow for days but can not find exactly what is need or the solution that worked with the new version of openlayers.
var vectorSource = vectorLayer.getSource();
var centerLongitudeLatitude = map.getView().getCenter();
var viewProjection = map.getView().getProjection();
var pointResolution = olProj.getPointResolution(viewProjection, 1, centerLongitudeLatitude);
console.log('pointResolution', pointResolution)
function addCirclePolygon(coordinates, radius=1600) {
var _radius = radius/pointResolution;
// var circle = new Feature(new Circle(coordinates, _radius));
var circle = new Feature(new Circle(coordinates, _radius));
circle.setStyle(new Style({
stroke: new Stroke({
color: 'blue',
width: 3
}),
fill: new Fill({
color: 'rgba(0, 0, 255, 0.1)'
})
}));
var geom=circle.get('geometry');
if (circle instanceof Circle) {
circle.set('geometry', fromCircle(geom));
}
vectorSource.addFeature(circle);
}
The distance from a point to the edge of a ctrcle is the distance from the point to the center of the circle minus the radius.
But OpenLayers has a getClosestPoint method which will work with any geometry:
var point1 = point.getGeometry().getCoordinates();
var point2 = circle.getClosestPoint(point1);
Then you can calculate a distance using Pythagoras and adjust for point resolution:
var dx = point1[0] - point2[0];
var dy = point1[1] - point2[1];
var meters = Math.sqrt(dx * dx + dy * dy) * pointResolution;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<link rel="stylesheet" href="https://openlayers.org/en/v6.4.3/css/ol.css" type="text/css">
<script src="https://openlayers.org/en/v6.4.3/build/ol.js"></script>
</script>
<style>
html, body, .map {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id="map" class="map"></div>
<script>
var vectorLayer = new ol.layer.Vector({
source: new ol.source.Vector()
});
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
vectorLayer
],
target: 'map',
view: new ol.View({
center: ol.proj.fromLonLat([0, 52]),
maxZoom: 20,
zoom: 12,
}),
});
var vectorSource = vectorLayer.getSource();
var centerLongitudeLatitude = map.getView().getCenter();
var viewProjection = map.getView().getProjection();
var pointResolution = ol.proj.getPointResolution(viewProjection, 1, centerLongitudeLatitude);
console.log('pointResolution', pointResolution);
var circle;
function addCirclePolygon(coordinates, radius=1600) {
var _radius = radius/pointResolution;
circle = new ol.Feature(new ol.geom.Circle(coordinates, _radius));
circle.setStyle(new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'blue',
width: 3
}),
fill: new ol.style.Fill({
color: 'rgba(0, 0, 255, 0.1)'
})
}));
var geom=circle.get('geometry');
if (circle instanceof ol.geom.Circle) {
circle.set('geometry', fromCircle(geom));
}
vectorSource.addFeature(circle);
}
addCirclePolygon(centerLongitudeLatitude);
map.on(
'click',
function (event) {
var point1 = event.coordinate;
var point2 = circle.getGeometry().getClosestPoint(point1);
console.log(point1, point2);
var line = new ol.Feature(new ol.geom.LineString([point1, point2]));
vectorSource.addFeature(line);
var dx = point1[0] - point2[0];
var dy = point1[1] - point2[1];
var meters = Math.sqrt(dx * dx + dy * dy) * pointResolution;
console.log('meters to edge = ' + meters);
var dx = point1[0] - centerLongitudeLatitude[0];
var dy = point1[1] - centerLongitudeLatitude[1];
var toCenter = Math.sqrt(dx * dx + dy * dy) * pointResolution;
console.log('to center = ' + toCenter);
}
);
</script>
</body>
</html>

How to rotate cubee by quaternion in three.js?

I have some problems with understanding of how to rotate the figure by a quaternion. Can somebody please explain how to do it? In function render I want to rotate cubes by quaternions
function main() {
const canvas = document.querySelector('#c');
const renderer = new THREE.WebGLRenderer({canvas});
const fov = 100;
const aspect = 2; // the canvas default
const near = 0.1;
const far = 5;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.z = 3;
const scene = new THREE.Scene();
{
const color = 0xFFFFFF;
const intensity = 1;
const light = new THREE.DirectionalLight(color, intensity);
light.position.set(-1, 2, 4);
scene.add(light);
}
function makeInstance(color, x, width, height, depth) {
const material = new THREE.MeshPhongMaterial({color});
const geometry = new THREE.BoxGeometry(width, height, depth);
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
cube.position.x = x;
return cube;
}
const cubes = [
makeInstance(0x8844aa, -2, 3, 1, 1),
makeInstance(0xaa8844, 0.5, 2, 1, 1),
];
function resizeRendererToDisplaySize(renderer) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
function render(time) {
time *= 0.001;
if (resizeRendererToDisplaySize(renderer)) {
const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
// cubes.forEach((cube, ndx) => {
//const speed = 1 + ndx * .1;
//const rot = time * speed;
//cube.rotation.x = rot;
//cube.rotation.y = rot;
//});
renderer.render(scene, camera);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
main();
You have an Object3d (Points, Lines, Meshes, etc.) that you want to rotate via quaternions. You have a mesh (the cube). The immediate answer is to:
cube.applyQuaternion(myquat);
And where does myquat come from? Probably from one of these:
myquat = new THREE.Quaternion(); // now, Probably from one of these:
myquat.setFromAxisAngle ( axis : Vector3, angle : Float )
myquat.setFromEuler ( euler : Euler )
myquat.setFromRotationMatrix ( m : Matrix4 )
myquat.setFromUnitVectors ( vFrom : Vector3, vTo : Vector3 )
I hope this gives you a start, even to ask a more specific question.

Create a SVG object with a arrow line Highcharts

I need to draw a arrow line pointing to a particular point in my highcharts.
I was able to get the line drawn but not sure how to have a arrow before that being displayed.
Here is my fiddle and code.
http://jsfiddle.net/48kyq3wq/1/
$.getJSON('https://www.highcharts.com/samples/data/jsonp.php?filename=usdeur.json&callback=?', function(data) {
var callout = function(chart) {
$('.cO').remove();
var xAxis = chart.xAxis[0],
yAxis = chart.yAxis[0],
point = chart.series[0].data[100],
lineXLength = 100,
lineYLength = -50;
chart.renderer.path(['M', xAxis.toPixels(point.x), yAxis.toPixels(point.y), 'L', xAxis.toPixels(point.x) + lineXLength, yAxis.toPixels(point.y) + lineYLength,]).attr({
'stroke-width': 5,
stroke: 'red',
zIndex: 0
}).addClass('C0').add();
chart.renderer.label('Custom label', xAxis.toPixels(point.x) + lineXLength, yAxis.toPixels(point.y) + lineYLength - 22, 'rect')
.css({
color: '#FFFFFF'
})
.attr({
fill: 'rgba(0, 0, 0, 0.75)',
padding: 8,
r: 5,
width: 100,
height: 30,
zIndex: 6
}).addClass('cO')
.add();
};
Highcharts.chart('container', {
chart: {
events: {
load: function() {
callout(this);
},
redraw: function() {
callout(this);
}
}
},
xAxis: {
type: 'datetime'
},
legend: {
enabled: false
},
series: [{
data: data
}]
});
});
You need to create an arrow and rotate it depending on the position of point and the label.
Create a path which connects the label and the point
const x0 = label.x;
const y0 = label.y + label.height / 2;
const x1 = x;
const y1 = y;
const path = chart.renderer.path([
'M', label.x, label.y + label.height / 2,
'L', x, y,
]).attr({
'stroke-width': 1,
stroke: 'black',
zIndex: 6
}).add()
Create a method for rotating points. It will rotate the point around the top point of the arrow
function rotatePoint(c, angle, p) {
const sin = Math.sin(angle);
const cos = Math.cos(angle);
const x = p[0] - c[0];
const y = p[1] - c[1];
const nx = x * cos - y * sin;
const ny = x * sin + y * cos;
return [nx + c[0], ny + c[1]];
}
Create an arrow, find the angle between the label and the point and rotate the arrow according to the angle.
const array = [[x1 - 5, y1 - 15], [x1 + 5, y1 - 15], [x1, y1], [x1 - 5, y1- 15]]
const angle = Math.atan2(y0 - y1, x0 - x1) + 90 * Math.PI / 180;
const ma = array.map(point => rotatePoint(array[2], angle, point));
Render the arrow
const arrow = chart.renderer.path({
fill: 'black',
zIndex: 6,
d: ['M', ma[0].join(' '), 'L', ma[1].join(' '), ma[2].join(' '), ma[3].join(' ')].join(' ')
}).add()
You should also consider cases when the point is on the right of the label and the top of the label - rotation and calculation of the angle stay the same but connecting the point with the label needs to be adjusted.
Live example and output
http://jsfiddle.net/savpscya/

Openlayers - Route (linestring) behind of polygon after click

I have a LineString and some points on it as Polygon. When I click on the yellow line, than the green polygon gets rendered behind the line. I would like to disable the click on the line.
Here is a picture about my problem
http://i57.tinypic.com/2rc3kg3.png
Here is a code snipet:
function PointDrawing(Lon, Lat, VectorLayer)
{
var circlreFeatureStyle = new OpenLayers.Style();
circlreFeatureStyle.fillColor = '#009900';
circlreFeatureStyle.fillOpacity =0.8
circlreFeatureStyle.strokeColor = '#004F00';
var circle = OpenLayers.Geometry.Polygon.createRegularPolygon(
new OpenLayers.Geometry.Point(Lon, Lat),
(1 * 15),
30
);
circleFeature = new OpenLayers.Feature.Vector(circle);
circleFeature.style = circlreFeatureStyle;
VectorLayer.addFeatures(circleFeature);
}
function LineDrawing(Map,VectorLayer)
{
var line = new OpenLayers.Geometry.LineString(points);
var style = {
strokeColor: 'yellow',
strokeOpacity: 4.5,
strokeWidth: 5
};
var lineFeature = new OpenLayers.Feature.Vector(line, null, style);
VectorLayer.removeAllFeatures();
VectorLayer.addFeatures([lineFeature]);
}

Problems when interactively resizing and moving svg rectangles with D3

I am trying to create panel components that will hold some visualizations.
I am making the panel component with svgs. They look ok, but I am getting some weird behavior when resizing and moving the panels.
var groups = ["uno", "dos", "tres", "cuatro"];
var w = 350;
var x = 0;
var y = 0;
var width = 800;
var h = 200;
var height = 800;
var val = [];
var drag = d3.behavior.drag()
.origin(Object)
.on("drag", move);
var resize = d3.behavior.drag()
.origin(Object)
.on("drag", dragResize);
svg = d3.select("body").append("div").append("svg");
charts = svg.selectAll("g.chart")
.data(groups); //(dims);
box = charts.enter()
.append("g").classed("chart", true)
.attr("id", function(d,i) { return "box"+i})
//.data([{x: 95, y: 0}]);
box.append("rect").classed("box", true)
var t = box.append("rect").classed("titleBox", true)
t.call(drag);
box.append("text").classed("title", true).data(groups)
box.append("text").classed("legend", true).data(groups)
box.append("rect").classed("icon", true)
.call(resize);
box.selectAll("rect.box")
.data([{x: 95, y: 0}])
.attr({
x: function(d) { return d.x; },
y: function(d) { return d.y; },
width: w,
height: function(d) { return 200}//d.length*30 + 60}
})
box.selectAll("rect.titleBox")
.classed("drag", true)
.data([{x: 95, y: 0}])
.attr({
x: function(d) { return d.x; },
y: function(d) { return d.y; },
width: w,
height: 25,
fill: "#000000"
})
box.selectAll("text.title")
.attr({
x: 105,
y: 20,
width: 350,
height: 25,
fill: "#ffffff"
})
.text(function(d) {
console.log("i from title "+ d);
return d;
})
box.selectAll("text.legend")
.attr({
x: 105,
y: 45,
width: 200,
height: 25,
fill: "#999999"
})
.text(function(d) {
return d;
})
box.selectAll("rect.icon")
.data([{x: 429, y: 184}])
.attr({
x: function(d) { return d.x; },
y: function(d) { return d.y; },
width: 16,
height: 16,
fill: "#999999"
})
var dx = 429;
var dy = 184;
function move(){
var dragTarget = d3.select(this);
var dragObject = d3.select(this.parentNode);
console.log("move x:"+x+" y:"+y);
//console.log("d3.event.x:"+d3.event.x+" d3.event.y:"+d3.event.y);
x += d3.event.x - parseInt(dragTarget.attr('x'));
y += d3.event.y - parseInt(dragTarget.attr("y"));
console.log("x:"+x+" y:"+y);
dragObject
.attr("transform", "translate(" + x + "," + y + ")")
};
function dragResize(){
var dragx = Math.max(dx + (16/2), Math.min(w, dx + width + d3.event.dx));
var dragy = Math.max(dy + (16/2), Math.min(h, dy + height + d3.event.dy));
//console.log("resize x:"+x+" y:"+y);
console.log("d3.event.x:"+d3.event.dx+" d3.event.y:"+d3.event.dy);
var dragTarget = d3.select(this);
var dragObject = d3.select(this.parentNode);
var o = dragObject.select("rect.box");
var o1 = dragObject.select("rect.titleBox");
var oldx = dx;
var oldy = dy;
dx = Math.max(0, Math.min(dx + width - (16 / 2), d3.event.x));
dy = Math.max(0, Math.min(dy + height - (16 ), d3.event.y));
w = w - (oldx - dx);
h = h - (oldy - dy);
dragTarget
.attr("x", function(d) { return dragx - (16/2) })
.attr("y", function(d) { return dragy - (16) })
o.attr("width", w)
.attr("height", h);
o1.attr("width", w);
};
I have posted the code at http://jsfiddle.net/dtqY5/
The problem is the following: I can move each panel, by dragging the title area, with no problem. Howvwer, after I resize any of the panels, I cannot move them anymore. They jump to their original position. The x and y becones NaN, but I cannot understand why.
ANy ideas and suggestions will be welcomed.
D3 uses the drag.origin accessor you provide to calculate an offset. Since the access you provide is just an empty object, this offset is NaN which results in x and y on the event also being NaN.
If you remove drag.origin altogether it uses the current mouse position as the origin which makes the panels jump when you start dragging. If you specify the origin to be the position of the shape being dragged it looks better:
.origin(function() {
var current = d3.select(this);
return {x: current.attr("x"), y: current.attr("y") };
})
Here's an updated fiddle: http://jsfiddle.net/4nvhc/

Resources