UNPKG

siafun

Version:
92 lines (91 loc) 3.79 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const _ = require("lodash"); const arrayutils_1 = require("arrayutils"); const util_1 = require("./util"); function siatec(points, minPatternLength = 0, removeRedundant = true) { let vectorTable = getVectorTable(points); let patterns = calculateSiaPatterns(vectorTable); //remove short patterns patterns = patterns.filter(p => p.length >= minPatternLength); //calculate vectors const vectors = getVectorMap(points, patterns, vectorTable); vectorTable = null; //release memory //calculate occurrences let occs = []; for (let i = 0; i < patterns.length; i += 1000) { occs.push(toOccs(patterns.slice(i, i + 1000), vectors)); } let occurrences = new Map(_.zip(patterns, _.flatten(occs))); //remove redundant if (removeRedundant) { const reduced = {}; patterns.forEach(p => { const stringO = JSON.stringify(occurrences.get(p)); if (!reduced[stringO] || vectors.get(p).length > vectors.get(reduced[stringO]).length) { reduced[stringO] = p; } }); //console.log('removed redundant:', patterns.length-_.values(reduced).length, 'of', patterns.length) patterns = _.values(reduced); } //console.log("RETURN") return { points: points, minPatternLength: minPatternLength, patterns: patterns.map((p, i) => ({ points: p, vectors: vectors.get(p), occurrences: occurrences.get(p) })) }; } exports.siatec = siatec; function toOccs(patterns, vectors) { return patterns.map(p => vectors.get(p).map(v => p.map(point => point.map((p, k) => p + v[k])))); } function getVectorMap(points, patterns, vectorTable) { const vectors = calculateSiatecOccurrences(points, patterns, vectorTable) .map(i => i.map(v => v.map(e => _.round(e, 8)))); //eliminate float errors return new Map(_.zip(patterns, vectors)); } function getVectorTable(points) { return points.map(p => points.map(q => [_.zipWith(q, p, _.subtract), p])); } //returns a list with the sia patterns detected for the given points function calculateSiaPatterns(vectorTable) { //get all the vectors below the diagonal of the translation matrix var halfTable = vectorTable.map((col, i) => col.slice(i + 1)); //transform into a sorted list by merging the table's columns var vectorList = arrayutils_1.mergeSortedArrays(halfTable); //group by translation vectors var patternMap = groupByKeys(vectorList); //get the map's values, get rid of duplicates return _.uniq(_.values(patternMap).map(util_1.toOrderedPointString)) .map(p => JSON.parse(p)); } //returns a list with the function calculateSiatecOccurrences(points, pointSets, vectorTable) { var vectorMap = new Map(); points.forEach((v, i) => vectorMap.set(JSON.stringify(v), i)); //get rid of points of origin in vector table var fullTable = vectorTable.map(col => col.map(row => row[0])); var translations = pointSets.map(pat => pat.map(point => fullTable[vectorMap.get(JSON.stringify(point))])); return translations.map(occ => getIntersection(occ)); } //takes an array of arrays of vectors and calculates their intersection function getIntersection(vectors) { if (vectors.length > 1) { var isect = vectors.slice(1).reduce((isect, tsls) => arrayutils_1.intersectSortedArrays(isect, tsls), vectors[0]); return isect; } return vectors[0]; } function groupByKeys(vectors) { return vectors.reduce((grouped, item) => { var key = JSON.stringify(item[0]); grouped[key] = grouped[key] || []; grouped[key].push(item[1]); return grouped; }, {}); }