Skip to content

Instantly share code, notes, and snippets.

@kaligrafy
Last active June 2, 2020 16:24
Show Gist options
  • Save kaligrafy/5ad25e6a4ce1e0809623f1fac7700501 to your computer and use it in GitHub Desktop.
Save kaligrafy/5ad25e6a4ce1e0809623f1fac7700501 to your computer and use it in GitHub Desktop.
export function actionFollow(selectedIDs, projection) {
// tgt: target
// src: source
// cnt: count
// idx: index
var getStartNodeId = function(startNodeId, tgtNodes, srcNodes, graph) {
if (startNodeId) {
return startNodeId;
} else {
for (var tgtI = 0, tgtNodesCnt = tgtNodes.length; tgtI < tgtNodesCnt; tgtI++) {
var tgtNodeIdxInSrc = srcNodes.indexOf(tgtNodes[tgtI]);
if (tgtNodeIdxInSrc >= 0)
{
return tgtNodes[tgtI];
}
}
}
return null;
}
var getEndNodeId = function(startNodeId, endNodeId, tgtNodes, srcNodes, graph) {
if (endNodeId) {
return endNodeId;
} else {
for (var tgtI = 0, tgtNodesCnt = tgtNodes.length; tgtI < tgtNodesCnt; tgtI++) {
var tgtNodeIdxInSrc = srcNodes.indexOf(tgtNodes[tgtI]);
if (tgtNodeIdxInSrc >= 0 && tgtNodes[tgtI] !== startNodeId)
{
return tgtNodes[tgtI];
}
}
}
return null;
}
var action = function(graph, t) {
var tgtWay = graph.entity(selectedIDs[0]);
var tgtWayIsClosed = tgtWay.isClosed();
var tgtNodes = tgtWay.nodes.slice();
var tgtNodesCnt = tgtNodes.length;
var srcWay = graph.entity(selectedIDs[1]);
var srcWayIsClosed = srcWay.isClosed();
var srcNodes = srcWay.nodes.slice();
var srcNodesCnt = srcNodes.length;
var startNodeId = getStartNodeId(selectedIDs[2], tgtNodes, srcNodes);
var endNodeId = getEndNodeId(startNodeId, selectedIDs[3], tgtNodes, srcNodes);
var startNodeIdxInSrc = srcNodes.indexOf(startNodeId);
var endNodeIdxInSrc = srcNodes.indexOf(endNodeId);
var startNodeIdxInTgt = tgtNodes.indexOf(startNodeId);
var endNodeIdxInTgt = tgtNodes.indexOf(endNodeId);
if (!srcWayIsClosed && startNodeIdxInSrc > endNodeIdxInSrc) { // reverse direction for src if backward
var tmpNodeIdx = startNodeIdxInSrc;
startNodeIdxInSrc = endNodeIdxInSrc;
endNodeIdxInSrc = tmpNodeIdx;
}
if (!tgtWayIsClosed && !srcWayIsClosed && startNodeIdxInTgt > endNodeIdxInTgt) { // reverse direction for src if backward
var tmpNodeIdx = startNodeIdxInTgt;
startNodeIdxInTgt = endNodeIdxInTgt;
endNodeIdxInTgt = tmpNodeIdx;
}
// check if target is closed and if start and end target nodes are the last segment of the loop :
var tgtIsLastSegmentOfClosedWay = tgtWayIsClosed && ((startNodeIdxInTgt === 0 && endNodeIdxInTgt === tgtNodesCnt - 2) || (endNodeIdxInTgt === 0 && startNodeIdxInTgt === tgtNodesCnt - 2));
var sameDirection = srcNodes[startNodeIdxInSrc] === tgtNodes[startNodeIdxInTgt];
var newTgtNodes = tgtNodes;
var insertIdx = endNodeIdxInTgt;
var srcNodeIdx = srcWayIsClosed && startNodeIdxInSrc === srcNodesCnt - 2 ? 0 : startNodeIdxInSrc + 1;
var srcIndexIncrement = sameDirection ? 1 : 0;
var insertIdx = endNodeIdxInTgt;
if (srcWayIsClosed)
{
var tgtDirectionAsc = endNodeIdxInTgt > startNodeIdxInTgt;
srcIndexIncrement = tgtDirectionAsc ? 1 : 0;
insertIdx = tgtDirectionAsc ? endNodeIdxInTgt : startNodeIdxInTgt;
if (tgtIsLastSegmentOfClosedWay) {
insertIdx = tgtNodesCnt - 1;
srcIndexIncrement = tgtDirectionAsc ? 0 : 1;
}
}
else
{
if (tgtIsLastSegmentOfClosedWay) {
insertIdx = tgtNodesCnt - 1;
srcIndexIncrement = 0;
}
}
while (srcNodeIdx !== endNodeIdxInSrc)
{
newTgtNodes.splice(insertIdx, 0, srcNodes[srcNodeIdx]);
insertIdx = insertIdx + srcIndexIncrement;
// jump to the first node if source is closed:
srcNodeIdx = srcWayIsClosed && srcNodeIdx + 1 === srcNodesCnt - 1 ? 0 : srcNodeIdx + 1;
}
tgtWay = tgtWay.update({nodes: newTgtNodes});
graph = graph.replace(tgtWay);
return graph;
};
action.disabled = function(graph) {
var tgtWay = graph.entity(selectedIDs[0]);
var tgtWayIsClosed = tgtWay.isClosed();
var tgtNodes = tgtWay.nodes.slice();
var tgtNodesCnt = tgtNodes.length;
var srcWay = graph.entity(selectedIDs[1]);
var srcNodes = srcWay.nodes.slice();
var startNodeId = getStartNodeId(selectedIDs[2], tgtNodes, srcNodes);
var endNodeId = getEndNodeId(startNodeId, selectedIDs[3], tgtNodes, srcNodes);
var startNodeIdxInTgt = tgtNodes.indexOf(startNodeId);
var endNodeIdxInTgt = tgtNodes.indexOf(endNodeId);
var startNodeIdxInSrc = srcNodes.indexOf(startNodeId);
var endNodeIdxInSrc = srcNodes.indexOf(endNodeId);
var tgtNodesCnt = tgtNodes.length;
var tgtIsLastSegmentOfClosedWay = tgtWayIsClosed && ((startNodeIdxInTgt === 0 && endNodeIdxInTgt === tgtNodesCnt - 2) || (endNodeIdxInTgt === 0 && startNodeIdxInTgt === tgtNodesCnt - 2));
// make sure the nodes are shared by source and target ways, and that are consecutive in target way
if (startNodeIdxInTgt === -1 || endNodeIdxInTgt === -1 || startNodeIdxInSrc === -1 || endNodeIdxInSrc === -1) {
return 'nodes_are_not_shared_by_both_ways';
}
if (tgtIsLastSegmentOfClosedWay) {
return false;
}
if (Math.abs(startNodeIdxInTgt - endNodeIdxInTgt) !== 1 && (endNodeIdxInTgt !== tgtNodesCnt - 1 || startNodeIdxInTgt !== 0)) {
return 'nodes_are_not_consecutive_in_target';
}
return false;
};
action.transitionable = true;
return action;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment