[OpenLayers-Users] International date line and bounds
[SEC=UNCLASSIFIED]
Piero Campa
piero.campa at gmail.com
Thu Aug 5 12:38:45 EDT 2010
Of course: the code in the attachment.
Anyway, for more clearness:
°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
OpenLayers.Handler.myRegularPolygon = OpenLayers.Class.create();
OpenLayers.Handler.myRegularPolygon.prototype = OpenLayers.Class.inherit
(OpenLayers.Handler.RegularPolygon, {
/**
* Constant: LIMIT
* Maximum Polygon width (default is 180° of longitude)
*/
LIMIT: 20037508.34,
/**
* Constant: GLOBE_LON
* Longitude width of 'one globe' (360°)
*/
GLOBE_LON: 20037508.34*2,
/**
* Property: lastX
* X-coordinate of the last mouse movement
*/
lastX: null,
/**
* Property: IDL
* Boolean: mouse is beyond IDL.
*/
IDL: false,
/**
* Method: downFeature
* Start drawing a new feature
*
* Parameters:
* evt - {Event} The drag start event
*/
down: function(evt){
var aoiLayer = // enter here the OpenLayers.Layer.Vector layer controlled
by the DrawFeature Control
// Remove preceding boxes (max 1 polygon per layer, if you want to)
if (aoiLayer.features.length > 0) {
for (var i = 0; i < aoiLayer.features.length; i++)
aoiLayer.removeFeatures(aoiLayer.features[i]);
}
this.fixedRadius = !!(this.radius);
var maploc = this.map.getLonLatFromPixel(evt.xy); // wrapped lonlat
// Check if I'm on an inactive side-globe
var map_size = map_vac.getSize();
var center = parseInt(map_size.w / 2, 10);
var centerLonLat = this.map.getLonLatFromPixel(new
OpenLayers.Pixel(center,0));
var centerPx = this.map.getPixelFromLonLat(new OpenLayers.LonLat(0,0));
if(evt.xy.x < map_size.w / 2 && maploc.lon > 0 &&
(centerLonLat.lon < 0 || centerPx.x > evt.xy.x)) {
// I'm on left side-globe
maploc.lon -= this.GLOBE_LON;
this.IDL = true;
} else if (evt.xy.x > map_size.w / 2 && maploc.lon < 0 &&
(centerLonLat.lon > 0 || centerPx.x < evt.xy.x)) {
// I'm on right side-globe
maploc.lon += this.GLOBE_LON;
this.IDL = true;
}
this.origin = new OpenLayers.Geometry.Point(maploc.lon, maploc.lat);
// Store this.origin position (pixel) in the map, to handle IDL
AOI.originPx = new OpenLayers.Pixel(evt.xy.x, evt.xy.y); // AOI.originPx
is a global variable
// create the new polygon
if (!this.fixedRadius || this.irregular) {
// smallest radius should not be less one pixel in map units
// VML doesn't behave well with smaller
this.radius = this.map.getResolution();
}
if (this.persist) {
this.clear();
}
this.feature = new OpenLayers.Feature.Vector();
this.createGeometry();
this.layer.addFeatures([this.feature], {
silent: true
});
this.layer.drawFeature(this.feature, this.style);
},
move: function(evt) {
var maploc = this.map.getLonLatFromPixel(evt.xy);
var point = new OpenLayers.Geometry.Point(maploc.lon, maploc.lat);
// Check if IDL has been crossed
if (Math.abs(this.lastX - point.x) >= this.LIMIT && this.lastX != null) {
this.IDL = (this.IDL == true) ? false : true; // Toggle
}
// IDL handler
var sign;
var diff = point.x - this.origin.x;
if (this.IDL) {
// Continue drawing one-piece AOI
//point.x = this.lastX; // Cut at the IDL
(evt.xy.x > this.map.getSize().w / 2) ? (sign = 1) : (sign = -1);
if (Math.abs(diff) < this.LIMIT)
point.x = this.origin.x + this.LIMIT * sign;
else
point.x = point.x + this.GLOBE_LON * sign;
}
else if (Math.abs(diff) >= this.LIMIT) {
// The point is beyond the IDL (diff is low but origin and point are on
different globes)
(evt.xy.x > AOI.originPx.x) ? (sign = 1) : (sign = -1);
point.x = this.origin.x + this.LIMIT * sign;
} else {
// Not IDL nor >180°: do nothing
}
// Keep trace of the movement direction
this.lastX = maploc.lon;
// Continue with default OL instructions:
if (this.irregular) {
var ry = Math.sqrt(2) * Math.abs(point.y - this.origin.y) / 2;
this.radius = Math.max(this.map.getResolution() / 2, ry);
}
else
if (this.fixedRadius) {
this.origin = point;
}
else {
this.calculateAngle(point, evt);
this.radius = Math.max(this.map.getResolution() / 2,
point.distanceTo(this.origin));
}
this.modifyGeometry();
if (this.irregular) {
/* The new polygon is first calculated as it would be regular (origin in
the centre and
* same-length sides), then it is resized by x/y ratio and moved so that
the origin
* is again the first clicked point (handled by the 'down' method).
*/
var dx = point.x - this.origin.x;
var dy = point.y - this.origin.y;
var ratio;
if (dy == 0) {
ratio = dx / (this.radius * Math.sqrt(2));
}
else {
ratio = dx / dy;
}
this.feature.geometry.resize(1, this.origin, ratio);
this.feature.geometry.move(dx / 2, dy / 2);
}
this.layer.drawFeature(this.feature, this.style);
// Keep trace of origin pixel to manage IDL in this.move() function
this.originPixel = this.layer.getViewPortPxFromLonLat(this.origin);
},
/** @final @type String */
CLASS_NAME: "OpenLayers.Handler.myRegularPolygon"
})
°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
This way the name of the handler is myRegularPolygon.
I had to make use of external variables such as the OpenLayers.Layer.Vector
layer controlled by the DrawFeature control and a global variable in which
to store the pixel location of the origin of the polygon (I didn't
understand yet why I could not store it as a property of the class),
anyway... This has been tested with irregular rectangles.
Piero
--
View this message in context: http://osgeo-org.1803224.n2.nabble.com/International-date-line-and-bounds-tp2541265p5377316.html
Sent from the OpenLayers Users mailing list archive at Nabble.com.
More information about the Users
mailing list