summaryrefslogtreecommitdiff
path: root/misc/openlayers/lib/OpenLayers/Geometry.js
diff options
context:
space:
mode:
Diffstat (limited to 'misc/openlayers/lib/OpenLayers/Geometry.js')
-rw-r--r--misc/openlayers/lib/OpenLayers/Geometry.js500
1 files changed, 500 insertions, 0 deletions
diff --git a/misc/openlayers/lib/OpenLayers/Geometry.js b/misc/openlayers/lib/OpenLayers/Geometry.js
new file mode 100644
index 0000000..e7b8e59
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Geometry.js
@@ -0,0 +1,500 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/BaseTypes/Class.js
+ */
+
+/**
+ * Class: OpenLayers.Geometry
+ * A Geometry is a description of a geographic object. Create an instance of
+ * this class with the <OpenLayers.Geometry> constructor. This is a base class,
+ * typical geometry types are described by subclasses of this class.
+ *
+ * Note that if you use the <OpenLayers.Geometry.fromWKT> method, you must
+ * explicitly include the OpenLayers.Format.WKT in your build.
+ */
+OpenLayers.Geometry = OpenLayers.Class({
+
+ /**
+ * Property: id
+ * {String} A unique identifier for this geometry.
+ */
+ id: null,
+
+ /**
+ * Property: parent
+ * {<OpenLayers.Geometry>}This is set when a Geometry is added as component
+ * of another geometry
+ */
+ parent: null,
+
+ /**
+ * Property: bounds
+ * {<OpenLayers.Bounds>} The bounds of this geometry
+ */
+ bounds: null,
+
+ /**
+ * Constructor: OpenLayers.Geometry
+ * Creates a geometry object.
+ */
+ initialize: function() {
+ this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME+ "_");
+ },
+
+ /**
+ * Method: destroy
+ * Destroy this geometry.
+ */
+ destroy: function() {
+ this.id = null;
+ this.bounds = null;
+ },
+
+ /**
+ * APIMethod: clone
+ * Create a clone of this geometry. Does not set any non-standard
+ * properties of the cloned geometry.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry>} An exact clone of this geometry.
+ */
+ clone: function() {
+ return new OpenLayers.Geometry();
+ },
+
+ /**
+ * Method: setBounds
+ * Set the bounds for this Geometry.
+ *
+ * Parameters:
+ * bounds - {<OpenLayers.Bounds>}
+ */
+ setBounds: function(bounds) {
+ if (bounds) {
+ this.bounds = bounds.clone();
+ }
+ },
+
+ /**
+ * Method: clearBounds
+ * Nullify this components bounds and that of its parent as well.
+ */
+ clearBounds: function() {
+ this.bounds = null;
+ if (this.parent) {
+ this.parent.clearBounds();
+ }
+ },
+
+ /**
+ * Method: extendBounds
+ * Extend the existing bounds to include the new bounds.
+ * If geometry's bounds is not yet set, then set a new Bounds.
+ *
+ * Parameters:
+ * newBounds - {<OpenLayers.Bounds>}
+ */
+ extendBounds: function(newBounds){
+ var bounds = this.getBounds();
+ if (!bounds) {
+ this.setBounds(newBounds);
+ } else {
+ this.bounds.extend(newBounds);
+ }
+ },
+
+ /**
+ * APIMethod: getBounds
+ * Get the bounds for this Geometry. If bounds is not set, it
+ * is calculated again, this makes queries faster.
+ *
+ * Returns:
+ * {<OpenLayers.Bounds>}
+ */
+ getBounds: function() {
+ if (this.bounds == null) {
+ this.calculateBounds();
+ }
+ return this.bounds;
+ },
+
+ /**
+ * APIMethod: calculateBounds
+ * Recalculate the bounds for the geometry.
+ */
+ calculateBounds: function() {
+ //
+ // This should be overridden by subclasses.
+ //
+ },
+
+ /**
+ * APIMethod: distanceTo
+ * Calculate the closest distance between two geometries (on the x-y plane).
+ *
+ * Parameters:
+ * geometry - {<OpenLayers.Geometry>} The target geometry.
+ * options - {Object} Optional properties for configuring the distance
+ * calculation.
+ *
+ * Valid options depend on the specific geometry type.
+ *
+ * Returns:
+ * {Number | Object} The distance between this geometry and the target.
+ * If details is true, the return will be an object with distance,
+ * x0, y0, x1, and x2 properties. The x0 and y0 properties represent
+ * the coordinates of the closest point on this geometry. The x1 and y1
+ * properties represent the coordinates of the closest point on the
+ * target geometry.
+ */
+ distanceTo: function(geometry, options) {
+ },
+
+ /**
+ * APIMethod: getVertices
+ * Return a list of all points in this geometry.
+ *
+ * Parameters:
+ * nodes - {Boolean} For lines, only return vertices that are
+ * endpoints. If false, for lines, only vertices that are not
+ * endpoints will be returned. If not provided, all vertices will
+ * be returned.
+ *
+ * Returns:
+ * {Array} A list of all vertices in the geometry.
+ */
+ getVertices: function(nodes) {
+ },
+
+ /**
+ * Method: atPoint
+ * Note - This is only an approximation based on the bounds of the
+ * geometry.
+ *
+ * Parameters:
+ * lonlat - {<OpenLayers.LonLat>|Object} OpenLayers.LonLat or an
+ * object with a 'lon' and 'lat' properties.
+ * toleranceLon - {float} Optional tolerance in Geometric Coords
+ * toleranceLat - {float} Optional tolerance in Geographic Coords
+ *
+ * Returns:
+ * {Boolean} Whether or not the geometry is at the specified location
+ */
+ atPoint: function(lonlat, toleranceLon, toleranceLat) {
+ var atPoint = false;
+ var bounds = this.getBounds();
+ if ((bounds != null) && (lonlat != null)) {
+
+ var dX = (toleranceLon != null) ? toleranceLon : 0;
+ var dY = (toleranceLat != null) ? toleranceLat : 0;
+
+ var toleranceBounds =
+ new OpenLayers.Bounds(this.bounds.left - dX,
+ this.bounds.bottom - dY,
+ this.bounds.right + dX,
+ this.bounds.top + dY);
+
+ atPoint = toleranceBounds.containsLonLat(lonlat);
+ }
+ return atPoint;
+ },
+
+ /**
+ * Method: getLength
+ * Calculate the length of this geometry. This method is defined in
+ * subclasses.
+ *
+ * Returns:
+ * {Float} The length of the collection by summing its parts
+ */
+ getLength: function() {
+ //to be overridden by geometries that actually have a length
+ //
+ return 0.0;
+ },
+
+ /**
+ * Method: getArea
+ * Calculate the area of this geometry. This method is defined in subclasses.
+ *
+ * Returns:
+ * {Float} The area of the collection by summing its parts
+ */
+ getArea: function() {
+ //to be overridden by geometries that actually have an area
+ //
+ return 0.0;
+ },
+
+ /**
+ * APIMethod: getCentroid
+ * Calculate the centroid of this geometry. This method is defined in subclasses.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry.Point>} The centroid of the collection
+ */
+ getCentroid: function() {
+ return null;
+ },
+
+ /**
+ * Method: toString
+ * Returns a text representation of the geometry. If the WKT format is
+ * included in a build, this will be the Well-Known Text
+ * representation.
+ *
+ * Returns:
+ * {String} String representation of this geometry.
+ */
+ toString: function() {
+ var string;
+ if (OpenLayers.Format && OpenLayers.Format.WKT) {
+ string = OpenLayers.Format.WKT.prototype.write(
+ new OpenLayers.Feature.Vector(this)
+ );
+ } else {
+ string = Object.prototype.toString.call(this);
+ }
+ return string;
+ },
+
+ CLASS_NAME: "OpenLayers.Geometry"
+});
+
+/**
+ * Function: OpenLayers.Geometry.fromWKT
+ * Generate a geometry given a Well-Known Text string. For this method to
+ * work, you must include the OpenLayers.Format.WKT in your build
+ * explicitly.
+ *
+ * Parameters:
+ * wkt - {String} A string representing the geometry in Well-Known Text.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry>} A geometry of the appropriate class.
+ */
+OpenLayers.Geometry.fromWKT = function(wkt) {
+ var geom;
+ if (OpenLayers.Format && OpenLayers.Format.WKT) {
+ var format = OpenLayers.Geometry.fromWKT.format;
+ if (!format) {
+ format = new OpenLayers.Format.WKT();
+ OpenLayers.Geometry.fromWKT.format = format;
+ }
+ var result = format.read(wkt);
+ if (result instanceof OpenLayers.Feature.Vector) {
+ geom = result.geometry;
+ } else if (OpenLayers.Util.isArray(result)) {
+ var len = result.length;
+ var components = new Array(len);
+ for (var i=0; i<len; ++i) {
+ components[i] = result[i].geometry;
+ }
+ geom = new OpenLayers.Geometry.Collection(components);
+ }
+ }
+ return geom;
+};
+
+/**
+ * Method: OpenLayers.Geometry.segmentsIntersect
+ * Determine whether two line segments intersect. Optionally calculates
+ * and returns the intersection point. This function is optimized for
+ * cases where seg1.x2 >= seg2.x1 || seg2.x2 >= seg1.x1. In those
+ * obvious cases where there is no intersection, the function should
+ * not be called.
+ *
+ * Parameters:
+ * seg1 - {Object} Object representing a segment with properties x1, y1, x2,
+ * and y2. The start point is represented by x1 and y1. The end point
+ * is represented by x2 and y2. Start and end are ordered so that x1 < x2.
+ * seg2 - {Object} Object representing a segment with properties x1, y1, x2,
+ * and y2. The start point is represented by x1 and y1. The end point
+ * is represented by x2 and y2. Start and end are ordered so that x1 < x2.
+ * options - {Object} Optional properties for calculating the intersection.
+ *
+ * Valid options:
+ * point - {Boolean} Return the intersection point. If false, the actual
+ * intersection point will not be calculated. If true and the segments
+ * intersect, the intersection point will be returned. If true and
+ * the segments do not intersect, false will be returned. If true and
+ * the segments are coincident, true will be returned.
+ * tolerance - {Number} If a non-null value is provided, if the segments are
+ * within the tolerance distance, this will be considered an intersection.
+ * In addition, if the point option is true and the calculated intersection
+ * is within the tolerance distance of an end point, the endpoint will be
+ * returned instead of the calculated intersection. Further, if the
+ * intersection is within the tolerance of endpoints on both segments, or
+ * if two segment endpoints are within the tolerance distance of eachother
+ * (but no intersection is otherwise calculated), an endpoint on the
+ * first segment provided will be returned.
+ *
+ * Returns:
+ * {Boolean | <OpenLayers.Geometry.Point>} The two segments intersect.
+ * If the point argument is true, the return will be the intersection
+ * point or false if none exists. If point is true and the segments
+ * are coincident, return will be true (and the instersection is equal
+ * to the shorter segment).
+ */
+OpenLayers.Geometry.segmentsIntersect = function(seg1, seg2, options) {
+ var point = options && options.point;
+ var tolerance = options && options.tolerance;
+ var intersection = false;
+ var x11_21 = seg1.x1 - seg2.x1;
+ var y11_21 = seg1.y1 - seg2.y1;
+ var x12_11 = seg1.x2 - seg1.x1;
+ var y12_11 = seg1.y2 - seg1.y1;
+ var y22_21 = seg2.y2 - seg2.y1;
+ var x22_21 = seg2.x2 - seg2.x1;
+ var d = (y22_21 * x12_11) - (x22_21 * y12_11);
+ var n1 = (x22_21 * y11_21) - (y22_21 * x11_21);
+ var n2 = (x12_11 * y11_21) - (y12_11 * x11_21);
+ if(d == 0) {
+ // parallel
+ if(n1 == 0 && n2 == 0) {
+ // coincident
+ intersection = true;
+ }
+ } else {
+ var along1 = n1 / d;
+ var along2 = n2 / d;
+ if(along1 >= 0 && along1 <= 1 && along2 >=0 && along2 <= 1) {
+ // intersect
+ if(!point) {
+ intersection = true;
+ } else {
+ // calculate the intersection point
+ var x = seg1.x1 + (along1 * x12_11);
+ var y = seg1.y1 + (along1 * y12_11);
+ intersection = new OpenLayers.Geometry.Point(x, y);
+ }
+ }
+ }
+ if(tolerance) {
+ var dist;
+ if(intersection) {
+ if(point) {
+ var segs = [seg1, seg2];
+ var seg, x, y;
+ // check segment endpoints for proximity to intersection
+ // set intersection to first endpoint within the tolerance
+ outer: for(var i=0; i<2; ++i) {
+ seg = segs[i];
+ for(var j=1; j<3; ++j) {
+ x = seg["x" + j];
+ y = seg["y" + j];
+ dist = Math.sqrt(
+ Math.pow(x - intersection.x, 2) +
+ Math.pow(y - intersection.y, 2)
+ );
+ if(dist < tolerance) {
+ intersection.x = x;
+ intersection.y = y;
+ break outer;
+ }
+ }
+ }
+
+ }
+ } else {
+ // no calculated intersection, but segments could be within
+ // the tolerance of one another
+ var segs = [seg1, seg2];
+ var source, target, x, y, p, result;
+ // check segment endpoints for proximity to intersection
+ // set intersection to first endpoint within the tolerance
+ outer: for(var i=0; i<2; ++i) {
+ source = segs[i];
+ target = segs[(i+1)%2];
+ for(var j=1; j<3; ++j) {
+ p = {x: source["x"+j], y: source["y"+j]};
+ result = OpenLayers.Geometry.distanceToSegment(p, target);
+ if(result.distance < tolerance) {
+ if(point) {
+ intersection = new OpenLayers.Geometry.Point(p.x, p.y);
+ } else {
+ intersection = true;
+ }
+ break outer;
+ }
+ }
+ }
+ }
+ }
+ return intersection;
+};
+
+/**
+ * Function: OpenLayers.Geometry.distanceToSegment
+ *
+ * Parameters:
+ * point - {Object} An object with x and y properties representing the
+ * point coordinates.
+ * segment - {Object} An object with x1, y1, x2, and y2 properties
+ * representing endpoint coordinates.
+ *
+ * Returns:
+ * {Object} An object with distance, along, x, and y properties. The distance
+ * will be the shortest distance between the input point and segment.
+ * The x and y properties represent the coordinates along the segment
+ * where the shortest distance meets the segment. The along attribute
+ * describes how far between the two segment points the given point is.
+ */
+OpenLayers.Geometry.distanceToSegment = function(point, segment) {
+ var result = OpenLayers.Geometry.distanceSquaredToSegment(point, segment);
+ result.distance = Math.sqrt(result.distance);
+ return result;
+};
+
+/**
+ * Function: OpenLayers.Geometry.distanceSquaredToSegment
+ *
+ * Usually the distanceToSegment function should be used. This variant however
+ * can be used for comparisons where the exact distance is not important.
+ *
+ * Parameters:
+ * point - {Object} An object with x and y properties representing the
+ * point coordinates.
+ * segment - {Object} An object with x1, y1, x2, and y2 properties
+ * representing endpoint coordinates.
+ *
+ * Returns:
+ * {Object} An object with squared distance, along, x, and y properties.
+ * The distance will be the shortest distance between the input point and
+ * segment. The x and y properties represent the coordinates along the
+ * segment where the shortest distance meets the segment. The along
+ * attribute describes how far between the two segment points the given
+ * point is.
+ */
+OpenLayers.Geometry.distanceSquaredToSegment = function(point, segment) {
+ var x0 = point.x;
+ var y0 = point.y;
+ var x1 = segment.x1;
+ var y1 = segment.y1;
+ var x2 = segment.x2;
+ var y2 = segment.y2;
+ var dx = x2 - x1;
+ var dy = y2 - y1;
+ var along = ((dx * (x0 - x1)) + (dy * (y0 - y1))) /
+ (Math.pow(dx, 2) + Math.pow(dy, 2));
+ var x, y;
+ if(along <= 0.0) {
+ x = x1;
+ y = y1;
+ } else if(along >= 1.0) {
+ x = x2;
+ y = y2;
+ } else {
+ x = x1 + along * dx;
+ y = y1 + along * dy;
+ }
+ return {
+ distance: Math.pow(x - x0, 2) + Math.pow(y - y0, 2),
+ x: x, y: y,
+ along: along
+ };
+};