admin管理员组文章数量:1399180
I'm working on a project where we're using OpenLayers3.
We need to give users the ability to draw various features on map. Here is an official example to draw features on map.
We need to draw an ellipse on map but there is not such a functionality given officially. I'm wondering if its possible to customize the circle geometry in such a way that we can draw an ellipse on map.
I'm working on a project where we're using OpenLayers3.
We need to give users the ability to draw various features on map. Here is an official example to draw features on map.
We need to draw an ellipse on map but there is not such a functionality given officially. I'm wondering if its possible to customize the circle geometry in such a way that we can draw an ellipse on map.
Share Improve this question edited Jul 27, 2015 at 7:38 muzaffar asked Jul 27, 2015 at 7:29 muzaffarmuzaffar 1,7361 gold badge16 silver badges28 bronze badges6 Answers
Reset to default 3Draw a circle, convert it to a circular polygon and then scale the x and y directions. Two clicks are sufficient to define the center and radii of an ellipse along the axes. For an oblique ellipse three clicks would be needed, one for the center, and one click for each radius with the third click also setting the rotation.
var raster = new ol.layer.Tile({
source: new ol.source.OSM()
});
var source = new ol.source.Vector({wrapX: false});
var vector = new ol.layer.Vector({
source: source,
});
var map = new ol.Map({
layers: [raster, vector],
target: 'map',
view: new ol.View({
center: [-11000000, 4600000],
zoom: 4
})
});
var typeSelect = document.getElementById('type');
var draw; // global so we can remove it later
function addInteraction() {
var value = typeSelect.value;
var maxPoints;
if (value !== 'None') {
var geometryFunction;
if (value === 'Square') {
value = 'Circle';
geometryFunction = ol.interaction.Draw.createRegularPolygon(4);
} else if (value === 'Box') {
value = 'Circle';
geometryFunction = ol.interaction.Draw.createBox();
} else if (value === 'Star') {
value = 'Circle';
geometryFunction = function(coordinates, geometry) {
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 rotation = Math.atan2(dy, dx);
var newCoordinates = [];
var numPoints = 12;
for (var i = 0; i < numPoints; ++i) {
var angle = rotation + i * 2 * Math.PI / numPoints;
var fraction = i % 2 === 0 ? 1 : 0.5;
var offsetX = radius * fraction * Math.cos(angle);
var offsetY = radius * fraction * Math.sin(angle);
newCoordinates.push([center[0] + offsetX, center[1] + offsetY]);
}
newCoordinates.push(newCoordinates[0].slice());
if (!geometry) {
geometry = new ol.geom.Polygon([newCoordinates]);
} else {
geometry.setCoordinates([newCoordinates]);
}
return geometry;
};
} else if (value === 'Ellipse') {
value = 'Circle';
geometryFunction = function(coordinates, geometry) {
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 = new ol.geom.Circle(center, radius);
var polygon = ol.geom.Polygon.fromCircle(circle, 64);
polygon.scale(dx/radius, dy/radius);
if (!geometry) {
geometry = polygon;
} else {
geometry.setCoordinates(polygon.getCoordinates());
}
return geometry;
};
} else if (value === 'Oblique Ellipse') {
value = 'LineString';
maxPoints = 3;
geometryFunction = function(coordinates, geometry) {
var center = coordinates[0];
var first = coordinates[1];
var dx = center[0] - first[0];
var dy = center[1] - first[1];
var radius1 = Math.sqrt(dx * dx + dy * dy);
if (coordinates.length > 2) {
var last = coordinates[2];
dx = center[0] - last[0];
dy = center[1] - last[1];
}
var radius2 = Math.sqrt(dx * dx + dy * dy);
var rotation = Math.atan2(dy, dx);
var circle = new ol.geom.Circle(center, radius1);
var polygon = ol.geom.Polygon.fromCircle(circle, 64);
polygon.scale(radius2/radius1, 1);
polygon.rotate(rotation, center);
if (!geometry) {
geometry = polygon;
} else {
geometry.setCoordinates(polygon.getCoordinates());
}
return geometry;
};
}
draw = new ol.interaction.Draw({
source: source,
type: value,
maxPoints: maxPoints,
geometryFunction: geometryFunction
});
map.addInteraction(draw);
}
}
/**
* Handle change event.
*/
typeSelect.onchange = function() {
map.removeInteraction(draw);
addInteraction();
};
addInteraction();
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
.map {
width: 100%;
height: 90%;
}
<link href="https://cdn.rawgit./openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet" />
<script src="https://cdn.rawgit./openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<div id="map" class="map"></div>
<form class="form-inline">
<label>Shape type </label>
<select id="type">
<option value="Ellipse">Ellipse</option>
<option value="Oblique Ellipse">Oblique Ellipse</option>
<option value="Circle">Circle</option>
<option value="Square">Square</option>
<option value="Box">Box</option>
<option value="Star">Star</option>
<option value="None">None</option>
</select>
</form>
For people that will search this in the future, I hope that It will help. Working code for creating an ellipse in open layer V5.3:
// this works for a static image (pixels) but the idea can be on any coordinate system
addEllipseFeature(center, semiMajor, semiMinor) {
let coordinates = [] ;
const radinas = Math.PI / 180 ;
for (let angle = 1; angle <= 360; angle ++) {
const px = center[0] + semiMajor * Math.cos(radinas * angle);
const py = center[0] + semiMinor * Math.sin(radinas * angle);
coordinates.push([px, py]);
}
const geoJson = {
'type': 'Feature',
'geometry': {
'type': 'Polygon',
'coordinates': []
}
};
const featureId = source.getFeatures().length;
coordinates = this.convertCoordinates('Polygon', [coordinates]);
geoJson.geometry.coordinates = coordinates ;
const polygonFeature = (new GeoJSON()).readFeature(geoJson);
polygonFeature.setId(featureId );
const layerStyle = [ new Style({
stroke: new Stroke({
color: 'blue',
width: 3
}),
fill: new Fill({
color: 'rgba(0, 0, 255, 0.1)'
})
})];
polygonFeature.setStyle(layerStyle);
source.addFeature(polygonFeature);
return featureId;
}
In the draw interaction you can specify a geometryFunction
as parameter. This function will draw an additional geometry when you're drawing. That's currently what does the draw interaction in Circle
mode, see the code
Have a look to the draw interaction api for more informations.
Most of the mapping systems don't provide an ellipse geometry or feature. I had the same requirement while working with google maps in Android, the way I solve it is using a polygon by calculating the vertices through the parametric equation of the ellipse.
x = h + a * cos(t)
y = k + b *sin(t)
Take a look to this post to see an example.
From Mike's code, worked on OL 6.1.1:
const circle = new Circle(
fromLonLat([longitude, latitude]),
radius
)
// fromCircle is a function inside Polygon class
const ellipse = fromCircle(circle, 100)
ellipse.scale(1, bigRadius / smallRadius)
// OL is counterclockwise rotation
ellipse.rotate(-(angleDegree * Math.PI) / 180, circle.getCenter())
this.yourLayer.getSource().addFeature(
new Feature({
geometry: ellipse
})
)
Regards
Thanks to @Ezri Y I made a Working example and added more functionality.
look here
本文标签: javascriptHow to draw an Ellipse using Openlayers3Stack Overflow
版权声明:本文标题:javascript - How to draw an Ellipse using Openlayers3 - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744213609a2595536.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论