Index: tests/Geometry/LineString.html
===================================================================
--- tests/Geometry/LineString.html	(revision 8842)
+++ tests/Geometry/LineString.html	(working copy)
@@ -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) {
         var wkt = OpenLayers.Geometry.fromWKT;
         var geoms = [
Index: tests/Geometry/MultiLineString.html
===================================================================
--- tests/Geometry/MultiLineString.html	(revision 8842)
+++ tests/Geometry/MultiLineString.html	(working copy)
@@ -21,6 +21,196 @@
         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) {
         t.plan(16);
         
Index: lib/OpenLayers/Geometry/MultiLineString.js
===================================================================
--- lib/OpenLayers/Geometry/MultiLineString.js	(revision 8842)
+++ lib/OpenLayers/Geometry/MultiLineString.js	(working copy)
@@ -39,6 +39,223 @@
         OpenLayers.Geometry.Collection.prototype.initialize.apply(this, 
                                                                   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"
 });
Index: lib/OpenLayers/Geometry/LineString.js
===================================================================
--- lib/OpenLayers/Geometry/LineString.js	(revision 8842)
+++ lib/OpenLayers/Geometry/LineString.js	(working copy)
@@ -153,8 +153,239 @@
         }
         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.
      *
@@ -221,7 +452,7 @@
                 if(result.distance < min) {
                     min = result.distance;
                     best = result;
-                    if(min == 0) {
+                    if(min === 0) {
                         break;
                     }
                 } else {
@@ -245,13 +476,14 @@
             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, true);
+                    intersection = OpenLayers.Geometry.segmentsIntersect(seg0, seg1, interOptions);
                     if(intersection) {
                         min = 0;
                         best = {
Index: lib/OpenLayers/Geometry.js
===================================================================
--- lib/OpenLayers/Geometry.js	(revision 8842)
+++ lib/OpenLayers/Geometry.js	(working copy)
@@ -285,11 +285,23 @@
  * 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.
@@ -298,7 +310,9 @@
  *     are coincident, return will be true (and the instersection is equal
  *     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 x11_21 = seg1.x1 - seg2.x1;
     var y11_21 = seg1.y1 - seg2.y1;
@@ -330,6 +344,57 @@
             }
         }
     }
+    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;
 };
 
