JPolygon.defaultColor = "#0000ff"; JPolygon.outlineThickness = 1; JPolygon.fillThickness = 1; JPolygon.defaultOutlineOpacity = 0.3; JPolygon.defaultFillOpacity = 0.2; JPolygon.maxLinePoints = 200; function JPolygon(points, color, fill, map) { this.points = []; this.sortedPoints = []; if (points) { this.points = points.slice(); this.points.push(points[0]); // copy the points array into one that will be sorted to find the lowest latitude this.sortedPoints = points.slice(); this.sortedPoints.sort(); } this.color = JPolygon.defaultColor; if (color) { this.color = color; } this.outlineThickness = JPolygon.outlineThickness; this.fillThickness = JPolygon.fillThickness; this.outlineOpacity = JPolygon.defaultOutlineOpacity; this.fillOpacity = JPolygon.defaultFillOpacity; this.polygonOutline = new GPolyline(this.points, this.color, this.outlineThickness, this.outlineOpacity); this.map = null; if (map) { this.map = map; } this.fillLines = null; if (fill) { this.pre1 = JPolygon.posInArray(this.sortedPoints[0], this.points); this.pre2 = JPolygon.backPos(this.pre1, this.points.length); this.post1 = this.pre1; this.post2 = JPolygon.forwardPos(this.post1, this.points.length); this.preSlope = 0; this.postSlope = 0; this.fillLines = []; this.fillPolygon(); } this.minLat = this.sortedPoints[0].lat(); this.maxLat = this.sortedPoints[this.sortedPoints.length-1].lat(); this.minLng = 0; this.maxLng = 0; this.getMinMaxLng(this.points); this.latlngBounds = new GLatLngBounds(new GLatLng(this.minLat, this.minLng), new GLatLng(this.maxLat, this.maxLng)); } JPolygon.prototype = new GOverlay(); JPolygon.prototype.initialize = function(map) { this.map = map; if (this.polygonOutline) { this.polygonOutline.initialize(map) } if (this.fillLines) { for (var i = 0; i < this.fillLines.length; i++) { this.fillLines[i].initialize(map); } } } JPolygon.prototype.remove = function() { if (this.polygonOutline) { this.polygonOutline.remove() } if (this.fillLines) { for (var i = 0; i < this.fillLines.length; i++) { this.fillLines[i].remove(); } } } JPolygon.prototype.redraw = function(force) { if (this.polygonOutline) { this.polygonOutline.redraw(force) } if (this.fillLines) { for (var i = 0; i < this.fillLines.length; i++) { this.fillLines[i].redraw(force); } } } JPolygon.prototype.getBounds = function() { return this.latlngBounds; } // Gets the minimum and maximum longitudes in an array of points JPolygon.prototype.getMinMaxLng = function(a) { this.minLng = a[0].lng(); this.maxLng = a[0].lng(); for (var i = 1; i < a.length; i++) { if (a[i].lng() < this.minLng) { this.minLng = a[i].lng(); } if (a[i].lng() > this.maxLng) { this.maxLng = a[i].lng(); } } } // Determines if a point is inside a polygon JPolygon.prototype.inZone = function(pt) { var isInZone = 0; var j = this.points.length-1; for (var i = 0; i < this.points.length; j = i++) { if ((((this.points[i].lat() <= pt.lat()) && (pt.lat() < this.points[j].lat())) || ((this.points[j].lat() <= pt.lat()) && (pt.lat() < this.points[i].lat()))) && (pt.lng() < (this.points[j].lng() - this.points[i].lng()) * (pt.lat() - this.points[i].lat()) / (this.points[j].lat() - this.points[i].lat()) + this.points[i].lng())) { isInZone++; } } if ((isInZone % 2) == 0) { return false; } else { return true; } } JPolygon.prototype.getNextPreSegment = function() { var pt1; var pt2; do { this.pre1 = JPolygon.backPos(this.pre1, this.points.length); this.pre2 = JPolygon.backPos(this.pre2, this.points.length); pt1 = this.map.getCurrentMapType().getProjection().fromLatLngToPixel(this.points[this.pre1],this.map.getZoom()); pt2 = this.map.getCurrentMapType().getProjection().fromLatLngToPixel(this.points[this.pre2],this.map.getZoom()); } while ((pt1.y == pt2.y) && (this.pre1 != this.post2) && (this.pre2 != this.post1)); } JPolygon.prototype.getNextPostSegment = function() { var pt1; var pt2; do { this.post1 = JPolygon.forwardPos(this.post1, this.points.length); this.post2 = JPolygon.forwardPos(this.post2, this.points.length); pt1 = this.map.getCurrentMapType().getProjection().fromLatLngToPixel(this.points[this.post1],this.map.getZoom()); pt2 = this.map.getCurrentMapType().getProjection().fromLatLngToPixel(this.points[this.post2],this.map.getZoom()); } while ((pt1.y <= pt2.y) && (this.pre1 != this.post2) && (this.pre2 != this.post1)); // NOTE: Larger y value means lower latitude } JPolygon.prototype.fillPolygon = function() { this.pre1 = JPolygon.posInArray(this.sortedPoints[0], this.points); this.pre2 = JPolygon.backPos(this.pre1, this.points.length); this.post1 = this.pre1; this.post2 = JPolygon.forwardPos(this.post1, this.points.length); var tpt1; var tpt2; tpt1 = this.map.getCurrentMapType().getProjection().fromLatLngToPixel(this.points[this.pre1],this.map.getZoom()); tpt2 = this.map.getCurrentMapType().getProjection().fromLatLngToPixel(this.points[this.pre2],this.map.getZoom()); if (tpt1.y == tpt2.y) { this.getNextPreSegment(); } tpt1 = this.map.getCurrentMapType().getProjection().fromLatLngToPixel(this.points[this.post1],this.map.getZoom()); tpt2 = this.map.getCurrentMapType().getProjection().fromLatLngToPixel(this.points[this.post2],this.map.getZoom()); if (tpt1.y == tpt2.y) { this.getNextPostSegment(); } //GLog.write("pre1 = "+this.pre1); //GLog.write("pre2 = "+this.pre2); //GLog.write("post1 = "+this.post1); //GLog.write("post2 = "+this.post2); this.preSlope = this.getLineSlope(this.pre1, this.pre2); this.postSlope = this.getLineSlope(this.post1, this.post2); // safetycount is here in case there is a bug in the code. Don't want to loop forever. var safetycount = 0; while ((this.pre1 != this.post2) && (this.pre2 != this.post1) && (safetycount < this.points.length)) { // fill a portion of the polygon safetycount++; //GLog.write("pre1="+this.pre1+" pre2="+this.pre2+" post1="+this.post1+" post2="+this.post2); this.fillBetweenSegments(); } } JPolygon.prototype.fillBetweenSegments = function() { var prePt1 = this.map.getCurrentMapType().getProjection().fromLatLngToPixel(this.points[this.pre1],this.map.getZoom()); var prePt2 = this.map.getCurrentMapType().getProjection().fromLatLngToPixel(this.points[this.pre2],this.map.getZoom()); var postPt1 = this.map.getCurrentMapType().getProjection().fromLatLngToPixel(this.points[this.post1],this.map.getZoom()); var postPt2 = this.map.getCurrentMapType().getProjection().fromLatLngToPixel(this.points[this.post2],this.map.getZoom()); var preLatDif = prePt2.y - prePt1.y; var preLngDif = prePt2.x - prePt1.x; var postLatDif = postPt2.y - postPt1.y; var postLngDif = postPt2.x - postPt1.x; var fillArray = []; //GLog.write("pre1="+this.pre1+" pre2="+this.pre2+" post1="+this.post1+" post2="+this.post2); //GLog.write("preLatDif = "+preLatDif); ////GLog.write("preLngDif = "+preLngDif); //GLog.write("postLatDif = "+postLatDif); ////GLog.write("postLngDif = "+postLngDif); // var preLatInc = preLatDif == 0 ? 0 : preLatDif / Math.abs(preLatDif); var preLatInc = preLatDif == 0 ? 0 : (this.fillThickness * preLatDif) / Math.abs(preLatDif); var preLngOffset = 0; // var postLatInc = postLatDif == 0 ? 0 : postLatDif / Math.abs(postLatDif); var postLatInc = postLatDif == 0 ? 0 : (this.fillThickness * postLatDif) / Math.abs(postLatDif); var postLngOffset = 0; var preLatOffset = 0; var postLatOffset = 0; //GLog.write("preLatInc = "+preLatInc); //GLog.write("postLatInc = "+postLatInc); // while ((preLatOffset < Math.abs(preLatDif)) && (postLatOffset < Math.abs(postLatDif))) { // if (preLatOffset != preLatDif) { // if (preLatInc > 0) preLatOffset++; // else preLatOffset--; while ((preLatOffset < Math.abs(preLatDif)) && (postLatOffset < Math.abs(postLatDif))) { if (preLatOffset < Math.abs(preLatDif)) { if (preLatInc > 0) preLatOffset += this.fillThickness; else preLatOffset -= this.fillThickness; } if (postLatOffset < Math.abs(postLatDif)) { postLatOffset = (prePt1.y + preLatOffset) - postPt1.y; } //GLog.write("preLatInc= "+preLatInc+" preLatOffset= "+preLatOffset); //GLog.write("postLatInc= "+postLatInc+" postLatOffset= "+postLatOffset+" postLatDif= "+postLatDif); if (preLngOffset < Math.abs(preLngDif)) { if (this.preSlope != 0) { preLngOffset = Math.round(preLatOffset / this.preSlope); if (Math.abs(preLngOffset) > Math.abs(preLngDif)) { preLngOffset = preLngDif+1; } } } if (postLngOffset < Math.abs(postLngDif)) { if (this.postSlope != 0) { postLngOffset = Math.round(postLatOffset / this.postSlope); if (Math.abs(postLngOffset) > Math.abs(postLngDif)) { postLngOffset = postLngDif; } } } //GLog.write("preLngOffset= "+preLngOffset+" preLngDif= "+preLngDif); //GLog.write("postLngOffset= "+postLngOffset+" postLngDif= "+postLngDif); tmpPrePt = new GPoint(prePt1.x + preLngOffset, prePt1.y + preLatOffset); tmpPostPt = new GPoint(postPt1.x + postLngOffset, tmpPrePt.y); //GLog.write("preLatOffset = "+preLatOffset); //GLog.write("postLatOffset = "+postLatOffset); //GLog.write("tmpPrePt = "+tmpPrePt.toString()); //GLog.write("tmpPostPt = "+tmpPostPt.toString()); pt1 = this.map.getCurrentMapType().getProjection().fromPixelToLatLng(tmpPrePt, this.map.getZoom(), true); pt2 = this.map.getCurrentMapType().getProjection().fromPixelToLatLng(tmpPostPt, this.map.getZoom(), true); if (((fillArray.length / 2) % 2) == 0) { fillArray.push(pt1); fillArray.push(pt2); } else { fillArray.push(pt2); fillArray.push(pt1); } if (fillArray.length >= JPolygon.maxLinePoints) { //GLog.write("fillArray size = "+fillArray.length); //pointcount += fillArray.length; var fillLine = new GPolyline(fillArray,this.color,this.fillThickness,this.fillOpacity); this.fillLines.push(fillLine); fillArray = []; } if (((preLatInc > 0) && (preLatOffset >= preLatDif)) || ((preLatInc < 0) && (preLatOffset <= preLatDif))) { // get new point this.getNextPreSegment(); if ((this.pre1 == this.post2) || (this.pre2 == this.post1)) break; prePt1 = this.map.getCurrentMapType().getProjection().fromLatLngToPixel(this.points[this.pre1],this.map.getZoom()); prePt2 = this.map.getCurrentMapType().getProjection().fromLatLngToPixel(this.points[this.pre2],this.map.getZoom()); this.preSlope = this.getLineSlope(this.pre1, this.pre2); preLatDif = prePt2.y - prePt1.y; preLngDif = prePt2.x - prePt1.x; preLatInc = preLatDif == 0 ? 0 : (this.fillThickness * preLatDif) / Math.abs(preLatDif); preLngOffset = 0; preLatOffset = 0; } if (((postLatInc > 0) && (postLatOffset >= postLatDif)) || ((postLatInc < 0) && (postLatOffset <= postLatDif))) { if ((this.points[this.pre1].lat() < this.points[this.pre2].lat()) && ((this.points[this.post1].lat() < this.points[this.pre2].lat()) || (this.points[this.post2].lat() < this.points[this.pre2].lat()))) { // get new point this.getNextPostSegment(); if ((this.pre1 == this.post2) || (this.pre2 == this.post1)) break; postPt1 = this.map.getCurrentMapType().getProjection().fromLatLngToPixel(this.points[this.post1],this.map.getZoom()); postPt2 = this.map.getCurrentMapType().getProjection().fromLatLngToPixel(this.points[this.post2],this.map.getZoom()); this.postSlope = this.getLineSlope(this.post1, this.post2); postLatDif = postPt2.y - postPt1.y; postLngDif = postPt2.x - postPt1.x; postLatInc = postLatDif == 0 ? 0 : (this.fillThickness *postLatDif) / Math.abs(postLatDif); postLngOffset = 0; postLatOffset = 0; } } } if (fillArray.length > 0) { var fillLine = new GPolyline(fillArray,this.color,this.fillThickness,this.fillOpacity); this.fillLines.push(fillLine); } } JPolygon.prototype.getLineSlope = function(p1, p2) { var pt1 = this.map.getCurrentMapType().getProjection().fromLatLngToPixel(this.points[p1],this.map.getZoom()); var pt2 = this.map.getCurrentMapType().getProjection().fromLatLngToPixel(this.points[p2],this.map.getZoom()); var slope = 0; if (pt1.x != pt2.x) { slope = (pt2.y - pt1.y) / (pt2.x - pt1.x); } return slope; } JPolygon.printArray = function(a) { for (var i = 0; i < a.length; i++) { GLog.write("a["+i+"] = "+a[i].toString()); } } JPolygon.posInArray = function(pt, arr) { var pos = 0; while (pos < arr.length) { if (pt == arr[pos]) { break; } else { pos++; if (pos == arr.length) alert("array position not found"); } } return pos; } JPolygon.backPos = function(pos, len) { pos--; if (pos < 0) { pos = len -1; } return pos; } JPolygon.forwardPos = function(pos, len) { pos++; if (pos >= len) { pos = 0; } return pos; } // XUserAgent is a copy of the user agent code in maps.10.js // user agent types XUserAgent.IE = 1; XUserAgent.MOZILLA = 2; XUserAgent.SAFARI = 3; XUserAgent.OPERA = 4; // user agent OSes XUserAgent.WIN = 0; XUserAgent.NIX = 1; XUserAgent.MAC = 2; function XUserAgent(type, version, os) { this.type = type; this.version = version; this.os = os }; XUserAgent.create = function() { var userAgent = new XUserAgent(0, 0, null); var userAgentName = navigator.userAgent.toLowerCase(); if (userAgentName.indexOf("opera") != -1) { userAgent.type = XUserAgent.OPERA; if (userAgentName.indexOf("opera/7") != -1 || userAgentName.indexOf("opera 7") != -1) { userAgent.version = 7 } else if (userAgentName.indexOf("opera/8") != -1 || userAgentName.indexOf("opera 8") != -1) { userAgent.version = 8 } } else if (userAgentName.indexOf("msie") != -1 && document.all) { userAgent.type = XUserAgent.IE; if (userAgentName.indexOf("msie 5")) { userAgent.version = 5 } } else if (userAgentName.indexOf("safari") != -1) { userAgent.type = XUserAgent.SAFARI } else if (userAgentName.indexOf("mozilla") != -1) { userAgent.type = XUserAgent.MOZILLA } if (userAgentName.indexOf("x11;") != -1) { userAgent.os = XUserAgent.NIX } else if (userAgentName.indexOf("macintosh") != -1) { userAgent.os = XUserAgent.MAC } return userAgent; }; // XDistance provides convenience functions for converting between various // measures of distance. XDistance.M = 0; XDistance.KM = 1; XDistance.FT = 2; XDistance.MI = 3; XDistance.NM = 4; //XDistance.latConstantMeters = 180 / XDistance.earthRadiusInMetersWGS84 / Math.PI; //XDistance.latConstantMiles = 180 / XDistance.earthRadiusInMilesWGS84 / Math.PI; XDistance.conversionTable = [ [1, 1 / 1000, 3.2808399, 0.000621371192, 0.000539956803], [1000, 1, 3280.8399, 0.621371192, 0.539956803], [0.3048, 0.0003048, 1, 1 / 5280, 0.000164578834], [1609.344, 1.609344, 5280, 1, 0.868976242], [1852, 1.85200, 6076.11549, 1.15077945, 1] ]; function XDistance(value, units) { this.value = value; this.units = units; } XDistance.prototype.convert = function(toUnits) { return XDistance.convert(this.value, this.units, toUnits) } XDistance.prototype.toMeters = function() { return XDistance.convert(this.value, this.units, XDistance.M) } XDistance.prototype.toKilometers = function() { return XDistance.convert(this.value, this.units, XDistance.KM) } XDistance.prototype.toFeet = function() { return XDistance.convert(this.value, this.units, XDistance.FT) } XDistance.prototype.toMiles = function() { return XDistance.convert(this.value, this.units, XDistance.MI) } XDistance.prototype.toNauticalMiles = function() { return XDistance.convert(this.value, this.units, XDistance.NM) } XDistance.convert = function(value, fromUnits, toUnits) { return value * XDistance.conversionTable[fromUnits][toUnits]; } XDistance.between = function(point1, point2) { return XMaps.model.getDistanceAndAngle(point1, point2).distance; } XDistance.resolveToMeters = function(distanceOrMeters) { if (typeof distanceOrMeters == 'number') { return distanceOrMeters } else { return distanceOrMeters.toMeters() } } XAngle.RAD = 0; XAngle.DEG = 1; XAngle.radToDeg = 180 / Math.PI; XAngle.degToRad = Math.PI / 180; XAngle.conversionTable = [ [1, XAngle.radToDeg], [XAngle.degToRad, 1] ]; XAngle.normalizeRadians = function(rad) { while (rad < 0) { rad += 2 * Math.PI } while (rad > 2 * Math.PI) { rad -= 2 * Math.PI } return rad } XAngle.normalizeDegrees = function(deg) { while (deg < 0) { deg += 360 } while (deg > 360) { deg -= 360 } return deg } XAngle.normalizationTable = [ XAngle.normalizeRadians, XAngle.normalizeDegrees ]; function XAngle(value, units) { this.value = value; this.units = units; } XAngle.prototype.convert = function(toUnits) { return XAngle.convert(this.value, this.units, toUnits) } XAngle.prototype.toRadians = function() { return XAngle.convert(this.value, this.units, XAngle.RAD) } XAngle.prototype.toDegrees = function() { return XAngle.convert(this.value, this.units, XAngle.DEG) } XAngle.prototype.normalize = function() { this.value = XAngle.normalizationTable[this.units](this.value); } XAngle.convert = function(value, fromUnits, toUnits) { if (fromUnits == toUnits) { return value; } else { return value * XAngle.conversionTable[fromUnits][toUnits]; } } XAngle.radiansToDegrees = function(radians) { var deg = radians * XAngle.radToDeg; while (deg < 0) { deg += 360 } while (deg >= 360) { deg -= 360 } return deg } XAngle.degreesToRadians = function(degrees) { var rad = degrees * XAngle.degToRad; while (rad < 0) { rad += 2 * Math.PI } while (rad >= 2 * Math.PI) { rad -= 2 * Math.PI } return rad } XAngle.resolveToRadians = function(angleOrRadians) { if (typeof angleOrRadians == 'number') { return XAngle.normalizeRadians(angleOrRadians) } else { angleOrRadians.normalize(); return angleOrRadians.toRadians() } } function XDistanceAndAngle(distance, angle) { this.distance = distance; this.angle = angle; } // XModel is a model of the world we're mapping. // The meat of this class is from the source code of Navigate for Palm OS, // written by Rick Chapman. // http://fermi.jhuapl.edu/navigate/index.html function XModel(flatteningFactor, semimajorAxis) { this.flatteningFactor = flatteningFactor; this.semimajorAxisInMeters = semimajorAxis.toMeters(); } XModel.prototype.getDistanceAndAngle = function(from, to, distance, angle, distanceAndAngle) { distance = distance || new XDistance(); distance.units = XDistance.M; angle = angle || new XAngle(); angle.units = XAngle.RAD; distanceAndAngle = distanceAndAngle || new XDistanceAndAngle(); distanceAndAngle.distance = distance; distanceAndAngle.angle = angle; var f = 1 / this.flatteningFactor; var ra = this.semimajorAxisInMeters; var eps = 5e-14; var r = 1 - f; var tu1 = r * Math.tan(from.y / XAngle.radToDeg); var tu2 = r * Math.tan(to.y / XAngle.radToDeg); var cu1 = 1 / Math.sqrt(tu1 * tu1 + 1); var su1 = cu1 * tu1; var cu2 = 1 / Math.sqrt(tu2 * tu2 + 1); var s = cu1 * cu2; var baz = s * tu2; var faz = baz * tu1; var x = (to.x - from.x) / XAngle.radToDeg; var d, sx, cx, sy, cy, cz, c2a, c, e, y, sa; var count = 0; do { sx = Math.sin(x); cx = Math.cos(x); tu1 = cu2 * sx; tu2 = baz - su1 * cu2 * cx; sy = Math.sqrt(tu1 * tu1 + tu2 * tu2); cy = s * cx + faz; y = Math.atan2(sy, cy); sa = s * sx / sy; c2a = -sa * sa + 1; cz = faz + faz; if (c2a > 0) { cz = -cz / c2a + cy } e = cz * cz * 2 - 1; c = ((-3 * c2a + 4) * f + 4) * c2a * f / 16; d = x; x = ((e * cy * c + cz) * sy * c + y) * sa; x = (1 - c) * x * f + (to.x - from.x) / XAngle.radToDeg; } while (Math.abs(d - x) > eps || count++ == 100); faz = Math.atan2(tu1, tu2); baz = Math.atan2(cu1 * sx, baz * cx - su1 * cu2) + Math.PI; x = Math.sqrt((1 / r / r - 1) * c2a + 1) + 1; x = (x - 2) / x; c = 1 - x; c = (x * x / 4 + 1) / c; d = (0.375 * x * x - 1) * x; x = e * cy; s = 1 - e * e; s = ((((sy * sy * 4 - 3) * s * cz * d / 6 - x) * d / 4 + cz) * sy * d + y) * c * ra * r; distance.value = s; angle.value = XAngle.normalizeRadians(faz); return distanceAndAngle; } XModel.prototype.getPointAtDistanceAndAngle = function(point, distance, angle, outPoint) { var meters = XDistance.resolveToMeters(distance); var radians = XAngle.resolveToRadians(angle); outPoint = outPoint || new GPoint(); var f = 1 / this.flatteningFactor; var ra = this.semimajorAxisInMeters; var eps = 1e-13; var r = 1 - f; var tu = r * Math.tan(point.y * XAngle.degToRad); var sf = Math.sin(radians); var cf = Math.cos(radians); var baz = Math.atan2(tu, cf) * 2; var cu = 1 / Math.sqrt(tu * tu + 1); var su = tu * cu; var sa = cu * sf; var c2a = 1 - sa * sa; var x = Math.sqrt((1 / r / r - 1) * c2a + 1) + 1; var c, d, y, sy, cy, cz, e; x = (x - 2) / x; c = 1 - x; c = (x * x / 4 + 1) / c; d = (0.375 * x * x - 1) * x; tu = meters / r / ra / c; y = tu; var count = 0; do { sy = Math.sin(y); cy = Math.cos(y); cz = Math.cos(baz + y); e = cz * cz * 2 - 1; c = y; x = e * cy; y = e * e - 1; y = (((sy * sy * 4 - 3) * y * cz * d / 6 + x) * d / 4 - cz) * sy * d + tu; } while(Math.abs(y - c) > eps || count++ == 100); baz = cu * cy * cf - su * sy; c = r * Math.sqrt(sa * sa + baz * baz); d = su * cy + cu * sy * cf; var lat2 = Math.atan2(d, c) / XAngle.degToRad; c = cu * cy - su * sy * cf; x = Math.atan2(sy * sf, c); c = ((-3 * c2a + 4) * f + 4) * c2a * f / 16; d = ((e * cy * c + cz) * sy * c + y) * sa; var lng2 = (point.x * XAngle.degToRad + x - (1 - c) * d * f) / XAngle.degToRad; baz = Math.atan2(sa, baz) + Math.PI; outPoint.x = lng2; outPoint.y = lat2; return outPoint } XModel.earth = new XModel(298.257223563, new XDistance(6378137, XDistance.M)); // XMaps is the namespace for functions in GMaps that are not exposed but should be along // with a bunch of other useful code. Some of these functions are copied from maps.10.js. function XMaps() {}; XMaps.getElementById = function(id) { return document.getElementById(id) } XMaps.userAgent = XUserAgent.create(); XMaps.toPixelString = function(pixels) { return Math.round(pixels) + "px" } XMaps.addClassName = function(element, className) { if(element.className) { element.className += " " + className } else { element.className = className } } XMaps.falseFunction = function() { return false } XMaps.integerCompare = function(a, b) { return (a < b) ? -1 : ((a > b) * 1); } XMaps.defaultColor = { red: 0, green: 0, blue: 0xff }; XMaps.parseColor = function(color, defaultColor) { try { if (color.charAt(0) == "#") { color = color.substring(1) } var red = parseInt(color.substring(0, 2), 16); var green = parseInt(color.substring(2, 4), 16); var blue = parseInt(color.substring(4, 6), 16); return { red: red, green: green, blue: blue }; } catch (e) { if (typeof defaultColor == 'object') { return defaultColor } else { return XMaps.parseColor(defaultColor, XMaps.defaultColor) } } } XMaps.model = XModel.earth; JPolygon.createRegularPolygonFromRadius = function(center, radius, numPoints, startAngle, color, fill) { numPoints = numPoints || 8; startAngle = startAngle || 0; var meters = XDistance.resolveToMeters(radius); var startRadians = XAngle.resolveToRadians(startAngle); startRadians = XAngle.normalizeRadians(startRadians); var points = []; var latScale = meters / XMaps.model.semimajorAxisInMeters * XAngle.radToDeg; var lngScale = latScale / Math.cos(center.y * XAngle.degToRad); for (var i = 0; i < numPoints; i++) { var radians = startRadians + 2 * Math.PI * i / numPoints; points.push(new GLatLng( center.y + latScale * Math.sin(radians), center.x + lngScale * Math.cos(radians))); } //alert(points.toString()); //return new GPolyline(points,linecolor,lineweight,lineopacity); return new JPolygon(points,color,true,map); }