Add split method for linestring and multilinestring geometries. Use for splitting one geometry with another. Optionally performs a mutual split. r=ahocevar (closes #1929)
git-svn-id: http://svn.openlayers.org/trunk/openlayers@8974 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
@@ -287,11 +287,23 @@ OpenLayers.Geometry.fromWKT = function(wkt) {
|
|||||||
* seg2 - {Object} Object representing a segment with properties x1, y1, 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
|
* 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.
|
* 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
|
* point - {Boolean} Return the intersection point. If false, the actual
|
||||||
* intersection point will not be calculated. If true and the segments
|
* intersection point will not be calculated. If true and the segments
|
||||||
* intersect, the intersection point will be returned. If true and
|
* intersect, the intersection point will be returned. If true and
|
||||||
* the segments do not intersect, false 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.
|
* 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:
|
* Returns:
|
||||||
* {Boolean | <OpenLayers.Geometry.Point>} The two segments intersect.
|
* {Boolean | <OpenLayers.Geometry.Point>} The two segments intersect.
|
||||||
@@ -300,7 +312,9 @@ OpenLayers.Geometry.fromWKT = function(wkt) {
|
|||||||
* are coincident, return will be true (and the instersection is equal
|
* are coincident, return will be true (and the instersection is equal
|
||||||
* to the shorter segment).
|
* to the shorter segment).
|
||||||
*/
|
*/
|
||||||
OpenLayers.Geometry.segmentsIntersect = function(seg1, seg2, point) {
|
OpenLayers.Geometry.segmentsIntersect = function(seg1, seg2, options) {
|
||||||
|
var point = options && options.point;
|
||||||
|
var tolerance = options && options.tolerance;
|
||||||
var intersection = false;
|
var intersection = false;
|
||||||
var x11_21 = seg1.x1 - seg2.x1;
|
var x11_21 = seg1.x1 - seg2.x1;
|
||||||
var y11_21 = seg1.y1 - seg2.y1;
|
var y11_21 = seg1.y1 - seg2.y1;
|
||||||
@@ -332,6 +346,57 @@ OpenLayers.Geometry.segmentsIntersect = function(seg1, seg2, point) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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;
|
return intersection;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -153,6 +153,237 @@ OpenLayers.Geometry.LineString = OpenLayers.Class(OpenLayers.Geometry.Curve, {
|
|||||||
}
|
}
|
||||||
return segments.sort(byX1);
|
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
|
* APIMethod: getVertices
|
||||||
@@ -225,7 +456,7 @@ OpenLayers.Geometry.LineString = OpenLayers.Class(OpenLayers.Geometry.Curve, {
|
|||||||
if(result.distance < min) {
|
if(result.distance < min) {
|
||||||
min = result.distance;
|
min = result.distance;
|
||||||
best = result;
|
best = result;
|
||||||
if(min == 0) {
|
if(min === 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -249,13 +480,14 @@ OpenLayers.Geometry.LineString = OpenLayers.Class(OpenLayers.Geometry.Curve, {
|
|||||||
var segs1 = geometry.getSortedSegments();
|
var segs1 = geometry.getSortedSegments();
|
||||||
var seg0, seg1, intersection, x0, y0;
|
var seg0, seg1, intersection, x0, y0;
|
||||||
var len1 = segs1.length;
|
var len1 = segs1.length;
|
||||||
|
var interOptions = {point: true};
|
||||||
outer: for(var i=0, len=segs0.length; i<len; ++i) {
|
outer: for(var i=0, len=segs0.length; i<len; ++i) {
|
||||||
seg0 = segs0[i];
|
seg0 = segs0[i];
|
||||||
x0 = seg0.x1;
|
x0 = seg0.x1;
|
||||||
y0 = seg0.y1;
|
y0 = seg0.y1;
|
||||||
for(var j=0; j<len1; ++j) {
|
for(var j=0; j<len1; ++j) {
|
||||||
seg1 = segs1[j];
|
seg1 = segs1[j];
|
||||||
intersection = OpenLayers.Geometry.segmentsIntersect(seg0, seg1, true);
|
intersection = OpenLayers.Geometry.segmentsIntersect(seg0, seg1, interOptions);
|
||||||
if(intersection) {
|
if(intersection) {
|
||||||
min = 0;
|
min = 0;
|
||||||
best = {
|
best = {
|
||||||
|
|||||||
@@ -39,6 +39,223 @@ OpenLayers.Geometry.MultiLineString = OpenLayers.Class(
|
|||||||
OpenLayers.Geometry.Collection.prototype.initialize.apply(this,
|
OpenLayers.Geometry.Collection.prototype.initialize.apply(this,
|
||||||
arguments);
|
arguments);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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(geometry, options) {
|
||||||
|
var results = null;
|
||||||
|
var mutual = options && options.mutual;
|
||||||
|
var splits, sourceLine, sourceLines, sourceSplit, targetSplit;
|
||||||
|
var sourceParts = [];
|
||||||
|
var targetParts = [geometry];
|
||||||
|
for(var i=0, len=this.components.length; i<len; ++i) {
|
||||||
|
sourceLine = this.components[i];
|
||||||
|
sourceSplit = false;
|
||||||
|
for(var j=0; j < targetParts.length; ++j) {
|
||||||
|
splits = sourceLine.split(targetParts[j], options);
|
||||||
|
if(splits) {
|
||||||
|
if(mutual) {
|
||||||
|
sourceLines = splits[0];
|
||||||
|
for(var k=0, klen=sourceLines.length; k<klen; ++k) {
|
||||||
|
if(k===0 && sourceParts.length) {
|
||||||
|
sourceParts[sourceParts.length-1].addComponent(
|
||||||
|
sourceLines[k]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
sourceParts.push(
|
||||||
|
new OpenLayers.Geometry.MultiLineString([
|
||||||
|
sourceLines[k]
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sourceSplit = true;
|
||||||
|
splits = splits[1];
|
||||||
|
}
|
||||||
|
if(splits.length) {
|
||||||
|
// splice in new target parts
|
||||||
|
splits.unshift(j, 1);
|
||||||
|
Array.prototype.splice.apply(targetParts, splits);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!sourceSplit) {
|
||||||
|
// source line was not hit
|
||||||
|
if(sourceParts.length) {
|
||||||
|
// add line to existing multi
|
||||||
|
sourceParts[sourceParts.length-1].addComponent(
|
||||||
|
sourceLine.clone()
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// create a fresh multi
|
||||||
|
sourceParts = [
|
||||||
|
new OpenLayers.Geometry.MultiLineString(
|
||||||
|
sourceLine.clone()
|
||||||
|
)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(sourceParts && sourceParts.length > 1) {
|
||||||
|
sourceSplit = true;
|
||||||
|
} else {
|
||||||
|
sourceParts = [];
|
||||||
|
}
|
||||||
|
if(targetParts && targetParts.length > 1) {
|
||||||
|
targetSplit = true;
|
||||||
|
} else {
|
||||||
|
targetParts = [];
|
||||||
|
}
|
||||||
|
if(sourceSplit || targetSplit) {
|
||||||
|
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) {
|
||||||
|
var results = null;
|
||||||
|
var mutual = options && options.mutual;
|
||||||
|
var splits, targetLine, sourceLines, sourceSplit, targetSplit, sourceParts, targetParts;
|
||||||
|
if(geometry instanceof OpenLayers.Geometry.LineString) {
|
||||||
|
targetParts = [];
|
||||||
|
sourceParts = [geometry];
|
||||||
|
for(var i=0, len=this.components.length; i<len; ++i) {
|
||||||
|
targetSplit = false;
|
||||||
|
targetLine = this.components[i];
|
||||||
|
for(var j=0; j<sourceParts.length; ++j) {
|
||||||
|
splits = sourceParts[j].split(targetLine, options);
|
||||||
|
if(splits) {
|
||||||
|
if(mutual) {
|
||||||
|
sourceLines = splits[0];
|
||||||
|
if(sourceLines.length) {
|
||||||
|
// splice in new source parts
|
||||||
|
sourceLines.unshift(j, 1);
|
||||||
|
Array.prototype.splice.apply(sourceParts, sourceLines);
|
||||||
|
j += sourceLines.length - 2;
|
||||||
|
}
|
||||||
|
splits = splits[1];
|
||||||
|
if(splits.length === 0) {
|
||||||
|
splits = [targetLine.clone()];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(var k=0, klen=splits.length; k<klen; ++k) {
|
||||||
|
if(k===0 && targetParts.length) {
|
||||||
|
targetParts[targetParts.length-1].addComponent(
|
||||||
|
splits[k]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
targetParts.push(
|
||||||
|
new OpenLayers.Geometry.MultiLineString([
|
||||||
|
splits[k]
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
targetSplit = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!targetSplit) {
|
||||||
|
// target component was not hit
|
||||||
|
if(targetParts.length) {
|
||||||
|
// add it to any existing multi-line
|
||||||
|
targetParts[targetParts.length-1].addComponent(
|
||||||
|
targetLine.clone()
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// or start with a fresh multi-line
|
||||||
|
targetParts = [
|
||||||
|
new OpenLayers.Geometry.MultiLineString([
|
||||||
|
targetLine.clone()
|
||||||
|
])
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
results = geometry.split(this);
|
||||||
|
}
|
||||||
|
if(sourceParts && sourceParts.length > 1) {
|
||||||
|
sourceSplit = true;
|
||||||
|
} else {
|
||||||
|
sourceParts = [];
|
||||||
|
}
|
||||||
|
if(targetParts && targetParts.length > 1) {
|
||||||
|
targetSplit = true;
|
||||||
|
} else {
|
||||||
|
targetParts = [];
|
||||||
|
}
|
||||||
|
if(sourceSplit || targetSplit) {
|
||||||
|
if(mutual) {
|
||||||
|
results = [sourceParts, targetParts];
|
||||||
|
} else {
|
||||||
|
results = targetParts;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
},
|
||||||
|
|
||||||
CLASS_NAME: "OpenLayers.Geometry.MultiLineString"
|
CLASS_NAME: "OpenLayers.Geometry.MultiLineString"
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -149,6 +149,105 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function test_split(t) {
|
||||||
|
var wkt = OpenLayers.Geometry.fromWKT;
|
||||||
|
|
||||||
|
var cases = [{
|
||||||
|
msg: "no intersection",
|
||||||
|
g1: "LINESTRING(0 0, 0 1)",
|
||||||
|
g2: "LINESTRING(1 0, 1 1)",
|
||||||
|
exp: null
|
||||||
|
} , {
|
||||||
|
msg: "intersection at midpoint",
|
||||||
|
g1: "LINESTRING(0 0, 1 1)",
|
||||||
|
g2: "LINESTRING(1 0, 0 1)",
|
||||||
|
exp: ["LINESTRING(1 0, 0.5 0.5)", "LINESTRING(0.5 0.5, 0 1)"]
|
||||||
|
}, {
|
||||||
|
msg: "intersection at midpoint (reverse source/target)",
|
||||||
|
g1: "LINESTRING(1 0, 0 1)",
|
||||||
|
g2: "LINESTRING(0 0, 1 1)",
|
||||||
|
exp: ["LINESTRING(0 0, 0.5 0.5)", "LINESTRING(0.5 0.5, 1 1)"]
|
||||||
|
}, {
|
||||||
|
msg: "intersection at endpoint",
|
||||||
|
g1: "LINESTRING(0 0, 1 1)",
|
||||||
|
g2: "LINESTRING(1 0, 1 1)",
|
||||||
|
exp: null
|
||||||
|
}, {
|
||||||
|
msg: "midpoint intersection, no options",
|
||||||
|
g1: "LINESTRING(0 0, 2 2)",
|
||||||
|
g2: "LINESTRING(0 2, 2 0)",
|
||||||
|
exp: ["LINESTRING(0 2, 1 1)", "LINESTRING(1 1, 2 0)"]
|
||||||
|
}, {
|
||||||
|
msg: "midpoint intersection, edge false",
|
||||||
|
opt: {edge: false},
|
||||||
|
g1: "LINESTRING(0 0, 2 2)",
|
||||||
|
g2: "LINESTRING(0 2, 2 0)",
|
||||||
|
exp: null
|
||||||
|
}, {
|
||||||
|
msg: "midpoint intersection, mutual",
|
||||||
|
opt: {mutual: true},
|
||||||
|
g1: "LINESTRING(0 0, 2 2)",
|
||||||
|
g2: "LINESTRING(0 2, 2 0)",
|
||||||
|
exp: [["LINESTRING(0 0, 1 1)", "LINESTRING(1 1, 2 2)"], ["LINESTRING(0 2, 1 1)", "LINESTRING(1 1, 2 0)"]]
|
||||||
|
}, {
|
||||||
|
msg: "close intersection, no tolerance",
|
||||||
|
g1: "LINESTRING(0 0, 0.9 0.9)",
|
||||||
|
g2: "LINESTRING(0 2, 2 0)",
|
||||||
|
exp: null
|
||||||
|
}, {
|
||||||
|
msg: "close intersection, within tolerance",
|
||||||
|
opt: {tolerance: 0.2},
|
||||||
|
g1: "LINESTRING(0 0, 0.9 0.9)",
|
||||||
|
g2: "LINESTRING(0 2, 2 0)",
|
||||||
|
exp: ["LINESTRING(0 2, 0.9 0.9)", "LINESTRING(0.9 0.9, 2 0)"]
|
||||||
|
}];
|
||||||
|
|
||||||
|
t.plan(cases.length);
|
||||||
|
var c, parts, part, midparts;
|
||||||
|
for(var i=0; i<cases.length; ++i) {
|
||||||
|
c = cases[i];
|
||||||
|
var g1 = wkt(c.g1);
|
||||||
|
var g2 = wkt(c.g2);
|
||||||
|
var got = g1.split(g2, c.opt);
|
||||||
|
var exp = c.exp;
|
||||||
|
if(got instanceof Array) {
|
||||||
|
parts = [];
|
||||||
|
for(var j=0; j<got.length; ++j) {
|
||||||
|
part = got[j];
|
||||||
|
if(part instanceof Array) {
|
||||||
|
midparts = [];
|
||||||
|
for(var k=0; k<part.length; ++k) {
|
||||||
|
midparts.push(part[k].toString());
|
||||||
|
}
|
||||||
|
parts.push("[" + midparts.join(", ") + "]");
|
||||||
|
} else {
|
||||||
|
parts.push(got[j].toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
got = parts.join(", ");
|
||||||
|
}
|
||||||
|
if(exp instanceof Array) {
|
||||||
|
parts = [];
|
||||||
|
for(var j=0; j<exp.length; ++j) {
|
||||||
|
part = exp[j];
|
||||||
|
if(part instanceof Array) {
|
||||||
|
midparts = [];
|
||||||
|
for(var k=0; k<part.length; ++k) {
|
||||||
|
midparts.push(wkt(part[k]).toString());
|
||||||
|
}
|
||||||
|
parts.push("[" + midparts.join(", ") + "]");
|
||||||
|
} else {
|
||||||
|
parts.push(wkt(exp[j]).toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exp = parts.join(", ");
|
||||||
|
}
|
||||||
|
t.eq(got, exp, "case " + i + ": " + c.msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function test_distanceTo(t) {
|
function test_distanceTo(t) {
|
||||||
var wkt = OpenLayers.Geometry.fromWKT;
|
var wkt = OpenLayers.Geometry.fromWKT;
|
||||||
var geoms = [
|
var geoms = [
|
||||||
|
|||||||
@@ -21,6 +21,196 @@
|
|||||||
t.eq( mline.components.length, 1, "mline.components.length is set correctly");
|
t.eq( mline.components.length, 1, "mline.components.length is set correctly");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function test_split(t) {
|
||||||
|
var wkt = OpenLayers.Geometry.fromWKT;
|
||||||
|
|
||||||
|
var cases = [{
|
||||||
|
msg: "no intersection",
|
||||||
|
g1: "MULTILINESTRING((0 0, 0 1), (2 2, 3 3))",
|
||||||
|
g2: "MULTILINESTRING((1 0, 1 1), (2 2, 3 2))",
|
||||||
|
exp: null
|
||||||
|
} , {
|
||||||
|
msg: "intersection at midpoint",
|
||||||
|
g1: "MULTILINESTRING((0 0, 1 1))",
|
||||||
|
g2: "MULTILINESTRING((1 0, 0 1))",
|
||||||
|
exp: ["MULTILINESTRING((1 0, 0.5 0.5))", "MULTILINESTRING((0.5 0.5, 0 1))"]
|
||||||
|
}, {
|
||||||
|
msg: "intersection at midpoint (reverse source/target)",
|
||||||
|
g1: "MULTILINESTRING((1 0, 0 1))",
|
||||||
|
g2: "MULTILINESTRING((0 0, 1 1))",
|
||||||
|
exp: ["MULTILINESTRING((0 0, 0.5 0.5))", "MULTILINESTRING((0.5 0.5, 1 1))"]
|
||||||
|
}, {
|
||||||
|
msg: "intersection at endpoint",
|
||||||
|
g1: "MULTILINESTRING((0 0, 1 1))",
|
||||||
|
g2: "MULTILINESTRING((1 0, 1 1))",
|
||||||
|
exp: null
|
||||||
|
}, {
|
||||||
|
msg: "midpoint intersection, no options",
|
||||||
|
g1: "MULTILINESTRING((0 0, 2 2))",
|
||||||
|
g2: "MULTILINESTRING((0 2, 2 0))",
|
||||||
|
exp: ["MULTILINESTRING((0 2, 1 1))", "MULTILINESTRING((1 1, 2 0))"]
|
||||||
|
}, {
|
||||||
|
msg: "midpoint intersection, edge false",
|
||||||
|
opt: {edge: false},
|
||||||
|
g1: "MULTILINESTRING((0 0, 2 2))",
|
||||||
|
g2: "MULTILINESTRING((0 2, 2 0))",
|
||||||
|
exp: null
|
||||||
|
}, {
|
||||||
|
msg: "midpoint intersection, mutual",
|
||||||
|
opt: {mutual: true},
|
||||||
|
g1: "MULTILINESTRING((0 0, 2 2))",
|
||||||
|
g2: "MULTILINESTRING((0 2, 2 0))",
|
||||||
|
exp: [["MULTILINESTRING((0 0, 1 1))", "MULTILINESTRING((1 1, 2 2))"], ["MULTILINESTRING((0 2, 1 1))", "MULTILINESTRING((1 1, 2 0))"]]
|
||||||
|
}, {
|
||||||
|
msg: "close intersection, no tolerance",
|
||||||
|
g1: "MULTILINESTRING((0 0, 0.9 0.9))",
|
||||||
|
g2: "MULTILINESTRING((0 2, 2 0))",
|
||||||
|
exp: null
|
||||||
|
}, {
|
||||||
|
msg: "close intersection, within tolerance",
|
||||||
|
opt: {tolerance: 0.2},
|
||||||
|
g1: "MULTILINESTRING((0 0, 0.9 0.9))",
|
||||||
|
g2: "MULTILINESTRING((0 2, 2 0))",
|
||||||
|
exp: ["MULTILINESTRING((0 2, 0.9 0.9))", "MULTILINESTRING((0.9 0.9, 2 0))"]
|
||||||
|
}, {
|
||||||
|
msg: "multi source, single target",
|
||||||
|
g1: "MULTILINESTRING((0 0, 2 2))",
|
||||||
|
g2: "LINESTRING(0 2, 2 0)",
|
||||||
|
exp: ["LINESTRING(0 2, 1 1)", "LINESTRING(1 1, 2 0)"]
|
||||||
|
}, {
|
||||||
|
msg: "multi source, single target, mutual split",
|
||||||
|
opt: {mutual: true},
|
||||||
|
g1: "MULTILINESTRING((0 0, 2 2))",
|
||||||
|
g2: "LINESTRING(0 2, 2 0)",
|
||||||
|
exp: [["MULTILINESTRING((0 0, 1 1))", "MULTILINESTRING((1 1, 2 2))"], ["LINESTRING(0 2, 1 1)", "LINESTRING(1 1, 2 0)"]]
|
||||||
|
}, {
|
||||||
|
msg: "single source, multi target",
|
||||||
|
g1: "LINESTRING(0 2, 2 0)",
|
||||||
|
g2: "MULTILINESTRING((0 0, 2 2))",
|
||||||
|
exp: ["MULTILINESTRING((0 0, 1 1))", "MULTILINESTRING((1 1, 2 2))"]
|
||||||
|
}, {
|
||||||
|
msg: "partial target split",
|
||||||
|
g1: "MULTILINESTRING((2 0, 0 2))",
|
||||||
|
g2: "MULTILINESTRING((0 0, 2 2), (3 3, 4 4))",
|
||||||
|
exp: ["MULTILINESTRING((0 0, 1 1))", "MULTILINESTRING((1 1, 2 2), (3 3, 4 4))"]
|
||||||
|
}, {
|
||||||
|
msg: "partial target split, mutual true",
|
||||||
|
opt: {mutual: true},
|
||||||
|
g1: "MULTILINESTRING((2 0, 0 2))",
|
||||||
|
g2: "MULTILINESTRING((0 0, 2 2), (3 3, 4 4))",
|
||||||
|
exp: [["MULTILINESTRING((2 0, 1 1))", "MULTILINESTRING((1 1, 0 2))"], ["MULTILINESTRING((0 0, 1 1))", "MULTILINESTRING((1 1, 2 2), (3 3, 4 4))"]]
|
||||||
|
}, {
|
||||||
|
msg: "partial source split, mutual true",
|
||||||
|
opt: {mutual: true},
|
||||||
|
g1: "MULTILINESTRING((0 0, 2 2), (3 3, 4 4))",
|
||||||
|
g2: "MULTILINESTRING((2 0, 0 2))",
|
||||||
|
exp: [["MULTILINESTRING((0 0, 1 1))", "MULTILINESTRING((1 1, 2 2), (3 3, 4 4))"], ["MULTILINESTRING((2 0, 1 1))", "MULTILINESTRING((1 1, 0 2))"]]
|
||||||
|
}, {
|
||||||
|
msg: "partial target split with source endpoint",
|
||||||
|
g1: "MULTILINESTRING((1 0, 1 1))",
|
||||||
|
g2: "MULTILINESTRING((0 0, 2 2), (3 3, 4 4))",
|
||||||
|
exp: ["MULTILINESTRING((0 0, 1 1))", "MULTILINESTRING((1 1, 2 2), (3 3, 4 4))"]
|
||||||
|
}, {
|
||||||
|
msg: "partial target split with source endpoint, mutual true",
|
||||||
|
opt: {mutual: true},
|
||||||
|
g1: "MULTILINESTRING((5 5, 6 6), (1 0, 1 1))",
|
||||||
|
g2: "MULTILINESTRING((0 0, 2 2), (3 3, 4 4))",
|
||||||
|
exp: [[], ["MULTILINESTRING((0 0, 1 1))", "MULTILINESTRING((1 1, 2 2), (3 3, 4 4))"]]
|
||||||
|
}, {
|
||||||
|
msg: "partial source split with target endpoint",
|
||||||
|
g1: "MULTILINESTRING((0 0, 2 2), (3 3, 4 4))",
|
||||||
|
g2: "MULTILINESTRING((1 0, 1 1))",
|
||||||
|
exp: null
|
||||||
|
}, {
|
||||||
|
msg: "partial source split with target endpoint, mutual true",
|
||||||
|
opt: {mutual: true},
|
||||||
|
g1: "MULTILINESTRING((0 0, 2 2), (3 3, 4 4), (5 5, 6 6))",
|
||||||
|
g2: "MULTILINESTRING((1 0, 1 1))",
|
||||||
|
exp: [["MULTILINESTRING((0 0, 1 1))", "MULTILINESTRING((1 1, 2 2), (3 3, 4 4), (5 5, 6 6))"], []]
|
||||||
|
}, {
|
||||||
|
msg: "partial target and source split",
|
||||||
|
g1: "MULTILINESTRING((0 5, 2 5), (4 5, 6 5), (8 5, 10 5))",
|
||||||
|
g2: "MULTILINESTRING((5 0, 5 2), (5 4, 5 6), (5 8, 5 10))",
|
||||||
|
exp: ["MULTILINESTRING((5 0, 5 2), (5 4, 5 5))", "MULTILINESTRING((5 5, 5 6), (5 8, 5 10))"]
|
||||||
|
}, {
|
||||||
|
msg: "partial target and source split, mutual true",
|
||||||
|
opt: {mutual: true},
|
||||||
|
g1: "MULTILINESTRING((0 5, 2 5), (4 5, 6 5), (8 5, 10 5))",
|
||||||
|
g2: "MULTILINESTRING((5 0, 5 2), (5 4, 5 6), (5 8, 5 10))",
|
||||||
|
exp: [["MULTILINESTRING((0 5, 2 5), (4 5, 5 5))", "MULTILINESTRING((5 5, 6 5), (8 5, 10 5))"],
|
||||||
|
["MULTILINESTRING((5 0, 5 2), (5 4, 5 5))", "MULTILINESTRING((5 5, 5 6), (5 8, 5 10))"]]
|
||||||
|
}, {
|
||||||
|
msg: "partial target and source split with source endpoint, mutual true",
|
||||||
|
opt: {mutual: true},
|
||||||
|
g1: "MULTILINESTRING((0 5, 2 5), (4 5, 6 5), (8 5, 10 5))",
|
||||||
|
g2: "MULTILINESTRING((4 0, 4 2), (4 4, 4 6), (4 8, 4 10))",
|
||||||
|
exp: [[], ["MULTILINESTRING((4 0, 4 2), (4 4, 4 5))", "MULTILINESTRING((4 5, 4 6), (4 8, 4 10))"]]
|
||||||
|
}, {
|
||||||
|
msg: "partial target and source split with target endpoint, mutual true",
|
||||||
|
opt: {mutual: true},
|
||||||
|
g1: "MULTILINESTRING((4 0, 4 2), (4 4, 4 6), (4 8, 4 10))",
|
||||||
|
g2: "MULTILINESTRING((0 5, 2 5), (4 5, 6 5), (8 5, 10 5))",
|
||||||
|
exp: [["MULTILINESTRING((4 0, 4 2), (4 4, 4 5))", "MULTILINESTRING((4 5, 4 6), (4 8, 4 10))"], []]
|
||||||
|
}, {
|
||||||
|
msg: "partial target and source split with source vertex, mutual true",
|
||||||
|
opt: {mutual: true},
|
||||||
|
g1: "MULTILINESTRING((0 5, 2 5), (4 5, 5 5, 6 5), (8 5, 10 5))",
|
||||||
|
g2: "MULTILINESTRING((5 0, 5 2), (5 4, 5 6), (5 8, 5 10))",
|
||||||
|
exp: [["MULTILINESTRING((0 5, 2 5), (4 5, 5 5))", "MULTILINESTRING((5 5, 6 5), (8 5, 10 5))"], ["MULTILINESTRING((5 0, 5 2), (5 4, 5 5))", "MULTILINESTRING((5 5, 5 6), (5 8, 5 10))"]]
|
||||||
|
}, {
|
||||||
|
msg: "partial target and source split with target vertex, mutual true",
|
||||||
|
opt: {mutual: true},
|
||||||
|
g1: "MULTILINESTRING((5 0, 5 2), (5 4, 5 6), (5 8, 5 10))",
|
||||||
|
g2: "MULTILINESTRING((0 5, 2 5), (4 5, 5 5, 6 5), (8 5, 10 5))",
|
||||||
|
exp: [["MULTILINESTRING((5 0, 5 2), (5 4, 5 5))", "MULTILINESTRING((5 5, 5 6), (5 8, 5 10))"], ["MULTILINESTRING((0 5, 2 5), (4 5, 5 5))", "MULTILINESTRING((5 5, 6 5), (8 5, 10 5))"]]
|
||||||
|
}];
|
||||||
|
|
||||||
|
|
||||||
|
t.plan(cases.length);
|
||||||
|
var c, parts, part, midparts;
|
||||||
|
for(var i=0; i<cases.length; ++i) {
|
||||||
|
c = cases[i];
|
||||||
|
var g1 = wkt(c.g1);
|
||||||
|
var g2 = wkt(c.g2);
|
||||||
|
var got = g1.split(g2, c.opt);
|
||||||
|
var exp = c.exp;
|
||||||
|
if(got instanceof Array) {
|
||||||
|
parts = [];
|
||||||
|
for(var j=0; j<got.length; ++j) {
|
||||||
|
part = got[j];
|
||||||
|
if(part instanceof Array) {
|
||||||
|
midparts = [];
|
||||||
|
for(var k=0; k<part.length; ++k) {
|
||||||
|
midparts.push(part[k].toString());
|
||||||
|
}
|
||||||
|
parts.push("[" + midparts.join(", ") + "]");
|
||||||
|
} else {
|
||||||
|
parts.push(got[j].toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
got = parts.join(", ");
|
||||||
|
}
|
||||||
|
if(exp instanceof Array) {
|
||||||
|
parts = [];
|
||||||
|
for(var j=0; j<exp.length; ++j) {
|
||||||
|
part = exp[j];
|
||||||
|
if(part instanceof Array) {
|
||||||
|
midparts = [];
|
||||||
|
for(var k=0; k<part.length; ++k) {
|
||||||
|
midparts.push(wkt(part[k]).toString());
|
||||||
|
}
|
||||||
|
parts.push("[" + midparts.join(", ") + "]");
|
||||||
|
} else {
|
||||||
|
parts.push(wkt(exp[j]).toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exp = parts.join(", ");
|
||||||
|
}
|
||||||
|
t.eq(got, exp, "case " + i + ": " + c.msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
function test_getVertices(t) {
|
function test_getVertices(t) {
|
||||||
t.plan(22);
|
t.plan(22);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user