mirror of
https://github.com/Doodle3D/Doodle3D-Core.git
synced 2024-06-29 07:21:23 +02:00
137 lines
4.6 KiB
JavaScript
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));
|
||
|
}
|