Skip to content
Snippets Groups Projects
Commit ff67c421 authored by Tom Robinson's avatar Tom Robinson
Browse files

New split axis logic

parent b800489e
Branches
Tags
No related merge requests found
import _ from "underscore";
import d3 from "d3";
import * as colors from "metabase/lib/colors";
const SPLIT_AXIS_UNSPLIT_COST = -100;
const SPLIT_AXIS_COST_FACTOR = 2;
// computed size properties (drop 'px' and convert string -> Number)
function getComputedSizeProperty(prop, element) {
var val = document.defaultView.getComputedStyle(element, null).getPropertyValue(prop);
......@@ -30,50 +34,43 @@ export function getAvailableCanvasWidth(element) {
return parentWidth - parentPaddingLeft - parentPaddingRight;
}
export function computeSplit(extents) {
// copy and sort the intervals by the lower bound
let intervals = extents.map(e => e.slice()).sort((a,b) => a[0] - b[0]);
// start with a zero width gap
let gap = [0,0];
// iterate over each interval
let current = intervals[0];
for (let i = 1; i < intervals.length; i++) {
let next = intervals[i];
// merge next interval with the current one if appropriate
if (next[0] <= current[1]) {
if (next[1] > current[1]) {
current[1] = next[1];
}
// otheriwse update the gap if it's larger than the previously recorded gap
} else {
if (next[0] - current[1] > gap[1] - gap[0]) {
gap = [current[1], next[0]];
}
current = next;
}
function generateSplits(list, left = [], right = []) {
// NOTE: currently generates all permutations, some of which are equivalent
if (list.length === 0) {
return [[left, right]];
} else {
return [
...generateSplits(list.slice(1), left.concat([list[0]]), right),
...generateSplits(list.slice(1), left, right.concat([list[0]]))
];
}
}
let partitionIndexes;
// if there is a gap, and it's larger than an order of magnitude, then split
if (gap[1] - gap[0] !== 0 && (gap[1] / gap[0]) >= 10) {
partitionIndexes = [[],[]];
extents.forEach(([min, max], index) => {
// if the end of an extent is less or equal to than the beginning of the gap
// put it in the lower partition
if (max <= gap[0]) {
partitionIndexes[0].push(index);
} else {
partitionIndexes[1].push(index);
}
})
// otherwise don't partition
function cost(seriesExtents) {
let axisExtent = d3.extent([].concat(...seriesExtents)); // concat to flatten the array
let axisRange = axisExtent[1] - axisExtent[0];
if (seriesExtents.length === 0) {
return SPLIT_AXIS_UNSPLIT_COST;
} else {
partitionIndexes = [extents.map((e,i) => i)];
return seriesExtents.reduce((sum, seriesExtent) =>
sum + Math.pow(axisRange / (seriesExtent[1] - seriesExtent[0]), SPLIT_AXIS_COST_FACTOR)
, 0);
}
}
return partitionIndexes;
export function computeSplit(extents) {
let best = null;
let bestCost = Infinity;
let splits = generateSplits(extents.map((e,i) => i)).map(split =>
[split, cost(split[0].map(i => extents[i])) + cost(split[1].map(i => extents[i]))]
)
for (let [split, splitCost] of splits) {
if (splitCost < bestCost) {
best = split;
bestCost = splitCost;
}
}
return best.sort((a,b) => a[0] - b[0]);
}
const FRIENDLY_NAME_MAP = {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment