UNPKG

@visactor/vgrammar-venn

Version:

Venn layout transform for VGrammar

58 lines (53 loc) 2.69 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: !0 }), exports.constrainedMDSLayout = void 0; const vutils_1 = require("@visactor/vutils"), common_1 = require("./common"); function constrainedMDSLayout(areas, params) { const restarts = (params = params || {}).restarts || 10, sets = [], setIds = {}; let i; for (i = 0; i < areas.length; ++i) { const area = areas[i]; 1 === area.sets.length && (setIds[area.sets[0]] = sets.length, sets.push(area)); } const matrices = (0, common_1.getDistanceMatrices)(areas, sets, setIds); let distances = matrices.distances; const constraints = matrices.constraints, norm = (0, vutils_1.norm2)(distances.map(vutils_1.norm2)) / distances.length; distances = distances.map((row => row.map((value => value / norm)))); const obj = function(x, fxPrime) { return constrainedMDSGradient(x, fxPrime, distances, constraints); }; let best, current; for (i = 0; i < restarts; ++i) { const initial = (0, vutils_1.zeros)(2 * distances.length).map(((entry, i) => (0, vutils_1.seedRandom)(i))); current = (0, vutils_1.conjugateGradient)(obj, initial, params), (!best || current.fx < best.fx) && (best = current); } const positions = best.x, circles = {}; for (i = 0; i < sets.length; ++i) { const set = sets[i]; circles[set.sets[0]] = { x: positions[2 * i] * norm, y: positions[2 * i + 1] * norm, radius: Math.sqrt(set.size / Math.PI) }; } if (params.history) for (i = 0; i < params.history.length; ++i) vutils_1.scale(params.history[i].x, norm); return circles; } function constrainedMDSGradient(x, fxPrime, distances, constraints) { let i, loss = 0; for (i = 0; i < fxPrime.length; ++i) fxPrime[i] = 0; for (i = 0; i < distances.length; ++i) { const xi = x[2 * i], yi = x[2 * i + 1]; for (let j = i + 1; j < distances.length; ++j) { const xj = x[2 * j], yj = x[2 * j + 1], dij = distances[i][j], constraint = constraints[i][j], squaredDistance = (xj - xi) * (xj - xi) + (yj - yi) * (yj - yi), distance = Math.sqrt(squaredDistance), delta = squaredDistance - dij * dij; constraint > 0 && distance <= dij || constraint < 0 && distance >= dij || (loss += 2 * delta * delta, fxPrime[2 * i] += 4 * delta * (xi - xj), fxPrime[2 * i + 1] += 4 * delta * (yi - yj), fxPrime[2 * j] += 4 * delta * (xj - xi), fxPrime[2 * j + 1] += 4 * delta * (yj - yi)); } } return loss; } //# sourceMappingURL=constrained-mds-layout.js.map exports.constrainedMDSLayout = constrainedMDSLayout;