diff options
Diffstat (limited to 'misc/openlayers/lib/OpenLayers/Geometry/LineString.js')
-rw-r--r-- | misc/openlayers/lib/OpenLayers/Geometry/LineString.js | 646 |
1 files changed, 0 insertions, 646 deletions
diff --git a/misc/openlayers/lib/OpenLayers/Geometry/LineString.js b/misc/openlayers/lib/OpenLayers/Geometry/LineString.js deleted file mode 100644 index b7d7dac..0000000 --- a/misc/openlayers/lib/OpenLayers/Geometry/LineString.js +++ /dev/null @@ -1,646 +0,0 @@ -/* 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/Geometry/Curve.js - */ - -/** - * Class: OpenLayers.Geometry.LineString - * A LineString is a Curve which, once two points have been added to it, can - * never be less than two points long. - * - * Inherits from: - * - <OpenLayers.Geometry.Curve> - */ -OpenLayers.Geometry.LineString = OpenLayers.Class(OpenLayers.Geometry.Curve, { - - /** - * Constructor: OpenLayers.Geometry.LineString - * Create a new LineString geometry - * - * Parameters: - * points - {Array(<OpenLayers.Geometry.Point>)} An array of points used to - * generate the linestring - * - */ - - /** - * APIMethod: removeComponent - * Only allows removal of a point if there are three or more points in - * the linestring. (otherwise the result would be just a single point) - * - * Parameters: - * point - {<OpenLayers.Geometry.Point>} The point to be removed - * - * Returns: - * {Boolean} The component was removed. - */ - removeComponent: function(point) { - var removed = this.components && (this.components.length > 2); - if (removed) { - OpenLayers.Geometry.Collection.prototype.removeComponent.apply(this, - arguments); - } - return removed; - }, - - /** - * APIMethod: intersects - * Test for instersection between two geometries. This is a cheapo - * implementation of the Bently-Ottmann algorigithm. It doesn't - * really keep track of a sweep line data structure. It is closer - * to the brute force method, except that segments are sorted and - * potential intersections are only calculated when bounding boxes - * intersect. - * - * Parameters: - * geometry - {<OpenLayers.Geometry>} - * - * Returns: - * {Boolean} The input geometry intersects this geometry. - */ - intersects: function(geometry) { - var intersect = false; - var type = geometry.CLASS_NAME; - if(type == "OpenLayers.Geometry.LineString" || - type == "OpenLayers.Geometry.LinearRing" || - type == "OpenLayers.Geometry.Point") { - var segs1 = this.getSortedSegments(); - var segs2; - if(type == "OpenLayers.Geometry.Point") { - segs2 = [{ - x1: geometry.x, y1: geometry.y, - x2: geometry.x, y2: geometry.y - }]; - } else { - segs2 = geometry.getSortedSegments(); - } - var seg1, seg1x1, seg1x2, seg1y1, seg1y2, - seg2, seg2y1, seg2y2; - // sweep right - outer: for(var i=0, len=segs1.length; i<len; ++i) { - seg1 = segs1[i]; - seg1x1 = seg1.x1; - seg1x2 = seg1.x2; - seg1y1 = seg1.y1; - seg1y2 = seg1.y2; - inner: for(var j=0, jlen=segs2.length; j<jlen; ++j) { - seg2 = segs2[j]; - if(seg2.x1 > seg1x2) { - // seg1 still left of seg2 - break; - } - if(seg2.x2 < seg1x1) { - // seg2 still left of seg1 - continue; - } - seg2y1 = seg2.y1; - seg2y2 = seg2.y2; - if(Math.min(seg2y1, seg2y2) > Math.max(seg1y1, seg1y2)) { - // seg2 above seg1 - continue; - } - if(Math.max(seg2y1, seg2y2) < Math.min(seg1y1, seg1y2)) { - // seg2 below seg1 - continue; - } - if(OpenLayers.Geometry.segmentsIntersect(seg1, seg2)) { - intersect = true; - break outer; - } - } - } - } else { - intersect = geometry.intersects(this); - } - return intersect; - }, - - /** - * Method: getSortedSegments - * - * Returns: - * {Array} An array of segment objects. Segment objects have 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. - */ - getSortedSegments: function() { - var numSeg = this.components.length - 1; - var segments = new Array(numSeg), point1, point2; - for(var i=0; i<numSeg; ++i) { - point1 = this.components[i]; - point2 = this.components[i + 1]; - if(point1.x < point2.x) { - segments[i] = { - x1: point1.x, - y1: point1.y, - x2: point2.x, - y2: point2.y - }; - } else { - segments[i] = { - x1: point2.x, - y1: point2.y, - x2: point1.x, - y2: point1.y - }; - } - } - // more efficient to define this somewhere static - function byX1(seg1, seg2) { - return seg1.x1 - seg2.x1; - } - return segments.sort(byX1); - }, - - /** - * Method: splitWithSegment - * Split this geometry with the given segment. - * - * Parameters: - * seg - {Object} An object with x1, y1, x2, and y2 properties referencing - * segment endpoint coordinates. - * options - {Object} Properties of this object will be used to determine - * how the split is conducted. - * - * Valid options: - * edge - {Boolean} Allow splitting when only edges intersect. Default is - * true. If false, a vertex on the source segment must be within the - * tolerance distance of the intersection to be considered a split. - * tolerance - {Number} If a non-null value is provided, intersections - * within the tolerance distance of one of the source segment's - * endpoints will be assumed to occur at the endpoint. - * - * Returns: - * {Object} An object with *lines* and *points* properties. If the given - * segment intersects this linestring, the lines array will reference - * geometries that result from the split. The points array will contain - * all intersection points. Intersection points are sorted along the - * segment (in order from x1,y1 to x2,y2). - */ - splitWithSegment: function(seg, options) { - var edge = !(options && options.edge === false); - var tolerance = options && options.tolerance; - var lines = []; - var verts = this.getVertices(); - var points = []; - var intersections = []; - var split = false; - var vert1, vert2, point; - var node, vertex, target; - var interOptions = {point: true, tolerance: tolerance}; - var result = null; - for(var i=0, stop=verts.length-2; i<=stop; ++i) { - vert1 = verts[i]; - points.push(vert1.clone()); - vert2 = verts[i+1]; - target = {x1: vert1.x, y1: vert1.y, x2: vert2.x, y2: vert2.y}; - point = OpenLayers.Geometry.segmentsIntersect( - seg, target, interOptions - ); - if(point instanceof OpenLayers.Geometry.Point) { - if((point.x === seg.x1 && point.y === seg.y1) || - (point.x === seg.x2 && point.y === seg.y2) || - point.equals(vert1) || point.equals(vert2)) { - vertex = true; - } else { - vertex = false; - } - if(vertex || edge) { - // push intersections different than the previous - if(!point.equals(intersections[intersections.length-1])) { - intersections.push(point.clone()); - } - if(i === 0) { - if(point.equals(vert1)) { - continue; - } - } - if(point.equals(vert2)) { - continue; - } - split = true; - if(!point.equals(vert1)) { - points.push(point); - } - lines.push(new OpenLayers.Geometry.LineString(points)); - points = [point.clone()]; - } - } - } - if(split) { - points.push(vert2.clone()); - lines.push(new OpenLayers.Geometry.LineString(points)); - } - if(intersections.length > 0) { - // sort intersections along segment - var xDir = seg.x1 < seg.x2 ? 1 : -1; - var yDir = seg.y1 < seg.y2 ? 1 : -1; - result = { - lines: lines, - points: intersections.sort(function(p1, p2) { - return (xDir * p1.x - xDir * p2.x) || (yDir * p1.y - yDir * p2.y); - }) - }; - } - return result; - }, - - /** - * Method: split - * Use this geometry (the source) to attempt to split a target geometry. - * - * Parameters: - * target - {<OpenLayers.Geometry>} The target geometry. - * options - {Object} Properties of this object will be used to determine - * how the split is conducted. - * - * Valid options: - * mutual - {Boolean} Split the source geometry in addition to the target - * geometry. Default is false. - * edge - {Boolean} Allow splitting when only edges intersect. Default is - * true. If false, a vertex on the source must be within the tolerance - * distance of the intersection to be considered a split. - * tolerance - {Number} If a non-null value is provided, intersections - * within the tolerance distance of an existing vertex on the source - * will be assumed to occur at the vertex. - * - * Returns: - * {Array} A list of geometries (of this same type as the target) that - * result from splitting the target with the source geometry. The - * source and target geometry will remain unmodified. If no split - * results, null will be returned. If mutual is true and a split - * results, return will be an array of two arrays - the first will be - * all geometries that result from splitting the source geometry and - * the second will be all geometries that result from splitting the - * target geometry. - */ - split: function(target, options) { - var results = null; - var mutual = options && options.mutual; - var sourceSplit, targetSplit, sourceParts, targetParts; - if(target instanceof OpenLayers.Geometry.LineString) { - var verts = this.getVertices(); - var vert1, vert2, seg, splits, lines, point; - var points = []; - sourceParts = []; - for(var i=0, stop=verts.length-2; i<=stop; ++i) { - vert1 = verts[i]; - vert2 = verts[i+1]; - seg = { - x1: vert1.x, y1: vert1.y, - x2: vert2.x, y2: vert2.y - }; - targetParts = targetParts || [target]; - if(mutual) { - points.push(vert1.clone()); - } - for(var j=0; j<targetParts.length; ++j) { - splits = targetParts[j].splitWithSegment(seg, options); - if(splits) { - // splice in new features - lines = splits.lines; - if(lines.length > 0) { - lines.unshift(j, 1); - Array.prototype.splice.apply(targetParts, lines); - j += lines.length - 2; - } - if(mutual) { - for(var k=0, len=splits.points.length; k<len; ++k) { - point = splits.points[k]; - if(!point.equals(vert1)) { - points.push(point); - sourceParts.push(new OpenLayers.Geometry.LineString(points)); - if(point.equals(vert2)) { - points = []; - } else { - points = [point.clone()]; - } - } - } - } - } - } - } - if(mutual && sourceParts.length > 0 && points.length > 0) { - points.push(vert2.clone()); - sourceParts.push(new OpenLayers.Geometry.LineString(points)); - } - } else { - results = target.splitWith(this, options); - } - if(targetParts && targetParts.length > 1) { - targetSplit = true; - } else { - targetParts = []; - } - if(sourceParts && sourceParts.length > 1) { - sourceSplit = true; - } else { - sourceParts = []; - } - if(targetSplit || sourceSplit) { - if(mutual) { - results = [sourceParts, targetParts]; - } else { - results = targetParts; - } - } - return results; - }, - - /** - * Method: splitWith - * Split this geometry (the target) with the given geometry (the source). - * - * Parameters: - * geometry - {<OpenLayers.Geometry>} A geometry used to split this - * geometry (the source). - * options - {Object} Properties of this object will be used to determine - * how the split is conducted. - * - * Valid options: - * mutual - {Boolean} Split the source geometry in addition to the target - * geometry. Default is false. - * edge - {Boolean} Allow splitting when only edges intersect. Default is - * true. If false, a vertex on the source must be within the tolerance - * distance of the intersection to be considered a split. - * tolerance - {Number} If a non-null value is provided, intersections - * within the tolerance distance of an existing vertex on the source - * will be assumed to occur at the vertex. - * - * Returns: - * {Array} A list of geometries (of this same type as the target) that - * result from splitting the target with the source geometry. The - * source and target geometry will remain unmodified. If no split - * results, null will be returned. If mutual is true and a split - * results, return will be an array of two arrays - the first will be - * all geometries that result from splitting the source geometry and - * the second will be all geometries that result from splitting the - * target geometry. - */ - splitWith: function(geometry, options) { - return geometry.split(this, 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) { - var vertices; - if(nodes === true) { - vertices = [ - this.components[0], - this.components[this.components.length-1] - ]; - } else if (nodes === false) { - vertices = this.components.slice(1, this.components.length-1); - } else { - vertices = this.components.slice(); - } - return vertices; - }, - - /** - * 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: - * details - {Boolean} Return details from the distance calculation. - * Default is false. - * edge - {Boolean} Calculate the distance from this geometry to the - * nearest edge of the target geometry. Default is true. If true, - * calling distanceTo from a geometry that is wholly contained within - * the target will result in a non-zero distance. If false, whenever - * geometries intersect, calling distanceTo will return 0. If false, - * details cannot be returned. - * - * 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) { - var edge = !(options && options.edge === false); - var details = edge && options && options.details; - var result, best = {}; - var min = Number.POSITIVE_INFINITY; - if(geometry instanceof OpenLayers.Geometry.Point) { - var segs = this.getSortedSegments(); - var x = geometry.x; - var y = geometry.y; - var seg; - for(var i=0, len=segs.length; i<len; ++i) { - seg = segs[i]; - result = OpenLayers.Geometry.distanceToSegment(geometry, seg); - if(result.distance < min) { - min = result.distance; - best = result; - if(min === 0) { - break; - } - } else { - // if distance increases and we cross y0 to the right of x0, no need to keep looking. - if(seg.x2 > x && ((y > seg.y1 && y < seg.y2) || (y < seg.y1 && y > seg.y2))) { - break; - } - } - } - if(details) { - best = { - distance: best.distance, - x0: best.x, y0: best.y, - x1: x, y1: y - }; - } else { - best = best.distance; - } - } else if(geometry instanceof OpenLayers.Geometry.LineString) { - var segs0 = this.getSortedSegments(); - var segs1 = geometry.getSortedSegments(); - var seg0, seg1, intersection, x0, y0; - var len1 = segs1.length; - var interOptions = {point: true}; - outer: for(var i=0, len=segs0.length; i<len; ++i) { - seg0 = segs0[i]; - x0 = seg0.x1; - y0 = seg0.y1; - for(var j=0; j<len1; ++j) { - seg1 = segs1[j]; - intersection = OpenLayers.Geometry.segmentsIntersect(seg0, seg1, interOptions); - if(intersection) { - min = 0; - best = { - distance: 0, - x0: intersection.x, y0: intersection.y, - x1: intersection.x, y1: intersection.y - }; - break outer; - } else { - result = OpenLayers.Geometry.distanceToSegment({x: x0, y: y0}, seg1); - if(result.distance < min) { - min = result.distance; - best = { - distance: min, - x0: x0, y0: y0, - x1: result.x, y1: result.y - }; - } - } - } - } - if(!details) { - best = best.distance; - } - if(min !== 0) { - // check the final vertex in this line's sorted segments - if(seg0) { - result = geometry.distanceTo( - new OpenLayers.Geometry.Point(seg0.x2, seg0.y2), - options - ); - var dist = details ? result.distance : result; - if(dist < min) { - if(details) { - best = { - distance: min, - x0: result.x1, y0: result.y1, - x1: result.x0, y1: result.y0 - }; - } else { - best = dist; - } - } - } - } - } else { - best = geometry.distanceTo(this, options); - // swap since target comes from this line - if(details) { - best = { - distance: best.distance, - x0: best.x1, y0: best.y1, - x1: best.x0, y1: best.y0 - }; - } - } - return best; - }, - - /** - * APIMethod: simplify - * This function will return a simplified LineString. - * Simplification is based on the Douglas-Peucker algorithm. - * - * - * Parameters: - * tolerance - {number} threshhold for simplification in map units - * - * Returns: - * {OpenLayers.Geometry.LineString} the simplified LineString - */ - simplify: function(tolerance){ - if (this && this !== null) { - var points = this.getVertices(); - if (points.length < 3) { - return this; - } - - var compareNumbers = function(a, b){ - return (a-b); - }; - - /** - * Private function doing the Douglas-Peucker reduction - */ - var douglasPeuckerReduction = function(points, firstPoint, lastPoint, tolerance){ - var maxDistance = 0; - var indexFarthest = 0; - - for (var index = firstPoint, distance; index < lastPoint; index++) { - distance = perpendicularDistance(points[firstPoint], points[lastPoint], points[index]); - if (distance > maxDistance) { - maxDistance = distance; - indexFarthest = index; - } - } - - if (maxDistance > tolerance && indexFarthest != firstPoint) { - //Add the largest point that exceeds the tolerance - pointIndexsToKeep.push(indexFarthest); - douglasPeuckerReduction(points, firstPoint, indexFarthest, tolerance); - douglasPeuckerReduction(points, indexFarthest, lastPoint, tolerance); - } - }; - - /** - * Private function calculating the perpendicular distance - * TODO: check whether OpenLayers.Geometry.LineString::distanceTo() is faster or slower - */ - var perpendicularDistance = function(point1, point2, point){ - //Area = |(1/2)(x1y2 + x2y3 + x3y1 - x2y1 - x3y2 - x1y3)| *Area of triangle - //Base = v((x1-x2)²+(x1-x2)²) *Base of Triangle* - //Area = .5*Base*H *Solve for height - //Height = Area/.5/Base - - var area = Math.abs(0.5 * (point1.x * point2.y + point2.x * point.y + point.x * point1.y - point2.x * point1.y - point.x * point2.y - point1.x * point.y)); - var bottom = Math.sqrt(Math.pow(point1.x - point2.x, 2) + Math.pow(point1.y - point2.y, 2)); - var height = area / bottom * 2; - - return height; - }; - - var firstPoint = 0; - var lastPoint = points.length - 1; - var pointIndexsToKeep = []; - - //Add the first and last index to the keepers - pointIndexsToKeep.push(firstPoint); - pointIndexsToKeep.push(lastPoint); - - //The first and the last point cannot be the same - while (points[firstPoint].equals(points[lastPoint])) { - lastPoint--; - //Addition: the first point not equal to first point in the LineString is kept as well - pointIndexsToKeep.push(lastPoint); - } - - douglasPeuckerReduction(points, firstPoint, lastPoint, tolerance); - var returnPoints = []; - pointIndexsToKeep.sort(compareNumbers); - for (var index = 0; index < pointIndexsToKeep.length; index++) { - returnPoints.push(points[pointIndexsToKeep[index]]); - } - return new OpenLayers.Geometry.LineString(returnPoints); - - } - else { - return this; - } - }, - - CLASS_NAME: "OpenLayers.Geometry.LineString" -}); |