UNPKG

@visactor/vgrammar-venn

Version:

Venn layout transform for VGrammar

67 lines (61 loc) 2.47 kB
import { greedyLayout } from "./greedy-layout"; import { lossFunction } from "./loss"; import { constrainedMDSLayout } from "./constrained-mds-layout"; import { nelderMead } from "@visactor/vutils"; export function venn(areas, parameters) { (parameters = parameters || {}).maxIterations = parameters.maxIterations || 500; const initialLayout = parameters.initialLayout || bestInitialLayout, loss = parameters.lossFunction || lossFunction, circles = initialLayout(areas = addMissingAreas(areas), parameters), initial = [], setIds = []; for (const setId in circles) circles.hasOwnProperty(setId) && (initial.push(circles[setId].x), initial.push(circles[setId].y), setIds.push(setId)); const positions = nelderMead((function(values) { const current = {}; for (let i = 0; i < setIds.length; ++i) { const setId = setIds[i]; current[setId] = { x: values[2 * i], y: values[2 * i + 1], radius: circles[setId].radius }; } return loss(current, areas); }), initial, parameters).x; for (let i = 0; i < setIds.length; ++i) { const setId = setIds[i]; circles[setId].x = positions[2 * i], circles[setId].y = positions[2 * i + 1]; } return circles; } function addMissingAreas(areas) { areas = areas.slice(); const ids = [], pairs = {}; for (let i = 0; i < areas.length; ++i) { const area = areas[i]; if (1 === area.sets.length) ids.push(area.sets[0]); else if (2 === area.sets.length) { const a = area.sets[0], b = area.sets[1]; pairs[[ a, b ].toString()] = !0, pairs[[ b, a ].toString()] = !0; } } ids.sort((function(a, b) { return +(a > b); })); for (let i = 0; i < ids.length; ++i) { const a = ids[i]; for (let j = i + 1; j < ids.length; ++j) { const b = ids[j]; [ a, b ].toString() in pairs || areas.push({ sets: [ a, b ], size: 0 }); } } return areas; } export function bestInitialLayout(areas, params) { let initial = greedyLayout(areas, params); const loss = params.lossFunction || lossFunction; if (areas.length >= 8) { const constrained = constrainedMDSLayout(areas, params); loss(constrained, areas) + 1e-8 < loss(initial, areas) && (initial = constrained); } return initial; }