function split()

in modules/actions/split.js [99:264]


    function split(graph, nodeId, wayA, newWayId) {
        var wayB = osmWay({ id: newWayId, tags: wayA.tags });   // `wayB` is the NEW way
        var origNodes = wayA.nodes.slice();
        var nodesA;
        var nodesB;
        var isArea = wayA.isArea();
        var isOuter = osmIsOldMultipolygonOuterMember(wayA, graph);

        if (wayA.isClosed()) {
            var nodes = wayA.nodes.slice(0, -1);
            var idxA = nodes.indexOf(nodeId);
            var idxB = splitArea(nodes, idxA, graph);

            if (idxB < idxA) {
                nodesA = nodes.slice(idxA).concat(nodes.slice(0, idxB + 1));
                nodesB = nodes.slice(idxB, idxA + 1);
            } else {
                nodesA = nodes.slice(idxA, idxB + 1);
                nodesB = nodes.slice(idxB).concat(nodes.slice(0, idxA + 1));
            }
        } else {
            var idx = wayA.nodes.indexOf(nodeId, 1);
            nodesA = wayA.nodes.slice(0, idx + 1);
            nodesB = wayA.nodes.slice(idx);
        }

        var lengthA = totalLengthBetweenNodes(graph, nodesA);
        var lengthB = totalLengthBetweenNodes(graph, nodesB);

        if (_keepHistoryOn === 'longest' &&
            lengthB > lengthA) {
            // keep the history on the longer way, regardless of the node count
            wayA = wayA.update({ nodes: nodesB });
            wayB = wayB.update({ nodes: nodesA });

            var temp = lengthA;
            lengthA = lengthB;
            lengthB = temp;
        } else {
            wayA = wayA.update({ nodes: nodesA });
            wayB = wayB.update({ nodes: nodesB });
        }

        if (wayA.tags.step_count) {
            // divide up the the step count proportionally between the two ways

            var stepCount = parseFloat(wayA.tags.step_count);
            if (stepCount &&
                // ensure a number
                isFinite(stepCount) &&
                // ensure positive
                stepCount > 0 &&
                // ensure integer
                Math.round(stepCount) === stepCount) {

                var tagsA = Object.assign({}, wayA.tags);
                var tagsB = Object.assign({}, wayB.tags);

                var ratioA = lengthA / (lengthA + lengthB);
                var countA = Math.round(stepCount * ratioA);
                tagsA.step_count = countA.toString();
                tagsB.step_count = (stepCount - countA).toString();

                wayA = wayA.update({ tags: tagsA });
                wayB = wayB.update({ tags: tagsB });
            }
        }


        graph = graph.replace(wayA);
        graph = graph.replace(wayB);

        graph.parentRelations(wayA).forEach(function(relation) {
            var member;

            // Turn restrictions - make sure:
            // 1. Splitting a FROM/TO way - only `wayA` OR `wayB` remains in relation
            //    (whichever one is connected to the VIA node/ways)
            // 2. Splitting a VIA way - `wayB` remains in relation as a VIA way
            if (relation.hasFromViaTo()) {
                var f = relation.memberByRole('from');
                var v = relation.membersByRole('via');
                var t = relation.memberByRole('to');
                var i;

                // 1. split a FROM/TO
                if (f.id === wayA.id || t.id === wayA.id) {
                    var keepB = false;
                    if (v.length === 1 && v[0].type === 'node') {   // check via node
                        keepB = wayB.contains(v[0].id);
                    } else {                                        // check via way(s)
                        for (i = 0; i < v.length; i++) {
                            if (v[i].type === 'way') {
                                var wayVia = graph.hasEntity(v[i].id);
                                if (wayVia && utilArrayIntersection(wayB.nodes, wayVia.nodes).length) {
                                    keepB = true;
                                    break;
                                }
                            }
                        }
                    }

                    if (keepB) {
                        relation = relation.replaceMember(wayA, wayB);
                        graph = graph.replace(relation);
                    }

                // 2. split a VIA
                } else {
                    for (i = 0; i < v.length; i++) {
                        if (v[i].type === 'way' && v[i].id === wayA.id) {
                            member = {
                                id: wayB.id,
                                type: 'way',
                                role: 'via'
                            };
                            graph = actionAddMember(relation.id, member, v[i].index + 1)(graph);
                            break;
                        }
                    }
                }

            // All other relations (Routes, Multipolygons, etc):
            // 1. Both `wayA` and `wayB` remain in the relation
            // 2. But must be inserted as a pair (see `actionAddMember` for details)
            } else {
                if (relation === isOuter) {
                    graph = graph.replace(relation.mergeTags(wayA.tags));
                    graph = graph.replace(wayA.update({ tags: {} }));
                    graph = graph.replace(wayB.update({ tags: {} }));
                }

                member = {
                    id: wayB.id,
                    type: 'way',
                    role: relation.memberById(wayA.id).role
                };

                var insertPair = {
                    originalID: wayA.id,
                    insertedID: wayB.id,
                    nodes: origNodes
                };

                graph = actionAddMember(relation.id, member, undefined, insertPair)(graph);
            }
        });

        if (!isOuter && isArea) {
            var multipolygon = osmRelation({
                tags: Object.assign({}, wayA.tags, { type: 'multipolygon' }),
                members: [
                    { id: wayA.id, role: 'outer', type: 'way' },
                    { id: wayB.id, role: 'outer', type: 'way' }
                ]
            });

            graph = graph.replace(multipolygon);
            graph = graph.replace(wayA.update({ tags: {} }));
            graph = graph.replace(wayB.update({ tags: {} }));
        }

        _createdWayIDs.push(wayB.id);

        return graph;
    }