Merge pull request #1514 from twpayne/vector-api-circle
[vector-api] Add ol.geom.Circle
This commit is contained in:
@@ -2,6 +2,7 @@ goog.require('ol.Feature');
|
|||||||
goog.require('ol.Map');
|
goog.require('ol.Map');
|
||||||
goog.require('ol.RendererHint');
|
goog.require('ol.RendererHint');
|
||||||
goog.require('ol.View2D');
|
goog.require('ol.View2D');
|
||||||
|
goog.require('ol.geom.Circle');
|
||||||
goog.require('ol.layer.Tile');
|
goog.require('ol.layer.Tile');
|
||||||
goog.require('ol.layer.Vector');
|
goog.require('ol.layer.Vector');
|
||||||
goog.require('ol.source.GeoJSON');
|
goog.require('ol.source.GeoJSON');
|
||||||
@@ -71,6 +72,15 @@ var styles = {
|
|||||||
color: 'magenta'
|
color: 'magenta'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
})],
|
||||||
|
'Circle': [new ol.style.Style({
|
||||||
|
stroke: new ol.style.Stroke({
|
||||||
|
color: 'red',
|
||||||
|
width: 2
|
||||||
|
}),
|
||||||
|
fill: new ol.style.Fill({
|
||||||
|
color: 'rgba(255,0,0,0.2)'
|
||||||
|
})
|
||||||
})]
|
})]
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -164,6 +174,8 @@ var vectorSource = new ol.source.GeoJSON(
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
vectorSource.addFeature(new ol.Feature(new ol.geom.Circle([5e6, 7e6], 1e6)));
|
||||||
|
|
||||||
var vectorLayer = new ol.layer.Vector({
|
var vectorLayer = new ol.layer.Vector({
|
||||||
source: vectorSource,
|
source: vectorSource,
|
||||||
styleFunction: styleFunction
|
styleFunction: styleFunction
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// FIXME use an ol.geom.Circle to display a circle with accuracy
|
||||||
|
// FIXME this circle will need to compensate for the pointResolution of the
|
||||||
|
// FIXME EPSG:3857 projection
|
||||||
|
|
||||||
goog.require('ol.Geolocation');
|
goog.require('ol.Geolocation');
|
||||||
goog.require('ol.Map');
|
goog.require('ol.Map');
|
||||||
goog.require('ol.Overlay');
|
goog.require('ol.Overlay');
|
||||||
|
|||||||
@@ -153,6 +153,19 @@ ol.format.GeoJSON.writeGeometry_ = function(geometry) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ol.geom.Geometry} geometry Geometry.
|
||||||
|
* @private
|
||||||
|
* @return {GeoJSONGeometryCollection} Empty GeoJSON geometry collection.
|
||||||
|
*/
|
||||||
|
ol.format.GeoJSON.writeEmptyGeometryCollectionGeometry_ = function(geometry) {
|
||||||
|
return /** @type {GeoJSONGeometryCollection} */ ({
|
||||||
|
'type': 'GeometryCollection',
|
||||||
|
'geometries': []
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {ol.geom.Geometry} geometry Geometry.
|
* @param {ol.geom.Geometry} geometry Geometry.
|
||||||
* @private
|
* @private
|
||||||
@@ -283,7 +296,8 @@ ol.format.GeoJSON.GEOMETRY_WRITERS_ = {
|
|||||||
'MultiPoint': ol.format.GeoJSON.writeMultiPointGeometry_,
|
'MultiPoint': ol.format.GeoJSON.writeMultiPointGeometry_,
|
||||||
'MultiLineString': ol.format.GeoJSON.writeMultiLineStringGeometry_,
|
'MultiLineString': ol.format.GeoJSON.writeMultiLineStringGeometry_,
|
||||||
'MultiPolygon': ol.format.GeoJSON.writeMultiPolygonGeometry_,
|
'MultiPolygon': ol.format.GeoJSON.writeMultiPolygonGeometry_,
|
||||||
'GeometryCollection': ol.format.GeoJSON.writeGeometryCollectionGeometry_
|
'GeometryCollection': ol.format.GeoJSON.writeGeometryCollectionGeometry_,
|
||||||
|
'Circle': ol.format.GeoJSON.writeEmptyGeometryCollectionGeometry_
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
@exportSymbol ol.geom.Circle
|
||||||
|
@exportProperty ol.geom.Circle.prototype.clone
|
||||||
|
@exportProperty ol.geom.Circle.prototype.getCenter
|
||||||
|
@exportProperty ol.geom.Circle.prototype.getExtent
|
||||||
|
@exportProperty ol.geom.Circle.prototype.getRadius
|
||||||
|
@exportProperty ol.geom.Circle.prototype.getSimplifiedGeometry
|
||||||
|
@exportProperty ol.geom.Circle.prototype.getType
|
||||||
|
@exportProperty ol.geom.Circle.prototype.setCenter
|
||||||
|
@exportProperty ol.geom.Circle.prototype.setCenterAndRadius
|
||||||
|
@exportProperty ol.geom.Circle.prototype.setRadius
|
||||||
|
@exportProperty ol.geom.Circle.prototype.transform
|
||||||
@@ -0,0 +1,197 @@
|
|||||||
|
goog.provide('ol.geom.Circle');
|
||||||
|
|
||||||
|
goog.require('goog.asserts');
|
||||||
|
goog.require('ol.extent');
|
||||||
|
goog.require('ol.geom.GeometryType');
|
||||||
|
goog.require('ol.geom.SimpleGeometry');
|
||||||
|
goog.require('ol.geom.flat');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @extends {ol.geom.SimpleGeometry}
|
||||||
|
* @param {ol.geom.RawPoint} center Center.
|
||||||
|
* @param {number=} opt_radius Radius.
|
||||||
|
* @param {ol.geom.GeometryLayout=} opt_layout Layout.
|
||||||
|
*/
|
||||||
|
ol.geom.Circle = function(center, opt_radius, opt_layout) {
|
||||||
|
goog.base(this);
|
||||||
|
var radius = goog.isDef(opt_radius) ? opt_radius : 0;
|
||||||
|
this.setCenterAndRadius(center, radius, opt_layout);
|
||||||
|
};
|
||||||
|
goog.inherits(ol.geom.Circle, ol.geom.SimpleGeometry);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
ol.geom.Circle.prototype.clone = function() {
|
||||||
|
var circle = new ol.geom.Circle(null);
|
||||||
|
circle.setFlatCoordinates(this.layout, this.flatCoordinates.slice());
|
||||||
|
return circle;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
ol.geom.Circle.prototype.closestPointXY =
|
||||||
|
function(x, y, closestPoint, minSquaredDistance) {
|
||||||
|
var flatCoordinates = this.flatCoordinates;
|
||||||
|
var radius = flatCoordinates[this.stride] - flatCoordinates[0];
|
||||||
|
var dx = x - flatCoordinates[0];
|
||||||
|
var dy = y - flatCoordinates[1];
|
||||||
|
var d = Math.sqrt(dx * dx + dy * dy);
|
||||||
|
var distance = Math.max(d, 0);
|
||||||
|
var squaredDistance = distance * distance;
|
||||||
|
if (squaredDistance < minSquaredDistance) {
|
||||||
|
if (d === 0) {
|
||||||
|
closestPoint[0] = flatCoordinates[0];
|
||||||
|
closestPoint[1] = flatCoordinates[1];
|
||||||
|
} else {
|
||||||
|
var delta = radius / d;
|
||||||
|
closestPoint[0] = flatCoordinates[0] + delta * dx;
|
||||||
|
closestPoint[1] = flatCoordinates[1] + delta * dy;
|
||||||
|
}
|
||||||
|
return squaredDistance;
|
||||||
|
} else {
|
||||||
|
return minSquaredDistance;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
ol.geom.Circle.prototype.containsXY = function(x, y) {
|
||||||
|
var flatCoordinates = this.flatCoordinates;
|
||||||
|
var dx = x - flatCoordinates[0];
|
||||||
|
var dy = y - flatCoordinates[1];
|
||||||
|
var r = flatCoordinates[this.stride] - flatCoordinates[0];
|
||||||
|
return dx * dx + dy * dy <= r;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {ol.geom.RawPoint} Center.
|
||||||
|
*/
|
||||||
|
ol.geom.Circle.prototype.getCenter = function() {
|
||||||
|
return this.flatCoordinates.slice(0, this.stride);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
ol.geom.Circle.prototype.getExtent = function(opt_extent) {
|
||||||
|
if (this.extentRevision != this.revision) {
|
||||||
|
var flatCoordinates = this.flatCoordinates;
|
||||||
|
var radius = flatCoordinates[this.stride] - flatCoordinates[0];
|
||||||
|
this.extent = ol.extent.createOrUpdate(
|
||||||
|
flatCoordinates[0] - radius, flatCoordinates[1] - radius,
|
||||||
|
flatCoordinates[0] + radius, flatCoordinates[1] + radius,
|
||||||
|
this.extent);
|
||||||
|
this.extentRevision = this.revision;
|
||||||
|
}
|
||||||
|
goog.asserts.assert(goog.isDef(this.extent));
|
||||||
|
return ol.extent.returnOrUpdate(this.extent, opt_extent);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {number} Radius.
|
||||||
|
*/
|
||||||
|
ol.geom.Circle.prototype.getRadius = function() {
|
||||||
|
var dx = this.flatCoordinates[this.stride] - this.flatCoordinates[0];
|
||||||
|
var dy = this.flatCoordinates[this.stride + 1] - this.flatCoordinates[1];
|
||||||
|
return Math.sqrt(dx * dx + dy * dy);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
ol.geom.Circle.prototype.getSimplifiedGeometry = function(squaredTolerance) {
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
ol.geom.Circle.prototype.getType = function() {
|
||||||
|
return ol.geom.GeometryType.CIRCLE;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ol.geom.RawPoint} center Center.
|
||||||
|
*/
|
||||||
|
ol.geom.Circle.prototype.setCenter = function(center) {
|
||||||
|
var stride = this.stride;
|
||||||
|
goog.asserts.assert(center.length == stride);
|
||||||
|
var radius = this.flatCoordinates[stride] - this.flatCoordinates[0];
|
||||||
|
var flatCoordinates = center.slice();
|
||||||
|
flatCoordinates[stride] = flatCoordinates[0] + radius;
|
||||||
|
var i;
|
||||||
|
for (i = 1; i < stride; ++i) {
|
||||||
|
flatCoordinates[stride + i] = center[i];
|
||||||
|
}
|
||||||
|
this.setFlatCoordinates(this.layout, flatCoordinates);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ol.geom.RawPoint} center Center.
|
||||||
|
* @param {number} radius Radius.
|
||||||
|
* @param {ol.geom.GeometryLayout=} opt_layout Layout.
|
||||||
|
*/
|
||||||
|
ol.geom.Circle.prototype.setCenterAndRadius =
|
||||||
|
function(center, radius, opt_layout) {
|
||||||
|
if (goog.isNull(center)) {
|
||||||
|
this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null);
|
||||||
|
} else {
|
||||||
|
this.setLayout(opt_layout, center, 0);
|
||||||
|
if (goog.isNull(this.flatCoordinates)) {
|
||||||
|
this.flatCoordinates = [];
|
||||||
|
}
|
||||||
|
var flatCoordinates = this.flatCoordinates;
|
||||||
|
var offset = ol.geom.flat.deflateCoordinate(
|
||||||
|
flatCoordinates, 0, center, this.stride);
|
||||||
|
flatCoordinates[offset++] = flatCoordinates[0] + radius;
|
||||||
|
var i, ii;
|
||||||
|
for (i = 1, ii = this.stride; i < ii; ++i) {
|
||||||
|
flatCoordinates[offset++] = flatCoordinates[i];
|
||||||
|
}
|
||||||
|
flatCoordinates.length = offset;
|
||||||
|
this.dispatchChangeEvent();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ol.geom.GeometryLayout} layout Layout.
|
||||||
|
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||||
|
*/
|
||||||
|
ol.geom.Circle.prototype.setFlatCoordinates =
|
||||||
|
function(layout, flatCoordinates) {
|
||||||
|
this.setFlatCoordinatesInternal(layout, flatCoordinates);
|
||||||
|
this.dispatchChangeEvent();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number} radius Radius.
|
||||||
|
*/
|
||||||
|
ol.geom.Circle.prototype.setRadius = function(radius) {
|
||||||
|
goog.asserts.assert(!goog.isNull(this.flatCoordinates));
|
||||||
|
this.flatCoordinates[this.stride] = this.flatCoordinates[0] + radius;
|
||||||
|
this.dispatchChangeEvent();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
ol.geom.Circle.prototype.transform = goog.abstractMethod;
|
||||||
@@ -18,7 +18,8 @@ ol.geom.GeometryType = {
|
|||||||
MULTI_POINT: 'MultiPoint',
|
MULTI_POINT: 'MultiPoint',
|
||||||
MULTI_LINE_STRING: 'MultiLineString',
|
MULTI_LINE_STRING: 'MultiLineString',
|
||||||
MULTI_POLYGON: 'MultiPolygon',
|
MULTI_POLYGON: 'MultiPolygon',
|
||||||
GEOMETRY_COLLECTION: 'GeometryCollection'
|
GEOMETRY_COLLECTION: 'GeometryCollection',
|
||||||
|
CIRCLE: 'Circle'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -263,6 +263,39 @@ ol.render.canvas.Immediate.prototype.drawAsync = function(zIndex, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
ol.render.canvas.Immediate.prototype.drawCircleGeometry =
|
||||||
|
function(circleGeometry, data) {
|
||||||
|
/*
|
||||||
|
if (!ol.extent.intersects(this.extent_, circleGeometry.getExtent())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var state = this.state_;
|
||||||
|
if (!goog.isDef(state.fillStyle) && !goog.isDef(state.strokeStyle)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.setFillStrokeStyles_();
|
||||||
|
var context = this.context_;
|
||||||
|
var pixelCoordinates = ol.geom.transformSimpleGeometry2D(
|
||||||
|
circleGeometry, this.transform_, this.pixelCoordinates_);
|
||||||
|
var dx = pixelCoordinates[2] - pixelCoordinates[0];
|
||||||
|
var dy = pixelCoordinates[3] - pixelCoordinates[1];
|
||||||
|
var radius = Math.sqrt(dx * dx + dy * dy);
|
||||||
|
context.beginPath();
|
||||||
|
context.arc(pixelCoordinates[0], pixelCoordinates[1], radius, 0, 2 * Math.PI);
|
||||||
|
if (goog.isDef(state.fillStyle)) {
|
||||||
|
context.fill();
|
||||||
|
}
|
||||||
|
if (goog.isDef(state.strokeStyle)) {
|
||||||
|
goog.asserts.assert(goog.isDef(state.lineWidth));
|
||||||
|
context.stroke();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
@@ -597,5 +630,6 @@ ol.render.canvas.Immediate.GEOMETRY_RENDERES_ = {
|
|||||||
ol.render.canvas.Immediate.prototype.drawMultiLineStringGeometry,
|
ol.render.canvas.Immediate.prototype.drawMultiLineStringGeometry,
|
||||||
'MultiPolygon': ol.render.canvas.Immediate.prototype.drawMultiPolygonGeometry,
|
'MultiPolygon': ol.render.canvas.Immediate.prototype.drawMultiPolygonGeometry,
|
||||||
'GeometryCollection':
|
'GeometryCollection':
|
||||||
ol.render.canvas.Immediate.prototype.drawGeometryCollectionGeometry
|
ol.render.canvas.Immediate.prototype.drawGeometryCollectionGeometry,
|
||||||
|
'Circle': ol.render.canvas.Immediate.prototype.drawCircleGeometry
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -27,14 +27,15 @@ goog.require('ol.vec.Mat4');
|
|||||||
ol.render.canvas.Instruction = {
|
ol.render.canvas.Instruction = {
|
||||||
BEGIN_GEOMETRY: 0,
|
BEGIN_GEOMETRY: 0,
|
||||||
BEGIN_PATH: 1,
|
BEGIN_PATH: 1,
|
||||||
CLOSE_PATH: 2,
|
CIRCLE: 2,
|
||||||
DRAW_IMAGE: 3,
|
CLOSE_PATH: 3,
|
||||||
END_GEOMETRY: 4,
|
DRAW_IMAGE: 4,
|
||||||
FILL: 5,
|
END_GEOMETRY: 5,
|
||||||
MOVE_TO_LINE_TO: 6,
|
FILL: 6,
|
||||||
SET_FILL_STYLE: 7,
|
MOVE_TO_LINE_TO: 7,
|
||||||
SET_STROKE_STYLE: 8,
|
SET_FILL_STYLE: 8,
|
||||||
STROKE: 9
|
SET_STROKE_STYLE: 9,
|
||||||
|
STROKE: 10
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -178,7 +179,7 @@ ol.render.canvas.Replay.prototype.replay_ =
|
|||||||
}
|
}
|
||||||
var i = 0; // instruction index
|
var i = 0; // instruction index
|
||||||
var ii = instructions.length; // end of instructions
|
var ii = instructions.length; // end of instructions
|
||||||
var d; // data index
|
var d = 0; // data index
|
||||||
var dd; // end of per-instruction data
|
var dd; // end of per-instruction data
|
||||||
var localTransform = this.tmpLocalTransform_;
|
var localTransform = this.tmpLocalTransform_;
|
||||||
while (i < ii) {
|
while (i < ii) {
|
||||||
@@ -198,6 +199,18 @@ ol.render.canvas.Replay.prototype.replay_ =
|
|||||||
context.beginPath();
|
context.beginPath();
|
||||||
++i;
|
++i;
|
||||||
break;
|
break;
|
||||||
|
case ol.render.canvas.Instruction.CIRCLE:
|
||||||
|
var x1 = pixelCoordinates[d];
|
||||||
|
var y1 = pixelCoordinates[d + 1];
|
||||||
|
var x2 = pixelCoordinates[d + 2];
|
||||||
|
var y2 = pixelCoordinates[d + 3];
|
||||||
|
var dx = x2 - x1;
|
||||||
|
var dy = y2 - y1;
|
||||||
|
var r = Math.sqrt(dx * dx + dy * dy);
|
||||||
|
context.arc(x1, y1, r, 0, 2 * Math.PI, true);
|
||||||
|
d += 4;
|
||||||
|
++i;
|
||||||
|
break;
|
||||||
case ol.render.canvas.Instruction.CLOSE_PATH:
|
case ol.render.canvas.Instruction.CLOSE_PATH:
|
||||||
context.closePath();
|
context.closePath();
|
||||||
++i;
|
++i;
|
||||||
@@ -379,6 +392,12 @@ ol.render.canvas.Replay.prototype.reverseHitDetectionInstructions_ =
|
|||||||
ol.render.canvas.Replay.prototype.drawAsync = goog.abstractMethod;
|
ol.render.canvas.Replay.prototype.drawAsync = goog.abstractMethod;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
ol.render.canvas.Replay.prototype.drawCircleGeometry = goog.abstractMethod;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
@@ -997,6 +1016,57 @@ ol.render.canvas.PolygonReplay.prototype.drawFlatCoordinatess_ =
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
ol.render.canvas.PolygonReplay.prototype.drawCircleGeometry =
|
||||||
|
function(circleGeometry, data) {
|
||||||
|
var state = this.state_;
|
||||||
|
goog.asserts.assert(!goog.isNull(state));
|
||||||
|
var fillStyle = state.fillStyle;
|
||||||
|
var strokeStyle = state.strokeStyle;
|
||||||
|
if (!goog.isDef(fillStyle) && !goog.isDef(strokeStyle)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (goog.isDef(strokeStyle)) {
|
||||||
|
goog.asserts.assert(goog.isDef(state.lineWidth));
|
||||||
|
}
|
||||||
|
ol.extent.extend(this.extent_, circleGeometry.getExtent());
|
||||||
|
this.setFillStrokeStyles_();
|
||||||
|
this.beginGeometry(circleGeometry);
|
||||||
|
// always fill the circle for hit detection
|
||||||
|
this.hitDetectionInstructions.push(
|
||||||
|
[ol.render.canvas.Instruction.SET_FILL_STYLE,
|
||||||
|
ol.color.asString(ol.render.canvas.defaultFillStyle)]);
|
||||||
|
if (goog.isDef(state.strokeStyle)) {
|
||||||
|
this.hitDetectionInstructions.push(
|
||||||
|
[ol.render.canvas.Instruction.SET_STROKE_STYLE,
|
||||||
|
state.strokeStyle, state.lineWidth, state.lineCap, state.lineJoin,
|
||||||
|
state.miterLimit, state.lineDash]);
|
||||||
|
}
|
||||||
|
var flatCoordinates = circleGeometry.getFlatCoordinates();
|
||||||
|
var stride = circleGeometry.getStride();
|
||||||
|
this.appendFlatCoordinates(
|
||||||
|
flatCoordinates, 0, flatCoordinates.length, stride, false);
|
||||||
|
var beginPathInstruction = [ol.render.canvas.Instruction.BEGIN_PATH];
|
||||||
|
var circleInstruction = [ol.render.canvas.Instruction.CIRCLE];
|
||||||
|
this.instructions.push(beginPathInstruction, circleInstruction);
|
||||||
|
this.hitDetectionInstructions.push(beginPathInstruction, circleInstruction);
|
||||||
|
this.endGeometry(circleGeometry, data);
|
||||||
|
var fillInstruction = [ol.render.canvas.Instruction.FILL];
|
||||||
|
this.hitDetectionInstructions.push(fillInstruction);
|
||||||
|
if (goog.isDef(state.fillStyle)) {
|
||||||
|
this.instructions.push(fillInstruction);
|
||||||
|
}
|
||||||
|
if (goog.isDef(state.strokeStyle)) {
|
||||||
|
goog.asserts.assert(goog.isDef(state.lineWidth));
|
||||||
|
var strokeInstruction = [ol.render.canvas.Instruction.STROKE];
|
||||||
|
this.instructions.push(strokeInstruction);
|
||||||
|
this.hitDetectionInstructions.push(strokeInstruction);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -19,6 +19,15 @@ ol.render.IRender.prototype.drawAsync = function(zIndex, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ol.geom.Circle} circleGeometry Circle geometry.
|
||||||
|
* @param {Object} data Opaque data object,
|
||||||
|
*/
|
||||||
|
ol.render.IRender.prototype.drawCircleGeometry =
|
||||||
|
function(circleGeometry, data) {
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {ol.Feature} feature Feature.
|
* @param {ol.Feature} feature Feature.
|
||||||
* @param {ol.style.Style} style Style.
|
* @param {ol.style.Style} style Style.
|
||||||
|
|||||||
+26
-1
@@ -1,6 +1,7 @@
|
|||||||
goog.provide('ol.renderer.vector');
|
goog.provide('ol.renderer.vector');
|
||||||
|
|
||||||
goog.require('goog.asserts');
|
goog.require('goog.asserts');
|
||||||
|
goog.require('ol.geom.Circle');
|
||||||
goog.require('ol.geom.GeometryCollection');
|
goog.require('ol.geom.GeometryCollection');
|
||||||
goog.require('ol.geom.LineString');
|
goog.require('ol.geom.LineString');
|
||||||
goog.require('ol.geom.MultiLineString');
|
goog.require('ol.geom.MultiLineString');
|
||||||
@@ -12,6 +13,29 @@ goog.require('ol.render.IReplayGroup');
|
|||||||
goog.require('ol.style.Style');
|
goog.require('ol.style.Style');
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ol.render.IReplayGroup} replayGroup Replay group.
|
||||||
|
* @param {ol.geom.Geometry} geometry Geometry.
|
||||||
|
* @param {ol.style.Style} style Style.
|
||||||
|
* @param {Object} data Opaque data object.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
ol.renderer.vector.renderCircleGeometry_ =
|
||||||
|
function(replayGroup, geometry, style, data) {
|
||||||
|
var fillStyle = style.getFill();
|
||||||
|
var strokeStyle = style.getStroke();
|
||||||
|
if (goog.isNull(fillStyle) && goog.isNull(strokeStyle)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
goog.asserts.assertInstanceof(geometry, ol.geom.Circle);
|
||||||
|
var circleGeometry = /** @type {ol.geom.Circle} */ (geometry);
|
||||||
|
var replay = replayGroup.getReplay(
|
||||||
|
style.getZIndex(), ol.render.ReplayType.POLYGON);
|
||||||
|
replay.setFillStrokeStyle(fillStyle, strokeStyle);
|
||||||
|
replay.drawCircleGeometry(circleGeometry, data);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {ol.render.IReplayGroup} replayGroup Replay group.
|
* @param {ol.render.IReplayGroup} replayGroup Replay group.
|
||||||
* @param {ol.Feature} feature Feature.
|
* @param {ol.Feature} feature Feature.
|
||||||
@@ -196,5 +220,6 @@ ol.renderer.vector.GEOMETRY_RENDERERS_ = {
|
|||||||
'MultiPoint': ol.renderer.vector.renderMultiPointGeometry_,
|
'MultiPoint': ol.renderer.vector.renderMultiPointGeometry_,
|
||||||
'MultiLineString': ol.renderer.vector.renderMultiLineStringGeometry_,
|
'MultiLineString': ol.renderer.vector.renderMultiLineStringGeometry_,
|
||||||
'MultiPolygon': ol.renderer.vector.renderMultiPolygonGeometry_,
|
'MultiPolygon': ol.renderer.vector.renderMultiPolygonGeometry_,
|
||||||
'GeometryCollection': ol.renderer.vector.renderGeometryCollectionGeometry_
|
'GeometryCollection': ol.renderer.vector.renderGeometryCollectionGeometry_,
|
||||||
|
'Circle': ol.renderer.vector.renderCircleGeometry_
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,6 +20,14 @@ ol.render.webgl.Immediate.prototype.drawAsync = function(zIndex, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
ol.render.webgl.Immediate.prototype.drawCircleGeometry =
|
||||||
|
function(circleGeometry, data) {
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -458,6 +458,16 @@ describe('ol.format.GeoJSON', function() {
|
|||||||
expect(geometries[i].getCoordinates()).
|
expect(geometries[i].getCoordinates()).
|
||||||
to.eql(gotGeometries[i].getCoordinates());
|
to.eql(gotGeometries[i].getCoordinates());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('encodes a circle as an empty geometry collection', function() {
|
||||||
|
var circle = new ol.geom.Circle([0, 0], 1);
|
||||||
|
var geojson = format.writeGeometry(circle);
|
||||||
|
expect(geojson).to.eql({
|
||||||
|
'type': 'GeometryCollection',
|
||||||
|
'geometries': []
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
@@ -468,6 +478,7 @@ describe('ol.format.GeoJSON', function() {
|
|||||||
goog.require('ol.Feature');
|
goog.require('ol.Feature');
|
||||||
goog.require('ol.extent');
|
goog.require('ol.extent');
|
||||||
goog.require('ol.format.GeoJSON');
|
goog.require('ol.format.GeoJSON');
|
||||||
|
goog.require('ol.geom.Circle');
|
||||||
goog.require('ol.geom.GeometryCollection');
|
goog.require('ol.geom.GeometryCollection');
|
||||||
goog.require('ol.geom.LineString');
|
goog.require('ol.geom.LineString');
|
||||||
goog.require('ol.geom.LinearRing');
|
goog.require('ol.geom.LinearRing');
|
||||||
|
|||||||
@@ -0,0 +1,192 @@
|
|||||||
|
goog.provide('ol.test.geom.Circle');
|
||||||
|
|
||||||
|
|
||||||
|
describe('ol.geom.Circle', function() {
|
||||||
|
|
||||||
|
describe('with a unit circle', function() {
|
||||||
|
|
||||||
|
var circle;
|
||||||
|
beforeEach(function() {
|
||||||
|
circle = new ol.geom.Circle([0, 0], 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#clone', function() {
|
||||||
|
|
||||||
|
it('returns a clone', function() {
|
||||||
|
var clone = circle.clone();
|
||||||
|
expect(clone).to.be.an(ol.geom.Circle);
|
||||||
|
expect(clone.getCenter()).to.eql(circle.getCenter());
|
||||||
|
expect(clone.getCenter()).not.to.be(circle.getCenter());
|
||||||
|
expect(clone.getRadius()).to.be(circle.getRadius());
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#containsCoordinate', function() {
|
||||||
|
|
||||||
|
it('contains the center', function() {
|
||||||
|
expect(circle.containsCoordinate([0, 0])).to.be(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('contains points inside the perimeter', function() {
|
||||||
|
expect(circle.containsCoordinate([0.5, 0.5])).to.be(true);
|
||||||
|
expect(circle.containsCoordinate([-0.5, 0.5])).to.be(true);
|
||||||
|
expect(circle.containsCoordinate([-0.5, -0.5])).to.be(true);
|
||||||
|
expect(circle.containsCoordinate([0.5, -0.5])).to.be(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('contains points on the perimeter', function() {
|
||||||
|
expect(circle.containsCoordinate([1, 0])).to.be(true);
|
||||||
|
expect(circle.containsCoordinate([0, 1])).to.be(true);
|
||||||
|
expect(circle.containsCoordinate([-1, 0])).to.be(true);
|
||||||
|
expect(circle.containsCoordinate([0, -1])).to.be(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not contain points outside the perimeter', function() {
|
||||||
|
expect(circle.containsCoordinate([2, 0])).to.be(false);
|
||||||
|
expect(circle.containsCoordinate([1, 1])).to.be(false);
|
||||||
|
expect(circle.containsCoordinate([-2, 0])).to.be(false);
|
||||||
|
expect(circle.containsCoordinate([0, -2])).to.be(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#getCenter', function() {
|
||||||
|
|
||||||
|
it('returns the expected value', function() {
|
||||||
|
expect(circle.getCenter()).to.eql([0, 0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#getClosestPoint', function() {
|
||||||
|
|
||||||
|
it('returns the closest point on the perimeter', function() {
|
||||||
|
var closestPoint;
|
||||||
|
closestPoint = circle.getClosestPoint([2, 0]);
|
||||||
|
expect(closestPoint[0]).to.roughlyEqual(1, 1e-15);
|
||||||
|
expect(closestPoint[1]).to.roughlyEqual(0, 1e-15);
|
||||||
|
closestPoint = circle.getClosestPoint([2, 2]);
|
||||||
|
expect(closestPoint[0]).to.roughlyEqual(Math.sqrt(0.5), 1e-15);
|
||||||
|
expect(closestPoint[1]).to.roughlyEqual(Math.sqrt(0.5), 1e-15);
|
||||||
|
closestPoint = circle.getClosestPoint([0, 2]);
|
||||||
|
expect(closestPoint[0]).to.roughlyEqual(0, 1e-15);
|
||||||
|
expect(closestPoint[1]).to.roughlyEqual(1, 1e-15);
|
||||||
|
closestPoint = circle.getClosestPoint([-2, 2]);
|
||||||
|
expect(closestPoint[0]).to.roughlyEqual(-Math.sqrt(0.5), 1e-15);
|
||||||
|
expect(closestPoint[1]).to.roughlyEqual(Math.sqrt(0.5), 1e-15);
|
||||||
|
closestPoint = circle.getClosestPoint([-2, 0]);
|
||||||
|
expect(closestPoint[0]).to.roughlyEqual(-1, 1e-15);
|
||||||
|
expect(closestPoint[1]).to.roughlyEqual(0, 1e-15);
|
||||||
|
closestPoint = circle.getClosestPoint([-2, -2]);
|
||||||
|
expect(closestPoint[0]).to.roughlyEqual(-Math.sqrt(0.5), 1e-15);
|
||||||
|
expect(closestPoint[1]).to.roughlyEqual(-Math.sqrt(0.5), 1e-15);
|
||||||
|
closestPoint = circle.getClosestPoint([0, -2]);
|
||||||
|
expect(closestPoint[0]).to.roughlyEqual(0, 1e-15);
|
||||||
|
expect(closestPoint[1]).to.roughlyEqual(-1, 1e-15);
|
||||||
|
closestPoint = circle.getClosestPoint([2, -2]);
|
||||||
|
expect(closestPoint[0]).to.roughlyEqual(Math.sqrt(0.5), 1e-15);
|
||||||
|
expect(closestPoint[1]).to.roughlyEqual(-Math.sqrt(0.5), 1e-15);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#getExtent', function() {
|
||||||
|
|
||||||
|
it('returns the expected value', function() {
|
||||||
|
expect(circle.getExtent()).to.eql([-1, -1, 1, 1]);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#getRadius', function() {
|
||||||
|
|
||||||
|
it('returns the expected value', function() {
|
||||||
|
expect(circle.getRadius()).to.be(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#getSimplifiedGeometry', function() {
|
||||||
|
|
||||||
|
it('returns the same geometry', function() {
|
||||||
|
expect(circle.getSimplifiedGeometry(1)).to.be(circle);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#getType', function() {
|
||||||
|
|
||||||
|
it('returns the expected value', function() {
|
||||||
|
expect(circle.getType()).to.be(ol.geom.GeometryType.CIRCLE);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#setCenter', function() {
|
||||||
|
|
||||||
|
it('sets the center', function() {
|
||||||
|
circle.setCenter([1, 2]);
|
||||||
|
expect(circle.getCenter()).to.eql([1, 2]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fires a change event', function() {
|
||||||
|
var spy = sinon.spy();
|
||||||
|
circle.on('change', spy);
|
||||||
|
circle.setCenter([1, 2]);
|
||||||
|
expect(spy.calledOnce).to.be(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#setFlatCoordinates', function() {
|
||||||
|
|
||||||
|
it('sets both center and radius', function() {
|
||||||
|
circle.setFlatCoordinates(ol.geom.GeometryLayout.XY, [1, 2, 4, 2]);
|
||||||
|
expect(circle.getCenter()).to.eql([1, 2]);
|
||||||
|
expect(circle.getRadius()).to.be(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fires a single change event', function() {
|
||||||
|
var spy = sinon.spy();
|
||||||
|
circle.on('change', spy);
|
||||||
|
circle.setFlatCoordinates(ol.geom.GeometryLayout.XY, [1, 2, 4, 2]);
|
||||||
|
expect(spy.calledOnce).to.be(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#setRadius', function() {
|
||||||
|
|
||||||
|
it('sets the radius', function() {
|
||||||
|
circle.setRadius(2);
|
||||||
|
expect(circle.getRadius()).to.be(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fires a change event', function() {
|
||||||
|
var spy = sinon.spy();
|
||||||
|
circle.on('change', spy);
|
||||||
|
circle.setRadius(2);
|
||||||
|
expect(spy.calledOnce).to.be(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#transform', function() {
|
||||||
|
|
||||||
|
it('throws an exception', function() {
|
||||||
|
expect(function() {
|
||||||
|
circle.transform(ol.proj.identityTransform);
|
||||||
|
}).to.throwException();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
goog.require('ol.geom.Circle');
|
||||||
|
goog.require('ol.geom.GeometryType');
|
||||||
|
goog.require('ol.proj');
|
||||||
Reference in New Issue
Block a user