adding irregular option to regular polygon control - now, go draw rectangles, and more - thanks for the review elem (closes #1098).

git-svn-id: http://svn.openlayers.org/trunk/openlayers@5200 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
Tim Schaub
2007-11-15 23:37:36 +00:00
parent 75163f6635
commit ceecacfe3a
7 changed files with 102 additions and 11 deletions

View File

@@ -66,6 +66,7 @@
map.setCenter(new OpenLayers.LonLat(0, 0), 3);
document.getElementById('noneToggle').checked = true;
document.getElementById('irregularToggle').checked = false;
}
function setOptions(options) {
polygonControl.handler.setOptions(options);
@@ -146,6 +147,16 @@
</select>
</td>
</tr>
<tr>
<td>
irregular
</td>
<td>
<input id="irregularToggle" name="irregular"
type="checkbox"
onchange="setOptions({irregular: this.checked})") />
</td>
</tr>
</tbody>
</table>
</div>
@@ -156,5 +167,7 @@
the snap angle is non-null) and you hold down the <b>Shift</b> key, you
will toggle to non-snapping mode.
</p>
<p>
The <i>irregular</i> option allows drawing of irregular polygons. With this option, the fixed radius option is ignored.
</body>
</html>

View File

@@ -269,10 +269,11 @@ OpenLayers.Geometry.Collection = OpenLayers.Class(OpenLayers.Geometry, {
* (lines, for example, will be twice as long, and polygons
* will have four times the area).
* origin - {<OpenLayers.Geometry.Point>} Point of origin for resizing
* ratio - {Float} Optional x:y ratio for resizing. Default ratio is 1.
*/
resize: function(scale, origin) {
resize: function(scale, origin, ratio) {
for(var i=0; i<this.components.length; ++i) {
this.components[i].resize(scale, origin);
this.components[i].resize(scale, origin, ratio);
}
},

View File

@@ -145,10 +145,11 @@ OpenLayers.Geometry.LinearRing = OpenLayers.Class(
* (lines, for example, will be twice as long, and polygons
* will have four times the area).
* origin - {<OpenLayers.Geometry.Point>} Point of origin for resizing
* ratio - {Float} Optional x:y ratio for resizing. Default ratio is 1.
*/
resize: function(scale, origin) {
resize: function(scale, origin, ratio) {
for(var i=0; i<this.components.length - 1; ++i) {
this.components[i].resize(scale, origin);
this.components[i].resize(scale, origin, ratio);
}
},

View File

@@ -160,10 +160,11 @@ OpenLayers.Geometry.Point = OpenLayers.Class(OpenLayers.Geometry, {
* distance from the origin. A scale of 2 doubles the
* distance between the point and origin.
* origin - {<OpenLayers.Geometry.Point>} Point of origin for resizing
* ratio - {Float} Optional x:y ratio for resizing. Default ratio is 1.
*/
resize: function(scale, origin) {
this.x = origin.x + (scale * (this.x - origin.x));
resize: function(scale, origin, ratio) {
ratio = (ratio == undefined) ? 1 : ratio;
this.x = origin.x + (scale * ratio * (this.x - origin.x));
this.y = origin.y + (scale * (this.y - origin.y));
this.clearBounds();
},

View File

@@ -62,6 +62,18 @@ OpenLayers.Handler.RegularPolygon = OpenLayers.Class(OpenLayers.Handler.Drag, {
*/
persist: false,
/**
* APIProperty: irregular
* {Boolean} Draw an irregular polygon instead of a regular polygon.
* Default is false. If true, the initial mouse down will represent
* one corner of the polygon bounds and with each mouse movement, the
* polygon will be stretched so the opposite corner of its bounds
* follows the mouse position. This property takes precedence over
* the radius property. If set to true, the radius property will
* be ignored.
*/
irregular: false,
/**
* Property: angle
* {Float} The angle from the origin (mouse down) to the current mouse
@@ -194,7 +206,7 @@ OpenLayers.Handler.RegularPolygon = OpenLayers.Class(OpenLayers.Handler.Drag, {
var maploc = this.map.getLonLatFromPixel(evt.xy);
this.origin = new OpenLayers.Geometry.Point(maploc.lon, maploc.lat);
// create the new polygon
if(!this.fixedRadius) {
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();
@@ -218,7 +230,10 @@ OpenLayers.Handler.RegularPolygon = OpenLayers.Class(OpenLayers.Handler.Drag, {
move: function(evt) {
var maploc = this.map.getLonLatFromPixel(evt.xy);
var point = new OpenLayers.Geometry.Point(maploc.lon, maploc.lat);
if(this.fixedRadius) {
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);
@@ -226,6 +241,18 @@ OpenLayers.Handler.RegularPolygon = OpenLayers.Class(OpenLayers.Handler.Drag, {
point.distanceTo(this.origin));
}
this.modifyGeometry();
if(this.irregular) {
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);
},
@@ -277,6 +304,7 @@ OpenLayers.Handler.RegularPolygon = OpenLayers.Class(OpenLayers.Handler.Drag, {
// if the number of sides ever changes, create a new geometry
if(ring.components.length != (this.sides + 1)) {
this.createGeometry();
ring = this.feature.geometry.components[0];
}
for(var i=0; i<this.sides; ++i) {
point = ring.components[i];

View File

@@ -109,7 +109,7 @@
}
function test_Point_resize(t) {
t.plan(3);
t.plan(5);
var tolerance = 1e-10;
var x = 100 * Math.random();
@@ -134,6 +134,13 @@
t.ok(point.bounds == null, "bounds is correctly cleared after a resize()");
// resize with non uniform scaling (ratio != 1)
point = new OpenLayers.Geometry.Point(10, 10);
origin = new OpenLayers.Geometry.Point(0, 0);
point.resize(2, origin, 4);
t.eq(point.x, 80, "non-uniform scaling correctly applied in x dim");
t.eq(point.y, 20, "non-uniform scaling correctly applied in y dim");
}
function test_Point_equals(t) {

View File

@@ -140,7 +140,47 @@
t.eq(handler.feature.geometry.getBounds().toBBOX(),
"34.159333,-8.028167,36.153167,-6.034333",
"bounds with manual radius setting and mousemove");
}
}
function test_Handler_RegularPolygon_irregular(t) {
t.plan(4);
var map = {
getLonLatFromPixel: function(px) {
return {lon: px.x, lat: px.y};
},
getResolution: function() {
return 1;
}
};
var layer = {
addFeatures: function() {},
drawFeature: function(feature, style) {
var ring = feature.geometry.components[0];
t.eq(ring.components[0].x, 20, "correct right");
t.eq(ring.components[0].y, 10, "correct bottom");
t.eq(ring.components[2].x, 10, "correct left");
t.eq(ring.components[2].y, 15, "correct top");
}
};
var control = {};
var options = {
sides: 4,
irregular: true,
layer: layer,
map: map
};
var handler = new OpenLayers.Handler.RegularPolygon(
control, null, options
);
handler.origin = new OpenLayers.Geometry.Point(10, 10);
handler.feature = new OpenLayers.Feature.Vector(
new OpenLayers.Geometry.Polygon(
[new OpenLayers.Geometry.LinearRing()]
)
);
// should result in a 10 x 5 rectangle
handler.move({xy: {x: 20, y: 15}});
}
</script>
</head>