Doodle3D-Core/src/reducer/pointsReducers.js
2017-11-14 16:01:04 +01:00

137 lines
4.6 KiB
JavaScript

import R from 'ramda';
// import createDebug from 'debug';
// const debug = createDebug('d3d:reducers:points');
export function mergePaths(pathA, pathB, matchIndexes) {
if (matchIndexes[0] !== -1) { // if first path's first point matches
// always reverse first path
const sortedA = R.reverse(pathA);
// if matches with second path's second point reverse
const sortedB = (matchIndexes[0] === 1) ? R.reverse(pathB) : pathB;
// add b behind a, removing overlapping point
return sortedA.concat(sortedB.slice(1));
} else if (matchIndexes[1] !== -1) { // if first path's second point matches
// no need to reorder first path
const sortedA = pathA;
// if matches with second path's second point reverse
const sortedB = (matchIndexes[1] === 1) ? R.reverse(pathB) : pathB;
// add b behind a, removing overlapping point
return sortedA.concat(sortedB.slice(1));
} else {
return null;
}
}
// get just the end points of a path
export const getEndPoints = R.juxt([R.head, R.last]);
export const getEndPointPaths = R.map(getEndPoints);
const vectorEquals = R.curry(
(a, b) => a.equals(b)
);
// find the index of a point in an array of points
export const findPointIndex = R.curry(
(points, point) => R.findIndex(vectorEquals(point), points)
);
export const findEndPointIndex = R.curry(
(points, point) => findPointIndex(getEndPoints(points), point)
);
// find indexes of multiple points in array of points,
// returned as array of indexes
// Result examples:
// [0]: a's first point matches b's first point
// [1]: a's first point matches b's second point
// [-1]: a's first point matches none of b's points
// [1, 0]: a's first point matches and b's second point and a's second point matches b's first point
export const findPointsIndexes = R.curry(
(pointsA, pointsB) => R.map(findPointIndex(pointsB), pointsA)
);
export const findEndPointsIndexes = R.curry(
(pathA, pathB) => findPointsIndexes(
getEndPoints(pathA),
getEndPoints(pathB)
)
);
// find the index of a point in an array of paths
// (paths are arrays of points)
// returns first result
// returns array with
// - index of path with matching point
// - matching index (see findPointsIndexes)
export function findPointIndexInPaths(point, paths) {
// debug('findPointIndexInPaths: ', toString(point), toString(paths));
for (let i = 0; i < paths.length; i++) {
const path = paths[i];
// find matching endpoints
const index = findPointIndex(path, point);
// debug(` ${i}: index: `, index);
// if found stop searching
if (index > -1) return [i, index];
}
return null;
}
export const findEndPointIndexInPaths = R.curry(
(point, paths) => findPointIndexInPaths(point, getEndPointPaths(paths))
);
// find indexes of matching points of path inside other path
// returns first result
// returns array with
// - index of path with matching point
// - array of matching indexes (see findPointsIndexes)
export function findPointsIndexesOfPathInPaths(paths, path) {
// console.log('findPointsIndexesOfPathInPaths');
// console.log(' paths: ', toString(paths));
// console.log(' path: ', toString(path));
for (let i = 0; i < paths.length; i++) {
const otherPath = paths[i];
// skip current path
if (otherPath === path) continue;
// find matching endpoints
const indexes = findPointsIndexes(path, otherPath);
// console.log(` ${i}: indexes: `, indexes);
// found any matching indexes?
// indexes contains any item that's larget than -1
const foundMatch = R.any(R.lt(-1))(indexes);
// if found stop searching
// return index of matching path and indexes of machting end points
if (foundMatch) return [i, indexes];
}
return null;
}
// find indexes of matching end points of path inside other path
// see: findPointsIndexesOfPathInPaths
export function findEndPointsIndexesOfPathInPaths(paths, path) {
return findPointsIndexesOfPathInPaths(
R.map(getEndPoints, paths),
getEndPoints(path)
);
}
// cross-compare points of multiple paths
// returns first match
// array with
// - index of path A with matching point
// - index of path B with matching point
// - array of matching indexes (see findPointsIndexes)
export function findPointIndexesOfPaths(paths) {
// console.log('findPointIndexesOfPaths');
for (let i = 0; i < paths.length; i++) {
const path = paths[i];
const indexes = findPointsIndexesOfPathInPaths(paths, path);
// console.log(' indexes: ', toString(indexes));
if (indexes !== null) return [i, ...indexes];
}
return null;
}
// cross-compare endpoints of multiple paths
export function findEndPointIndexesOfPaths(paths) {
return findPointIndexesOfPaths(R.map(getEndPoints, paths));
}