diff --git a/README.md b/README.md index 7745060..e9ad804 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,11 @@ After instantiating the map create a new ellipse. var ellipse = L.ellipse([51.5, -0.09], [500, 100], 90).addTo(map); +Access the typed data via + + import 'leaflet-ellipse/l.ellipse'; + + ## API *Factory method* diff --git a/l.ellipse.d.ts b/l.ellipse.d.ts new file mode 100644 index 0000000..52fc27b --- /dev/null +++ b/l.ellipse.d.ts @@ -0,0 +1,31 @@ +import * as L from 'leaflet' + +declare module 'leaflet' { + + /** + * Creates an ellipse. + * @param latlng The position of the center of the ellipse. + * @param radii The semi-major and semi-minor axis in meters + * @param tilt The rotation of the ellipse in degrees from west + * @param options Options dictionary to pass to L.Path + */ + function ellipse(latlng: number[], radii: number[], tilt: number, options: EllipseOptions): Path.Ellipse; + + interface EllipseOptions extends L.PathOptions { + fill: boolean; + startAngle: number; + endAngle: number; + } + + namespace Path { + class Ellipse extends L.Path { + constructor(options?: EllipseOptions) + + setRadius(radii: number[]): this + getRadius(): L.Point + setTilt(tilt: number): this + getBounds(): L.LatLngBounds + } + + } +} diff --git a/l.ellipse.js b/l.ellipse.js index f4d7ba3..0706978 100644 --- a/l.ellipse.js +++ b/l.ellipse.js @@ -168,10 +168,18 @@ L.Ellipse = L.Path.extend({ }, _getLatRadius: function () { + var simpleCrs = !!this._map.options.crs.infinite; + if(simpleCrs) + return this._mRadiusY; + else return (this._mRadiusY / 40075017) * 360; }, _getLngRadius: function () { + var simpleCrs = !!this._map.options.crs.infinite; + if(simpleCrs) + return this._mRadiusX; + else return ((this._mRadiusX / 40075017) * 360) / Math.cos((Math.PI / 180) * this._latlng.lat); }, diff --git a/l.ellipse.min.js b/l.ellipse.min.js index dbe75cc..90e3fda 100644 --- a/l.ellipse.min.js +++ b/l.ellipse.min.js @@ -1 +1 @@ -L.SVG.include({_updateEllipse:function(a){var c=(a._point,a._radiusX),d=a._radiusY,e=a._tiltDeg,f=a._endPointParams,g="M"+f.x0+","+f.y0+"A"+c+","+d+","+e+","+f.largeArc+","+f.sweep+","+f.x1+","+f.y1+" z";this._setPath(a,g)}}),L.Canvas.include({_updateEllipse:function(a){if(!a._empty()){var b=a._point,c=this._ctx,d=a._radiusX,e=(a._radiusY||d)/d;this._drawnLayers[a._leaflet_id]=a,c.save(),c.translate(b.x,b.y),0!==a._tilt&&c.rotate(a._tilt),1!==e&&c.scale(1,e),c.beginPath(),c.arc(0,0,d,0,2*Math.PI),c.restore(),this._fillStroke(c,a)}}}),L.Ellipse=L.Path.extend({options:{fill:!0,startAngle:0,endAngle:359.9},initialize:function(a,b,c,d){L.setOptions(this,d),this._latlng=L.latLng(a),c?this._tiltDeg=c:this._tiltDeg=0,b&&(this._mRadiusX=b[0],this._mRadiusY=b[1])},setRadius:function(a){return this._mRadiusX=a[0],this._mRadiusY=a[1],this.redraw()},getRadius:function(){return new L.point(this._mRadiusX,this._mRadiusY)},setTilt:function(a){return this._tiltDeg=a,this.redraw()},getBounds:function(){var a=this._getLngRadius(),b=this._getLatRadius(),c=this._latlng;return new L.LatLngBounds([c.lat-b,c.lng-a],[c.lat+b,c.lng+a])},setLatLng:function(a){return this._latlng=L.latLng(a),this.redraw(),this.fire("move",{latlng:this._latlng})},getLatLng:function(){return this._latlng},setStyle:L.Path.prototype.setStyle,_project:function(){var a=this._getLngRadius(),b=this._getLatRadius(),c=this._latlng,d=this._map.latLngToLayerPoint([c.lat,c.lng-a]),e=this._map.latLngToLayerPoint([c.lat-b,c.lng]);this._point=this._map.latLngToLayerPoint(c),this._radiusX=Math.max(this._point.x-d.x,1),this._radiusY=Math.max(e.y-this._point.y,1),this._tilt=Math.PI*this._tiltDeg/180,this._endPointParams=this._centerPointToEndPoint(),this._updateBounds()},_updateBounds:function(){var a=Math.sin(this._tilt),b=Math.cos(this._tilt),c=a*a,d=b*b,e=this._radiusX*this._radiusX,f=this._radiusY*this._radiusY,g=Math.sqrt(e*d+f*c),h=Math.sqrt(e*c+f*d),i=this._clickTolerance(),j=[g+i,h+i];this._pxBounds=new L.Bounds(this._point.subtract(j),this._point.add(j))},_update:function(){this._map&&this._updatePath()},_updatePath:function(){this._renderer._updateEllipse(this)},_getLatRadius:function(){return this._mRadiusY/40075017*360},_getLngRadius:function(){return this._mRadiusX/40075017*360/Math.cos(Math.PI/180*this._latlng.lat)},_centerPointToEndPoint:function(){var a=this._point,b=this._radiusX,c=this._radiusY,d=(this.options.startAngle+this.options.endAngle)*(Math.PI/180),e=this.options.startAngle*(Math.PI/180),f=this.options.endAngle,g=this._tiltDeg*(Math.PI/180),h=a.x+Math.cos(g)*b*Math.cos(e)+Math.sin(-g)*c*Math.sin(e),i=a.y+Math.sin(g)*b*Math.cos(e)+Math.cos(g)*c*Math.sin(e),j=a.x+Math.cos(g)*b*Math.cos(d)+Math.sin(-g)*c*Math.sin(d),k=a.y+Math.sin(g)*b*Math.cos(d)+Math.cos(g)*c*Math.sin(d),l=f>180?1:0,m=f>0?1:0;return{x0:h,y0:i,tilt:g,largeArc:l,sweep:m,x1:j,y1:k}},_empty:function(){return this._radiusX&&this._radiusY&&!this._renderer._bounds.intersects(this._pxBounds)},_containsPoint:function(a){var b=Math.sin(this._tilt),c=Math.cos(this._tilt),d=a.x-this._point.x,e=a.y-this._point.y,f=c*d+b*e,g=b*d-c*e;return f*f/(this._radiusX*this._radiusX)+g*g/(this._radiusY*this._radiusY)<=1}}),L.ellipse=function(a,b,c,d){return new L.Ellipse(a,b,c,d)}; \ No newline at end of file +L.SVG.include({_updateEllipse:function(layer){var c=layer._point,rx=layer._radiusX,ry=layer._radiusY,phi=layer._tiltDeg,endPoint=layer._endPointParams;var d="M"+endPoint.x0+","+endPoint.y0+"A"+rx+","+ry+","+phi+","+endPoint.largeArc+","+endPoint.sweep+","+endPoint.x1+","+endPoint.y1+" z";this._setPath(layer,d)}});L.Canvas.include({_updateEllipse:function(layer){if(layer._empty()){return}var p=layer._point,ctx=this._ctx,r=layer._radiusX,s=(layer._radiusY||r)/r;this._drawnLayers[layer._leaflet_id]=layer;ctx.save();ctx.translate(p.x,p.y);if(layer._tilt!==0){ctx.rotate(layer._tilt)}if(s!==1){ctx.scale(1,s)}ctx.beginPath();ctx.arc(0,0,r,0,Math.PI*2);ctx.restore();this._fillStroke(ctx,layer)}});L.Ellipse=L.Path.extend({options:{fill:true,startAngle:0,endAngle:359.9},initialize:function(latlng,radii,tilt,options){L.setOptions(this,options);this._latlng=L.latLng(latlng);if(tilt){this._tiltDeg=tilt}else{this._tiltDeg=0}if(radii){this._mRadiusX=radii[0];this._mRadiusY=radii[1]}},setRadius:function(radii){this._mRadiusX=radii[0];this._mRadiusY=radii[1];return this.redraw()},getRadius:function(){return new L.point(this._mRadiusX,this._mRadiusY)},setTilt:function(tilt){this._tiltDeg=tilt;return this.redraw()},getBounds:function(){var lngRadius=this._getLngRadius(),latRadius=this._getLatRadius(),latlng=this._latlng;return new L.LatLngBounds([latlng.lat-latRadius,latlng.lng-lngRadius],[latlng.lat+latRadius,latlng.lng+lngRadius])},setLatLng:function(latlng){this._latlng=L.latLng(latlng);this.redraw();return this.fire("move",{latlng:this._latlng})},getLatLng:function(){return this._latlng},setStyle:L.Path.prototype.setStyle,_project:function(){var lngRadius=this._getLngRadius(),latRadius=this._getLatRadius(),latlng=this._latlng,pointLeft=this._map.latLngToLayerPoint([latlng.lat,latlng.lng-lngRadius]),pointBelow=this._map.latLngToLayerPoint([latlng.lat-latRadius,latlng.lng]);this._point=this._map.latLngToLayerPoint(latlng);this._radiusX=Math.max(this._point.x-pointLeft.x,1);this._radiusY=Math.max(pointBelow.y-this._point.y,1);this._tilt=Math.PI*this._tiltDeg/180;this._endPointParams=this._centerPointToEndPoint();this._updateBounds()},_updateBounds:function(){var sin=Math.sin(this._tilt);var cos=Math.cos(this._tilt);var sinSquare=sin*sin;var cosSquare=cos*cos;var aSquare=this._radiusX*this._radiusX;var bSquare=this._radiusY*this._radiusY;var halfWidth=Math.sqrt(aSquare*cosSquare+bSquare*sinSquare);var halfHeight=Math.sqrt(aSquare*sinSquare+bSquare*cosSquare);var w=this._clickTolerance();var p=[halfWidth+w,halfHeight+w];this._pxBounds=new L.Bounds(this._point.subtract(p),this._point.add(p))},_update:function(){if(this._map){this._updatePath()}},_updatePath:function(){this._renderer._updateEllipse(this)},_getLatRadius:function(){var simpleCrs=!!this._map.options.crs.infinite;if(simpleCrs)return this._mRadiusY;else return this._mRadiusY/40075017*360},_getLngRadius:function(){var simpleCrs=!!this._map.options.crs.infinite;if(simpleCrs)return this._mRadiusX;else return this._mRadiusX/40075017*360/Math.cos(Math.PI/180*this._latlng.lat)},_centerPointToEndPoint:function(){var c=this._point,rx=this._radiusX,ry=this._radiusY,theta2=(this.options.startAngle+this.options.endAngle)*(Math.PI/180),theta1=this.options.startAngle*(Math.PI/180),delta=this.options.endAngle,phi=this._tiltDeg*(Math.PI/180);var x0=c.x+Math.cos(phi)*rx*Math.cos(theta1)+Math.sin(-phi)*ry*Math.sin(theta1);var y0=c.y+Math.sin(phi)*rx*Math.cos(theta1)+Math.cos(phi)*ry*Math.sin(theta1);var x1=c.x+Math.cos(phi)*rx*Math.cos(theta2)+Math.sin(-phi)*ry*Math.sin(theta2);var y1=c.y+Math.sin(phi)*rx*Math.cos(theta2)+Math.cos(phi)*ry*Math.sin(theta2);var largeArc=delta>180?1:0;var sweep=delta>0?1:0;return{x0:x0,y0:y0,tilt:phi,largeArc:largeArc,sweep:sweep,x1:x1,y1:y1}},_empty:function(){return this._radiusX&&this._radiusY&&!this._renderer._bounds.intersects(this._pxBounds)},_containsPoint:function(p){var sin=Math.sin(this._tilt);var cos=Math.cos(this._tilt);var dx=p.x-this._point.x;var dy=p.y-this._point.y;var sumA=cos*dx+sin*dy;var sumB=sin*dx-cos*dy;return sumA*sumA/(this._radiusX*this._radiusX)+sumB*sumB/(this._radiusY*this._radiusY)<=1}});L.ellipse=function(latlng,radii,tilt,options){return new L.Ellipse(latlng,radii,tilt,options)}; \ No newline at end of file