diff --git a/Gruntfile.js b/Gruntfile.js index c05cde5..a46ae9d 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -28,7 +28,7 @@ module.exports = function(grunt) { }, jshint: { - all: ['Gruntfile.js', 'src/*.js'], + all: ['Gruntfile.js', 'src/*.js', 'tests/*js'], } }); diff --git a/README.md b/README.md index b56bf05..0d187a8 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,10 @@ venn.js A javascript library for laying out area proportional venn and euler diagrams. -Details of how this library works can be found on the [blog +Details of how this library works can be found on the [blog post](http://www.benfrederickson.com/venn-diagrams-with-d3.js/) -I wrote about this. +I wrote about this. A follow up post [discusses testing strategy and +algorithmic improvements](http://www.benfrederickson.con/better-venn-diagrams). #### Usage @@ -137,32 +138,6 @@ div.selectAll("g") ``` [View this example](http://benfred.github.io/venn.js/examples/intersection_tooltip.html) -##### MDS Layout - -In most cases the greedy initial layout does a good job of positioning the -sets, but there are cases where it breaks down. One case is detailed in [this -blog post](http://www.benfrederickson.com/2013/05/16/multidimensional-scaling.html), -and it can be better laid out using [multidimensional -scaling](https://en.wikipedia.org/wiki/Multidimensional_scaling) to generate -the initial layout. - -To enable this just include the [mds.js](http://github.com/benfred/mds.js) -and [numeric.js](http://numericjs.com) libraries first, and then change the -layout function on the VennDiagam object: - -```javascript -var chart = venn.VennDiagram() - .width(600) - .height(400) - .layoutFunction( - function(d) { return venn.venn(d, { initialLayout: venn.classicMDSLayout });} - ); - -d3.select("#venn").datum(sets).call(chart); -``` - -[View this example](http://benfred.github.io/venn.js/examples/mds.html) - #### Building To build venn.js and venn.min.js from the files in src/ - you should first diff --git a/src/diagram.js b/src/diagram.js index 5aad638..d565d4e 100644 --- a/src/diagram.js +++ b/src/diagram.js @@ -255,7 +255,7 @@ return margin; } - // compute the center of some circles by maximizing the margin of + // compute the center of some circles by maximizing the margin of // the center point relative to the circles (interior) after subtracting // nearby circles (exterior) function computeTextCentre(interior, exterior) { diff --git a/src/export.js b/src/export.js index 5ee5f78..92d7028 100644 --- a/src/export.js +++ b/src/export.js @@ -3,5 +3,5 @@ window.venn = lib; } else { module.exports = lib; - } + } })(venn); diff --git a/src/fmin.js b/src/fmin.js index ebec457..989e85f 100644 --- a/src/fmin.js +++ b/src/fmin.js @@ -33,6 +33,33 @@ return a + delta; }; + // need some basic operations on vectors, rather than adding a dependency, + // just define here + function zeros(x) { var r = new Array(x); for (var i = 0; i < x; ++i) { r[i] = 0; } return r; } + function zerosM(x,y) { return zeros(x).map(function() { return zeros(y); }); } + venn.zerosM = zerosM; + venn.zeros = zeros; + + function dot(a, b) { + var ret = 0; + for (var i = 0; i < a.length; ++i) { + ret += a[i] * b[i]; + } + return ret; + } + + function norm2(a) { + return Math.sqrt(dot(a, a)); + } + venn.norm2 = norm2; + + function multiplyBy(a, c) { + for (var i = 0; i < a.length; ++i) { + a[i] *= c; + } + } + venn.multiplyBy = multiplyBy; + function weightedSum(ret, w1, v1, w2, v2) { for (var j = 0; j < ret.length; ++j) { ret[j] = w1 * v1[j] + w2 * v2[j]; @@ -161,4 +188,129 @@ return {f : simplex[0].fx, solution : simplex[0]}; }; + + + venn.minimizeConjugateGradient = function(f, initial, params) { + // allocate all memory up front here, keep out of the loop for perfomance + // reasons + var current = {x: initial.slice(), fx: 0, fxprime: initial.slice()}, + next = {x: initial.slice(), fx: 0, fxprime: initial.slice()}, + yk = initial.slice(), + pk, temp, + a = 1, + maxIterations; + + params = params || {}; + maxIterations = params.maxIterations || initial.length * 5; + + current.fx = f(current.x, current.fxprime); + pk = current.fxprime.slice(); + multiplyBy(pk, -1); + + for (var i = 0; i < maxIterations; ++i) { + if (params.history) { + params.history.push({x: current.x.slice(), + fx: current.fx, + fxprime: current.fxprime.slice()}); + } + + a = venn.wolfeLineSearch(f, pk, current, next, a); + if (!a) { + // faiiled to find point that satifies wolfe conditions. + // reset direction for next iteration + for (var j = 0; j < pk.length; ++j) { + pk[j] = -1 * current.fxprime[j]; + } + } else { + // update direction using Polak–Ribiere CG method + weightedSum(yk, 1, next.fxprime, -1, current.fxprime); + + var delta_k = dot(current.fxprime, current.fxprime), + beta_k = Math.max(0, dot(yk, next.fxprime) / delta_k); + + weightedSum(pk, beta_k, pk, -1, next.fxprime); + + temp = current; + current = next; + next = temp; + } + + if (norm2(current.fxprime) <= 1e-5) { + break; + } + } + + if (params.history) { + params.history.push({x: current.x.slice(), + fx: current.fx, + fxprime: current.fxprime.slice()}); + } + + return current; + }; + + var c1 = 1e-6, c2 = 0.1; + + /// searches along line 'pk' for a point that satifies the wolfe conditions + /// See 'Numerical Optimization' by Nocedal and Wright p59-60 + venn.wolfeLineSearch = function(f, pk, current, next, a) { + var phi0 = current.fx, phiPrime0 = dot(current.fxprime, pk), + phi = phi0, phi_old = phi0, + phiPrime = phiPrime0, + a0 = 0; + + a = a || 1; + + function zoom(a_lo, a_high, phi_lo) { + for (var iteration = 0; iteration < 16; ++iteration) { + a = (a_lo + a_high)/2; + weightedSum(next.x, 1.0, current.x, a, pk); + phi = next.fx = f(next.x, next.fxprime); + phiPrime = dot(next.fxprime, pk); + + if ((phi > (phi0 + c1 * a * phiPrime0)) || + (phi >= phi_lo)) { + a_high = a; + + } else { + if (Math.abs(phiPrime) <= -c2 * phiPrime0) { + return a; + } + + if (phiPrime * (a_high - a_lo) >=0) { + a_high = a_lo; + } + + a_lo = a; + phi_lo = phi; + } + } + + return 0; + } + + for (var iteration = 0; iteration < 10; ++iteration) { + weightedSum(next.x, 1.0, current.x, a, pk); + phi = next.fx = f(next.x, next.fxprime); + phiPrime = dot(next.fxprime, pk); + if ((phi > (phi0 + c1 * a * phiPrime0)) || + (iteration && (phi >= phi_old))) { + return zoom(a0, a, phi_old); + } + + if (Math.abs(phiPrime) <= -c2 * phiPrime0) { + return a; + } + + if (phiPrime >= 0 ) { + return zoom(a, a0, phi); + } + + phi_old = phi; + a0 = a; + a *= 2; + } + + return 0; + }; })(venn); diff --git a/src/init.js b/src/init.js index 1b49ba0..e04f217 100644 --- a/src/init.js +++ b/src/init.js @@ -1 +1 @@ -var venn = venn || {}; +var venn = venn || {'version' : '0.2'}; diff --git a/src/layout.js b/src/layout.js index c61c8bb..af72a4b 100644 --- a/src/layout.js +++ b/src/layout.js @@ -7,7 +7,7 @@ parameters = parameters || {}; parameters.maxIterations = parameters.maxIterations || 500; var lossFunction = parameters.lossFunction || venn.lossFunction; - var initialLayout = parameters.initialLayout || venn.greedyLayout; + var initialLayout = parameters.initialLayout || venn.bestInitialLayout; var fmin = parameters.fmin || venn.fmin; // initial layout is done greedily @@ -52,7 +52,7 @@ return circles; }; - + var SMALL = 1e-10; /** Returns the distance necessary for two circles of radius r1 + r2 to @@ -68,24 +68,17 @@ }, 0, r1 + r2); }; - /// gets a matrix of euclidean distances between all sets in venn diagram - venn.getDistanceMatrix = function(areas, sets, setids) { + /// Returns two matrices, one of the euclidean distances between the sets + /// and the other indicating if there are subset or disjoint set relationships + venn.getDistanceMatrices = function(areas, sets, setids) { // initialize an empty distance matrix between all the points - var distances = []; - for (var i = 0; i < sets.length; ++i) { - distances.push([]); - for (var j = 0; j < sets.length; ++j) { - distances[i].push(0); - } - } - - // compute distances between all the points - for (i = 0; i < areas.length; ++i) { - var current = areas[i]; - if (current.sets.length !== 2) { - continue; - } + var distances = venn.zerosM(sets.length, sets.length), + constraints = venn.zerosM(sets.length, sets.length); + // compute required distances between all the sets such that + // the areas match + areas.filter(function(x) { return x.sets.length == 2; }) + .map(function(current) { var left = setids[current.sets[0]], right = setids[current.sets[1]], r1 = Math.sqrt(sets[left].size / Math.PI), @@ -93,8 +86,134 @@ distance = venn.distanceFromIntersectArea(r1, r2, current.size); distances[left][right] = distances[right][left] = distance; + + // also update constraints to indicate if its a subset or disjoint + // relationship + var c = 0; + if (current.size + 1e-10 >= Math.min(sets[left].size, + sets[right].size)) { + c = 1; + } else if (current.size <= 1e-10) { + c = -1; + } + constraints[left][right] = constraints[right][left] = c; + }); + + return {distances: distances, constraints: constraints}; + }; + + /// computes the gradient and loss simulatenously for our constrained MDS optimizer + function constrainedMDSGradient(x, fxprime, distances, constraints) { + var loss = 0, i; + for (i = 0; i < fxprime.length; ++i) { + fxprime[i] = 0; } - return distances; + + for (i = 0; i < distances.length; ++i) { + var xi = x[2 * i], yi = x[2 * i + 1]; + for (var j = i + 1; j < distances.length; ++j) { + var xj = x[2 * j], yj = x[2 * j + 1], + dij = distances[i][j], + constraint = constraints[i][j]; + + var squaredDistance = (xj - xi) * (xj - xi) + (yj - yi) * (yj - yi), + distance = Math.sqrt(squaredDistance), + delta = squaredDistance - dij * dij; + + if (((constraint > 0) && (distance <= dij)) || + ((constraint < 0) && (distance >= dij))) { + continue; + } + + 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; + } + + /// takes the best working variant of either constrained MDS or greedy + venn.bestInitialLayout = function(areas, params) { + var initial = venn.greedyLayout(areas, params); + + // greedylayout is sufficient for all 2/3 circle cases. try out + // constrained MDS for higher order problems, take its output + // if it outperforms. (greedy is aesthetically better on 2/3 circles + // since it axis aligns) + if (areas.length >= 8) { + var constrained = venn.constrainedMDSLayout(areas, params), + constrainedLoss = venn.lossFunction(constrained, areas), + greedyLoss = venn.lossFunction(initial, areas); + + if (constrainedLoss + 1e-8 < greedyLoss) { + initial = constrained; + } + } + return initial; + }; + + /// use the constrained MDS variant to generate an initial layout + venn.constrainedMDSLayout = function(areas, params) { + params = params || {}; + var restarts = params.restarts || 10; + + // bidirectionally map sets to a rowid (so we can create a matrix) + var sets = [], setids = {}, i; + for (i = 0; i < areas.length; ++i ) { + var area = areas[i]; + if (area.sets.length == 1) { + setids[area.sets[0]] = sets.length; + sets.push(area); + } + } + + var matrices = venn.getDistanceMatrices(areas, sets, setids), + distances = matrices.distances, + constraints = matrices.constraints; + + // keep distances bounded, things get messed up otherwise. + // TODO: proper preconditioner? + var norm = venn.norm2(distances.map(venn.norm2))/(distances.length); + distances = distances.map(function (row) { + return row.map(function (value) { return value / norm; });}); + + var obj = function(x, fxprime) { + return constrainedMDSGradient(x, fxprime, distances, constraints); + }; + + var best, current; + for (i = 0; i < restarts; ++i) { + var initial = venn.zeros(distances.length*2).map(Math.random); + + current = venn.minimizeConjugateGradient(obj, initial, params); + if (!best || (current.fx < best.fx)) { + best = current; + } + } + var positions = best.x; + + // translate rows back to (x,y,radius) coordinates + var circles = {}; + for (i = 0; i < sets.length; ++i) { + var 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) { + venn.multiplyBy(params.history[i].x, norm); + } + } + return circles; }; /** Lays out a Venn diagram greedily, going from most overlapped sets to @@ -169,7 +288,7 @@ // get distances between all points. TODO, necessary? // answer: probably not - // var distances = venn.getDistanceMatrix(circles, areas); + // var distances = venn.getDistanceMatrices(circles, areas).distances; for (i = 1; i < mostOverlapped.length; ++i) { var setIndex = mostOverlapped[i].set, overlap = setOverlaps[setIndex].filter(isPositioned); @@ -242,7 +361,7 @@ } // get the distance matrix, and use to position sets - var distances = venn.getDistanceMatrix(areas, sets, setids); + var distances = venn.getDistanceMatrices(areas, sets, setids).distances; var positions = mds.classic(distances); // translate rows back to (x,y,radius) coordinates diff --git a/tests/performance_test.html b/tests/performance_test.html new file mode 100644 index 0000000..f83f854 --- /dev/null +++ b/tests/performance_test.html @@ -0,0 +1,200 @@ + + + + + venn.js perfomance/accuracy tests + + + + + + + +
+
+
+ +

This page tests out a couple different venn diagram layout + algorithms for accuracy and performance on random data.

+ +

Circles are randomly positioned and then the intersection + areas are calculated from these circles. Using only the intersection areas, + each algorithm has to lay out a venn diagram that is isomorphic to + the original input.

+ +

The graphs below measure the percentage of the time the + algorithm successfully reconstructs the input, and how long it + takes to do so.

+
+ +
+
+
+

Performance by Version

+

+
+
+ +
+
+ +
+
+
+ +
+

Success Rate

+
+
+
+

Average Time (ms)

+
+
+
+ +
+
+

These charts show the difference in performance from the original version + compared with the algorithm + improvements detailed in this post.

+ +

A failure in this case is if any laid out area differs by a + perceptible amount from the input: I chose a 10% difference in + size to be perceptible.

+ +

The difficulty in this test is strongly dependant on how the + circles are positioned randomly. I'm setting the centres of each + circle to be in randomly (0, 1) and then setting the radii to be + in (0.1, 0.5). This can be made easier by setting the radii to (0.5, 1.0) or + harder by setting to (0.1, 0.3) for instance.

+
+
+
+ + + + + + + + + + + + + diff --git a/tests/test_utils.js b/tests/test_utils.js index 762d194..f83b864 100644 --- a/tests/test_utils.js +++ b/tests/test_utils.js @@ -7,7 +7,7 @@ function generateRandomCircles(count, minRadius, maxRadius) { var range = {x : 0, y : 0, height : 1, width : 1}, output = []; - for (var i = 0; i < count; ++i ) { + for (var i = 0; i < count; ++i ) { var p = randomPoint(range); p.radius = Math.random() * (maxRadius - minRadius) + minRadius; output.push(p); @@ -34,7 +34,7 @@ function getAllIntersections(circles) { var setids = circles.map(function (x, i) { return i; }); return getCombinations(setids).map(function (ids) { return {sets: ids, - size: venn.intersectionArea(ids.map(function(i) { + size: venn.intersectionArea(ids.map(function(i) { return circles[i]; })) }; }); @@ -46,12 +46,12 @@ function getIntersections(circles) { } function getErrors(areas, current) { - var intersections = areas.filter(function (a) { + var intersections = areas.filter(function (a) { return a.sets.length ==2; }); - + var total = 0, i; - for (i = 0; i < areas.length; ++i) { + for (i = 0; i < areas.length; ++i) { total += areas[i].size; } @@ -67,11 +67,11 @@ function getErrors(areas, current) { if (isNaN(delta)) { ret.push(area); } - + else if ((delta / (1e-10 + Math.max(area.size, overlap)) >= 0.1) && (delta > total / (50000))) { ret.push(area); - } + } } } return ret; @@ -95,3 +95,292 @@ function hilightErrors(div, areas, current, duration) { } return failedAreas.length === 0; } + +// converts our areas into disjoint areas for use by other libraries +// like matplotlib_venn, venneuler etc +function makeDisjoint(areas) { + var lookup = {}; + var ret = [], i; + for (i = 0; i < areas.length; ++i) { + var clone = {sets: areas[i].sets, size:areas[i].size}; + lookup[areas[i].sets] = clone; + ret.push(clone); + } + + ret.sort(function(a, b) { + return b.sets.length - a.sets.length; + }); + + for (i = 0; i < ret.length; ++i) { + var area = ret[i]; + var supersets = getCombinations(area.sets); + for (var j = 0; j < supersets.length; ++j) { + if (supersets[j].length < area.sets.length) { + lookup[supersets[j]].size -= area.size; + } + } + } + return ret; +} + +var MIN_CIRCLES = 2, MAX_CIRCLES = 8; +function getCircleCategories() { + var ret = []; + for (var i = MIN_CIRCLES; i <= MAX_CIRCLES; ++i) { + ret.push(i); + } + return ret; +} + +// tracks status of perfomance of each algorithm +function VennAlgorithm(name, method) { + this.name = name; + this.method = method; + this.errors = {}; + this.counts = {}; + this.times = {}; + + for (var i = MIN_CIRCLES; i <= MAX_CIRCLES; ++i) { + this.errors[i] = 0; + this.counts[i] = 0; + this.times[i] = 0; + } +} + +// test out the algorithm with the current circles/intersection areas +VennAlgorithm.prototype.update = function(intersections, computed, elapsed) { + var count = intersections.filter(function(a) { return a.sets.length == 1; }).length; + if (getErrors(intersections, computed).length > 0) { + this.errors[count] += 1; + } + this.counts[count] += 1; + this.times[count] += elapsed; +}; + +VennAlgorithm.prototype.reset = function() { + for (var i = MIN_CIRCLES; i <= MAX_CIRCLES; ++i) { + this.errors[i] = 0; + this.counts[i] = 0; + this.times[i] = 0; + } +}; + +// random layout: poor choice +function randomLayout(areas) { + var range = {x : 0, y : 0, height : 1, width : 1}; + var ret = []; + for (var i = 0; i < areas.length; ++i) { + var area = areas[i]; + if (area.sets.length == 1) { + ret.push({x : Math.random(), + y : Math.random(), + radius: Math.sqrt(area.size / Math.PI)}); + } + } + return ret; +} + +function bestInitial(areas) { + var g = venn.greedyLayout(areas); + var w = constrainedMDSLayout(areas, {restarts:5}); + if (venn.lossFunction(w, areas) < venn.lossFunction(g, areas)) { + g = w; + } + return g; +} + +function createPerformanceChart(selector, + algorithms, + precalcPerf, + precalcSpeed) { + function getPerformanceData() { + var columns = []; + for (var i = 0; i < algorithms.length; ++i) { + var algo = algorithms[i]; + var column = [algo.name]; + for (var j = MIN_CIRCLES; j <= MAX_CIRCLES; ++j) { + + var c = algo.counts[j] || 1; + column.push((c - algo.errors[j] ) / c); + } + columns.push(column); + } + + return { 'columns' : columns }; + } + this.getPerformanceData = getPerformanceData; + + function getSpeedData() { + var columns = []; + for (var i = 0; i < algorithms.length; ++i) { + var algo = algorithms[i]; + var column = [algo.name]; + for (var j = MIN_CIRCLES; j <= MAX_CIRCLES; ++j) { + var c = algo.counts[j] || 1; + column.push(algo.times[j] / c); + } + columns.push(column); + } + + return { 'columns' : columns }; + } + + this.getSpeedData = getSpeedData; + + var performanceChart = c3.generate({ + bindto: selector + " #perfchart", + axis: { + x: { + label: {text: 'Number of Sets', position: 'outer-center'}, + type: 'category', + categories: getCircleCategories(), + }, + y: {label: {text: 'Success Rate', position: 'outer-middle'}, + min:0.05, + max:1, + tick : {format: function(d) { return (100*d).toFixed(0) + + "%";}} + }, + }, + tooltip : { + format : { + title: function(x) { return (x + MIN_CIRCLES) + " Sets";} , + value: function(x) { return "" + (100*x).toFixed(2) + "%"; }, + }, + }, + data:precalcPerf || getPerformanceData() }); + + + var speedChart = c3.generate({ + bindto: selector + " #speedchart", + axis: { + x: { + label: {text: 'Number of Sets', position: 'outer-center'}, + type: 'category', + categories: getCircleCategories(), + }, + y: {label: {text: 'Average Time (ms)', position: 'outer-middle'}} + }, + tooltip : { + format : { + title: function(x) { return (x + MIN_CIRCLES) + " Sets";} , + value: function(x) { return "" + x.toFixed(2) + " ms"; }, + }, + }, + data:precalcSpeed || getSpeedData() }); + + var lastCount = 0, lastTime = 0, totalCount = 0; + var circleCount = MIN_CIRCLES; + paused = true; + var element = d3.select(selector); + var pauseIcon = element.select(".pause-button .glyphicon"); + + + function pause() { + paused = true; + element.select(".pause-label").text(" Resume"); + pauseIcon.attr("class", "glyphicon glyphicon-play"); + } + + function resume() { + paused = false; + element.select(".pause-label").text(" Pause"); + pauseIcon.attr("class", "glyphicon glyphicon-pause"); + testIteration(); + } + + function togglePause() { + if (paused) { + resume(); + } else { + pause(); + } + } + + var minRadius = 0.1, maxRadius = 1.0; + function setRadii(low, hi) { + minRadius = low; + maxRadius = hi; + for (var i = 0; i < algorithms.length; ++i) { + algorithms[i].reset(); + } + lastCount = 0; + lastTime = 0; + totalCount = 0; + circleCount = MIN_CIRCLES; + resume(); + } + this.setRadii = setRadii; + + element.select(".pause-button").on("click", togglePause); + + var intersectionFunction = getIntersections; + this.intersectionFunction = function(_) { + if (!arguments.length) return intersectionFunction; + intersectionFunction = _; + }; + + // single iteration + function testIteration() { + element.select("#warning").style("display", "none"); + circleCount += 1; + if (circleCount > MAX_CIRCLES) { + circleCount = MIN_CIRCLES; + } + + // slightly awkkard here, needed to work properly with deferreds, + // returns a function that when called with the computed values + // updates the algorithm counts. + function update(algorithm, intersections, start) { + return function(computed) { + var elapsed = performance.now() - start; + algorithm.update(intersections, computed, elapsed); + }; + } + + var circles = generateRandomCircles(circleCount, minRadius, maxRadius); + + var intersections = intersectionFunction(circles); + + var deferred = []; + for (var i = 0; i < algorithms.length; ++i ) { + var updateResults = update(algorithms[i], intersections, performance.now()), + computed = algorithms[i].method(intersections); + + if ("then" in computed) { + deferred.push(computed.then(updateResults)); + } else { + updateResults(computed); + } + } + + // wait for deferred objects to finish, possibly reload graph if + // needed + $.when.apply($, deferred).then(function() { + var count = 0; + for (var i = MIN_CIRCLES; i < MAX_CIRCLES; ++i) { + count += algorithms[0].counts[i]; + } + element.select("#iterations").text("Total trails: " + count); + + // constantly reloading the charts causes issues with hover + // slow it down to every 10 seconds, with faster reloads at beginning + if (((Math.log(count) - Math.log(lastCount)) >= 0.1) || + (performance.now() >= lastTime + 10 * 1000)) { + performanceChart.load(getPerformanceData()); + speedChart.load(getSpeedData()); + lastCount = count; + lastTime = performance.now(); + } + + if (!paused) { + window.setTimeout(testIteration, 0); + } + }, function(error) { + console.log("Failed to run performance test"); + console.log(error); + element.select("#warning").html("Failed! Well that didn't work, is everything running ok?").style("display", "block"); + pause(); + }); + } +} diff --git a/tests/unittest.html b/tests/unittest.html index 4bf8945..bb347e7 100644 --- a/tests/unittest.html +++ b/tests/unittest.html @@ -14,7 +14,7 @@ tolerance = tolerance || 1e-5; ok(Math.abs(left - right) < tolerance, message + ": " + left + " ~== " + right); - } + } function lessThan(left, right, message) { message = message || "lessThan"; @@ -76,6 +76,16 @@ nearlyEqual(solution[0], 10, 1e-10); }); + test("minimizeConjugateGradient", function() { + // minimize simple 1 diminesial quadratic + var loss = function(x, xprime) { + xprime[0] = 2 * (x[0] - 10); + return (x[0] - 10) * (x[0] - 10); + } + var solution = venn.minimizeConjugateGradient(loss, [0]).x; + nearlyEqual(solution[0], 10, 1e-10); + }); + test("circleIntegral", function() { nearlyEqual(venn.circleIntegral(10, 0), 0, venn.SMALL, "empty circle test"); @@ -211,7 +221,6 @@ area = venn.intersectionArea(circles); ok(Math.abs(area - 0.0008914) < 0.0001, area); - }); test("computeTextCentre", function() { diff --git a/tests/venneuler_comparison/build.gradle b/tests/venneuler_comparison/build.gradle new file mode 100644 index 0000000..f4877fd --- /dev/null +++ b/tests/venneuler_comparison/build.gradle @@ -0,0 +1,24 @@ +buildscript { + repositories { + mavenCentral() + } +} + +apply plugin: 'java' + +repositories { + mavenCentral() + flatDir { + dirs '.' + } +} + +dependencies { + compile 'com.google.code.gson:gson:2.2.4' + compile name: 'venneuler' +} + +task run(type: JavaExec, dependsOn: 'jar') { + main = 'VennEulerServer' + classpath=sourceSets.main.runtimeClasspath +} diff --git a/tests/venneuler_comparison/index.html b/tests/venneuler_comparison/index.html new file mode 100644 index 0000000..2ba6ba5 --- /dev/null +++ b/tests/venneuler_comparison/index.html @@ -0,0 +1,503 @@ + + + + + venn.js compared to venneuler + + + + + + + +
+
+
+ +

+

The VennEuler approach is described in an excellent + paper by Leland Wilkinson. As far as I'm aware this is the + best published academic research on laying out area proportional Venn + and Euler diagrams. + +

This page runs the same performance test on VennEuler that was used to test venn.js.

+ +

Circles are randomly positioned and then the intersection areas + are calculated from these circles. Using only the intersection areas, + VennEuler has to plot circles whose areas match the input.

+ +

Unfortunately, the VennEuler package doesn't perform all that well + on this test. The problem seems to be that while VennEuler frequently + gets a solution that is close to being correct, it rarely gets a + solution that is close enough for this test to say it succeeded.

+ +

Examples of failure cases are shown first, followed by aggregate + graphs showing performance relative to venn.js. Finally a couple of + reasons for VennEuler's performance on this test are discussed. +

+ +


+

A simple failing example

+ +

+ Calling VennEuler with two disjoint sets can produce a diagram where + the circles overlap.

+ +

+ For example, calling VennEuler with two sets of size + 98 and 48 that have 0 overlap between them produces this diagram:

+ +
+ +

+ The overlap is this diagram is small (about 2.2% of the size of the + '1' set), but very noticeable. The performance test I'm using here + labels this diagram as failing to adequately represent the input since + the two sets shouldn't overlap at all. +

+ +

However, VennEuler reports that it successfully laid out this + diagram. The VennEuler paper defines a 'stress' metric that measures how well + the diagram fits the input. Lower values are better, and the paper + suggests that if the stress is less than 0.01 then the solution is + good enough to use. +

+ +

+ The stress for the above solution above is 0.0001 - 100x lower than + the cutoff suggested. This is because of how that stress metric is + calculated: its the sum of squared errors normalized by the sum of + squared total areas. Since the circles themselves are included in the + total areas, the error in this case is divided by (982 + + 482). Since the error is only ~ 12 and that is + divided by the large squared total area - the stress value is very + low. +

+ + +
+

Other Examples

+ +

More examples of individual trials in this test are shown below. While VennEuler occasionally works, it frequently produces solutions that differ by a significant amount from the original. These areas + are shown in red if the difference in areas is more than 10%, at which stage we say it failed to reconstruct. + +

+
+
+
+ + +
+ + +
+
+ + +
+
+

Original

+
+
+

Reconstructed

+
+
+
+ +
+
+

The results here are precomputed, with random circles being chosen + uniformly in (0, 1) with radii uniformly in (.1, .5).

+
+
+
+
+

Aggregate Performance

+

Since VennEuler is a java package, precomputed results are shown + here. To get results from live code, or to change the test parameters + - type 'gradle run' from the same directory as this file. This + will launch a simple java server that exposes the layouts from + VennEuler to this page over a HTTP JSON api.

+
+ +

+
+
+ +
+ +
+ +
+
+
+ +
+

Success Rate

+
+
+
+

Average Time (ms)

+
+
+
+
+
+
+

Discussion

+ +

+ Wilkinson performs a similar test in his paper, and reports positive + results with an average stress of .006. Since the performance here + seems much worse than whats reported in the paper, I thought I'd + quickly list out some of the reasons behind this discrepancy. +

+ +

+ The test here is exceedingly strict and simply an average of + a binary success/failure judgement. VennEuler frequently produces + diagrams that are very close to being correct, but with a few + failing areas. +

+ +

The stress metric that VennEuler reports breaks down in the + case of small regions in larger diagrams as seen in the first + example. VennEuler uses this stress metric for an early exit + performance optimization causing it to potentially stop the + optimization process too early in some cases. +

+ +

VennEuler does three separate steps to generate the layout. The + first step is an initial layout based off of MDS. This is followed by + steepest descent on a pseudo-gradient function and + then finally coordinate descent directly on the loss function.

+ +

For an initial layout, MDS is better than random - but + much worse than the greedy layout I wrote or the Constrained + MDS variant I came up with. VennEuler also computes MDS on Jaccard distance + to generate the initial layout, which seems to perform worse than the + Euclidean distance that I used.

+ +

+ The pseudo-gradient descent step is interesting and actually performs fairly + well. I ran some experiments with my own version of it when developing this + code. I found it is the second best optimization technique + I tried when starting from a random layout. However to get + good results I had to run it for many more iterations than in the + VennEuler package: VennEuler ran 50 iterations and I was seeing good + results at 5000 iterations. This explains why VennEuler seems to get + solutions that are mostly right, but frequently contains some small + errors. Ultimately the Constrained MDS optimizer I wrote outperformed + this method in terms of both speed and accuracy, so I decided not to + use this.

+ +

+ Finally VennEuler uses coordinate descent to fine tune the results. I + don't believe this will perform as well as a fine tuning step as the + Nelder-Mead optimizer I'm using though I haven't done any experiments + to verify. +

+ +

While the running time seems worse in VennEuler, + VennEuler scales up better than venn.js does. This is because the + number of regions in the venn diagram grows exponentially with the + number of sets. VennEuler uses an approximation method for + calculating intersection area sizes that mitigates this, while venn.js calculates the sizes of each region directly. While each call is individually + fast the sheer number of calls explodes as the number of sets + increases, causing venn.js to perform sluggishly. Also worth noting is + that timing results reported elsewhere in this repo + are done on just the 2-way set intersections: I'm doing all circle + intersections here to exactly match the input given to VennEuler. + Using only 2-way set intersections leads to identical diagrams in this + test, and is roughly a 100x faster on the 8-set case.

+ +

Most of the discrepancy in results is just because this test + expects basically exact replicas of the input. VennEuler does a fine + job of capturing the global structure, but it frequently lacks the + fine details that are necessary to pass this test. +

+
+
+ + + + + + + + + + + + + + + + + diff --git a/tests/venneuler_comparison/precomputed.jsonp b/tests/venneuler_comparison/precomputed.jsonp new file mode 100644 index 0000000..bb0c1df --- /dev/null +++ b/tests/venneuler_comparison/precomputed.jsonp @@ -0,0 +1,7444 @@ +var precomputed = [ + { + "original": [ + { + "x": 0.7254790707957, + "y": 0.16883126320317388, + "radius": 0.13306202339008452 + }, + { + "x": 0.07453475659713149, + "y": 0.6891235711518675, + "radius": 0.4231152990832925 + }, + { + "x": 0.553756182314828, + "y": 0.18066823622211814, + "radius": 0.3101601562462747 + }, + { + "x": 0.8426710774656385, + "y": 0.4238041758071631, + "radius": 0.22107575051486494 + } + ], + "computed": { + "0": { + "x": 0.8427579725615442, + "y": 1.1808908127131033, + "radius": 0.13306202339008452 + }, + "1": { + "x": 1.4358824954195097, + "y": 1.0585092048619036, + "radius": 0.42311529908329243 + }, + "2": { + "x": 0.7475136948332805, + "y": 1.0191201407435284, + "radius": 0.31016015624627463 + }, + "3": { + "x": 0.9223303607843184, + "y": 0.6899643652801173, + "radius": 0.22107575051486492 + } + } + }, + { + "original": [ + { + "x": 0.5920310071669519, + "y": 0.30767109291628003, + "radius": 0.23044590670615436 + }, + { + "x": 0.8630897181574255, + "y": 0.4741473912727088, + "radius": 0.46635681577026844 + }, + { + "x": 0.41611070465296507, + "y": 0.6643909881822765, + "radius": 0.4755152865312994 + }, + { + "x": 0.4175157544668764, + "y": 0.9813612042926252, + "radius": 0.4692613473162055 + } + ], + "computed": { + "0": { + "x": 1.476581350494586, + "y": 1.278743232889359, + "radius": 0.23044590670615436 + }, + "1": { + "x": 1.4147357122660498, + "y": 0.9678870536132806, + "radius": 0.46635681577026844 + }, + "2": { + "x": 1.092436996203878, + "y": 1.3053230847257713, + "radius": 0.4755152865312993 + }, + "3": { + "x": 0.7901028015000954, + "y": 1.2219034892361986, + "radius": 0.4692613473162055 + } + } + }, + { + "original": [ + { + "x": 0.5108560235239565, + "y": 0.8614258128218353, + "radius": 0.31493134731426836 + }, + { + "x": 0.1706427524331957, + "y": 0.7696887282654643, + "radius": 0.2786165731959045 + }, + { + "x": 0.20540619338862598, + "y": 0.4588855314068496, + "radius": 0.3475951340980828 + }, + { + "x": 0.2054324031341821, + "y": 0.056560610653832555, + "radius": 0.35451864218339324 + } + ], + "computed": { + "0": { + "x": 1.2542582132605011, + "y": 1.190870959761636, + "radius": 0.3149313473142684 + }, + "1": { + "x": 1.2109675993878046, + "y": 0.842289936839579, + "radius": 0.2786165731959045 + }, + "2": { + "x": 0.9036824852810275, + "y": 0.8380954216945357, + "radius": 0.3475951340980828 + }, + "3": { + "x": 0.621539946378504, + "y": 1.1191919260120866, + "radius": 0.35451864218339324 + } + } + }, + { + "original": [ + { + "x": 0.35137129621580243, + "y": 0.27042521396651864, + "radius": 0.38073428999632597 + }, + { + "x": 0.03328466322273016, + "y": 0.22101017483510077, + "radius": 0.41553132487460975 + }, + { + "x": 0.45582191250286996, + "y": 0.48117089085280895, + "radius": 0.3529208251275122 + }, + { + "x": 0.38781143305823207, + "y": 0.24625003337860107, + "radius": 0.4712693715468049 + } + ], + "computed": { + "0": { + "x": 0.975591799969597, + "y": 1.0612582446791996, + "radius": 0.38073428999632597 + }, + "1": { + "x": 1.2743051798064502, + "y": 0.9477086238936485, + "radius": 0.4155313248746098 + }, + "2": { + "x": 0.7951488416129314, + "y": 0.9091831570401812, + "radius": 0.3529208251275122 + }, + "3": { + "x": 0.9574699365649014, + "y": 1.0843657323408507, + "radius": 0.471269371546805 + } + } + }, + { + "original": [ + { + "x": 0.8217623017262667, + "y": 0.6257418158929795, + "radius": 0.17266136705875396 + }, + { + "x": 0.15262416168116033, + "y": 0.7598724628333002, + "radius": 0.31680881502106784 + }, + { + "x": 0.6033129887655377, + "y": 0.684210094390437, + "radius": 0.24637348633259537 + }, + { + "x": 0.7442391451913863, + "y": 0.6068302437197417, + "radius": 0.2166550572961569 + } + ], + "computed": { + "0": { + "x": 0.8617699537566494, + "y": 0.8256014466116331, + "radius": 0.17266136705875396 + }, + "1": { + "x": 0.3859218853605483, + "y": 0.7780304964260654, + "radius": 0.31680881502106784 + }, + "2": { + "x": 0.806047074776404, + "y": 0.607229876458497, + "radius": 0.24637348633259537 + }, + "3": { + "x": 0.896556418683512, + "y": 0.7394335130809183, + "radius": 0.2166550572961569 + } + } + }, + { + "original": [ + { + "x": 0.1833062688820064, + "y": 0.04834088496863842, + "radius": 0.3471298521384597 + }, + { + "x": 0.18368050828576088, + "y": 0.7408666065894067, + "radius": 0.4024250759743154 + }, + { + "x": 0.9248618970159441, + "y": 0.2618624910246581, + "radius": 0.3078200220130384 + }, + { + "x": 0.4955913885496557, + "y": 0.6344240768812597, + "radius": 0.353156313020736 + } + ], + "computed": { + "0": { + "x": 1.4514841428803387, + "y": 1.485864369731369, + "radius": 0.3471298521384597 + }, + "1": { + "x": 0.7933680768499446, + "y": 1.3087098736583915, + "radius": 0.4024250759743154 + }, + "2": { + "x": 1.4318260468128892, + "y": 0.7920956396975297, + "radius": 0.3078200220130384 + }, + "3": { + "x": 0.9439992289457082, + "y": 1.0340076124015911, + "radius": 0.35315631302073597 + } + } + }, + { + "original": [ + { + "x": 0.15949011710472405, + "y": 0.6862035987433046, + "radius": 0.2136092022061348 + }, + { + "x": 0.9222846894990653, + "y": 0.6373945372179151, + "radius": 0.2591553358361125 + }, + { + "x": 0.09930589515715837, + "y": 0.5641925963573158, + "radius": 0.16602885220199826 + }, + { + "x": 0.35975185479037464, + "y": 0.17944374261423945, + "radius": 0.28510074261575935 + } + ], + "computed": { + "0": { + "x": 0.5429675632360697, + "y": 0.7743084730663639, + "radius": 0.2136092022061348 + }, + "1": { + "x": 1.0014384971375097, + "y": 0.5230847178723261, + "radius": 0.25915533583611255 + }, + "2": { + "x": 0.6323797040820723, + "y": 0.8456994752293363, + "radius": 0.16602885220199828 + }, + "3": { + "x": 1.011281659469982, + "y": 1.044974757757607, + "radius": 0.2851007426157594 + } + } + }, + { + "original": [ + { + "x": 0.2161824726499617, + "y": 0.6952096752356738, + "radius": 0.34721396397799253 + }, + { + "x": 0.21326122269965708, + "y": 0.19078905205242336, + "radius": 0.43344566514715555 + }, + { + "x": 0.912860338576138, + "y": 0.04204188263975084, + "radius": 0.178256378415972 + }, + { + "x": 0.2733815999235958, + "y": 0.031487573171034455, + "radius": 0.3557834463194013 + } + ], + "computed": { + "0": { + "x": 0.8867883043262382, + "y": 1.3770541348597771, + "radius": 0.34721396397799253 + }, + "1": { + "x": 1.2173824267931013, + "y": 1.0031781801986162, + "radius": 0.43344566514715555 + }, + "2": { + "x": 0.645152361552494, + "y": 0.7925044341906735, + "radius": 0.17825637841597197 + }, + "3": { + "x": 1.2651755113424465, + "y": 0.8417618547652136, + "radius": 0.35578344631940123 + } + } + }, + { + "original": [ + { + "x": 0.2934757999610156, + "y": 0.4813103647902608, + "radius": 0.12547465078532696 + }, + { + "x": 0.1913505617994815, + "y": 0.9717413168400526, + "radius": 0.31514762220904236 + }, + { + "x": 0.8300519385375082, + "y": 0.9063396032433957, + "radius": 0.21657673716545106 + }, + { + "x": 0.6892000858206302, + "y": 0.24304359662346542, + "radius": 0.19469276862218976 + } + ], + "computed": { + "0": { + "x": 0.5635662652415634, + "y": 1.156948150936807, + "radius": 0.12547465078532696 + }, + "1": { + "x": 0.8188252101836653, + "y": 0.3646399041970873, + "radius": 0.31514762220904236 + }, + "2": { + "x": 0.6922847356218222, + "y": 0.8793966307688739, + "radius": 0.21657673716545106 + }, + "3": { + "x": 1.094976157554092, + "y": 0.7686676826983744, + "radius": 0.19469276862218973 + } + } + }, + { + "original": [ + { + "x": 0.21598066668957472, + "y": 0.056525472551584244, + "radius": 0.13558893352746965 + }, + { + "x": 0.9416472930461168, + "y": 0.7058973270468414, + "radius": 0.2595183303579688 + }, + { + "x": 0.3499985272064805, + "y": 0.4446470320690423, + "radius": 0.4902241537347436 + }, + { + "x": 0.3865357260219753, + "y": 0.5060671889223158, + "radius": 0.23095491817221048 + } + ], + "computed": { + "0": { + "x": 0.8224865457863333, + "y": 1.2899611931975452, + "radius": 0.13558893352746965 + }, + "1": { + "x": 0.647482434662801, + "y": 0.6967613559788118, + "radius": 0.25951833035796884 + }, + "2": { + "x": 1.169749333938274, + "y": 1.0622951039625959, + "radius": 0.4902241537347437 + }, + "3": { + "x": 1.2617116429299942, + "y": 0.8524123041784495, + "radius": 0.2309549181722105 + } + } + }, + { + "original": [ + { + "x": 0.7522954579908401, + "y": 0.8574656748678535, + "radius": 0.12944080876186492 + }, + { + "x": 0.12021522247232497, + "y": 0.38384242192842066, + "radius": 0.33008717838674784 + }, + { + "x": 0.1522011193446815, + "y": 0.1649118980858475, + "radius": 0.18805161537602544 + }, + { + "x": 0.8683050218969584, + "y": 0.534648034023121, + "radius": 0.4008500382304192 + } + ], + "computed": { + "0": { + "x": 1.0987751964078978, + "y": 1.0488915422753482, + "radius": 0.12944080876186492 + }, + "1": { + "x": 0.585363660167323, + "y": 1.0220119515710617, + "radius": 0.33008717838674784 + }, + "2": { + "x": 0.7692832803050894, + "y": 0.9695840988156291, + "radius": 0.18805161537602544 + }, + "3": { + "x": 1.3039791300920576, + "y": 0.7169136743103287, + "radius": 0.4008500382304192 + } + } + }, + { + "original": [ + { + "x": 0.8882105853408575, + "y": 0.4322263968642801, + "radius": 0.17169635901227592 + }, + { + "x": 0.631066671339795, + "y": 0.02034094650298357, + "radius": 0.4612813022918999 + }, + { + "x": 0.6699043021071702, + "y": 0.3896571935620159, + "radius": 0.3182535947300494 + }, + { + "x": 0.7039356546010822, + "y": 0.0750069604255259, + "radius": 0.2554601642303169 + } + ], + "computed": { + "0": { + "x": 1.1241247194720005, + "y": 0.9879949744023631, + "radius": 0.17169635901227592 + }, + "1": { + "x": 0.6841738848540808, + "y": 0.8821180917136133, + "radius": 0.4612813022918999 + }, + "2": { + "x": 1.042469926666976, + "y": 0.7821464445407954, + "radius": 0.3182535947300494 + }, + "3": { + "x": 0.7587833281473026, + "y": 0.9572923484835889, + "radius": 0.2554601642303169 + } + } + }, + { + "original": [ + { + "x": 0.2243096148595214, + "y": 0.3116356083191931, + "radius": 0.402042871247977 + }, + { + "x": 0.47446149098686874, + "y": 0.6636192831210792, + "radius": 0.46956878323107965 + }, + { + "x": 0.4543511117808521, + "y": 0.10721096466295421, + "radius": 0.13591646952554584 + }, + { + "x": 0.8118514453526586, + "y": 0.5697153334040195, + "radius": 0.48123670602217317 + } + ], + "computed": { + "0": { + "x": 1.3012798736360083, + "y": 1.3833048948728166, + "radius": 0.402042871247977 + }, + "1": { + "x": 0.9121282714863442, + "y": 1.2272005343264876, + "radius": 0.4695687832310797 + }, + "2": { + "x": 1.4546082032138055, + "y": 1.0927296020471138, + "radius": 0.13591646952554584 + }, + "3": { + "x": 0.9131772055021318, + "y": 0.8779585225918717, + "radius": 0.48123670602217317 + } + } + }, + { + "original": [ + { + "x": 0.17513810680247843, + "y": 0.7681713518686593, + "radius": 0.47447366463020446 + }, + { + "x": 0.40123985265381634, + "y": 0.4319079197011888, + "radius": 0.20712935887277129 + }, + { + "x": 0.9542820502538234, + "y": 0.5511297774501145, + "radius": 0.46041203178465373 + }, + { + "x": 0.4743498177267611, + "y": 0.5028236468788236, + "radius": 0.11078064311295749 + } + ], + "computed": { + "0": { + "x": 1.2415403934988105, + "y": 1.5510711758980666, + "radius": 0.47447366463020446 + }, + "1": { + "x": 1.313583372282145, + "y": 1.115536217208452, + "radius": 0.20712935887277126 + }, + "2": { + "x": 0.8503703482720333, + "y": 0.8634888540580481, + "radius": 0.4604120317846537 + }, + "3": { + "x": 1.26922812658208, + "y": 1.1446259934705028, + "radius": 0.1107806431129575 + } + } + }, + { + "original": [ + { + "x": 0.9931444260291755, + "y": 0.20522949961014092, + "radius": 0.22314981585368515 + }, + { + "x": 0.7962092412635684, + "y": 0.6358484823722392, + "radius": 0.22055337727069857 + }, + { + "x": 0.9903931405860931, + "y": 0.7598508521914482, + "radius": 0.18890808438882234 + }, + { + "x": 0.5482303635217249, + "y": 0.42760705668479204, + "radius": 0.3902258451096714 + } + ], + "computed": { + "0": { + "x": 1.1526723166354262, + "y": 1.0022997829957256, + "radius": 0.22314981585368512 + }, + "1": { + "x": 0.6845895562949943, + "y": 0.7986693960860091, + "radius": 0.22055337727069851 + }, + "2": { + "x": 0.6732363931614217, + "y": 1.0513613844579992, + "radius": 0.1889080843888223 + }, + "3": { + "x": 0.9174815386545451, + "y": 0.5756492412066536, + "radius": 0.3902258451096713 + } + } + }, + { + "original": [ + { + "x": 0.8818636501673609, + "y": 0.9766784815583378, + "radius": 0.33611831348389387 + }, + { + "x": 0.12987952469848096, + "y": 0.6744028546381742, + "radius": 0.23444598764181138 + }, + { + "x": 0.16494125360623002, + "y": 0.8209675650577992, + "radius": 0.43384525384753947 + }, + { + "x": 0.2438899353146553, + "y": 0.4081123429350555, + "radius": 0.2274993907660246 + } + ], + "computed": { + "0": { + "x": 1.4954484530918397, + "y": 0.994458383049692, + "radius": 0.336118313483894 + }, + "1": { + "x": 0.8378814435587658, + "y": 0.9567543189775821, + "radius": 0.2344459876418114 + }, + "2": { + "x": 0.8014398822110854, + "y": 0.8447172507165471, + "radius": 0.4338452538475395 + }, + "3": { + "x": 0.9149948234425687, + "y": 1.2538346495604382, + "radius": 0.2274993907660246 + } + } + }, + { + "original": [ + { + "x": 0.00970913260243833, + "y": 0.061454462353140116, + "radius": 0.45786838158965115 + }, + { + "x": 0.8913744008168578, + "y": 0.6955669349990785, + "radius": 0.15258347811177375 + }, + { + "x": 0.31542638735845685, + "y": 0.9583217175677419, + "radius": 0.28798071751371024 + }, + { + "x": 0.28519843658432364, + "y": 0.046708707232028246, + "radius": 0.18337554503232242 + } + ], + "computed": { + "0": { + "x": 1.3377260962428041, + "y": 1.11049344433347, + "radius": 0.45786838158965115 + }, + "1": { + "x": 0.7279275495776106, + "y": 1.2836991199006877, + "radius": 0.15258347811177375 + }, + "2": { + "x": 0.7143012067229101, + "y": 0.6345536648563135, + "radius": 0.28798071751371024 + }, + "3": { + "x": 1.2047184107467033, + "y": 0.9559270341995579, + "radius": 0.1833755450323224 + } + } + }, + { + "original": [ + { + "x": 0.09695981978438795, + "y": 0.14420695207081735, + "radius": 0.4490237732417882 + }, + { + "x": 0.271103051956743, + "y": 0.22543968819081783, + "radius": 0.3551521177403629 + }, + { + "x": 0.009892787784337997, + "y": 0.4506395277567208, + "radius": 0.1010258961468935 + }, + { + "x": 0.343460232950747, + "y": 0.5860035480000079, + "radius": 0.3592292805202305 + } + ], + "computed": { + "0": { + "x": 1.044052208524832, + "y": 1.1768158937790962, + "radius": 0.4490237732417882 + }, + "1": { + "x": 1.0958800803529116, + "y": 1.0114629911832356, + "radius": 0.355152117740363 + }, + "2": { + "x": 0.7410175437102909, + "y": 0.9862724948449207, + "radius": 0.1010258961468935 + }, + "3": { + "x": 0.9751970657760907, + "y": 0.6815955185568735, + "radius": 0.35922928052023056 + } + } + }, + { + "original": [ + { + "x": 0.8865532907657325, + "y": 0.691076269140467, + "radius": 0.19841513102874161 + }, + { + "x": 0.15997819206677377, + "y": 0.38348938012495637, + "radius": 0.20339729776605964 + }, + { + "x": 0.5699773179367185, + "y": 0.7529314318671823, + "radius": 0.29162763906642797 + }, + { + "x": 0.7480446223635226, + "y": 0.14183754147961736, + "radius": 0.263485371414572 + } + ], + "computed": { + "0": { + "x": 0.7463896710461019, + "y": 0.866284191594925, + "radius": 0.19841513102874161 + }, + "1": { + "x": 1.0476626284715438, + "y": 0.5710979480600413, + "radius": 0.20339729776605964 + }, + "2": { + "x": 0.42030898438075465, + "y": 0.7721817239099568, + "radius": 0.29162763906642797 + }, + "3": { + "x": 1.1260086534719116, + "y": 1.1308060738053887, + "radius": 0.26348537141457207 + } + } + }, + { + "original": [ + { + "x": 0.020200598053634167, + "y": 0.09088091133162379, + "radius": 0.2284567947499454 + }, + { + "x": 0.11564127984456718, + "y": 0.9171511451713741, + "radius": 0.16084035309031608 + }, + { + "x": 0.6082811015658081, + "y": 0.2647476296406239, + "radius": 0.2717525110580027 + }, + { + "x": 0.5610297110397369, + "y": 0.30688274977728724, + "radius": 0.10462259631603957 + } + ], + "computed": { + "0": { + "x": 0.4927900237055555, + "y": 0.9088331965874632, + "radius": 0.22845679474994543 + }, + "1": { + "x": 0.525867541202808, + "y": 0.4800778534369013, + "radius": 0.1608403530903161 + }, + "2": { + "x": 0.9331015498697068, + "y": 0.6628695304744198, + "radius": 0.27175251105800274 + }, + "3": { + "x": 0.8115554761324091, + "y": 0.7115340104116956, + "radius": 0.10462259631603958 + } + } + }, + { + "original": [ + { + "x": 0.3472261584829539, + "y": 0.26700308080762625, + "radius": 0.1298838428221643 + }, + { + "x": 0.04124205652624369, + "y": 0.3839032584801316, + "radius": 0.3615816529840231 + }, + { + "x": 0.7506029603537172, + "y": 0.40943725616671145, + "radius": 0.14725192543119192 + }, + { + "x": 0.7853423308115453, + "y": 0.7010664036497474, + "radius": 0.2676579718478024 + } + ], + "computed": { + "0": { + "x": 0.69255224218952, + "y": 0.9523796322629388, + "radius": 0.1298838428221643 + }, + "1": { + "x": 0.5175211370877785, + "y": 0.6448914457800665, + "radius": 0.3615816529840231 + }, + "2": { + "x": 0.9636893646469734, + "y": 0.7894095944658066, + "radius": 0.1472519254311919 + }, + "3": { + "x": 1.1747204118296113, + "y": 0.9618024832450714, + "radius": 0.2676579718478023 + } + } + }, + { + "original": [ + { + "x": 0.3533704122528434, + "y": 0.25087809353135526, + "radius": 0.21153331054374577 + }, + { + "x": 0.26308202906511724, + "y": 0.3510954414959997, + "radius": 0.18626508256420493 + }, + { + "x": 0.31054880283772945, + "y": 0.21948462794534862, + "radius": 0.24140587989240886 + }, + { + "x": 0.6719869920052588, + "y": 0.9293182867113501, + "radius": 0.32903499752283094 + } + ], + "computed": { + "0": { + "x": 0.6144687770530384, + "y": 0.7901411070825524, + "radius": 0.21153331054374575 + }, + "1": { + "x": 0.6342012815829291, + "y": 0.6506709694335461, + "radius": 0.1862650825642049 + }, + "2": { + "x": 0.5905908672452804, + "y": 0.7912333834136408, + "radius": 0.24140587989240883 + }, + "3": { + "x": 1.1422959073715853, + "y": 0.7495113733230938, + "radius": 0.32903499752283094 + } + } + }, + { + "original": [ + { + "x": 0.9823199843522161, + "y": 0.2981163398362696, + "radius": 0.184361657127738 + }, + { + "x": 0.45979932718910277, + "y": 0.1274556857533753, + "radius": 0.45802378421649337 + } + ], + "computed": { + "0": { + "x": 0.8809827735076561, + "y": 0.6113106694809578, + "radius": 0.184361657127738 + }, + "1": { + "x": 0.3416385654542595, + "y": 0.6113106694809578, + "radius": 0.45802378421649353 + } + } + }, + { + "original": [ + { + "x": 0.7874333194922656, + "y": 0.6057005035690963, + "radius": 0.47797708716243503 + }, + { + "x": 0.2731156467925757, + "y": 0.28554317518137395, + "radius": 0.2280944193713367 + } + ], + "computed": { + "0": { + "x": 0.9555899673107511, + "y": 0.6551734078526454, + "radius": 0.47797708716243503 + }, + "1": { + "x": 0.35475684839453986, + "y": 0.6551734078526454, + "radius": 0.2280944193713367 + } + } + }, + { + "original": [ + { + "x": 0.6622360916808248, + "y": 0.12105989432893693, + "radius": 0.3708657160401344 + }, + { + "x": 0.12967722886241972, + "y": 0.12178412382490933, + "radius": 0.39448404116556046 + } + ], + "computed": { + "0": { + "x": 0.9079108447751215, + "y": 0.6452747241890213, + "radius": 0.3708657160401344 + }, + "1": { + "x": 0.38263860360292107, + "y": 0.6452747241890213, + "radius": 0.3944840411655605 + } + } + }, + { + "original": [ + { + "x": 0.8286618394777179, + "y": 0.9253393923863769, + "radius": 0.13421818166971208 + }, + { + "x": 0.5546912662684917, + "y": 0.03915542387403548, + "radius": 0.14007041584700347 + } + ], + "computed": { + "0": { + "x": 0.39529750712592754, + "y": 0.24313726288356996, + "radius": 0.13421818166971208 + }, + "1": { + "x": 0.09097701864121238, + "y": 0.24313726288356996, + "radius": 0.14007041584700347 + } + } + }, + { + "original": [ + { + "x": 0.14709935896098614, + "y": 0.14548422349616885, + "radius": 0.4984419171698392 + }, + { + "x": 0.6103219313081354, + "y": 0.3624869571067393, + "radius": 0.3190851193852723 + } + ], + "computed": { + "0": { + "x": 0.9475805291283528, + "y": 0.6965147122191111, + "radius": 0.49844191716983927 + }, + "1": { + "x": 0.4454488953098695, + "y": 0.6965147122191111, + "radius": 0.31908511938527234 + } + } + }, + { + "original": [ + { + "x": 0.11224321741610765, + "y": 0.6286280546337366, + "radius": 0.4933453845791519 + }, + { + "x": 0.02141480753198266, + "y": 0.2582444923464209, + "radius": 0.12740766275674106 + } + ], + "computed": { + "0": { + "x": 0.8132577712650237, + "y": 0.6436582860001991, + "radius": 0.4933453845791519 + }, + "1": { + "x": 0.4245466248892054, + "y": 0.59414611015403, + "radius": 0.12740766275674106 + } + } + }, + { + "original": [ + { + "x": 0.3417481139767915, + "y": 0.5160376005806029, + "radius": 0.19635802544653416 + }, + { + "x": 0.39774560602381825, + "y": 0.23906215536408126, + "radius": 0.240510168671608 + } + ], + "computed": { + "0": { + "x": 0.5075142790571981, + "y": 0.36569271380484747, + "radius": 0.19635802544653416 + }, + "1": { + "x": 0.22387114855249673, + "y": 0.36569271380484747, + "radius": 0.240510168671608 + } + } + }, + { + "original": [ + { + "x": 0.5104466823395342, + "y": 0.2759565534070134, + "radius": 0.3450800741091371 + }, + { + "x": 0.8073304127901793, + "y": 0.27924562874250114, + "radius": 0.4377237781882286 + } + ], + "computed": { + "0": { + "x": 0.7485294547292217, + "y": 0.602888619023986, + "radius": 0.3450800741091371 + }, + "1": { + "x": 0.4572477833187504, + "y": 0.602888619023986, + "radius": 0.43772377818822866 + } + } + }, + { + "original": [ + { + "x": 0.7934885071590543, + "y": 0.8127780000213534, + "radius": 0.31815548045560715 + }, + { + "x": 0.4184978089760989, + "y": 0.4805545879062265, + "radius": 0.23691095868125558 + } + ], + "computed": { + "0": { + "x": 0.7396743799672614, + "y": 0.49281425948870805, + "radius": 0.31815548045560715 + }, + "1": { + "x": 0.24595413901015478, + "y": 0.49281425948870805, + "radius": 0.23691095868125558 + } + } + }, + { + "original": [ + { + "x": 0.25846129935234785, + "y": 0.008416705997660756, + "radius": 0.3640064472332597 + }, + { + "x": 0.8683422079775482, + "y": 0.20589282060973346, + "radius": 0.25145396022126076 + } + ], + "computed": { + "0": { + "x": 0.8674816494042769, + "y": 0.554483211309163, + "radius": 0.3640064472332597 + }, + "1": { + "x": 0.24148477321404915, + "y": 0.554483211309163, + "radius": 0.25145396022126076 + } + } + }, + { + "original": [ + { + "x": 0.7842510535847396, + "y": 0.9643997165840119, + "radius": 0.13803131803870203 + }, + { + "x": 0.5129147046245635, + "y": 0.774266853230074, + "radius": 0.1301973728463054 + } + ], + "computed": { + "0": { + "x": 0.37020009283593225, + "y": 0.2283003367156931, + "radius": 0.13803131803870203 + }, + "1": { + "x": 0.10542560865509511, + "y": 0.24732536477533423, + "radius": 0.1301973728463054 + } + } + }, + { + "original": [ + { + "x": 0.21170834940858185, + "y": 0.9796988884918392, + "radius": 0.45155355725437407 + }, + { + "x": 0.39897292107343674, + "y": 0.6989850467070937, + "radius": 0.3487892004661262 + } + ], + "computed": { + "0": { + "x": 0.7945236586405329, + "y": 0.6272756182772654, + "radius": 0.45155355725437407 + }, + "1": { + "x": 0.4600275779139981, + "y": 0.6272756182772654, + "radius": 0.3487892004661262 + } + } + }, + { + "original": [ + { + "x": 0.19422068493440747, + "y": 0.8471434179227799, + "radius": 0.476669301930815 + }, + { + "x": 0.4647158517036587, + "y": 0.9158361766021699, + "radius": 0.33527039475739007 + } + ], + "computed": { + "0": { + "x": 0.7660180521992427, + "y": 0.6272598522893714, + "radius": 0.47666930193081497 + }, + "1": { + "x": 0.4885016523795001, + "y": 0.6272598522893714, + "radius": 0.33527039475739007 + } + } + }, + { + "original": [ + { + "x": 0.8720098920166492, + "y": 0.48908425052650273, + "radius": 0.2027466228231788 + }, + { + "x": 0.43674361519515514, + "y": 0.4398743917699903, + "radius": 0.4552522852085531 + } + ], + "computed": { + "0": { + "x": 0.812609342127875, + "y": 0.5978935170880995, + "radius": 0.2027466228231788 + }, + "1": { + "x": 0.38317769204832397, + "y": 0.5978935170880995, + "radius": 0.4552522852085531 + } + } + }, + { + "original": [ + { + "x": 0.9707472755108029, + "y": 0.5719020992983133, + "radius": 0.3453997458331287 + }, + { + "x": 0.46989737381227314, + "y": 0.36498838826082647, + "radius": 0.3512350064702332 + } + ], + "computed": { + "0": { + "x": 0.8724799688107076, + "y": 0.5983721166791843, + "radius": 0.3453997458331287 + }, + "1": { + "x": 0.3242642645476611, + "y": 0.5983721166791843, + "radius": 0.35123500647023326 + } + } + }, + { + "original": [ + { + "x": 0.4238414254505187, + "y": 0.7938923700712621, + "radius": 0.44004855360835793 + }, + { + "x": 0.754271722631529, + "y": 0.49123451369814575, + "radius": 0.10633519729599357 + } + ], + "computed": { + "0": { + "x": 0.7822961478733794, + "y": 0.560673143418648, + "radius": 0.44004855360835793 + }, + "1": { + "x": 0.3390501389639167, + "y": 0.560673143418648, + "radius": 0.10633519729599358 + } + } + }, + { + "original": [ + { + "x": 0.4304109360091388, + "y": 0.20043306821025908, + "radius": 0.40665806895121936 + }, + { + "x": 0.4315392659045756, + "y": 0.7655735579319298, + "radius": 0.19480187557637693 + } + ], + "computed": { + "0": { + "x": 0.8467929237766877, + "y": 0.5855839939354467, + "radius": 0.4066580689512193 + }, + "1": { + "x": 0.27933014148378665, + "y": 0.5405390713250277, + "radius": 0.19480187557637693 + } + } + }, + { + "original": [ + { + "x": 0.31182450195774436, + "y": 0.059986499371007085, + "radius": 0.3266609069891274 + }, + { + "x": 0.7230435619130731, + "y": 0.5259784103836864, + "radius": 0.27852093065157535 + } + ], + "computed": { + "0": { + "x": 0.8300796539276651, + "y": 0.5380226031862474, + "radius": 0.32666090698912736 + }, + "1": { + "x": 0.24596555244482962, + "y": 0.5380226031862474, + "radius": 0.27852093065157535 + } + } + }, + { + "original": [ + { + "x": 0.7365055943373591, + "y": 0.14514570706523955, + "radius": 0.14228008640930057 + }, + { + "x": 0.7682361113838851, + "y": 0.29265989805571735, + "radius": 0.364193478319794 + } + ], + "computed": { + "0": { + "x": 0.5508253791519667, + "y": 0.4473198583943778, + "radius": 0.14228008640930057 + }, + "1": { + "x": 0.3620722910406411, + "y": 0.46557781179823, + "radius": 0.364193478319794 + } + } + }, + { + "original": [ + { + "x": 0.475131788989529, + "y": 0.7426769048906863, + "radius": 0.33002008507028224 + }, + { + "x": 0.22464189934544265, + "y": 0.4154704811517149, + "radius": 0.46773894792422654 + } + ], + "computed": { + "0": { + "x": 0.8583372018238441, + "y": 0.6516094431027019, + "radius": 0.33002008507028224 + }, + "1": { + "x": 0.44488168438155967, + "y": 0.6516094431027019, + "radius": 0.4677389479242265 + } + } + }, + { + "original": [ + { + "x": 0.8512994488701224, + "y": 0.9727145158685744, + "radius": 0.1206970083527267 + }, + { + "x": 0.9107501725666225, + "y": 0.5858213098254055, + "radius": 0.3011042554862797 + } + ], + "computed": { + "0": { + "x": 0.5980100227446166, + "y": 0.40480119321698027, + "radius": 0.1206970083527267 + }, + "1": { + "x": 0.211592363689344, + "y": 0.40480119321698027, + "radius": 0.3011042554862798 + } + } + }, + { + "original": [ + { + "x": 0.6820489175152034, + "y": 0.2718014873098582, + "radius": 0.32129671387374403 + }, + { + "x": 0.9543887237086892, + "y": 0.5554569966625422, + "radius": 0.11359418770298363 + } + ], + "computed": { + "0": { + "x": 0.6194877984172338, + "y": 0.4244756402625202, + "radius": 0.32129671387374403 + }, + "1": { + "x": 0.2294634821078066, + "y": 0.4244756402625202, + "radius": 0.11359418770298362 + } + } + }, + { + "original": [ + { + "x": 0.8360780305229127, + "y": 0.4385155967902392, + "radius": 0.3050684309564531 + }, + { + "x": 0.46689580962993205, + "y": 0.13939043646678329, + "radius": 0.22512372164055705 + } + ], + "computed": { + "0": { + "x": 0.7090610827600972, + "y": 0.4706298351068905, + "radius": 0.3050684309564531 + }, + "1": { + "x": 0.2321985874536838, + "y": 0.4706298351068905, + "radius": 0.22512372164055705 + } + } + }, + { + "original": [ + { + "x": 0.915666920831427, + "y": 0.5201043563429266, + "radius": 0.33185638925060634 + }, + { + "x": 0.9733213568106294, + "y": 0.9816319898236543, + "radius": 0.11125624617561698 + } + ], + "computed": { + "0": { + "x": 0.6529904263330564, + "y": 0.4386717924344711, + "radius": 0.33185638925060634 + }, + "1": { + "x": 0.2243531585358858, + "y": 0.4386717924344711, + "radius": 0.111256246175617 + } + } + }, + { + "original": [ + { + "x": 0.5839084435719997, + "y": 0.8704442305024713, + "radius": 0.16038772808387877 + }, + { + "x": 0.961734322598204, + "y": 0.050683882320299745, + "radius": 0.46988935945555566 + } + ], + "computed": { + "0": { + "x": 0.9406621043810599, + "y": 0.5973893235837775, + "radius": 0.16038772808387877 + }, + "1": { + "x": 0.3038989864184767, + "y": 0.6471717672157591, + "radius": 0.46988935945555566 + } + } + }, + { + "original": [ + { + "x": 0.5917612488847226, + "y": 0.5267091928981245, + "radius": 0.34629629608243706 + }, + { + "x": 0.8995063647162169, + "y": 0.25564497895538807, + "radius": 0.20610478809103372 + } + ], + "computed": { + "0": { + "x": 0.6881355416939217, + "y": 0.48773140195571135, + "radius": 0.34629629608243706 + }, + "1": { + "x": 0.2873272622175012, + "y": 0.48773140195571135, + "radius": 0.20610478809103372 + } + } + }, + { + "original": [ + { + "x": 0.6863077317830175, + "y": 0.9638095651753247, + "radius": 0.3454900925047696 + }, + { + "x": 0.7044540108181536, + "y": 0.4476924918126315, + "radius": 0.42846150426194074 + } + ], + "computed": { + "0": { + "x": 0.9085475556422514, + "y": 0.6518701779602706, + "radius": 0.3454900925047696 + }, + "1": { + "x": 0.3951928002782897, + "y": 0.6518701779602706, + "radius": 0.42846150426194063 + } + } + }, + { + "original": [ + { + "x": 0.4889097244013101, + "y": 0.21659997222013772, + "radius": 0.2622679151594639 + }, + { + "x": 0.017577393911778927, + "y": 0.7700846754014492, + "radius": 0.3229785902425647 + } + ], + "computed": { + "0": { + "x": 0.8291782589658843, + "y": 0.5214443992641707, + "radius": 0.2622679151594639 + }, + "1": { + "x": 0.21371053956245722, + "y": 0.5214443992641707, + "radius": 0.32297859024256476 + } + } + }, + { + "original": [ + { + "x": 0.7483567895833403, + "y": 0.9408360244706273, + "radius": 0.22246425570920111 + }, + { + "x": 0.18560411874204874, + "y": 0.3197397901676595, + "radius": 0.43241468640044334 + } + ], + "computed": { + "0": { + "x": 0.9287016123277839, + "y": 0.6094674849260829, + "radius": 0.22246425570920111 + }, + "1": { + "x": 0.29023335752438206, + "y": 0.6094674849260829, + "radius": 0.4324146864004433 + } + } + }, + { + "original": [ + { + "x": 0.4537492210511118, + "y": 0.07701822114177048, + "radius": 0.3540482789278031 + }, + { + "x": 0.17307456978596747, + "y": 0.5400282347109169, + "radius": 0.370720064546913 + } + ], + "computed": { + "0": { + "x": 0.8875807234590062, + "y": 0.6184757623178102, + "radius": 0.3540482789278031 + }, + "1": { + "x": 0.3493708011766144, + "y": 0.6184757623178102, + "radius": 0.370720064546913 + } + } + }, + { + "original": [ + { + "x": 0.642151118721813, + "y": 0.16654148302040994, + "radius": 0.41693129055202005 + }, + { + "x": 0.7175047087948769, + "y": 0.7209625672549009, + "radius": 0.16068123783916236 + }, + { + "x": 0.4013038235716522, + "y": 0.3165566704701632, + "radius": 0.25645294720306994 + } + ], + "computed": { + "0": { + "x": 0.5284601803208383, + "y": 0.8601412348092311, + "radius": 0.41693129055202 + }, + "1": { + "x": 1.0482137452240323, + "y": 0.6981773728338232, + "radius": 0.16068123783916233 + }, + "2": { + "x": 0.558146616269859, + "y": 0.5765019341716751, + "radius": 0.2564529472030699 + } + } + }, + { + "original": [ + { + "x": 0.1346723602619022, + "y": 0.006016513565555215, + "radius": 0.27310106065124273 + }, + { + "x": 0.29047713964246213, + "y": 0.22660772898234427, + "radius": 0.3208080822601914 + }, + { + "x": 0.9326747071463615, + "y": 0.06510516302660108, + "radius": 0.4605249960906804 + } + ], + "computed": { + "0": { + "x": 0.641016209513493, + "y": 1.0202548023489255, + "radius": 0.27310106065124273 + }, + "1": { + "x": 0.7036015260564028, + "y": 0.7570351591692496, + "radius": 0.3208080822601915 + }, + "2": { + "x": 1.3425179979750752, + "y": 0.9098457720267957, + "radius": 0.4605249960906805 + } + } + }, + { + "original": [ + { + "x": 0.5678381065372378, + "y": 0.13843998033553362, + "radius": 0.1033141520805657 + }, + { + "x": 0.15095193916931748, + "y": 0.44942846382036805, + "radius": 0.11283671911805869 + }, + { + "x": 0.6925268694758415, + "y": 0.14697862532921135, + "radius": 0.14300620192661884 + } + ], + "computed": { + "0": { + "x": 0.23199791949542795, + "y": 0.35927589175851005, + "radius": 0.1033141520805657 + }, + "1": { + "x": 0.4516984193087074, + "y": 0.3057740617877719, + "radius": 0.11283671911805872 + }, + "2": { + "x": 0.2165406673316821, + "y": 0.2351870525895354, + "radius": 0.14300620192661884 + } + } + }, + { + "original": [ + { + "x": 0.5075466332491487, + "y": 0.9368592945393175, + "radius": 0.38390435082837937 + }, + { + "x": 0.0018237566109746695, + "y": 0.9340777401812375, + "radius": 0.18976374054327608 + }, + { + "x": 0.11238173325546086, + "y": 0.2908476055599749, + "radius": 0.3964994139038026 + } + ], + "computed": { + "0": { + "x": 1.1214326552511695, + "y": 1.1817933973802015, + "radius": 0.38390435082837937 + }, + "1": { + "x": 1.0807101546194482, + "y": 0.6742391287682348, + "radius": 0.18976374054327608 + }, + "2": { + "x": 0.4671392161179454, + "y": 0.8132494998401267, + "radius": 0.3964994139038026 + } + } + }, + { + "original": [ + { + "x": 0.6634401318151504, + "y": 0.9710446852259338, + "radius": 0.10496439458802342 + }, + { + "x": 0.9364319208543748, + "y": 0.8702948384452611, + "radius": 0.2987169172614813 + }, + { + "x": 0.18997167167253792, + "y": 0.055351519491523504, + "radius": 0.45915059708058836 + } + ], + "computed": { + "0": { + "x": 0.6284833094819302, + "y": 0.9419927587723094, + "radius": 0.10496439458802342 + }, + "1": { + "x": 0.6162494686644542, + "y": 0.675889106848939, + "radius": 0.2987169172614813 + }, + "2": { + "x": 1.3003654971475542, + "y": 0.9272164096726896, + "radius": 0.45915059708058836 + } + } + }, + { + "original": [ + { + "x": 0.6640562964603305, + "y": 0.01877126470208168, + "radius": 0.33013710407540203 + }, + { + "x": 0.2526920400559902, + "y": 0.07869042153470218, + "radius": 0.4370285122655332 + }, + { + "x": 0.37509721354581416, + "y": 0.13249877956695855, + "radius": 0.47405532002449036 + } + ], + "computed": { + "0": { + "x": 1.0440635922528616, + "y": 0.7975410319595964, + "radius": 0.33013710407540203 + }, + "1": { + "x": 0.6423793489379034, + "y": 0.7511897080892843, + "radius": 0.43702851226553324 + }, + "2": { + "x": 0.7368469075174677, + "y": 0.8745591086593522, + "radius": 0.47405532002449036 + } + } + }, + { + "original": [ + { + "x": 0.5184742684941739, + "y": 0.14759716717526317, + "radius": 0.12571240924298765 + }, + { + "x": 0.8290709250140935, + "y": 0.8935072962194681, + "radius": 0.46745573114603756 + }, + { + "x": 0.05236531747505069, + "y": 0.17562593123875558, + "radius": 0.22962710252031684 + } + ], + "computed": { + "0": { + "x": 0.7068201214298119, + "y": 1.076956836835333, + "radius": 0.12571240924298765 + }, + "1": { + "x": 0.630389748449673, + "y": 0.4675394720135022, + "radius": 0.46745573114603756 + }, + "2": { + "x": 1.129984622545142, + "y": 0.9226981835757911, + "radius": 0.22962710252031684 + } + } + }, + { + "original": [ + { + "x": 0.9612254444509745, + "y": 0.7443692828528583, + "radius": 0.4886158744804562 + }, + { + "x": 0.8383843258488923, + "y": 0.23895372916013002, + "radius": 0.318682664539665 + }, + { + "x": 0.9205946729052812, + "y": 0.4469080991111696, + "radius": 0.43988153943791986 + } + ], + "computed": { + "0": { + "x": 1.1416308780408893, + "y": 0.8611445397343135, + "radius": 0.48861587448045624 + }, + "1": { + "x": 0.6086277150970854, + "y": 0.8738273858944906, + "radius": 0.318682664539665 + }, + "2": { + "x": 0.8555655027057046, + "y": 0.870852170214875, + "radius": 0.43988153943791986 + } + } + }, + { + "original": [ + { + "x": 0.2306821111124009, + "y": 0.1618422397878021, + "radius": 0.4773636457510293 + }, + { + "x": 0.6394021790474653, + "y": 0.44389454857446253, + "radius": 0.329798751976341 + }, + { + "x": 0.23827161802910268, + "y": 0.09388405689969659, + "radius": 0.3315937260165811 + } + ], + "computed": { + "0": { + "x": 0.976864107650033, + "y": 0.7356294224787011, + "radius": 0.4773636457510293 + }, + "1": { + "x": 0.49639800506410625, + "y": 0.857409560150403, + "radius": 0.329798751976341 + }, + "2": { + "x": 1.0240011895919559, + "y": 0.9042243196769915, + "radius": 0.3315937260165811 + } + } + }, + { + "original": [ + { + "x": 0.02606591093353927, + "y": 0.057360799983143806, + "radius": 0.16723858555778862 + }, + { + "x": 0.6932736802846193, + "y": 0.6650698746088892, + "radius": 0.2581042835488916 + }, + { + "x": 0.5118598423432559, + "y": 0.873840911546722, + "radius": 0.29279900779947643 + } + ], + "computed": { + "0": { + "x": 0.8750382348627572, + "y": 0.5938647701328998, + "radius": 0.16723858555778862 + }, + "1": { + "x": 0.46107169433803563, + "y": 0.4614428720219382, + "radius": 0.2581042835488916 + }, + "2": { + "x": 0.4530406688586209, + "y": 0.7338429559045758, + "radius": 0.2927990077994764 + } + } + }, + { + "original": [ + { + "x": 0.6035667404066771, + "y": 0.3446736722253263, + "radius": 0.29420544179156427 + }, + { + "x": 0.7346598790027201, + "y": 0.8669022626709193, + "radius": 0.24621134903281927 + }, + { + "x": 0.6414890699088573, + "y": 0.9758004429750144, + "radius": 0.43701966134831316 + } + ], + "computed": { + "0": { + "x": 1.1925956499318329, + "y": 0.7705231852611307, + "radius": 0.29420544179156427 + }, + "1": { + "x": 0.6059972329175284, + "y": 0.6979325458260093, + "radius": 0.2462113490328193 + }, + "2": { + "x": 0.5937668407195336, + "y": 0.9239039924817546, + "radius": 0.43701966134831316 + } + } + }, + { + "original": [ + { + "x": 0.34679196518845856, + "y": 0.7923827618360519, + "radius": 0.3369803066365421 + }, + { + "x": 0.8705159791279584, + "y": 0.5289000058546662, + "radius": 0.11360692474991084 + }, + { + "x": 0.3790104943327606, + "y": 0.3397432204801589, + "radius": 0.32450872752815485 + } + ], + "computed": { + "0": { + "x": 0.5623117709287585, + "y": 0.9285548701623025, + "radius": 0.3369803066365421 + }, + "1": { + "x": 0.984133786465054, + "y": 0.7028888792545093, + "radius": 0.11360692474991085 + }, + "2": { + "x": 0.5627622732378705, + "y": 0.4777640812148715, + "radius": 0.32450872752815485 + } + } + }, + { + "original": [ + { + "x": 0.6840728553943336, + "y": 0.8783114778343588, + "radius": 0.15534664047881963 + }, + { + "x": 0.7181171390693635, + "y": 0.5456978562287986, + "radius": 0.4579096384346485 + }, + { + "x": 0.6752940986771137, + "y": 0.778382936026901, + "radius": 0.2605917163193226 + } + ], + "computed": { + "0": { + "x": 0.860261262394419, + "y": 0.7277661078665199, + "radius": 0.15534664047881963 + }, + "1": { + "x": 0.5294381439793883, + "y": 0.6581909902862664, + "radius": 0.45790963843464855 + }, + "2": { + "x": 0.7355465953237521, + "y": 0.7392889035447734, + "radius": 0.2605917163193226 + } + } + }, + { + "original": [ + { + "x": 0.7903590835630894, + "y": 0.01706466916948557, + "radius": 0.4188389006070793 + }, + { + "x": 0.5125619499012828, + "y": 0.6397302795667201, + "radius": 0.2511666095815599 + }, + { + "x": 0.9731530847493559, + "y": 0.8998641811776906, + "radius": 0.37265027686953545 + } + ], + "computed": { + "0": { + "x": 1.3769901759308856, + "y": 0.9666156485549104, + "radius": 0.4188389006070793 + }, + "1": { + "x": 0.7428181905883154, + "y": 1.188776035541518, + "radius": 0.2511666095815599 + }, + "2": { + "x": 0.6842127311985325, + "y": 0.6486294136213054, + "radius": 0.37265027686953545 + } + } + }, + { + "original": [ + { + "x": 0.9529117511119694, + "y": 0.17964972299523652, + "radius": 0.18098066514357924 + }, + { + "x": 0.012967099202796817, + "y": 0.6291567976586521, + "radius": 0.33404187951236963 + }, + { + "x": 0.4948291548062116, + "y": 0.8966601055581123, + "radius": 0.41027303058654074 + } + ], + "computed": { + "0": { + "x": 0.4910057181526308, + "y": 0.8236552012555595, + "radius": 0.18098066514357924 + }, + "1": { + "x": 0.9922048028978326, + "y": 0.5551322473643696, + "radius": 0.3340418795123696 + }, + "2": { + "x": 1.0039576708939286, + "y": 1.1083807433244632, + "radius": 0.4102730305865407 + } + } + }, + { + "original": [ + { + "x": 0.7668520545121282, + "y": 0.4414248410612345, + "radius": 0.11631265319883824 + }, + { + "x": 0.23131116782315075, + "y": 0.49416504823602736, + "radius": 0.3776900839060545 + }, + { + "x": 0.8119680823292583, + "y": 0.9369214233011007, + "radius": 0.45758807891979814 + } + ], + "computed": { + "0": { + "x": 1.1997919558644674, + "y": 0.985593717586771, + "radius": 0.11631265319883824 + }, + "1": { + "x": 0.6315774492917544, + "y": 1.2096950676395108, + "radius": 0.37769008390605446 + }, + "2": { + "x": 0.9041154199334644, + "y": 0.5401960398634049, + "radius": 0.4575880789197981 + } + } + }, + { + "original": [ + { + "x": 0.4769035072531551, + "y": 0.7203771073836833, + "radius": 0.24239862328395248 + }, + { + "x": 0.6536909679416567, + "y": 0.06595580209977925, + "radius": 0.1924244304187596 + }, + { + "x": 0.8241126148495823, + "y": 0.8018063146155328, + "radius": 0.3981748605147004 + } + ], + "computed": { + "0": { + "x": 0.5727907217319007, + "y": 0.8924625541508998, + "radius": 0.24239862328395245 + }, + "1": { + "x": 1.0658919821650386, + "y": 0.7407673646514776, + "radius": 0.19242443041875956 + }, + "2": { + "x": 0.5337280662434032, + "y": 0.539180851337965, + "radius": 0.3981748605147004 + } + } + }, + { + "original": [ + { + "x": 0.18579843384213746, + "y": 0.017096039140596986, + "radius": 0.17240276467055082 + }, + { + "x": 0.430303119122982, + "y": 0.32006091461516917, + "radius": 0.37031266940757634 + }, + { + "x": 0.42398667498491704, + "y": 0.5581814574543387, + "radius": 0.44348561065271497 + } + ], + "computed": { + "0": { + "x": 0.46515418990569485, + "y": 0.7936313756393758, + "radius": 0.17240276467055082 + }, + "1": { + "x": 0.8292187987634104, + "y": 0.6978678135666735, + "radius": 0.37031266940757634 + }, + "2": { + "x": 1.004026045321365, + "y": 0.8068998447844207, + "radius": 0.443485610652715 + } + } + }, + { + "original": [ + { + "x": 0.5796969984658062, + "y": 0.1669444516301155, + "radius": 0.4712678759358824 + }, + { + "x": 0.7999489204958081, + "y": 0.209900755668059, + "radius": 0.38613091856241233 + }, + { + "x": 0.2191535911988467, + "y": 0.4123123260214925, + "radius": 0.4875309235416353 + } + ], + "computed": { + "0": { + "x": 0.8711515277453566, + "y": 1.054264027215961, + "radius": 0.4712678759358824 + }, + "1": { + "x": 0.6989193538315941, + "y": 0.8875615774896506, + "radius": 0.3861309185624123 + }, + "2": { + "x": 1.294638438339682, + "y": 0.9228837152110216, + "radius": 0.48753092354163524 + } + } + }, + { + "original": [ + { + "x": 0.05149980075657368, + "y": 0.7829297862481326, + "radius": 0.1857715961523354 + }, + { + "x": 0.14496283256448805, + "y": 0.6606882412452251, + "radius": 0.10440523391589523 + }, + { + "x": 0.5403830765280873, + "y": 0.9598807436414063, + "radius": 0.3374670178629458 + } + ], + "computed": { + "0": { + "x": 0.7742411895989316, + "y": 0.6930212534855716, + "radius": 0.1857715961523354 + }, + "1": { + "x": 0.7359812437243454, + "y": 0.5284096662153112, + "radius": 0.10440523391589523 + }, + "2": { + "x": 0.2873134801520963, + "y": 0.5761049937744905, + "radius": 0.33746701786294575 + } + } + }, + { + "original": [ + { + "x": 0.9258817157242447, + "y": 0.6499592834152281, + "radius": 0.42773298509418967 + }, + { + "x": 0.5306511209346354, + "y": 0.6582642532885075, + "radius": 0.35951577760279185 + }, + { + "x": 0.836884745862335, + "y": 0.18880730704404414, + "radius": 0.19603914003819228 + }, + { + "x": 0.0016905220691114664, + "y": 0.32882000622339547, + "radius": 0.2897753331810236 + }, + { + "x": 0.9961024606600404, + "y": 0.70083063445054, + "radius": 0.13011222993955018 + } + ], + "computed": { + "0": { + "x": 0.9628886771770961, + "y": 1.3147576405802746, + "radius": 0.4277329850941896 + }, + "1": { + "x": 0.8634072453618475, + "y": 0.938722333405757, + "radius": 0.3595157776027919 + }, + "2": { + "x": 1.323444566176229, + "y": 1.5890568991240792, + "radius": 0.1960391400381923 + }, + "3": { + "x": 1.5411245673638403, + "y": 0.8853910268397083, + "radius": 0.2897753331810236 + }, + "4": { + "x": 1.2664714266774366, + "y": 1.2294085828066308, + "radius": 0.13011222993955018 + } + } + }, + { + "original": [ + { + "x": 0.339874429628253, + "y": 0.9537650553975254, + "radius": 0.18680095756426454 + }, + { + "x": 0.686566615011543, + "y": 0.6275139776989818, + "radius": 0.12316041551530361 + }, + { + "x": 0.9626226299442351, + "y": 0.9818087134044617, + "radius": 0.12058775145560503 + }, + { + "x": 0.23627916048280895, + "y": 0.9098023036494851, + "radius": 0.33175715506076814 + }, + { + "x": 0.6786673485767096, + "y": 0.49226061976514757, + "radius": 0.27112228963524104 + } + ], + "computed": { + "0": { + "x": 1.1097398995642127, + "y": 0.8148689955202536, + "radius": 0.18680095756426454 + }, + "1": { + "x": 0.6969690085141103, + "y": 0.7491388053766503, + "radius": 0.12316041551530363 + }, + "2": { + "x": 0.865075113810526, + "y": 1.2467029027966883, + "radius": 0.12058775145560502 + }, + "3": { + "x": 1.153752946240533, + "y": 0.8559996205137571, + "radius": 0.33175715506076814 + }, + "4": { + "x": 0.5846276747046767, + "y": 0.7434543186267091, + "radius": 0.27112228963524104 + } + } + }, + { + "original": [ + { + "x": 0.28666755370795727, + "y": 0.7213681836146861, + "radius": 0.1744768817909062 + }, + { + "x": 0.16349541442468762, + "y": 0.6436922494322062, + "radius": 0.42481429120525716 + }, + { + "x": 0.02349335583858192, + "y": 0.6268901161383837, + "radius": 0.3382902740500867 + }, + { + "x": 0.9749171626754105, + "y": 0.8732355972751975, + "radius": 0.3419036705046892 + }, + { + "x": 0.9113568430766463, + "y": 0.7426093702670187, + "radius": 0.22779437061399221 + } + ], + "computed": { + "0": { + "x": 1.2897867472348592, + "y": 0.9210516955137071, + "radius": 0.1744768817909062 + }, + "1": { + "x": 1.4276753824186137, + "y": 1.148831138144749, + "radius": 0.4248142912052571 + }, + "2": { + "x": 1.3319458313785808, + "y": 1.1902186000317654, + "radius": 0.33829027405008666 + }, + "3": { + "x": 0.6723713529397923, + "y": 1.1111947330883098, + "radius": 0.34190367050468917 + }, + "4": { + "x": 0.7736378626078456, + "y": 1.124121009801159, + "radius": 0.2277943706139922 + } + } + }, + { + "original": [ + { + "x": 0.3073098282329738, + "y": 0.6483507971279323, + "radius": 0.404789621848613 + }, + { + "x": 0.3692827511113137, + "y": 0.29114699992351234, + "radius": 0.22569819623604417 + }, + { + "x": 0.8183229975402355, + "y": 0.2806380905676633, + "radius": 0.4531551502645016 + }, + { + "x": 0.28704357193782926, + "y": 0.4493537270464003, + "radius": 0.3775868388824165 + }, + { + "x": 0.1226664932910353, + "y": 0.8481829278171062, + "radius": 0.35194859467446804 + } + ], + "computed": { + "0": { + "x": 1.4334588130085633, + "y": 1.2087887294381428, + "radius": 0.40478962184861295 + }, + "1": { + "x": 1.0904522620932655, + "y": 1.1238729145822675, + "radius": 0.22569819623604417 + }, + "2": { + "x": 0.9017132931876558, + "y": 1.5356395894650774, + "radius": 0.4531551502645016 + }, + "3": { + "x": 1.2769227251558115, + "y": 1.135225869363394, + "radius": 0.3775868388824165 + }, + "4": { + "x": 1.6597091441688656, + "y": 1.3587291347652792, + "radius": 0.35194859467446804 + } + } + }, + { + "original": [ + { + "x": 0.7453324154485017, + "y": 0.48780062375590205, + "radius": 0.1449133945629001 + }, + { + "x": 0.4374888204038143, + "y": 0.8807741468772292, + "radius": 0.24567518448457124 + }, + { + "x": 0.43509681755676866, + "y": 0.7568800642620772, + "radius": 0.2687537902034819 + }, + { + "x": 0.6144831732381135, + "y": 0.03604786889627576, + "radius": 0.49718651250004775 + }, + { + "x": 0.18145379913039505, + "y": 0.6771428363863379, + "radius": 0.4484707411378622 + } + ], + "computed": { + "0": { + "x": 1.7229588988113933, + "y": 1.5527913364312984, + "radius": 0.1449133945629001 + }, + "1": { + "x": 1.0411766643070284, + "y": 1.490829209217496, + "radius": 0.2456751844845712 + }, + "2": { + "x": 1.0205215685641278, + "y": 1.3979897255137508, + "radius": 0.2687537902034819 + }, + "3": { + "x": 1.8253988652016357, + "y": 1.0744112865642987, + "radius": 0.49718651250004764 + }, + "4": { + "x": 1.0784070854139685, + "y": 1.1724415245713093, + "radius": 0.4484707411378622 + } + } + }, + { + "original": [ + { + "x": 0.3821828512009233, + "y": 0.7941879199352115, + "radius": 0.12634766837581993 + }, + { + "x": 0.6190056384075433, + "y": 0.6475507258437574, + "radius": 0.2066303730942309 + }, + { + "x": 0.4540969205554575, + "y": 0.24939995841123164, + "radius": 0.3481164599768818 + }, + { + "x": 0.807779738213867, + "y": 0.2596917429473251, + "radius": 0.2683526777662337 + }, + { + "x": 0.32005215156823397, + "y": 0.39807477965950966, + "radius": 0.22535735350102187 + } + ], + "computed": { + "0": { + "x": 1.296427365667493, + "y": 0.8202261820717113, + "radius": 0.12634766837581993 + }, + "1": { + "x": 1.0811728128270284, + "y": 0.8888976960371228, + "radius": 0.20663037309423088 + }, + "2": { + "x": 0.6725042030138193, + "y": 0.9405034488716324, + "radius": 0.3481164599768818 + }, + "3": { + "x": 0.8616234865052793, + "y": 1.2483277881469865, + "radius": 0.2683526777662337 + }, + "4": { + "x": 0.7249260103205086, + "y": 0.7386987632066749, + "radius": 0.22535735350102185 + } + } + }, + { + "original": [ + { + "x": 0.44124798267148435, + "y": 0.6146265452262014, + "radius": 0.4170113816857338 + }, + { + "x": 0.41728660045191646, + "y": 0.8143904819153249, + "radius": 0.23162522334605457 + }, + { + "x": 0.0998790271114558, + "y": 0.7245408329181373, + "radius": 0.24357053693383934 + }, + { + "x": 0.4771014794241637, + "y": 0.14968707994557917, + "radius": 0.3975155879743397 + }, + { + "x": 0.2938610683195293, + "y": 0.38791969791054726, + "radius": 0.13158159805461767 + } + ], + "computed": { + "0": { + "x": 1.1584840312180713, + "y": 1.145998108846137, + "radius": 0.41701138168573376 + }, + "1": { + "x": 1.37292656063683, + "y": 1.1955179222172487, + "radius": 0.2316252233460546 + }, + "2": { + "x": 1.3502833502859122, + "y": 0.8549907538617466, + "radius": 0.24357053693383934 + }, + "3": { + "x": 0.7239333360268525, + "y": 1.2808416799430666, + "radius": 0.3975155879743398 + }, + "4": { + "x": 0.869437196527749, + "y": 0.9977160098272159, + "radius": 0.13158159805461767 + } + } + }, + { + "original": [ + { + "x": 0.5567342075519264, + "y": 0.9028782402165234, + "radius": 0.1160106010735035 + }, + { + "x": 0.8775800839066505, + "y": 0.7556057672481984, + "radius": 0.38359430786222226 + }, + { + "x": 0.1961545734666288, + "y": 0.8108210733626038, + "radius": 0.45643312493339183 + }, + { + "x": 0.44528876431286335, + "y": 0.6792933638207614, + "radius": 0.39404885442927484 + }, + { + "x": 0.1737008795607835, + "y": 0.8472937769256532, + "radius": 0.3748746891506016 + } + ], + "computed": { + "0": { + "x": 1.309935222979357, + "y": 1.2343852886085551, + "radius": 0.11601060107350351 + }, + "1": { + "x": 1.602490803124724, + "y": 1.051107713107187, + "radius": 0.3835943078622224 + }, + "2": { + "x": 0.9592372392657249, + "y": 1.278794935590183, + "radius": 0.4564331249333919 + }, + "3": { + "x": 1.1703515096894637, + "y": 1.0691290692109328, + "radius": 0.39404885442927484 + }, + "4": { + "x": 0.8796308391760577, + "y": 1.2882286077184704, + "radius": 0.3748746891506017 + } + } + }, + { + "original": [ + { + "x": 0.08066105772741139, + "y": 0.452070624101907, + "radius": 0.3431322251446545 + }, + { + "x": 0.0937899174168706, + "y": 0.02995872567407787, + "radius": 0.1313807056285441 + }, + { + "x": 0.3794300709851086, + "y": 0.05522030428983271, + "radius": 0.289585105329752 + }, + { + "x": 0.3922348292544484, + "y": 0.9863172555342317, + "radius": 0.23155357185751202 + }, + { + "x": 0.845782388933003, + "y": 0.4933945187367499, + "radius": 0.1429905315861106 + } + ], + "computed": { + "0": { + "x": 1.0317820954670205, + "y": 1.1230063569877518, + "radius": 0.34313222514465447 + }, + "1": { + "x": 1.3277313576681853, + "y": 0.838312140547058, + "radius": 0.13138070562854406 + }, + "2": { + "x": 1.4988568973280316, + "y": 1.0840130149128355, + "radius": 0.28958510532975207 + }, + "3": { + "x": 0.6512229408781136, + "y": 0.6337646045400482, + "radius": 0.23155357185751202 + }, + "4": { + "x": 0.659194611720256, + "y": 1.4896917860739136, + "radius": 0.1429905315861106 + } + } + }, + { + "original": [ + { + "x": 0.7774985684081912, + "y": 0.288534845225513, + "radius": 0.25269099250435834 + }, + { + "x": 0.38040800392627716, + "y": 0.7460707481950521, + "radius": 0.34989291056990623 + }, + { + "x": 0.003166152397170663, + "y": 0.12088775681331754, + "radius": 0.28782903160899875 + }, + { + "x": 0.17689596000127494, + "y": 0.5485890449490398, + "radius": 0.10716425161808729 + }, + { + "x": 0.861955497879535, + "y": 0.030772394500672817, + "radius": 0.4483720580115914 + } + ], + "computed": { + "0": { + "x": 1.5024536317832389, + "y": 1.120300935289208, + "radius": 0.25269099250435834 + }, + "1": { + "x": 0.900234774260435, + "y": 1.0289816638229115, + "radius": 0.34989291056990623 + }, + "2": { + "x": 1.2638998540881508, + "y": 1.8529604258970904, + "radius": 0.2878290316089988 + }, + "3": { + "x": 1.029754577897785, + "y": 1.1482594929699803, + "radius": 0.10716425161808728 + }, + "4": { + "x": 1.6946535975958632, + "y": 1.2404939176462835, + "radius": 0.44837205801159147 + } + } + }, + { + "original": [ + { + "x": 0.8024934090208262, + "y": 0.13852981477975845, + "radius": 0.3894138257019222 + }, + { + "x": 0.21190647897310555, + "y": 0.7344962265342474, + "radius": 0.40614610267803075 + }, + { + "x": 0.4687248838599771, + "y": 0.22282650298438966, + "radius": 0.35896725859493017 + }, + { + "x": 0.9566498873755336, + "y": 0.5736480311024934, + "radius": 0.48913598582148554 + }, + { + "x": 0.45138592924922705, + "y": 0.7481802329421043, + "radius": 0.34410821087658405 + } + ], + "computed": { + "0": { + "x": 1.8349304760863574, + "y": 1.4609626170808079, + "radius": 0.3894138257019222 + }, + "1": { + "x": 1.024957476730417, + "y": 1.5776754485705091, + "radius": 0.40614610267803075 + }, + "2": { + "x": 1.5735879050688497, + "y": 1.678365449503982, + "radius": 0.35896725859493017 + }, + "3": { + "x": 1.5875686061058252, + "y": 1.0827799536444036, + "radius": 0.48913598582148554 + }, + "4": { + "x": 1.1469264657646834, + "y": 1.3681874609564297, + "radius": 0.34410821087658405 + } + } + }, + { + "original": [ + { + "x": 0.19380249991081655, + "y": 0.41579579026438296, + "radius": 0.3753194644115866 + }, + { + "x": 0.045419038739055395, + "y": 0.9344892925582826, + "radius": 0.36580921914428477 + }, + { + "x": 0.5574481685180217, + "y": 0.7193275219760835, + "radius": 0.25806265976279974 + }, + { + "x": 0.6009735420811921, + "y": 0.5510571969207376, + "radius": 0.3813448018394411 + }, + { + "x": 0.6220990011934191, + "y": 0.396351283416152, + "radius": 0.2233530031517148 + } + ], + "computed": { + "0": { + "x": 1.314754592581391, + "y": 1.4170725916108073, + "radius": 0.37531946441158653 + }, + "1": { + "x": 1.6209539923695035, + "y": 0.9875767447796596, + "radius": 0.3658092191442847 + }, + "2": { + "x": 1.067079481572752, + "y": 1.0177068882416958, + "radius": 0.2580626597627997 + }, + "3": { + "x": 0.9779764846042486, + "y": 1.159456794664411, + "radius": 0.381344801839441 + }, + "4": { + "x": 0.9156860575293664, + "y": 1.3146375893606883, + "radius": 0.22335300315171477 + } + } + }, + { + "original": [ + { + "x": 0.20273842592723668, + "y": 0.27557794307358563, + "radius": 0.3600566162727773 + }, + { + "x": 0.9418117415625602, + "y": 0.8865584535524249, + "radius": 0.40875261975452304 + }, + { + "x": 0.2602010313421488, + "y": 0.4898326024413109, + "radius": 0.32769526485353706 + }, + { + "x": 0.3358945152722299, + "y": 0.284392076311633, + "radius": 0.2714770359918475 + }, + { + "x": 0.18620512448251247, + "y": 0.3580863787792623, + "radius": 0.17904718015342952 + } + ], + "computed": { + "0": { + "x": 1.309350627224028, + "y": 1.0453493875139879, + "radius": 0.3600566162727773 + }, + "1": { + "x": 0.5642451403882196, + "y": 1.1257184557377693, + "radius": 0.4087526197545231 + }, + "2": { + "x": 1.2744810588098014, + "y": 1.2700605874878725, + "radius": 0.3276952648535371 + }, + "3": { + "x": 1.326838783328098, + "y": 1.0775950201533346, + "radius": 0.2714770359918476 + }, + "4": { + "x": 1.2805288253568774, + "y": 1.2367209842140598, + "radius": 0.17904718015342955 + } + } + }, + { + "original": [ + { + "x": 0.12540259188972414, + "y": 0.957394955214113, + "radius": 0.3542379709891975 + }, + { + "x": 0.9438754499424249, + "y": 0.02322030090726912, + "radius": 0.384426380135119 + }, + { + "x": 0.41044555115513504, + "y": 0.2648954102769494, + "radius": 0.15044116312637926 + }, + { + "x": 0.6312345077749342, + "y": 0.03201277460902929, + "radius": 0.1367428313009441 + }, + { + "x": 0.9318087911233306, + "y": 0.5320050283335149, + "radius": 0.16981779895722865 + } + ], + "computed": { + "0": { + "x": 0.5907551491966789, + "y": 0.7754767775551974, + "radius": 0.35423797098919757 + }, + "1": { + "x": 1.5069166787762578, + "y": 1.2800235338346722, + "radius": 0.384426380135119 + }, + "2": { + "x": 1.0638685404280646, + "y": 1.0789942275154145, + "radius": 0.15044116312637926 + }, + "3": { + "x": 1.4402811217418727, + "y": 1.0192057542828536, + "radius": 0.1367428313009441 + }, + "4": { + "x": 1.0616657513424594, + "y": 1.509786948297196, + "radius": 0.16981779895722865 + } + } + }, + { + "original": [ + { + "x": 0.922799387248233, + "y": 0.9612169624306262, + "radius": 0.4636292222887278 + }, + { + "x": 0.8483988111838698, + "y": 0.6978535165544599, + "radius": 0.2548111494630575 + }, + { + "x": 0.23337119026109576, + "y": 0.7300800334196538, + "radius": 0.20509912576526404 + }, + { + "x": 0.4226982353720814, + "y": 0.059680545469745994, + "radius": 0.13793346071615817 + }, + { + "x": 0.8621536314021796, + "y": 0.6284368662163615, + "radius": 0.45531521840021016 + } + ], + "computed": { + "0": { + "x": 1.3544674620819663, + "y": 1.344132051417435, + "radius": 0.46362922228872777 + }, + "1": { + "x": 1.3395278159694792, + "y": 1.169791191802515, + "radius": 0.2548111494630575 + }, + "2": { + "x": 0.9033634364119961, + "y": 0.8513063075490729, + "radius": 0.205099125765264 + }, + "3": { + "x": 0.8520366168264136, + "y": 1.5696216409103108, + "radius": 0.13793346071615814 + }, + "4": { + "x": 1.5622133016348274, + "y": 1.0767574412453487, + "radius": 0.45531521840021016 + } + } + }, + { + "original": [ + { + "x": 0.7737745237536728, + "y": 0.37505732267163694, + "radius": 0.2152919923886657 + }, + { + "x": 0.768676838837564, + "y": 0.32123650796711445, + "radius": 0.48112707845866687 + }, + { + "x": 0.15468474803492427, + "y": 0.11269261757843196, + "radius": 0.409590940643102 + }, + { + "x": 0.7381884979549795, + "y": 0.4980548690073192, + "radius": 0.4952966538257897 + }, + { + "x": 0.02259831433184445, + "y": 0.7186411852017045, + "radius": 0.447115885373205 + } + ], + "computed": { + "0": { + "x": 1.7439699920667426, + "y": 1.3664879641458931, + "radius": 0.2152919923886657 + }, + "1": { + "x": 1.7387787241979829, + "y": 1.6563586084424975, + "radius": 0.481127078458667 + }, + "2": { + "x": 1.1769986026365866, + "y": 1.8102836798285449, + "radius": 0.40959094064310203 + }, + "3": { + "x": 1.7741607838700741, + "y": 1.489382820426777, + "radius": 0.49529665382578975 + }, + "4": { + "x": 1.0892359454272562, + "y": 1.20063097535493, + "radius": 0.4471158853732051 + } + } + }, + { + "original": [ + { + "x": 0.317847088444978, + "y": 0.9043304598890245, + "radius": 0.14413282945752146 + }, + { + "x": 0.3372422044631094, + "y": 0.36834536655806005, + "radius": 0.14684342294931413 + }, + { + "x": 0.3412669552490115, + "y": 0.000819244422018528, + "radius": 0.3700186354108155 + }, + { + "x": 0.8554731814656407, + "y": 0.2872625421732664, + "radius": 0.3274209597148001 + }, + { + "x": 0.8999532787129283, + "y": 0.221017676172778, + "radius": 0.11090632872655988 + } + ], + "computed": { + "0": { + "x": 1.0986049765961128, + "y": 1.4181035861476499, + "radius": 0.14413282945752146 + }, + "1": { + "x": 1.3725914710348068, + "y": 1.0238075528313075, + "radius": 0.14684342294931413 + }, + "2": { + "x": 1.2341815686083564, + "y": 0.721262281461013, + "radius": 0.37001863541081553 + }, + "3": { + "x": 0.6929040302265858, + "y": 0.9331408852606079, + "radius": 0.32742095971480006 + }, + "4": { + "x": 0.7272421739770834, + "y": 1.029209914742367, + "radius": 0.11090632872655987 + } + } + }, + { + "original": [ + { + "x": 0.41793691157363355, + "y": 0.15871203690767288, + "radius": 0.33846118533983827 + }, + { + "x": 0.5493732411414385, + "y": 0.1641672959085554, + "radius": 0.43948960145935423 + }, + { + "x": 0.27034666296094656, + "y": 0.46307961479760706, + "radius": 0.21749756960198285 + }, + { + "x": 0.10975791024975479, + "y": 0.9899681464303285, + "radius": 0.10155256604775786 + }, + { + "x": 0.15181508427485824, + "y": 0.12983227847144008, + "radius": 0.3913655732758343 + } + ], + "computed": { + "0": { + "x": 1.2326589773049026, + "y": 1.0896263017918675, + "radius": 0.33846118533983827 + }, + "1": { + "x": 1.3333347938733169, + "y": 1.198136599415153, + "radius": 0.4394896014593542 + }, + "2": { + "x": 1.2785966032425444, + "y": 0.7914353541183933, + "radius": 0.21749756960198285 + }, + "3": { + "x": 0.5659156846660638, + "y": 1.3543303548244283, + "radius": 0.10155256604775785 + }, + "4": { + "x": 1.0103494964507003, + "y": 0.9873269453876854, + "radius": 0.39136557327583427 + } + } + }, + { + "original": [ + { + "x": 0.24661912373267114, + "y": 0.6246623310726136, + "radius": 0.29607443921267984 + }, + { + "x": 0.9971623797900975, + "y": 0.9632741922978312, + "radius": 0.12807626649737358 + }, + { + "x": 0.7984650474973023, + "y": 0.2876235318835825, + "radius": 0.4522132007405162 + }, + { + "x": 0.9211029428988695, + "y": 0.6175705485511571, + "radius": 0.1087732169777155 + }, + { + "x": 0.5115618084091693, + "y": 0.26881532720290124, + "radius": 0.4434898402541876 + } + ], + "computed": { + "0": { + "x": 1.1920532386307512, + "y": 1.5296003857990217, + "radius": 0.29607443921267984 + }, + "1": { + "x": 0.7933295723135453, + "y": 1.3677172568512566, + "radius": 0.12807626649737358 + }, + "2": { + "x": 1.3779453397238284, + "y": 0.9231993937013364, + "radius": 0.4522132007405161 + }, + "3": { + "x": 1.0003206530950641, + "y": 0.8286150250382117, + "radius": 0.10877321697771548 + }, + "4": { + "x": 1.4805207960780074, + "y": 1.19503753845137, + "radius": 0.4434898402541876 + } + } + }, + { + "original": [ + { + "x": 0.7752108110580593, + "y": 0.22782782278954983, + "radius": 0.37786658983677623 + }, + { + "x": 0.7170702302828431, + "y": 0.7157387956976891, + "radius": 0.4147251952439547 + }, + { + "x": 0.2766128515359014, + "y": 0.5187110204715282, + "radius": 0.24731225445866586 + }, + { + "x": 0.06657126382924616, + "y": 0.15717971418052912, + "radius": 0.3851094541139901 + }, + { + "x": 0.26028134138323367, + "y": 0.8491369499824941, + "radius": 0.10001792190596462 + } + ], + "computed": { + "0": { + "x": 0.8873458193872166, + "y": 1.2021875601583902, + "radius": 0.37786658983677623 + }, + "1": { + "x": 1.0590326475579468, + "y": 1.6296781117208494, + "radius": 0.4147251952439547 + }, + "2": { + "x": 1.4844780676475275, + "y": 1.5758588058204175, + "radius": 0.24731225445866586 + }, + "3": { + "x": 1.817104327040945, + "y": 1.3914191412645325, + "radius": 0.38510945411399017 + }, + "4": { + "x": 1.3900754356088858, + "y": 0.838892678278332, + "radius": 0.10001792190596462 + } + } + }, + { + "original": [ + { + "x": 0.7838443559594452, + "y": 0.7072165368590504, + "radius": 0.21618705224245788 + }, + { + "x": 0.3021095700096339, + "y": 0.10094113601371646, + "radius": 0.4900947582907975 + }, + { + "x": 0.5145510148722678, + "y": 0.45381913357414305, + "radius": 0.24621238447725774 + }, + { + "x": 0.527838431764394, + "y": 0.9120851941406727, + "radius": 0.4708059164695442 + }, + { + "x": 0.09613439883105457, + "y": 0.48563961940817535, + "radius": 0.4468843788839877 + } + ], + "computed": { + "0": { + "x": 1.9005472152957834, + "y": 1.5411918659782768, + "radius": 0.21618705224245788 + }, + "1": { + "x": 0.9615041425480227, + "y": 1.571998009091855, + "radius": 0.49009475829079757 + }, + "2": { + "x": 1.4025213650621977, + "y": 1.598653086696557, + "radius": 0.24621238447725774 + }, + "3": { + "x": 1.7588469334788115, + "y": 1.2916188524350107, + "radius": 0.47080591646954423 + }, + "4": { + "x": 1.179104779251972, + "y": 1.199062621435091, + "radius": 0.44688437888398774 + } + } + }, + { + "original": [ + { + "x": 0.7993378394749016, + "y": 0.18850293336436152, + "radius": 0.39098247410729525 + }, + { + "x": 0.9304568765219301, + "y": 0.22154317470267415, + "radius": 0.3658873302862048 + }, + { + "x": 0.6627018058206886, + "y": 0.4693019527476281, + "radius": 0.35959957642480733 + }, + { + "x": 0.36141537642106414, + "y": 0.3002201032359153, + "radius": 0.10243414053693414 + }, + { + "x": 0.5787612262647599, + "y": 0.875178455375135, + "radius": 0.2741952139884234 + }, + { + "x": 0.05047222110442817, + "y": 0.9283257185015827, + "radius": 0.3076274679973722 + } + ], + "computed": { + "0": { + "x": 1.618757161426281, + "y": 1.2616509028191416, + "radius": 0.3909824741072953 + }, + "1": { + "x": 1.7208151572230674, + "y": 1.314188000823538, + "radius": 0.3658873302862049 + }, + "2": { + "x": 1.4120396430395354, + "y": 1.5183730395225323, + "radius": 0.3595995764248074 + }, + "3": { + "x": 1.2696697490213116, + "y": 1.0258213790834176, + "radius": 0.10243414053693416 + }, + "4": { + "x": 1.1847883773103973, + "y": 1.81498264724112, + "radius": 0.27419521398842345 + }, + "5": { + "x": 0.8728517486176021, + "y": 1.143905867148445, + "radius": 0.30762746799737223 + } + } + }, + { + "original": [ + { + "x": 0.8752351065631956, + "y": 0.5195412847679108, + "radius": 0.2556913431733847 + }, + { + "x": 0.8010167824104428, + "y": 0.31975218816660345, + "radius": 0.21018384248018265 + }, + { + "x": 0.4814123010728508, + "y": 0.7094146022573113, + "radius": 0.4295851814560593 + }, + { + "x": 0.18225999968126416, + "y": 0.21179731446318328, + "radius": 0.36390469446778295 + }, + { + "x": 0.5224447117652744, + "y": 0.6019800649955869, + "radius": 0.39749243166297676 + }, + { + "x": 0.592947106808424, + "y": 0.9359612639527768, + "radius": 0.3005671946331859 + } + ], + "computed": { + "0": { + "x": 1.0702586744196285, + "y": 1.5051835645056426, + "radius": 0.2556913431733847 + }, + "1": { + "x": 0.9674122539820738, + "y": 1.3475036297751493, + "radius": 0.21018384248018263 + }, + "2": { + "x": 1.4718831981143001, + "y": 1.3745987441992957, + "radius": 0.4295851814560593 + }, + "3": { + "x": 1.3713392165350138, + "y": 0.8124029494603107, + "radius": 0.363904694467783 + }, + "4": { + "x": 1.374578730295616, + "y": 1.3278373771932825, + "radius": 0.39749243166297676 + }, + "5": { + "x": 1.648582246659098, + "y": 1.5365280548720481, + "radius": 0.3005671946331859 + } + } + }, + { + "original": [ + { + "x": 0.5681690443307161, + "y": 0.08096779650077224, + "radius": 0.46865692567080264 + }, + { + "x": 0.026670395396649837, + "y": 0.8811589339748025, + "radius": 0.15162408770993352 + }, + { + "x": 0.17326621478423476, + "y": 0.9773218466434628, + "radius": 0.48008690113201735 + }, + { + "x": 0.5654673969838768, + "y": 0.5089233249891549, + "radius": 0.42931809173896907 + }, + { + "x": 0.021991867572069168, + "y": 0.6686167463194579, + "radius": 0.11499559162184597 + }, + { + "x": 0.8687608758918941, + "y": 0.7378724699374288, + "radius": 0.10872540920972824 + } + ], + "computed": { + "0": { + "x": 2.213233731887879, + "y": 1.6941077198844856, + "radius": 0.46865692567080264 + }, + "1": { + "x": 1.1181631915983485, + "y": 1.696028191525664, + "radius": 0.15162408770993352 + }, + "2": { + "x": 1.325306591914073, + "y": 1.886666455803206, + "radius": 0.48008690113201735 + }, + "3": { + "x": 1.8186291951703506, + "y": 1.531663711652563, + "radius": 0.429318091738969 + }, + "4": { + "x": 1.2137153257132949, + "y": 1.494127082343065, + "radius": 0.11499559162184596 + }, + "5": { + "x": 1.6055591504424396, + "y": 0.992014025517401, + "radius": 0.10872540920972824 + } + } + }, + { + "original": [ + { + "x": 0.34372067684307694, + "y": 0.2682673076633364, + "radius": 0.4633487886749208 + }, + { + "x": 0.002424814272671938, + "y": 0.7182462755590677, + "radius": 0.38368985522538424 + }, + { + "x": 0.3126220656558871, + "y": 0.4959280197508633, + "radius": 0.35201570242643354 + }, + { + "x": 0.6747071873396635, + "y": 0.9760393772739917, + "radius": 0.491372087225318 + }, + { + "x": 0.2545386536512524, + "y": 0.47862299042753875, + "radius": 0.3530227674171329 + }, + { + "x": 0.06407421734184027, + "y": 0.3859790260903537, + "radius": 0.1304060203023255 + } + ], + "computed": { + "0": { + "x": 1.8758450454321596, + "y": 1.4810540392024245, + "radius": 0.46334878867492074 + }, + "1": { + "x": 1.4743596601050863, + "y": 1.857839817880738, + "radius": 0.38368985522538424 + }, + "2": { + "x": 1.658275996227067, + "y": 1.5315893633024482, + "radius": 0.35201570242643354 + }, + "3": { + "x": 1.1446880167502724, + "y": 1.2336269005354608, + "radius": 0.4913720872253179 + }, + "4": { + "x": 1.682935255314709, + "y": 1.585995470014653, + "radius": 0.35302276741713284 + }, + "5": { + "x": 1.6521851045080955, + "y": 1.7981834874016644, + "radius": 0.13040602030232548 + } + } + }, + { + "original": [ + { + "x": 0.4588234727270901, + "y": 0.4829150221776217, + "radius": 0.49853776879608636 + }, + { + "x": 0.10501669370569289, + "y": 0.622193573275581, + "radius": 0.16302163945510983 + }, + { + "x": 0.7435413266066462, + "y": 0.8941785427741706, + "radius": 0.1000806056894362 + }, + { + "x": 0.8225133898667991, + "y": 0.8511341991834342, + "radius": 0.4679184028878808 + }, + { + "x": 0.9495089517440647, + "y": 0.8943072613328695, + "radius": 0.3131663927808404 + }, + { + "x": 0.6711867398116738, + "y": 0.3975227961782366, + "radius": 0.30232991818338634 + } + ], + "computed": { + "0": { + "x": 1.0860425708809551, + "y": 1.3486956862141084, + "radius": 0.49853776879608636 + }, + "1": { + "x": 1.1417630604463096, + "y": 0.9648228875008759, + "radius": 0.16302163945510983 + }, + "2": { + "x": 1.5905832745196733, + "y": 1.1864788852901347, + "radius": 0.10008060568943619 + }, + "3": { + "x": 1.5498934219614218, + "y": 1.578690088415646, + "radius": 0.4679184028878808 + }, + "4": { + "x": 1.6955336890647454, + "y": 1.465280914297602, + "radius": 0.3131663927808404 + }, + "5": { + "x": 1.0742722568687821, + "y": 1.5941198120235198, + "radius": 0.30232991818338634 + } + } + }, + { + "original": [ + { + "x": 0.9285538319963962, + "y": 0.7710745157673955, + "radius": 0.3762407895177603 + }, + { + "x": 0.6856747269630432, + "y": 0.8010856518521905, + "radius": 0.30070885075256226 + }, + { + "x": 0.13383826077915728, + "y": 0.1802015311550349, + "radius": 0.4525085833854974 + }, + { + "x": 0.372228424763307, + "y": 0.42134789749979973, + "radius": 0.45183755084872246 + }, + { + "x": 0.17581957834772766, + "y": 0.12817339901812375, + "radius": 0.3989541530609131 + }, + { + "x": 0.2153111903462559, + "y": 0.09190393355675042, + "radius": 0.133086365647614 + } + ], + "computed": { + "0": { + "x": 0.8678480541186198, + "y": 1.4222281291446033, + "radius": 0.3762407895177603 + }, + "1": { + "x": 1.0288428362298594, + "y": 1.5822271745265115, + "radius": 0.3007088507525622 + }, + "2": { + "x": 1.8179753194612516, + "y": 1.4614215655618434, + "radius": 0.45250858338549727 + }, + "3": { + "x": 1.4960499040449142, + "y": 1.562588503240446, + "radius": 0.4518375508487224 + }, + "4": { + "x": 1.8036150476990445, + "y": 1.3963799338170937, + "radius": 0.398954153060913 + }, + "5": { + "x": 1.5945809111597273, + "y": 1.1840667664229192, + "radius": 0.13308636564761397 + } + } + }, + { + "original": [ + { + "x": 0.1538314763456583, + "y": 0.46681903675198555, + "radius": 0.36603871500119567 + }, + { + "x": 0.6080690703820437, + "y": 0.5542550943791866, + "radius": 0.1818220808170736 + }, + { + "x": 0.08202257636003196, + "y": 0.8046098845079541, + "radius": 0.4549951141700149 + }, + { + "x": 0.516217625932768, + "y": 0.4173212102614343, + "radius": 0.21544156279414894 + }, + { + "x": 0.38310219650156796, + "y": 0.1408588970080018, + "radius": 0.38035471653565767 + }, + { + "x": 0.9404507814906538, + "y": 0.4152024434879422, + "radius": 0.1656783205457032 + } + ], + "computed": { + "0": { + "x": 1.568026328841729, + "y": 1.5627595702944375, + "radius": 0.36603871500119567 + }, + "1": { + "x": 1.0799144629482567, + "y": 1.376488388344394, + "radius": 0.1818220808170736 + }, + "2": { + "x": 1.8111083687384633, + "y": 1.332502184034817, + "radius": 0.454995114170015 + }, + "3": { + "x": 1.2294380612248998, + "y": 1.4864157240511375, + "radius": 0.21544156279414894 + }, + "4": { + "x": 1.2412023104856025, + "y": 1.7684797341919543, + "radius": 0.3803547165356577 + }, + "5": { + "x": 1.3930641893895548, + "y": 0.796108120711767, + "radius": 0.1656783205457032 + } + } + }, + { + "original": [ + { + "x": 0.36204521963372827, + "y": 0.4466029228642583, + "radius": 0.17748762583360078 + }, + { + "x": 0.7200681045651436, + "y": 0.775765527272597, + "radius": 0.13754019914194943 + }, + { + "x": 0.17662906926125288, + "y": 0.49313602317124605, + "radius": 0.19856336023658516 + }, + { + "x": 0.7083078832365572, + "y": 0.6758551944512874, + "radius": 0.35250256555154924 + }, + { + "x": 0.7334812232293189, + "y": 0.7230729409493506, + "radius": 0.148841748572886 + }, + { + "x": 0.6768977041356266, + "y": 0.45299742789939046, + "radius": 0.3215720238164067 + } + ], + "computed": { + "0": { + "x": 1.2152926731221192, + "y": 0.9666443900389403, + "radius": 0.17748762583360078 + }, + "1": { + "x": 0.8119536800090356, + "y": 1.0689928995066937, + "radius": 0.13754019914194945 + }, + "2": { + "x": 1.2831453152090881, + "y": 1.1562946962357634, + "radius": 0.1985633602365852 + }, + "3": { + "x": 0.7965019280246147, + "y": 0.8994852986609608, + "radius": 0.35250256555154924 + }, + "4": { + "x": 0.8079144049175789, + "y": 1.0132574482245469, + "radius": 0.14884174857288604 + }, + "5": { + "x": 0.9700396192906077, + "y": 0.7801728879061381, + "radius": 0.3215720238164067 + } + } + }, + { + "original": [ + { + "x": 0.38445016206242144, + "y": 0.6991802519187331, + "radius": 0.1777894147671759 + }, + { + "x": 0.5453520461451262, + "y": 0.6981632323004305, + "radius": 0.4223902605473996 + }, + { + "x": 0.8174300531391054, + "y": 0.45919610070995986, + "radius": 0.21587027292698624 + }, + { + "x": 0.9278541286475956, + "y": 0.05627880897372961, + "radius": 0.4531828068196774 + }, + { + "x": 0.6008930169045925, + "y": 0.3096826949622482, + "radius": 0.3575460392050446 + }, + { + "x": 0.8785387435927987, + "y": 0.9789204257540405, + "radius": 0.11257286705076695 + } + ], + "computed": { + "0": { + "x": 1.6921333176859317, + "y": 1.0805975134172487, + "radius": 0.1777894147671759 + }, + "1": { + "x": 1.5045326541719302, + "y": 1.1418790734182522, + "radius": 0.42239026054739953 + }, + "2": { + "x": 1.1701457877783998, + "y": 1.3096424431394835, + "radius": 0.21587027292698624 + }, + "3": { + "x": 1.0359617986062744, + "y": 1.6792165981308707, + "radius": 0.4531828068196774 + }, + "4": { + "x": 1.1493608974396508, + "y": 1.2648633905147937, + "radius": 0.35754603920504463 + }, + "5": { + "x": 1.6997234438170499, + "y": 1.775658880878588, + "radius": 0.11257286705076695 + } + } + }, + { + "original": [ + { + "x": 0.7330947092268616, + "y": 0.6801536963321269, + "radius": 0.1883160767145455 + }, + { + "x": 0.8400536372791976, + "y": 0.02005583024583757, + "radius": 0.39339994536712763 + }, + { + "x": 0.8300470942631364, + "y": 0.68502935487777, + "radius": 0.2138280900195241 + }, + { + "x": 0.8261348037049174, + "y": 0.13185100187547505, + "radius": 0.19169492488726975 + }, + { + "x": 0.1034488866571337, + "y": 0.07421088451519608, + "radius": 0.46696688020601873 + }, + { + "x": 0.8176875209901482, + "y": 0.8916981273796409, + "radius": 0.28073104433715346 + } + ], + "computed": { + "0": { + "x": 1.0916755480955016, + "y": 1.6094855455610908, + "radius": 0.1883160767145455 + }, + "1": { + "x": 1.9212074807121071, + "y": 1.5912227559272705, + "radius": 0.39339994536712763 + }, + "2": { + "x": 1.052910290064177, + "y": 1.5554515886548042, + "radius": 0.2138280900195241 + }, + "3": { + "x": 1.8249152331670149, + "y": 1.7737649959769095, + "radius": 0.19169492488726972 + }, + "4": { + "x": 1.7127072047317655, + "y": 0.8437304392699727, + "radius": 0.46696688020601873 + }, + "5": { + "x": 1.2514015037559831, + "y": 1.4811619351365026, + "radius": 0.28073104433715346 + } + } + }, + { + "original": [ + { + "x": 0.4290960270445794, + "y": 0.6604102491401136, + "radius": 0.1548361085355282 + }, + { + "x": 0.823538311989978, + "y": 0.3215595146175474, + "radius": 0.3981367414817214 + }, + { + "x": 0.4029811806976795, + "y": 0.7426261499058455, + "radius": 0.28189451480284333 + }, + { + "x": 0.9352295096032321, + "y": 0.2578175626695156, + "radius": 0.3466732855886221 + }, + { + "x": 0.6076172452885658, + "y": 0.28745646169409156, + "radius": 0.4206984200514853 + }, + { + "x": 0.4973227467853576, + "y": 0.8001558342948556, + "radius": 0.4772027345374227 + } + ], + "computed": { + "0": { + "x": 1.638523448484672, + "y": 1.452421672029297, + "radius": 0.1548361085355282 + }, + "1": { + "x": 1.040345998461822, + "y": 1.3988270583887445, + "radius": 0.3981367414817215 + }, + "2": { + "x": 1.7102345060628565, + "y": 1.2931643784343927, + "radius": 0.2818945148028434 + }, + "3": { + "x": 0.9642680066717106, + "y": 1.4029950801820212, + "radius": 0.3466732855886221 + }, + "4": { + "x": 1.2480909418667738, + "y": 1.543449361953107, + "radius": 0.4206984200514853 + }, + "5": { + "x": 1.6333445566168936, + "y": 1.1439499071771662, + "radius": 0.47720273453742273 + } + } + }, + { + "original": [ + { + "x": 0.38687461824156344, + "y": 0.5496542504988611, + "radius": 0.23351621795445682 + }, + { + "x": 0.3129944645334035, + "y": 0.27053877292200923, + "radius": 0.4568795832805336 + }, + { + "x": 0.38012010138481855, + "y": 0.6593122312333435, + "radius": 0.22610668232664466 + }, + { + "x": 0.35237582540139556, + "y": 0.3397563884500414, + "radius": 0.43162581557407975 + }, + { + "x": 0.969290892360732, + "y": 0.4196402414236218, + "radius": 0.19234811812639238 + }, + { + "x": 0.6200325314421207, + "y": 0.1257087483536452, + "radius": 0.3303652241826057 + } + ], + "computed": { + "0": { + "x": 1.3999862932412883, + "y": 1.1797183268059763, + "radius": 0.2335162179544568 + }, + "1": { + "x": 1.256794817540164, + "y": 1.4118564208498228, + "radius": 0.4568795832805335 + }, + "2": { + "x": 1.4526462525846344, + "y": 1.0786630813575555, + "radius": 0.22610668232664463 + }, + "3": { + "x": 1.2755351028586528, + "y": 1.335216396169935, + "radius": 0.4316258155740797 + }, + "4": { + "x": 0.8761814698737739, + "y": 0.8700035720433615, + "radius": 0.19234811812639235 + }, + "5": { + "x": 0.9355837749838198, + "y": 1.3212699138556823, + "radius": 0.33036522418260567 + } + } + }, + { + "original": [ + { + "x": 0.7365154675208032, + "y": 0.4559257959481329, + "radius": 0.2570413529872895 + }, + { + "x": 0.5841387272812426, + "y": 0.09744470077566803, + "radius": 0.1205110063776374 + }, + { + "x": 0.41646418115124106, + "y": 0.7541856484021991, + "radius": 0.4985399160534144 + }, + { + "x": 0.17964643985033035, + "y": 0.21439962042495608, + "radius": 0.2715079918503761 + }, + { + "x": 0.5425382908433676, + "y": 0.8661633366718888, + "radius": 0.4327950481325388 + }, + { + "x": 0.9363787642214447, + "y": 0.9953095172531903, + "radius": 0.30875788861885667 + } + ], + "computed": { + "0": { + "x": 1.517668804659979, + "y": 0.9749559025200762, + "radius": 0.2570413529872895 + }, + "1": { + "x": 1.0176430920357145, + "y": 1.6228603386688596, + "radius": 0.12051100637763741 + }, + "2": { + "x": 1.74490668106463, + "y": 1.339990005581503, + "radius": 0.49853991605341447 + }, + "3": { + "x": 1.0413686988086936, + "y": 1.2219950551001866, + "radius": 0.27150799185037616 + }, + "4": { + "x": 1.6675779332443952, + "y": 1.4257399098672963, + "radius": 0.4327950481325388 + }, + "5": { + "x": 1.450328617510555, + "y": 1.8539526155860464, + "radius": 0.30875788861885667 + } + } + }, + { + "original": [ + { + "x": 0.7901170805562288, + "y": 0.9234570318367332, + "radius": 0.4842248857021332 + }, + { + "x": 0.07928371150046587, + "y": 0.4917281628586352, + "radius": 0.35353592680767176 + }, + { + "x": 0.17742270650342107, + "y": 0.9477330145891756, + "radius": 0.30059814574196936 + }, + { + "x": 0.22210219106636941, + "y": 0.45087895123288035, + "radius": 0.17507674135267737 + }, + { + "x": 0.05044402740895748, + "y": 0.3099105884321034, + "radius": 0.34766336996108294 + }, + { + "x": 0.4658474812749773, + "y": 0.18569354829378426, + "radius": 0.10574678219854833 + } + ], + "computed": { + "0": { + "x": 0.9166192708186873, + "y": 1.3763850953177255, + "radius": 0.4842248857021331 + }, + "1": { + "x": 1.7763861004687163, + "y": 1.3424772318936684, + "radius": 0.3535359268076717 + }, + "2": { + "x": 1.4090433304613057, + "y": 1.0529733974927744, + "radius": 0.30059814574196936 + }, + "3": { + "x": 1.6823340645191391, + "y": 1.5664474301008053, + "radius": 0.17507674135267737 + }, + "4": { + "x": 1.8896842410756616, + "y": 1.5055444230823098, + "radius": 0.3476633699610829 + }, + "5": { + "x": 1.18492853351515, + "y": 2.0151679629713772, + "radius": 0.10574678219854833 + } + } + }, + { + "original": [ + { + "x": 0.935220931423828, + "y": 0.8615431261714548, + "radius": 0.4420000073499978 + }, + { + "x": 0.8099958784878254, + "y": 0.21608882653526962, + "radius": 0.15602056728675961 + }, + { + "x": 0.07379413768649101, + "y": 0.4993492877110839, + "radius": 0.17612374210730197 + }, + { + "x": 0.3837161702103913, + "y": 0.39357905578799546, + "radius": 0.16868056189268826 + }, + { + "x": 0.7131447466090322, + "y": 0.8670544971246272, + "radius": 0.14431122718378903 + }, + { + "x": 0.305355085991323, + "y": 0.37608540104702115, + "radius": 0.4468963447026909 + } + ], + "computed": { + "0": { + "x": 1.7428357018966125, + "y": 1.141530295631557, + "radius": 0.44200000734999784 + }, + "1": { + "x": 1.5020667412436532, + "y": 1.9194323121493497, + "radius": 0.15602056728675961 + }, + "2": { + "x": 1.0700407503048466, + "y": 1.1089300840616785, + "radius": 0.17612374210730197 + }, + "3": { + "x": 1.196470494409883, + "y": 1.4706912102927325, + "radius": 0.16868056189268826 + }, + "4": { + "x": 1.8366328439044595, + "y": 1.31412883767559, + "radius": 0.14431122718378903 + }, + "5": { + "x": 0.9669697469244155, + "y": 1.360303538872964, + "radius": 0.4468963447026909 + } + } + }, + { + "original": [ + { + "x": 0.3194421329535544, + "y": 0.5162455148529261, + "radius": 0.4245066239498556 + }, + { + "x": 0.23262277781032026, + "y": 0.3661117434967309, + "radius": 0.46855972064659 + }, + { + "x": 0.7032479145564139, + "y": 0.7981704659759998, + "radius": 0.48378598215058444 + }, + { + "x": 0.23646283149719238, + "y": 0.46098682447336614, + "radius": 0.3374134531244636 + }, + { + "x": 0.3125857994891703, + "y": 0.9138717339374125, + "radius": 0.12254188060760499 + }, + { + "x": 0.2546960657928139, + "y": 0.9761070823296905, + "radius": 0.1953816100023687 + } + ], + "computed": { + "0": { + "x": 1.5565187624184234, + "y": 1.468027118716683, + "radius": 0.4245066239498556 + }, + "1": { + "x": 1.7169747265009394, + "y": 1.5526488635787712, + "radius": 0.46855972064658996 + }, + "2": { + "x": 1.3205498157232436, + "y": 1.0487400906151907, + "radius": 0.4837859821505843 + }, + "3": { + "x": 1.677931265881352, + "y": 1.5087221437887435, + "radius": 0.3374134531244635 + }, + "4": { + "x": 1.1336859052868715, + "y": 1.4636527815186464, + "radius": 0.12254188060760497 + }, + "5": { + "x": 1.0982269661343789, + "y": 1.4620964437271748, + "radius": 0.1953816100023687 + } + } + }, + { + "original": [ + { + "x": 0.5057592380326241, + "y": 0.7843215817119926, + "radius": 0.24997923616319895 + }, + { + "x": 0.3653196613304317, + "y": 0.6545118938665837, + "radius": 0.4699104307219386 + }, + { + "x": 0.8583381408825517, + "y": 0.07778019085526466, + "radius": 0.3008929383940995 + }, + { + "x": 0.18833827786147594, + "y": 0.6194319664500654, + "radius": 0.2537945915013552 + }, + { + "x": 0.2674319331999868, + "y": 0.7882209620438516, + "radius": 0.28558198940008883 + }, + { + "x": 0.11781973182223737, + "y": 0.29803354712203145, + "radius": 0.22894688062369825 + }, + { + "x": 0.18190383003093302, + "y": 0.746133737033233, + "radius": 0.36823571873828775 + } + ], + "computed": { + "0": { + "x": 1.2939295883065005, + "y": 1.590998100108746, + "radius": 0.24997923616319895 + }, + "1": { + "x": 1.3411094462439697, + "y": 1.416202191595585, + "radius": 0.4699104307219386 + }, + "2": { + "x": 2.0163407743507067, + "y": 1.8350166440819728, + "radius": 0.30089293839409953 + }, + "3": { + "x": 1.269476469025787, + "y": 1.22219225251268, + "radius": 0.2537945915013552 + }, + "4": { + "x": 1.1803798894717104, + "y": 1.4096294797322784, + "radius": 0.2855819894000889 + }, + "5": { + "x": 1.5030741371110021, + "y": 1.0074364704815089, + "radius": 0.22894688062369825 + }, + "6": { + "x": 1.1528497236554271, + "y": 1.2756848896523318, + "radius": 0.3682357187382878 + } + } + }, + { + "original": [ + { + "x": 0.7266579309944063, + "y": 0.7570597445592284, + "radius": 0.4213987573981285 + }, + { + "x": 0.9897381553892046, + "y": 0.06800056388601661, + "radius": 0.17561990898102522 + }, + { + "x": 0.4304285696707666, + "y": 0.5231964434497058, + "radius": 0.21787363942712545 + }, + { + "x": 0.18349125375971198, + "y": 0.3505753318313509, + "radius": 0.43592981845140455 + }, + { + "x": 0.9290164916310459, + "y": 0.39155707228928804, + "radius": 0.1025641747750342 + }, + { + "x": 0.6564349599648267, + "y": 0.49064847314730287, + "radius": 0.3138013846240938 + }, + { + "x": 0.17219536588527262, + "y": 0.5556291702669114, + "radius": 0.4380288441665471 + } + ], + "computed": { + "0": { + "x": 1.363619285831538, + "y": 1.1254876468773887, + "radius": 0.4213987573981285 + }, + "1": { + "x": 1.0977470133967666, + "y": 1.8915106742736914, + "radius": 0.1756199089810252 + }, + "2": { + "x": 1.7296513253561054, + "y": 1.4323041356565935, + "radius": 0.21787363942712545 + }, + "3": { + "x": 1.7820603383825806, + "y": 1.8088374173702246, + "radius": 0.43592981845140455 + }, + "4": { + "x": 1.3068692665697355, + "y": 1.4974397553263863, + "radius": 0.10256417477503418 + }, + "5": { + "x": 1.6101941392675427, + "y": 1.3617158022229734, + "radius": 0.31380138462409374 + }, + "6": { + "x": 1.9367066647052569, + "y": 1.7095526017822695, + "radius": 0.438028844166547 + } + } + }, + { + "original": [ + { + "x": 0.6253208441194147, + "y": 0.7599276739638299, + "radius": 0.2989642756991089 + }, + { + "x": 0.43935035658068955, + "y": 0.550885122269392, + "radius": 0.2430049049668014 + }, + { + "x": 0.8435382698662579, + "y": 0.05922960955649614, + "radius": 0.482860398106277 + }, + { + "x": 0.21553428028710186, + "y": 0.2763599075842649, + "radius": 0.37383032822981477 + }, + { + "x": 0.8787576304748654, + "y": 0.11686341953463852, + "radius": 0.13193890852853657 + }, + { + "x": 0.43888928228989244, + "y": 0.18251276621595025, + "radius": 0.41312927240505815 + }, + { + "x": 0.3246559128165245, + "y": 0.582676637917757, + "radius": 0.36704993639141326 + } + ], + "computed": { + "0": { + "x": 1.8689979324518653, + "y": 1.3380629123046337, + "radius": 0.2989642756991089 + }, + "1": { + "x": 1.8432960684306308, + "y": 1.6225757185784557, + "radius": 0.24300490496680138 + }, + "2": { + "x": 1.1897401395565927, + "y": 1.6188380771668673, + "radius": 0.48286039810627696 + }, + "3": { + "x": 1.747860522652981, + "y": 1.9574935745807973, + "radius": 0.37383032822981466 + }, + "4": { + "x": 1.1991350278745867, + "y": 1.2741925298859396, + "radius": 0.13193890852853654 + }, + "5": { + "x": 1.5390780774475201, + "y": 1.8194469614368567, + "radius": 0.41312927240505803 + }, + "6": { + "x": 1.9217481228458564, + "y": 1.6792461173064805, + "radius": 0.36704993639141326 + } + } + }, + { + "original": [ + { + "x": 0.3091927762143314, + "y": 0.8585083386860788, + "radius": 0.47388172149658203 + }, + { + "x": 0.739839866058901, + "y": 0.529907634248957, + "radius": 0.27233779886737464 + }, + { + "x": 0.04510801751166582, + "y": 0.3613374955020845, + "radius": 0.4034055683761836 + }, + { + "x": 0.8389933821745217, + "y": 0.18498309515416622, + "radius": 0.28467483827844264 + }, + { + "x": 0.23470718041062355, + "y": 0.6857131530996412, + "radius": 0.1903508171439171 + }, + { + "x": 0.7303113343659788, + "y": 0.3874265346676111, + "radius": 0.2581259161233902 + }, + { + "x": 0.535949365934357, + "y": 0.006863217102363706, + "radius": 0.3698094638995827 + } + ], + "computed": { + "0": { + "x": 1.9828279913928821, + "y": 2.0196977980783544, + "radius": 0.47388172149658203 + }, + "1": { + "x": 1.4503287257159927, + "y": 1.9394048391639784, + "radius": 0.2723377988673747 + }, + "2": { + "x": 2.1143002884776836, + "y": 1.477413653396661, + "radius": 0.40340556837618363 + }, + "3": { + "x": 1.3495863288039005, + "y": 1.6123568755038347, + "radius": 0.28467483827844264 + }, + "4": { + "x": 2.201247993437469, + "y": 1.8253546360284854, + "radius": 0.1903508171439171 + }, + "5": { + "x": 1.403221802662136, + "y": 1.7951791488210196, + "radius": 0.2581259161233902 + }, + "6": { + "x": 1.5285625170415802, + "y": 1.3606686965393109, + "radius": 0.3698094638995827 + } + } + }, + { + "original": [ + { + "x": 0.5031936836894602, + "y": 0.6848052646964788, + "radius": 0.1271633409895003 + }, + { + "x": 0.4544628085568547, + "y": 0.7975209727883339, + "radius": 0.2344573985785246 + }, + { + "x": 0.7490456833038479, + "y": 0.26016882713884115, + "radius": 0.47332492135465143 + }, + { + "x": 0.5396770685911179, + "y": 0.5582783767022192, + "radius": 0.42654180256649854 + }, + { + "x": 0.8578157427255064, + "y": 0.41888763569295406, + "radius": 0.3878055913373828 + }, + { + "x": 0.9335349739994854, + "y": 0.7927936064079404, + "radius": 0.17279737191274763 + }, + { + "x": 0.52625816850923, + "y": 0.24953942536376417, + "radius": 0.1464726376347244 + } + ], + "computed": { + "0": { + "x": 1.1501138124643873, + "y": 1.4237043295111023, + "radius": 0.1271633409895003 + }, + "1": { + "x": 1.04300535420391, + "y": 1.5239368821021742, + "radius": 0.2344573985785246 + }, + "2": { + "x": 1.6329707882639315, + "y": 1.53652983239903, + "radius": 0.47332492135465143 + }, + "3": { + "x": 1.2762645120317628, + "y": 1.4495827144197677, + "radius": 0.42654180256649854 + }, + "4": { + "x": 1.5962311227399721, + "y": 1.380037500622986, + "radius": 0.3878055913373828 + }, + "5": { + "x": 1.4459423855087852, + "y": 1.0192812498836312, + "radius": 0.1727973719127476 + }, + "6": { + "x": 1.420570535594606, + "y": 1.2320260018686635, + "radius": 0.14647263763472437 + } + } + }, + { + "original": [ + { + "x": 0.8016239539720118, + "y": 0.24927597655914724, + "radius": 0.3059927842579782 + }, + { + "x": 0.9573412188328803, + "y": 0.9174208252225071, + "radius": 0.23430673759430648 + }, + { + "x": 0.904138101497665, + "y": 0.5387566804420203, + "radius": 0.40727290594950316 + }, + { + "x": 0.3113381718285382, + "y": 0.4024138564709574, + "radius": 0.27757244259119035 + }, + { + "x": 0.059533382300287485, + "y": 0.34952945727854967, + "radius": 0.4290871631354094 + }, + { + "x": 0.5237345120403916, + "y": 0.031665756134316325, + "radius": 0.10389028424397112 + }, + { + "x": 0.2575918538495898, + "y": 0.23531553288921714, + "radius": 0.3536788917146624 + } + ], + "computed": { + "0": { + "x": 1.3706636737907085, + "y": 1.8480685003024082, + "radius": 0.30599278425797827 + }, + "1": { + "x": 1.2512855388437727, + "y": 1.385568850787024, + "radius": 0.23430673759430656 + }, + "2": { + "x": 1.139019215108096, + "y": 1.7645954271189714, + "radius": 0.4072729059495032 + }, + "3": { + "x": 1.8046953962013796, + "y": 1.7233487852939668, + "radius": 0.27757244259119035 + }, + "4": { + "x": 2.0278972221743894, + "y": 1.6090508316637506, + "radius": 0.42908716313540946 + }, + "5": { + "x": 1.487990931723779, + "y": 1.0401294011458146, + "radius": 0.10389028424397113 + }, + "6": { + "x": 1.7990696271208115, + "y": 1.509859808651, + "radius": 0.35367889171466244 + } + } + }, + { + "original": [ + { + "x": 0.4345399134326726, + "y": 0.9269798411987722, + "radius": 0.26580945448949933 + }, + { + "x": 0.055379191879183054, + "y": 0.509894945891574, + "radius": 0.2161553486250341 + }, + { + "x": 0.5971282806713134, + "y": 0.19301164359785616, + "radius": 0.14245880395174026 + }, + { + "x": 0.7597719605546445, + "y": 0.6034093981143087, + "radius": 0.367972990591079 + }, + { + "x": 0.8574109778273851, + "y": 0.22559689218178391, + "radius": 0.3201365263201297 + }, + { + "x": 0.6696419841609895, + "y": 0.615607647690922, + "radius": 0.28511712374165654 + }, + { + "x": 0.16152155632153153, + "y": 0.2298280738759786, + "radius": 0.4364557472057641 + } + ], + "computed": { + "0": { + "x": 1.6968543839731727, + "y": 1.969170984865824, + "radius": 0.26580945448949933 + }, + "1": { + "x": 1.0836569442142276, + "y": 1.8360945150868497, + "radius": 0.21615534862503413 + }, + "2": { + "x": 1.4688369537427803, + "y": 1.197789702887054, + "radius": 0.14245880395174026 + }, + "3": { + "x": 1.8780896626537198, + "y": 1.54556384743613, + "radius": 0.367972990591079 + }, + "4": { + "x": 1.7501654122327839, + "y": 1.191773249157309, + "radius": 0.3201365263201297 + }, + "5": { + "x": 1.8395811834835443, + "y": 1.6172798239042938, + "radius": 0.28511712374165654 + }, + "6": { + "x": 1.1883723799771053, + "y": 1.5478847969398752, + "radius": 0.4364557472057641 + } + } + }, + { + "original": [ + { + "x": 0.5557835381478071, + "y": 0.7802605971228331, + "radius": 0.18314695712178947 + }, + { + "x": 0.8443633599672467, + "y": 0.8743166201747954, + "radius": 0.1408276873640716 + }, + { + "x": 0.49125182325951755, + "y": 0.1115135399159044, + "radius": 0.37305732881650333 + }, + { + "x": 0.89368991041556, + "y": 0.17974142148159444, + "radius": 0.43473799163475635 + }, + { + "x": 0.23442049114964902, + "y": 0.5617102263495326, + "radius": 0.35338531453162436 + }, + { + "x": 0.31877905456349254, + "y": 0.6219356416258961, + "radius": 0.3157570732757449 + }, + { + "x": 0.24540796270594, + "y": 0.8384954987559468, + "radius": 0.48600097596645353 + } + ], + "computed": { + "0": { + "x": 1.8414528700305506, + "y": 1.87251050040641, + "radius": 0.18314695712178947 + }, + "1": { + "x": 1.424009360778524, + "y": 2.325403313961179, + "radius": 0.1408276873640716 + }, + "2": { + "x": 1.4753459655501722, + "y": 1.339543078479062, + "radius": 0.3730573288165034 + }, + "3": { + "x": 1.1225901984203377, + "y": 1.493130400703818, + "radius": 0.4347379916347564 + }, + "4": { + "x": 1.9599734020671065, + "y": 1.503583346652099, + "radius": 0.35338531453162436 + }, + "5": { + "x": 1.9620508213076762, + "y": 1.5868408755577816, + "radius": 0.3157570732757449 + }, + "6": { + "x": 2.0986302716520493, + "y": 1.763041374046064, + "radius": 0.4860009759664536 + } + } + }, + { + "original": [ + { + "x": 0.11464464315213263, + "y": 0.21175656304694712, + "radius": 0.4263272878713906 + }, + { + "x": 0.13341207476332784, + "y": 0.5633427111897618, + "radius": 0.11723120026290418 + }, + { + "x": 0.8073679036460817, + "y": 0.6727611261885613, + "radius": 0.13403469165787102 + }, + { + "x": 0.2317212875932455, + "y": 0.9344894327223301, + "radius": 0.3863128190860152 + }, + { + "x": 0.671973554417491, + "y": 0.7538750951644033, + "radius": 0.2156818309798837 + }, + { + "x": 0.4803289833944291, + "y": 0.17997115920297801, + "radius": 0.43994201589375737 + }, + { + "x": 0.9084006589837372, + "y": 0.43753765849396586, + "radius": 0.47005949122831225 + } + ], + "computed": { + "0": { + "x": 2.2913589688100213, + "y": 1.8500270826032206, + "radius": 0.4263272878713906 + }, + "1": { + "x": 2.0530300621168487, + "y": 2.221433500355027, + "radius": 0.11723120026290419 + }, + "2": { + "x": 1.3310876017870117, + "y": 1.6438055054580776, + "radius": 0.134034691657871 + }, + "3": { + "x": 1.6729821471349218, + "y": 2.1941129972695292, + "radius": 0.3863128190860153 + }, + "4": { + "x": 1.4262918024369016, + "y": 1.7372773431685424, + "radius": 0.21568183097988372 + }, + "5": { + "x": 2.1368568827397403, + "y": 1.5038776040030404, + "radius": 0.4399420158937574 + }, + "6": { + "x": 1.6408509256308619, + "y": 1.4019243577988716, + "radius": 0.47005949122831236 + } + } + }, + { + "original": [ + { + "x": 0.40144181810319424, + "y": 0.0053766274359077215, + "radius": 0.4805085385218263 + }, + { + "x": 0.2810717693064362, + "y": 0.8978256215341389, + "radius": 0.35027952976524834 + }, + { + "x": 0.37722113193012774, + "y": 0.3139609294012189, + "radius": 0.3459206083789468 + }, + { + "x": 0.7837898933794349, + "y": 0.7758790862280875, + "radius": 0.2249225301668048 + }, + { + "x": 0.011949960608035326, + "y": 0.5017291763797402, + "radius": 0.13655568193644285 + }, + { + "x": 0.8075678232125938, + "y": 0.262563249329105, + "radius": 0.1570479144342244 + }, + { + "x": 0.3060713007580489, + "y": 0.3152987661305815, + "radius": 0.42216823995113373 + } + ], + "computed": { + "0": { + "x": 1.3031296669524681, + "y": 1.3506799177406004, + "radius": 0.4805085385218263 + }, + "1": { + "x": 1.8164318268248543, + "y": 1.9898557208846677, + "radius": 0.35027952976524834 + }, + "2": { + "x": 1.288470443547804, + "y": 1.6606799729492931, + "radius": 0.3459206083789468 + }, + "3": { + "x": 2.083585885308183, + "y": 1.5551164701776425, + "radius": 0.22492253016680483 + }, + "4": { + "x": 1.6519828202622975, + "y": 1.8224902700490215, + "radius": 0.13655568193644285 + }, + "5": { + "x": 1.7032867053058907, + "y": 1.1222939411590946, + "radius": 0.1570479144342244 + }, + "6": { + "x": 1.327467056575741, + "y": 1.6732381118169193, + "radius": 0.4221682399511337 + } + } + }, + { + "original": [ + { + "x": 0.8079361331183463, + "y": 0.06179186492227018, + "radius": 0.16673322021961212 + }, + { + "x": 0.8598673681262881, + "y": 0.38084422959946096, + "radius": 0.44239421905949716 + }, + { + "x": 0.28516458137892187, + "y": 0.6026879602577537, + "radius": 0.23351960852742196 + }, + { + "x": 0.3275826582685113, + "y": 0.2814136608503759, + "radius": 0.41151629015803337 + }, + { + "x": 0.44613574515096843, + "y": 0.7797719652298838, + "radius": 0.2495930696837604 + }, + { + "x": 0.03176514175720513, + "y": 0.619229621719569, + "radius": 0.2959150100126863 + }, + { + "x": 0.8426543404348195, + "y": 0.1389005770906806, + "radius": 0.23494642963632942 + } + ], + "computed": { + "0": { + "x": 1.1569020207124165, + "y": 1.6266281540968341, + "radius": 0.16673322021961212 + }, + "1": { + "x": 1.1636647586629192, + "y": 1.504961728381012, + "radius": 0.44239421905949716 + }, + "2": { + "x": 1.7877695583085502, + "y": 1.529263597855464, + "radius": 0.23351960852742196 + }, + "3": { + "x": 1.6280331010863853, + "y": 1.2448176984358958, + "radius": 0.4115162901580334 + }, + "4": { + "x": 1.6925395740921905, + "y": 1.7450825318991026, + "radius": 0.2495930696837604 + }, + "5": { + "x": 2.024184410406481, + "y": 1.450629829432949, + "radius": 0.2959150100126863 + }, + "6": { + "x": 1.1718712647845912, + "y": 1.523581147952278, + "radius": 0.23494642963632945 + } + } + }, + { + "original": [ + { + "x": 0.5771242259070277, + "y": 0.5289076950866729, + "radius": 0.19136956585571172 + }, + { + "x": 0.3564206219743937, + "y": 0.2215933739207685, + "radius": 0.2328530427068472 + }, + { + "x": 0.23509838827885687, + "y": 0.8030816991813481, + "radius": 0.2672020878642798 + }, + { + "x": 0.7477285449858755, + "y": 0.6227133115753531, + "radius": 0.37532644337043164 + }, + { + "x": 0.377470196923241, + "y": 0.7330372233409435, + "radius": 0.36995664667338135 + }, + { + "x": 0.305759334936738, + "y": 0.9594190900679678, + "radius": 0.21025983346626165 + }, + { + "x": 0.9587773238308728, + "y": 0.7124923055525869, + "radius": 0.2014449023641646 + } + ], + "computed": { + "0": { + "x": 1.3833917594521794, + "y": 1.0574938974521546, + "radius": 0.19136956585571172 + }, + "1": { + "x": 1.3448486092600787, + "y": 1.6425503414216878, + "radius": 0.23285304270684726 + }, + "2": { + "x": 0.9590027539619105, + "y": 1.1723454272053981, + "radius": 0.26720208786427985 + }, + "3": { + "x": 1.4858359943418622, + "y": 1.1250893343340158, + "radius": 0.3753264433704317 + }, + "4": { + "x": 1.1139988832510805, + "y": 1.1775901382283147, + "radius": 0.36995664667338146 + }, + "5": { + "x": 0.9407203281820449, + "y": 1.326492846454868, + "radius": 0.2102598334662617 + }, + "6": { + "x": 1.6131617218447365, + "y": 1.3393980651974535, + "radius": 0.20144490236416462 + } + } + }, + { + "original": [ + { + "x": 0.623390382854268, + "y": 0.6574764191173017, + "radius": 0.2473144362680614 + }, + { + "x": 0.1047379884403199, + "y": 0.49731712555512786, + "radius": 0.34336441727355127 + }, + { + "x": 0.5606407856103033, + "y": 0.47822767216712236, + "radius": 0.3255056952126324 + }, + { + "x": 0.5660775906872004, + "y": 0.40723529015667737, + "radius": 0.2802650756202638 + }, + { + "x": 0.3869996499270201, + "y": 0.6151398685760796, + "radius": 0.44257220812141895 + }, + { + "x": 0.603102350840345, + "y": 0.9190860677044839, + "radius": 0.19037646483629944 + }, + { + "x": 0.8949798818212003, + "y": 0.4389573154039681, + "radius": 0.3028964040800929 + } + ], + "computed": { + "0": { + "x": 1.3486645006763518, + "y": 1.4548929354335085, + "radius": 0.24731443626806143 + }, + "1": { + "x": 1.5162140716534065, + "y": 0.9525104559780241, + "radius": 0.34336441727355127 + }, + "2": { + "x": 1.235759130969899, + "y": 1.3077467457254184, + "radius": 0.3255056952126324 + }, + "3": { + "x": 1.1677299105266314, + "y": 1.2675478555306077, + "radius": 0.28026507562026387 + }, + "4": { + "x": 1.441523887737592, + "y": 1.2420272970813075, + "radius": 0.442572208121419 + }, + "5": { + "x": 1.6092309008628443, + "y": 1.5505594667215377, + "radius": 0.19037646483629947 + }, + "6": { + "x": 1.0203066521995465, + "y": 1.564144298155868, + "radius": 0.30289640408009294 + } + } + }, + { + "original": [ + { + "x": 0.5257351601030678, + "y": 0.985062995692715, + "radius": 0.4224399131722748 + }, + { + "x": 0.09730036463588476, + "y": 0.3611773138400167, + "radius": 0.10867947638034821 + }, + { + "x": 0.3142827416304499, + "y": 0.29442035569809377, + "radius": 0.2796161687001586 + }, + { + "x": 0.19366948073729873, + "y": 0.8953930055722594, + "radius": 0.44328560568392283 + }, + { + "x": 0.5936500581447035, + "y": 0.622792816022411, + "radius": 0.10860025333240629 + }, + { + "x": 0.8097517099231482, + "y": 0.5849271148908883, + "radius": 0.19724774537608028 + }, + { + "x": 0.5836264446843415, + "y": 0.7023824097122997, + "radius": 0.10944990189746023 + } + ], + "computed": { + "0": { + "x": 1.552213046794339, + "y": 1.7756450073535974, + "radius": 0.4224399131722748 + }, + "1": { + "x": 1.1683464072404068, + "y": 1.0690023245519968, + "radius": 0.10867947638034817 + }, + "2": { + "x": 1.1108206644305991, + "y": 1.2205148409379236, + "radius": 0.27961616870015854 + }, + "3": { + "x": 1.2195657307686973, + "y": 1.8115026872157147, + "radius": 0.44328560568392283 + }, + "4": { + "x": 1.795997017007915, + "y": 1.4303137887564128, + "radius": 0.10860025333240628 + }, + "5": { + "x": 1.5616319027096435, + "y": 1.3320998504175579, + "radius": 0.19724774537608022 + }, + "6": { + "x": 1.7460083737267158, + "y": 1.5155046434451132, + "radius": 0.1094499018974602 + } + } + }, + { + "original": [ + { + "x": 0.07275471510365605, + "y": 0.7594428153242916, + "radius": 0.31667250748723746 + }, + { + "x": 0.5506337294355035, + "y": 0.9838023602496833, + "radius": 0.49132922589778905 + }, + { + "x": 0.33085945015773177, + "y": 0.6086594657972455, + "radius": 0.1767308007925749 + }, + { + "x": 0.6502704224549234, + "y": 0.394814325729385, + "radius": 0.31176791321486236 + }, + { + "x": 0.5322105530649424, + "y": 0.6403406609315425, + "radius": 0.25518635315820576 + }, + { + "x": 0.9996225640643388, + "y": 0.22882817266508937, + "radius": 0.4656234870664776 + }, + { + "x": 0.3347081409301609, + "y": 0.9202087065204978, + "radius": 0.19423072570934893 + }, + { + "x": 0.4934621131978929, + "y": 0.04006615001708269, + "radius": 0.22607389818876983 + } + ], + "computed": { + "0": { + "x": 2.478924051400036, + "y": 2.314933258155407, + "radius": 0.3166725074872375 + }, + "1": { + "x": 2.148704582842711, + "y": 1.9122780015801197, + "radius": 0.49132922589778893 + }, + "2": { + "x": 1.9421192015533115, + "y": 1.4314963915847752, + "radius": 0.1767308007925749 + }, + "3": { + "x": 1.6667750134361516, + "y": 1.5585897660251793, + "radius": 0.3117679132148623 + }, + "4": { + "x": 1.903153381112501, + "y": 1.6049696186799147, + "radius": 0.2551863531582058 + }, + "5": { + "x": 1.2959528989067102, + "y": 1.7459477613244672, + "radius": 0.4656234870664776 + }, + "6": { + "x": 2.2252337886180342, + "y": 2.295198136349454, + "radius": 0.1942307257093489 + }, + "7": { + "x": 1.5334840479192389, + "y": 2.330934032089374, + "radius": 0.22607389818876983 + } + } + }, + { + "original": [ + { + "x": 0.5313232056796551, + "y": 0.6246686286758631, + "radius": 0.4374504307284951 + }, + { + "x": 0.508301310474053, + "y": 0.8951827979180962, + "radius": 0.1372593122534454 + }, + { + "x": 0.5541455510538071, + "y": 0.13707281765528023, + "radius": 0.30767531460151076 + }, + { + "x": 0.8584751102607697, + "y": 0.44223159132525325, + "radius": 0.35885189063847067 + }, + { + "x": 0.7898124016355723, + "y": 0.45558374538086355, + "radius": 0.24188436903059485 + }, + { + "x": 0.4711075471714139, + "y": 0.027944659115746617, + "radius": 0.44677808107808237 + }, + { + "x": 0.9964479359332472, + "y": 0.13648808631114662, + "radius": 0.46453885259106753 + }, + { + "x": 0.6137786807958037, + "y": 0.5153739748056978, + "radius": 0.18425537776201964 + } + ], + "computed": { + "0": { + "x": 1.6206190496435844, + "y": 1.4753689956662224, + "radius": 0.4374504307284951 + }, + "1": { + "x": 1.5856225580281058, + "y": 1.241652115470588, + "radius": 0.1372593122534454 + }, + "2": { + "x": 2.0130411286780134, + "y": 1.8463169311510894, + "radius": 0.3076753146015107 + }, + "3": { + "x": 1.612188824184897, + "y": 1.9634305964799057, + "radius": 0.35885189063847067 + }, + "4": { + "x": 1.6034025092421784, + "y": 1.8446262077544053, + "radius": 0.24188436903059488 + }, + "5": { + "x": 2.225444423420451, + "y": 1.8073388186744326, + "radius": 0.44677808107808226 + }, + "6": { + "x": 1.819164529823966, + "y": 2.239964304647439, + "radius": 0.46453885259106753 + }, + "7": { + "x": 1.6661561110561198, + "y": 1.7269411642332309, + "radius": 0.18425537776201964 + } + } + }, + { + "original": [ + { + "x": 0.8425948990043253, + "y": 0.9616255245637149, + "radius": 0.2260580200701952 + }, + { + "x": 0.23462878190912306, + "y": 0.26980746537446976, + "radius": 0.3660282700322569 + }, + { + "x": 0.2787480177357793, + "y": 0.001456450903788209, + "radius": 0.18508804896846415 + }, + { + "x": 0.11698212171904743, + "y": 0.09753247001208365, + "radius": 0.21933045983314514 + }, + { + "x": 0.8190958786290139, + "y": 0.3071645055897534, + "radius": 0.22390286205336452 + }, + { + "x": 0.9386381811928004, + "y": 0.5688014088664204, + "radius": 0.29240207001566887 + }, + { + "x": 0.6371053708717227, + "y": 0.049290222115814686, + "radius": 0.4199417728930712 + }, + { + "x": 0.3174242803361267, + "y": 0.18239495833404362, + "radius": 0.3193938977085054 + } + ], + "computed": { + "0": { + "x": 1.9145873567176352, + "y": 2.0366618195702433, + "radius": 0.2260580200701952 + }, + "1": { + "x": 1.179353559002223, + "y": 1.4940460242714664, + "radius": 0.36602827003225685 + }, + "2": { + "x": 1.408068116124359, + "y": 1.6041052129081874, + "radius": 0.18508804896846415 + }, + "3": { + "x": 1.2518887890906853, + "y": 1.6877131803707197, + "radius": 0.21933045983314509 + }, + "4": { + "x": 1.9003509080198384, + "y": 1.3432435183719897, + "radius": 0.2239028620533645 + }, + "5": { + "x": 2.0299315451863276, + "y": 1.6370014751524131, + "radius": 0.2924020700156688 + }, + "6": { + "x": 1.5786651257044637, + "y": 1.2876208944135645, + "radius": 0.41994177289307116 + }, + "7": { + "x": 1.2956894799047867, + "y": 1.4681427546917347, + "radius": 0.3193938977085054 + } + } + }, + { + "original": [ + { + "x": 0.09360175323672593, + "y": 0.7122492205817252, + "radius": 0.3454912694171071 + }, + { + "x": 0.6352397971786559, + "y": 0.5216629011556506, + "radius": 0.32572803320363164 + }, + { + "x": 0.7573121355380863, + "y": 0.4358054813928902, + "radius": 0.30814688345417385 + }, + { + "x": 0.12459469167515635, + "y": 0.46503109694458544, + "radius": 0.2873931652866304 + }, + { + "x": 0.7383452660869807, + "y": 0.4402844242285937, + "radius": 0.2596936062909663 + }, + { + "x": 0.25529298442415893, + "y": 0.7999696109909564, + "radius": 0.2199596813879907 + }, + { + "x": 0.34930090932175517, + "y": 0.7621054968331009, + "radius": 0.40522349989041684 + }, + { + "x": 0.9338080734014511, + "y": 0.7568554824683815, + "radius": 0.2135899828746915 + } + ], + "computed": { + "0": { + "x": 1.0796566342764848, + "y": 1.4099073803580984, + "radius": 0.3454912694171071 + }, + "1": { + "x": 1.659688104998246, + "y": 1.417133524212582, + "radius": 0.32572803320363164 + }, + "2": { + "x": 1.807195622678639, + "y": 1.453185414303691, + "radius": 0.30814688345417385 + }, + "3": { + "x": 1.1926087723204355, + "y": 1.6388485655494318, + "radius": 0.2873931652866304 + }, + "4": { + "x": 1.7962464130864164, + "y": 1.4289254007585726, + "radius": 0.25969360629096633 + }, + "5": { + "x": 1.2067963098910184, + "y": 1.2989802687516592, + "radius": 0.2199596813879907 + }, + "6": { + "x": 1.3169170096048086, + "y": 1.294548371386692, + "radius": 0.4052234998904168 + }, + "7": { + "x": 1.660080770136933, + "y": 1.7776607116722543, + "radius": 0.21358998287469155 + } + } + }, + { + "original": [ + { + "x": 0.11637080134823918, + "y": 0.1124957527499646, + "radius": 0.1747694700025022 + }, + { + "x": 0.201551484875381, + "y": 0.7831128167454153, + "radius": 0.3228370450437069 + }, + { + "x": 0.424282826250419, + "y": 0.7527269695419818, + "radius": 0.33494448456913234 + }, + { + "x": 0.24600196979008615, + "y": 0.30609197774901986, + "radius": 0.457591463252902 + }, + { + "x": 0.30334831797517836, + "y": 0.5513720554299653, + "radius": 0.14952243259176612 + }, + { + "x": 0.16752861719578505, + "y": 0.5322646948043257, + "radius": 0.3564944412559271 + }, + { + "x": 0.6198151141870767, + "y": 0.38698866637423635, + "radius": 0.2546240834519267 + }, + { + "x": 0.6192519566975534, + "y": 0.13763158558867872, + "radius": 0.2765111198648811 + } + ], + "computed": { + "0": { + "x": 1.3922796055247721, + "y": 1.0703208944123088, + "radius": 0.1747694700025022 + }, + "1": { + "x": 1.8447063575073472, + "y": 1.5556929567547821, + "radius": 0.322837045043707 + }, + "2": { + "x": 1.7123523334396733, + "y": 1.7309249698391416, + "radius": 0.3349444845691324 + }, + "3": { + "x": 1.413832529491984, + "y": 1.3708959631503908, + "radius": 0.45759146325290206 + }, + "4": { + "x": 1.632128117058522, + "y": 1.5502220947671486, + "radius": 0.14952243259176615 + }, + "5": { + "x": 1.6422129619171768, + "y": 1.41073169115622, + "radius": 0.3564944412559271 + }, + "6": { + "x": 1.304956962457388, + "y": 1.7259663403526952, + "radius": 0.2546240834519267 + }, + "7": { + "x": 1.0888544005661047, + "y": 1.616568357530282, + "radius": 0.27651111986488114 + } + } + }, + { + "original": [ + { + "x": 0.11651514959521592, + "y": 0.6318131918087602, + "radius": 0.2935074402019382 + }, + { + "x": 0.45042965095490217, + "y": 0.28131781960837543, + "radius": 0.16475570639595388 + }, + { + "x": 0.7826851895079017, + "y": 0.8429262570571154, + "radius": 0.1686237401328981 + }, + { + "x": 0.3607310838997364, + "y": 0.7886622603982687, + "radius": 0.2871937945485115 + }, + { + "x": 0.7485614116303623, + "y": 0.49272177973762155, + "radius": 0.49025000007823116 + }, + { + "x": 0.5002307442482561, + "y": 0.3951502866111696, + "radius": 0.3162793463096023 + }, + { + "x": 0.8429953996092081, + "y": 0.2054443482775241, + "radius": 0.25731937075033784 + }, + { + "x": 0.1705728431697935, + "y": 0.3544776577036828, + "radius": 0.20638169711455703 + } + ], + "computed": { + "0": { + "x": 1.9144894310253942, + "y": 1.4611378213738395, + "radius": 0.2935074402019382 + }, + "1": { + "x": 1.3934370202316269, + "y": 1.2216186077357196, + "radius": 0.16475570639595388 + }, + "2": { + "x": 1.4229002958512131, + "y": 1.927882200194341, + "radius": 0.1686237401328981 + }, + "3": { + "x": 1.7601480695795524, + "y": 1.6913781898276647, + "radius": 0.2871937945485115 + }, + "4": { + "x": 1.296910763197622, + "y": 1.5861214477342225, + "radius": 0.49025000007823116 + }, + "5": { + "x": 1.4680610741202509, + "y": 1.3918453464833664, + "radius": 0.3162793463096023 + }, + "6": { + "x": 1.1430633851062706, + "y": 1.643644514898541, + "radius": 0.2573193707503379 + }, + "7": { + "x": 1.7501800640815637, + "y": 1.2255619749457989, + "radius": 0.20638169711455703 + } + } + }, + { + "original": [ + { + "x": 0.09371301648207009, + "y": 0.5603278225753456, + "radius": 0.323675698786974 + }, + { + "x": 0.3289893304463476, + "y": 0.6540855751372874, + "radius": 0.18461898919194938 + }, + { + "x": 0.1126076621003449, + "y": 0.1389240745920688, + "radius": 0.37469940939918167 + }, + { + "x": 0.9074209625832736, + "y": 0.7852328517474234, + "radius": 0.4969614296220243 + }, + { + "x": 0.20827201777137816, + "y": 0.3308673638384789, + "radius": 0.25872399043291805 + }, + { + "x": 0.4817479762714356, + "y": 0.7953505348414183, + "radius": 0.21087463153526187 + }, + { + "x": 0.7003585966303945, + "y": 0.34889600332826376, + "radius": 0.3877028516493738 + }, + { + "x": 0.23731651552952826, + "y": 0.8013929314911366, + "radius": 0.16234490284696224 + } + ], + "computed": { + "0": { + "x": 1.7085944660633354, + "y": 2.0708247931752126, + "radius": 0.323675698786974 + }, + "1": { + "x": 1.9674845644795762, + "y": 1.9828905249452633, + "radius": 0.18461898919194938 + }, + "2": { + "x": 1.321197427753974, + "y": 1.8281713933348795, + "radius": 0.37469940939918167 + }, + "3": { + "x": 2.256736942006825, + "y": 1.4405649092978048, + "radius": 0.49696142962202433 + }, + "4": { + "x": 1.5160538399672692, + "y": 1.896724778168688, + "radius": 0.25872399043291805 + }, + "5": { + "x": 2.140474867125882, + "y": 1.8672520720228851, + "radius": 0.21087463153526187 + }, + "6": { + "x": 1.8066208150093275, + "y": 1.4929474555369013, + "radius": 0.3877028516493738 + }, + "7": { + "x": 2.0380413794072387, + "y": 2.175828375331791, + "radius": 0.16234490284696226 + } + } + }, + { + "original": [ + { + "x": 0.25496588624082506, + "y": 0.9555728661362082, + "radius": 0.4729752528481186 + }, + { + "x": 0.049389589112252, + "y": 0.5318087232299149, + "radius": 0.24210391277447343 + }, + { + "x": 0.39624698646366596, + "y": 0.3091603866778314, + "radius": 0.19344976963475347 + }, + { + "x": 0.11051125614903867, + "y": 0.4541060070041567, + "radius": 0.2926294499076903 + }, + { + "x": 0.7848385537508875, + "y": 0.7222387148067355, + "radius": 0.10194503571838141 + }, + { + "x": 0.685586127685383, + "y": 0.9617279325611889, + "radius": 0.4690590557642281 + }, + { + "x": 0.4266283097676933, + "y": 0.22114698844961822, + "radius": 0.24923599557951093 + }, + { + "x": 0.6462332438677549, + "y": 0.5389535832218826, + "radius": 0.2094952015206218 + } + ], + "computed": { + "0": { + "x": 1.3348814122068393, + "y": 1.5445424437303137, + "radius": 0.47297525284811853 + }, + "1": { + "x": 1.7823254076902433, + "y": 1.2800929856041794, + "radius": 0.2421039127744734 + }, + "2": { + "x": 2.1745790991563747, + "y": 1.7315278030223469, + "radius": 0.19344976963475347 + }, + "3": { + "x": 1.7622196968080193, + "y": 1.3307535052423882, + "radius": 0.29262944990769024 + }, + "4": { + "x": 1.6908462202257208, + "y": 1.986754877555325, + "radius": 0.1019450357183814 + }, + "5": { + "x": 1.2401179006440168, + "y": 1.9342307614770755, + "radius": 0.46905905576422807 + }, + "6": { + "x": 2.101724547325135, + "y": 1.8629256175863504, + "radius": 0.2492359955795109 + }, + "7": { + "x": 1.6564198746785908, + "y": 2.072286164516959, + "radius": 0.20949520152062176 + } + } + }, + { + "original": [ + { + "x": 0.453601258341223, + "y": 0.44765141885727644, + "radius": 0.18076553456485273 + }, + { + "x": 0.45763479731976986, + "y": 0.058502666652202606, + "radius": 0.46821009851992135 + }, + { + "x": 0.9370152924675494, + "y": 0.5745347640477121, + "radius": 0.46966606602072714 + }, + { + "x": 0.8316981147509068, + "y": 0.7251409967429936, + "radius": 0.21591465836390855 + }, + { + "x": 0.9268259019590914, + "y": 0.6235416531562805, + "radius": 0.337542528193444 + }, + { + "x": 0.13474347977899015, + "y": 0.4373641354031861, + "radius": 0.3744110851548612 + }, + { + "x": 0.05907091940753162, + "y": 0.16265125619247556, + "radius": 0.2909369782544673 + }, + { + "x": 0.49754144344478846, + "y": 0.5625350729096681, + "radius": 0.3248422435484827 + } + ], + "computed": { + "0": { + "x": 1.7014050033855515, + "y": 1.6861320848282528, + "radius": 0.18076553456485273 + }, + "1": { + "x": 1.6683951420458878, + "y": 2.1301945266481686, + "radius": 0.4682100985199213 + }, + "2": { + "x": 2.212393729399381, + "y": 1.6530027542931793, + "radius": 0.4696660660207272 + }, + "3": { + "x": 2.198680912985488, + "y": 1.8546793614594157, + "radius": 0.21591465836390855 + }, + "4": { + "x": 2.263739078391358, + "y": 1.7597240583158789, + "radius": 0.337542528193444 + }, + "5": { + "x": 1.401035159461492, + "y": 1.7394673933736038, + "radius": 0.37441108515486127 + }, + "6": { + "x": 1.2726595485534529, + "y": 2.033630182279383, + "radius": 0.2909369782544673 + }, + "7": { + "x": 1.8062687639356287, + "y": 1.6677469769603575, + "radius": 0.32484224354848273 + } + } + }, + { + "original": [ + { + "x": 0.8767424030229449, + "y": 0.7678649823646992, + "radius": 0.3507522008381784 + }, + { + "x": 0.8005165092181414, + "y": 0.30630596564151347, + "radius": 0.4592623558826745 + }, + { + "x": 0.685188468080014, + "y": 0.054472102550789714, + "radius": 0.1309586538001895 + }, + { + "x": 0.4031720971688628, + "y": 0.13537580519914627, + "radius": 0.36586903342977173 + }, + { + "x": 0.8136333641596138, + "y": 0.9164379169233143, + "radius": 0.26547357020899653 + }, + { + "x": 0.9211119303945452, + "y": 0.4891475511249155, + "radius": 0.24833531118929386 + }, + { + "x": 0.2779191897716373, + "y": 0.7891364269889891, + "radius": 0.48951867036521435 + }, + { + "x": 0.5678682955913246, + "y": 0.7086034687235951, + "radius": 0.20664421338588002 + } + ], + "computed": { + "0": { + "x": 2.13763676299983, + "y": 1.975905718937698, + "radius": 0.3507522008381784 + }, + "1": { + "x": 1.6876848371844335, + "y": 2.064198653769658, + "radius": 0.45926235588267456 + }, + "2": { + "x": 1.4387293103081353, + "y": 1.780250790333555, + "radius": 0.1309586538001895 + }, + "3": { + "x": 1.3769856968777203, + "y": 1.7789117769866731, + "radius": 0.3658690334297717 + }, + "4": { + "x": 2.257691653945445, + "y": 1.8650244285387891, + "radius": 0.2654735702089965 + }, + "5": { + "x": 1.9245112152968258, + "y": 2.1493580214421018, + "radius": 0.24833531118929383 + }, + "6": { + "x": 1.9347606794571603, + "y": 1.4224765404004154, + "radius": 0.4895186703652143 + }, + "7": { + "x": 1.9929830098001493, + "y": 1.7148572354608076, + "radius": 0.20664421338588 + } + } + }, + { + "original": [ + { + "x": 0.021131554385647178, + "y": 0.8338533279020339, + "radius": 0.20721762543544175 + }, + { + "x": 0.9164798527490348, + "y": 0.08893540711142123, + "radius": 0.3512008039280773 + }, + { + "x": 0.6972017018124461, + "y": 0.49640341056510806, + "radius": 0.20577510613948108 + }, + { + "x": 0.896279857493937, + "y": 0.8343966195825487, + "radius": 0.26519573684781794 + }, + { + "x": 0.2432050269562751, + "y": 0.9118969431146979, + "radius": 0.3189229304902256 + }, + { + "x": 0.1103697104845196, + "y": 0.06436358136124909, + "radius": 0.2878097196109593 + }, + { + "x": 0.33599937707185745, + "y": 0.18275777297094464, + "radius": 0.16255227122455834 + }, + { + "x": 0.4387203629594296, + "y": 0.9021784199867398, + "radius": 0.24089313913136723 + } + ], + "computed": { + "0": { + "x": 1.9299370254363728, + "y": 1.872983548959903, + "radius": 0.20721762543544175 + }, + "1": { + "x": 1.2919180354310498, + "y": 1.5473344070137849, + "radius": 0.3512008039280773 + }, + "2": { + "x": 1.552668725621262, + "y": 1.0994359238701723, + "radius": 0.20577510613948105 + }, + "3": { + "x": 1.8987117470920354, + "y": 1.3172319496859068, + "radius": 0.26519573684781794 + }, + "4": { + "x": 2.191241246949228, + "y": 1.7858521436185524, + "radius": 0.3189229304902255 + }, + "5": { + "x": 1.2410195814531955, + "y": 2.219616047275119, + "radius": 0.28780971961095925 + }, + "6": { + "x": 1.10677420687544, + "y": 1.946488425308882, + "radius": 0.16255227122455834 + }, + "7": { + "x": 2.218900566220555, + "y": 1.6422286893468159, + "radius": 0.24089313913136726 + } + } + }, + { + "original": [ + { + "x": 0.7500620901118964, + "y": 0.6973643896635622, + "radius": 0.32250429568812256 + }, + { + "x": 0.5444313613697886, + "y": 0.015616560587659478, + "radius": 0.33736859196797014 + }, + { + "x": 0.2642467643599957, + "y": 0.34645732631906867, + "radius": 0.3322914230637253 + }, + { + "x": 0.4587820100132376, + "y": 0.7964231248479337, + "radius": 0.3115913345478475 + }, + { + "x": 0.6643326063640416, + "y": 0.8693828217219561, + "radius": 0.4659894212149084 + }, + { + "x": 0.01788544887676835, + "y": 0.6876496176701039, + "radius": 0.14238786613568666 + }, + { + "x": 0.5944569471757859, + "y": 0.9969841924030334, + "radius": 0.37622914081439374 + }, + { + "x": 0.19759053946472704, + "y": 0.6666428472381085, + "radius": 0.33833279395475985 + } + ], + "computed": { + "0": { + "x": 1.9583806174449516, + "y": 1.876044197864504, + "radius": 0.32250429568812256 + }, + "1": { + "x": 1.2963189239347719, + "y": 2.1939879894461733, + "radius": 0.3373685919679701 + }, + "2": { + "x": 1.3843287624250917, + "y": 1.7686757616716606, + "radius": 0.33229142306372533 + }, + "3": { + "x": 1.8442370071260472, + "y": 1.5933572821372184, + "radius": 0.31159133454784743 + }, + "4": { + "x": 2.031747281293223, + "y": 1.703061792108558, + "radius": 0.4659894212149082 + }, + "5": { + "x": 1.3606012420534552, + "y": 1.3200508293137236, + "radius": 0.14238786613568663 + }, + "6": { + "x": 2.078370098568863, + "y": 1.5856536983025271, + "radius": 0.37622914081439374 + }, + "7": { + "x": 1.577310341559726, + "y": 1.4904627235617638, + "radius": 0.3383327939547598 + } + } + }, + { + "original": [ + { + "x": 0.9116797340102494, + "y": 0.5175917975138873, + "radius": 0.17376249665394428 + }, + { + "x": 0.9188621581997722, + "y": 0.9840220499318093, + "radius": 0.4725021345540882 + }, + { + "x": 0.5981611083261669, + "y": 0.0772151097189635, + "radius": 0.2005464260466397 + }, + { + "x": 0.0065658180974423885, + "y": 0.3690323596820235, + "radius": 0.2625421985983849 + }, + { + "x": 0.43971956288442016, + "y": 0.12860602070577443, + "radius": 0.4193396659567953 + }, + { + "x": 0.10275954054668546, + "y": 0.850565197179094, + "radius": 0.3169958249665797 + }, + { + "x": 0.1568527224007994, + "y": 0.06627502874471247, + "radius": 0.4487205466255546 + }, + { + "x": 0.49387982953339815, + "y": 0.6432320333551615, + "radius": 0.2497371000237763 + } + ], + "computed": { + "0": { + "x": 1.722754504696938, + "y": 2.4620676882906656, + "radius": 0.17376249665394428 + }, + "1": { + "x": 1.38156751189203, + "y": 2.235638511224441, + "radius": 0.47250213455408824 + }, + "2": { + "x": 2.3700253582425406, + "y": 2.3252115061238094, + "radius": 0.20054642604663966 + }, + "3": { + "x": 2.2477004187260072, + "y": 1.6302980143115469, + "radius": 0.2625421985983849 + }, + "4": { + "x": 2.3043448601079155, + "y": 2.122431073310608, + "radius": 0.4193396659567953 + }, + "5": { + "x": 1.7592471778588037, + "y": 1.4926720101069864, + "radius": 0.3169958249665797 + }, + "6": { + "x": 2.4795505410649747, + "y": 1.8976112307839579, + "radius": 0.4487205466255546 + }, + "7": { + "x": 1.8278223137529643, + "y": 1.927082652190161, + "radius": 0.2497371000237763 + } + } + }, + { + "original": [ + { + "x": 0.32185476180166006, + "y": 0.12406933470629156, + "radius": 0.12259405879303814 + }, + { + "x": 0.2383392972406, + "y": 0.051823945017531514, + "radius": 0.24375819405540824 + }, + { + "x": 0.8206266772467643, + "y": 0.8355704850982875, + "radius": 0.22039482397958637 + }, + { + "x": 0.8923333398997784, + "y": 0.5894293279852718, + "radius": 0.27002394925802947 + }, + { + "x": 0.7925316309556365, + "y": 0.3651309171691537, + "radius": 0.28720414312556386 + }, + { + "x": 0.18227770226076245, + "y": 0.38898207363672554, + "radius": 0.22255127010867 + }, + { + "x": 0.8854047106578946, + "y": 0.6882542218081653, + "radius": 0.23970571663230658 + }, + { + "x": 0.3187103453092277, + "y": 0.4432863912079483, + "radius": 0.29265650184825065 + } + ], + "computed": { + "0": { + "x": 1.5449548698673012, + "y": 1.030459350990535, + "radius": 0.12259405879303813 + }, + "1": { + "x": 1.6977621925939392, + "y": 1.189575689887081, + "radius": 0.24375819405540824 + }, + "2": { + "x": 0.9927726496791908, + "y": 1.124529410914002, + "radius": 0.22039482397958637 + }, + "3": { + "x": 0.9831134668513877, + "y": 1.391271930135636, + "radius": 0.27002394925802947 + }, + "4": { + "x": 1.156034189430581, + "y": 1.5167000647376518, + "radius": 0.28720414312556386 + }, + "5": { + "x": 1.745216582263292, + "y": 1.511953614307925, + "radius": 0.22255127010866996 + }, + "6": { + "x": 0.9481175217859908, + "y": 1.2891667940740208, + "radius": 0.2397057166323066 + }, + "7": { + "x": 1.5814368513082202, + "y": 1.5957514687330505, + "radius": 0.2926565018482506 + } + } + }, + { + "original": [ + { + "x": 0.8823359292000532, + "y": 0.43816463369876146, + "radius": 0.1790906585752964 + }, + { + "x": 0.07324572838842869, + "y": 0.6110532574821264, + "radius": 0.11561281150206924 + }, + { + "x": 0.9147615463007241, + "y": 0.9378303152043372, + "radius": 0.16163490200415254 + }, + { + "x": 0.37905844021588564, + "y": 0.1981302103959024, + "radius": 0.1839988927356899 + }, + { + "x": 0.20044421614147723, + "y": 0.9811104082036763, + "radius": 0.28463084930554033 + }, + { + "x": 0.2528002690523863, + "y": 0.9732124856673181, + "radius": 0.4863603565841913 + }, + { + "x": 0.38356006145477295, + "y": 0.5806783766020089, + "radius": 0.3574546602554619 + }, + { + "x": 0.8263475727289915, + "y": 0.08225608593784273, + "radius": 0.14096610583364966 + } + ], + "computed": { + "0": { + "x": 2.0169777764768972, + "y": 1.680658273791544, + "radius": 0.1790906585752964 + }, + "1": { + "x": 1.5818891313297228, + "y": 1.7793361879707423, + "radius": 0.11561281150206926 + }, + "2": { + "x": 2.128906069420078, + "y": 1.1175068018140837, + "radius": 0.16163490200415254 + }, + "3": { + "x": 1.6519975582082256, + "y": 2.0091706196341197, + "radius": 0.18399889273568987 + }, + "4": { + "x": 1.2097051134948396, + "y": 1.4100230493754713, + "radius": 0.28463084930554033 + }, + "5": { + "x": 1.0527230717300662, + "y": 1.4987563324643258, + "radius": 0.48636035658419136 + }, + "6": { + "x": 1.2693752457549494, + "y": 1.8406875981799102, + "radius": 0.35745466025546185 + }, + "7": { + "x": 1.6850607053716744, + "y": 1.260495808556256, + "radius": 0.14096610583364966 + } + } + }, + { + "original": [ + { + "x": 0.3258938048966229, + "y": 0.6798728483263403, + "radius": 0.16266744509339331 + }, + { + "x": 0.8026760001666844, + "y": 0.2434185235761106, + "radius": 0.44829401401802904 + }, + { + "x": 0.2844947965350002, + "y": 0.501641359180212, + "radius": 0.30626842845231295 + }, + { + "x": 0.6821056187618524, + "y": 0.3758098704274744, + "radius": 0.10752349831163883 + }, + { + "x": 0.04627287038601935, + "y": 0.15679178875871003, + "radius": 0.4317157995887101 + }, + { + "x": 0.0456976592540741, + "y": 0.9253626596182585, + "radius": 0.15810264423489573 + }, + { + "x": 0.08346907491795719, + "y": 0.9243021607398987, + "radius": 0.16905579837039114 + }, + { + "x": 0.9163369825109839, + "y": 0.5866418236400932, + "radius": 0.24422375364229085 + } + ], + "computed": { + "0": { + "x": 2.188753458668966, + "y": 2.0724566737279932, + "radius": 0.16266744509339331 + }, + "1": { + "x": 2.1137877517807913, + "y": 1.489330420380119, + "radius": 0.44829401401802904 + }, + "2": { + "x": 2.06035173546985, + "y": 2.012916074849751, + "radius": 0.30626842845231295 + }, + "3": { + "x": 1.768367930287804, + "y": 1.4064738041292113, + "radius": 0.10752349831163883 + }, + "4": { + "x": 1.6373336850634157, + "y": 2.043747128910324, + "radius": 0.4317157995887101 + }, + "5": { + "x": 1.0206567644820146, + "y": 1.815499830934383, + "radius": 0.15810264423489573 + }, + "6": { + "x": 1.0243230901452667, + "y": 1.7498000217652425, + "radius": 0.16905579837039114 + }, + "7": { + "x": 1.8982080136694002, + "y": 1.1215584748704905, + "radius": 0.24422375364229082 + } + } + }, + { + "original": [ + { + "x": 0.8765770811587572, + "y": 0.6861295572016388, + "radius": 0.1422904203645885 + }, + { + "x": 0.19219745486043394, + "y": 0.11469919118098915, + "radius": 0.42979686660692096 + }, + { + "x": 0.3725763789843768, + "y": 0.7333921948447824, + "radius": 0.10048453332856298 + }, + { + "x": 0.9359309321735054, + "y": 0.7883771539200097, + "radius": 0.36965545583516357 + }, + { + "x": 0.8403154122643173, + "y": 0.8217576975002885, + "radius": 0.23058210732415318 + }, + { + "x": 0.057080430909991264, + "y": 0.023532875580713153, + "radius": 0.19781163269653917 + }, + { + "x": 0.7398419713135809, + "y": 0.34003381594084203, + "radius": 0.45510250451043255 + }, + { + "x": 0.06538353580981493, + "y": 0.8410374175291508, + "radius": 0.44393736710771925 + } + ], + "computed": { + "0": { + "x": 2.3580649491506027, + "y": 1.9410975860702524, + "radius": 0.1422904203645885 + }, + "1": { + "x": 1.4928690463688383, + "y": 2.2899602930748566, + "radius": 0.42979686660692096 + }, + "2": { + "x": 1.7293529125602871, + "y": 1.2862194330899315, + "radius": 0.100484533328563 + }, + "3": { + "x": 2.5158770065683744, + "y": 2.08197202010972, + "radius": 0.3696554558351635 + }, + "4": { + "x": 2.5256891806105144, + "y": 2.011338219504393, + "radius": 0.23058210732415318 + }, + "5": { + "x": 1.4612198476845595, + "y": 2.37379930053738, + "radius": 0.19781163269653917 + }, + "6": { + "x": 2.0704206539314343, + "y": 2.2097834958398335, + "radius": 0.4551025045104326 + }, + "7": { + "x": 1.594256207056681, + "y": 1.5535794557049267, + "radius": 0.4439373671077192 + } + } + }, + { + "original": [ + { + "x": 0.016111450968310237, + "y": 0.4839170330669731, + "radius": 0.40283224629238246 + }, + { + "x": 0.28692731494084, + "y": 0.48893491574563086, + "radius": 0.2379007455892861 + }, + { + "x": 0.8295576795935631, + "y": 0.7743689070921391, + "radius": 0.13536965167149903 + }, + { + "x": 0.2349571546074003, + "y": 0.25999374384991825, + "radius": 0.29619459817186 + }, + { + "x": 0.39915481046773493, + "y": 0.8935145826544613, + "radius": 0.13019391037523748 + }, + { + "x": 0.969396036118269, + "y": 0.13812412647530437, + "radius": 0.34657504307106135 + }, + { + "x": 0.17283098469488323, + "y": 0.13303479296155274, + "radius": 0.3034230961464346 + }, + { + "x": 0.10154671687632799, + "y": 0.7615526700392365, + "radius": 0.4162899903021753 + } + ], + "computed": { + "0": { + "x": 1.9435602366782092, + "y": 1.5070527153660602, + "radius": 0.40283224629238246 + }, + "1": { + "x": 1.920548112501942, + "y": 1.540084840748847, + "radius": 0.23790074558928612 + }, + "2": { + "x": 1.388568046104114, + "y": 1.731715084893311, + "radius": 0.13536965167149903 + }, + "3": { + "x": 1.9111323728780434, + "y": 1.807102557943786, + "radius": 0.29619459817186006 + }, + "4": { + "x": 1.4309682012134397, + "y": 1.3461720425524586, + "radius": 0.13019391037523748 + }, + "5": { + "x": 1.0537447806901286, + "y": 2.2087107439444114, + "radius": 0.34657504307106135 + }, + "6": { + "x": 1.9905624103561246, + "y": 1.870364859255714, + "radius": 0.30342309614643465 + }, + "7": { + "x": 1.732961430879887, + "y": 1.3608427465972999, + "radius": 0.4162899903021753 + } + } + }, + { + "original": [ + { + "x": 0.7189172969665378, + "y": 0.031199520686641335, + "radius": 0.3139297118410468 + }, + { + "x": 0.8232175291050225, + "y": 0.6535456667188555, + "radius": 0.27733462266623976 + }, + { + "x": 0.39909613551571965, + "y": 0.7800852209329605, + "radius": 0.44534864379093053 + }, + { + "x": 0.5511223068460822, + "y": 0.8760097906924784, + "radius": 0.32370895864441995 + }, + { + "x": 0.7914180001243949, + "y": 0.31860159733332694, + "radius": 0.24560284996405246 + }, + { + "x": 0.9790421170182526, + "y": 0.09079568576999009, + "radius": 0.18374410085380077 + }, + { + "x": 0.6160504696890712, + "y": 0.31452763988636434, + "radius": 0.4439207036048174 + }, + { + "x": 0.045904488768428564, + "y": 0.7853784419130534, + "radius": 0.19257736802101136 + } + ], + "computed": { + "0": { + "x": 1.123593443208931, + "y": 1.6280148507506733, + "radius": 0.31392971184104684 + }, + "1": { + "x": 1.7605214169627834, + "y": 1.9599858590669932, + "radius": 0.2773346226662398 + }, + "2": { + "x": 1.9332911138447768, + "y": 1.5401567120055923, + "radius": 0.4453486437909306 + }, + "3": { + "x": 2.027894746608184, + "y": 1.673268466229001, + "radius": 0.32370895864442 + }, + "4": { + "x": 1.4124238806177907, + "y": 1.7967546313240006, + "radius": 0.24560284996405246 + }, + "5": { + "x": 1.1814709769923968, + "y": 1.352856800630774, + "radius": 0.1837441008538008 + }, + "6": { + "x": 1.459033626176562, + "y": 1.6988785923923733, + "radius": 0.44392070360481745 + }, + "7": { + "x": 1.9778304358219982, + "y": 1.226143727834014, + "radius": 0.1925773680210114 + } + } + } +]; diff --git a/tests/venneuler_comparison/src/main/java/VennEulerServer.java b/tests/venneuler_comparison/src/main/java/VennEulerServer.java new file mode 100644 index 0000000..672577f --- /dev/null +++ b/tests/venneuler_comparison/src/main/java/VennEulerServer.java @@ -0,0 +1,107 @@ +import com.google.gson.Gson; +import com.sun.net.httpserver.Headers; +import edu.uic.ncdm.venn.VennAnalytic; +import edu.uic.ncdm.venn.VennDiagram; +import edu.uic.ncdm.venn.data.VennData; + +import java.util.HashMap; +import java.io.IOException; +import java.io.OutputStream; +import java.io.InputStream; +import java.net.InetSocketAddress; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; + + +public class VennEulerServer { + class SetSizes { + public String[] sets; + public double size; + SetSizes() { }; + } + + static class Circle { + public String label; + public double x; + public double y; + public double radius; + + Circle() {} + } + + public static String jsonFromVennDiagram(VennDiagram vd) { + + Circle[] circles = new Circle[vd.circleLabels.length]; + for (int i = 0; i < circles.length; ++i) { + circles[i] = new Circle(); + circles[i].radius = vd.diameters[i] / 2; + circles[i].x = vd.centers[i][0]; + circles[i].y = vd.centers[i][1]; + circles[i].label = vd.circleLabels[i]; + } + + Gson gson = new Gson(); + return gson.toJson(circles); + } + + public static VennData vennDataFromJSON(String json) { + Gson gson = new Gson(); + SetSizes[] sizes = gson.fromJson(json, SetSizes[].class); + + String [] regions = new String[sizes.length]; + double [] areas = new double[sizes.length]; + + for (int i = 0; i < sizes.length; ++i) { + StringBuilder s = new StringBuilder(); + for (int j = 0; j < sizes[i].sets.length; ++j) { + if (j != 0) s.append("&"); + s.append(sizes[i].sets[j]); + } + + regions[i] = s.toString(); + areas[i] = sizes[i].size; + } + + VennData data = new VennData(regions, areas); + return data; + } + + public static void main(String[] args) throws IOException { + System.out.println("starting webserver"); + HttpServer server = HttpServer.create(new InetSocketAddress(4242), 0); + server.createContext("/venneuler", new VennServer()); + server.setExecutor(null); + server.start(); + } + + static class VennServer implements HttpHandler { + public void handle(HttpExchange t) throws IOException { + // read json data from request + InputStream input = t.getRequestBody(); + java.util.Scanner s = new java.util.Scanner(input).useDelimiter("\\A"); + String serialized = s.hasNext() ? s.next() : ""; + + System.out.printf("Serialized:%s\n", serialized); + + // calculate venn layout + VennData data = vennDataFromJSON(serialized); + VennAnalytic va = new VennAnalytic(); + VennDiagram vd = va.compute(data); + System.out.printf("computed, stress=%.4f\n", vd.stress); + String output = jsonFromVennDiagram((vd)); + + Headers h = t.getResponseHeaders(); + h.set("Access-Control-Allow-Origin", "*"); + h.set("ContentType", "application/json"); + + t.sendResponseHeaders(200, output.length()); + + OutputStream os = t.getResponseBody(); + os.write(output.getBytes()); + os.close(); + + } + } +} \ No newline at end of file diff --git a/venn.js b/venn.js index 12e96f0..bc29a54 100644 --- a/venn.js +++ b/venn.js @@ -1,4 +1,4 @@ -var venn = venn || {}; +var venn = venn || {'version' : '0.2'}; (function(venn) { "use strict"; @@ -257,7 +257,7 @@ var venn = venn || {}; return margin; } - // compute the center of some circles by maximizing the margin of + // compute the center of some circles by maximizing the margin of // the center point relative to the circles (interior) after subtracting // nearby circles (exterior) function computeTextCentre(interior, exterior) { @@ -426,7 +426,7 @@ var venn = venn || {}; parameters = parameters || {}; parameters.maxIterations = parameters.maxIterations || 500; var lossFunction = parameters.lossFunction || venn.lossFunction; - var initialLayout = parameters.initialLayout || venn.greedyLayout; + var initialLayout = parameters.initialLayout || venn.bestInitialLayout; var fmin = parameters.fmin || venn.fmin; // initial layout is done greedily @@ -471,7 +471,7 @@ var venn = venn || {}; return circles; }; - + var SMALL = 1e-10; /** Returns the distance necessary for two circles of radius r1 + r2 to @@ -487,24 +487,17 @@ var venn = venn || {}; }, 0, r1 + r2); }; - /// gets a matrix of euclidean distances between all sets in venn diagram - venn.getDistanceMatrix = function(areas, sets, setids) { + /// Returns two matrices, one of the euclidean distances between the sets + /// and the other indicating if there are subset or disjoint set relationships + venn.getDistanceMatrices = function(areas, sets, setids) { // initialize an empty distance matrix between all the points - var distances = []; - for (var i = 0; i < sets.length; ++i) { - distances.push([]); - for (var j = 0; j < sets.length; ++j) { - distances[i].push(0); - } - } - - // compute distances between all the points - for (i = 0; i < areas.length; ++i) { - var current = areas[i]; - if (current.sets.length !== 2) { - continue; - } + var distances = venn.zerosM(sets.length, sets.length), + constraints = venn.zerosM(sets.length, sets.length); + // compute required distances between all the sets such that + // the areas match + areas.filter(function(x) { return x.sets.length == 2; }) + .map(function(current) { var left = setids[current.sets[0]], right = setids[current.sets[1]], r1 = Math.sqrt(sets[left].size / Math.PI), @@ -512,8 +505,134 @@ var venn = venn || {}; distance = venn.distanceFromIntersectArea(r1, r2, current.size); distances[left][right] = distances[right][left] = distance; + + // also update constraints to indicate if its a subset or disjoint + // relationship + var c = 0; + if (current.size + 1e-10 >= Math.min(sets[left].size, + sets[right].size)) { + c = 1; + } else if (current.size <= 1e-10) { + c = -1; + } + constraints[left][right] = constraints[right][left] = c; + }); + + return {distances: distances, constraints: constraints}; + }; + + /// computes the gradient and loss simulatenously for our constrained MDS optimizer + function constrainedMDSGradient(x, fxprime, distances, constraints) { + var loss = 0, i; + for (i = 0; i < fxprime.length; ++i) { + fxprime[i] = 0; + } + + for (i = 0; i < distances.length; ++i) { + var xi = x[2 * i], yi = x[2 * i + 1]; + for (var j = i + 1; j < distances.length; ++j) { + var xj = x[2 * j], yj = x[2 * j + 1], + dij = distances[i][j], + constraint = constraints[i][j]; + + var squaredDistance = (xj - xi) * (xj - xi) + (yj - yi) * (yj - yi), + distance = Math.sqrt(squaredDistance), + delta = squaredDistance - dij * dij; + + if (((constraint > 0) && (distance <= dij)) || + ((constraint < 0) && (distance >= dij))) { + continue; + } + + 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; + } + + /// takes the best working variant of either constrained MDS or greedy + venn.bestInitialLayout = function(areas, params) { + var initial = venn.greedyLayout(areas, params); + + // greedylayout is sufficient for all 2/3 circle cases. try out + // constrained MDS for higher order problems, take its output + // if it outperforms. (greedy is aesthetically better on 2/3 circles + // since it axis aligns) + if (areas.length >= 8) { + var constrained = venn.constrainedMDSLayout(areas, params), + constrainedLoss = venn.lossFunction(constrained, areas), + greedyLoss = venn.lossFunction(initial, areas); + + if (constrainedLoss + 1e-8 < greedyLoss) { + initial = constrained; + } + } + return initial; + }; + + /// use the constrained MDS variant to generate an initial layout + venn.constrainedMDSLayout = function(areas, params) { + params = params || {}; + var restarts = params.restarts || 10; + + // bidirectionally map sets to a rowid (so we can create a matrix) + var sets = [], setids = {}, i; + for (i = 0; i < areas.length; ++i ) { + var area = areas[i]; + if (area.sets.length == 1) { + setids[area.sets[0]] = sets.length; + sets.push(area); + } } - return distances; + + var matrices = venn.getDistanceMatrices(areas, sets, setids), + distances = matrices.distances, + constraints = matrices.constraints; + + // keep distances bounded, things get messed up otherwise. + // TODO: proper preconditioner? + var norm = venn.norm2(distances.map(venn.norm2))/(distances.length); + distances = distances.map(function (row) { + return row.map(function (value) { return value / norm; });}); + + var obj = function(x, fxprime) { + return constrainedMDSGradient(x, fxprime, distances, constraints); + }; + + var best, current; + for (i = 0; i < restarts; ++i) { + var initial = venn.zeros(distances.length*2).map(Math.random); + + current = venn.minimizeConjugateGradient(obj, initial, params); + if (!best || (current.fx < best.fx)) { + best = current; + } + } + var positions = best.x; + + // translate rows back to (x,y,radius) coordinates + var circles = {}; + for (i = 0; i < sets.length; ++i) { + var 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) { + venn.multiplyBy(params.history[i].x, norm); + } + } + return circles; }; /** Lays out a Venn diagram greedily, going from most overlapped sets to @@ -588,7 +707,7 @@ var venn = venn || {}; // get distances between all points. TODO, necessary? // answer: probably not - // var distances = venn.getDistanceMatrix(circles, areas); + // var distances = venn.getDistanceMatrices(circles, areas).distances; for (i = 1; i < mostOverlapped.length; ++i) { var setIndex = mostOverlapped[i].set, overlap = setOverlaps[setIndex].filter(isPositioned); @@ -661,7 +780,7 @@ var venn = venn || {}; } // get the distance matrix, and use to position sets - var distances = venn.getDistanceMatrix(areas, sets, setids); + var distances = venn.getDistanceMatrices(areas, sets, setids).distances; var positions = mds.classic(distances); // translate rows back to (x,y,radius) coordinates @@ -977,6 +1096,33 @@ var venn = venn || {}; return a + delta; }; + // need some basic operations on vectors, rather than adding a dependency, + // just define here + function zeros(x) { var r = new Array(x); for (var i = 0; i < x; ++i) { r[i] = 0; } return r; } + function zerosM(x,y) { return zeros(x).map(function() { return zeros(y); }); } + venn.zerosM = zerosM; + venn.zeros = zeros; + + function dot(a, b) { + var ret = 0; + for (var i = 0; i < a.length; ++i) { + ret += a[i] * b[i]; + } + return ret; + } + + function norm2(a) { + return Math.sqrt(dot(a, a)); + } + venn.norm2 = norm2; + + function multiplyBy(a, c) { + for (var i = 0; i < a.length; ++i) { + a[i] *= c; + } + } + venn.multiplyBy = multiplyBy; + function weightedSum(ret, w1, v1, w2, v2) { for (var j = 0; j < ret.length; ++j) { ret[j] = w1 * v1[j] + w2 * v2[j]; @@ -1105,6 +1251,131 @@ var venn = venn || {}; return {f : simplex[0].fx, solution : simplex[0]}; }; + + + venn.minimizeConjugateGradient = function(f, initial, params) { + // allocate all memory up front here, keep out of the loop for perfomance + // reasons + var current = {x: initial.slice(), fx: 0, fxprime: initial.slice()}, + next = {x: initial.slice(), fx: 0, fxprime: initial.slice()}, + yk = initial.slice(), + pk, temp, + a = 1, + maxIterations; + + params = params || {}; + maxIterations = params.maxIterations || initial.length * 5; + + current.fx = f(current.x, current.fxprime); + pk = current.fxprime.slice(); + multiplyBy(pk, -1); + + for (var i = 0; i < maxIterations; ++i) { + if (params.history) { + params.history.push({x: current.x.slice(), + fx: current.fx, + fxprime: current.fxprime.slice()}); + } + + a = venn.wolfeLineSearch(f, pk, current, next, a); + if (!a) { + // faiiled to find point that satifies wolfe conditions. + // reset direction for next iteration + for (var j = 0; j < pk.length; ++j) { + pk[j] = -1 * current.fxprime[j]; + } + } else { + // update direction using Polak–Ribiere CG method + weightedSum(yk, 1, next.fxprime, -1, current.fxprime); + + var delta_k = dot(current.fxprime, current.fxprime), + beta_k = Math.max(0, dot(yk, next.fxprime) / delta_k); + + weightedSum(pk, beta_k, pk, -1, next.fxprime); + + temp = current; + current = next; + next = temp; + } + + if (norm2(current.fxprime) <= 1e-5) { + break; + } + } + + if (params.history) { + params.history.push({x: current.x.slice(), + fx: current.fx, + fxprime: current.fxprime.slice()}); + } + + return current; + }; + + var c1 = 1e-6, c2 = 0.1; + + /// searches along line 'pk' for a point that satifies the wolfe conditions + /// See 'Numerical Optimization' by Nocedal and Wright p59-60 + venn.wolfeLineSearch = function(f, pk, current, next, a) { + var phi0 = current.fx, phiPrime0 = dot(current.fxprime, pk), + phi = phi0, phi_old = phi0, + phiPrime = phiPrime0, + a0 = 0; + + a = a || 1; + + function zoom(a_lo, a_high, phi_lo) { + for (var iteration = 0; iteration < 16; ++iteration) { + a = (a_lo + a_high)/2; + weightedSum(next.x, 1.0, current.x, a, pk); + phi = next.fx = f(next.x, next.fxprime); + phiPrime = dot(next.fxprime, pk); + + if ((phi > (phi0 + c1 * a * phiPrime0)) || + (phi >= phi_lo)) { + a_high = a; + + } else { + if (Math.abs(phiPrime) <= -c2 * phiPrime0) { + return a; + } + + if (phiPrime * (a_high - a_lo) >=0) { + a_high = a_lo; + } + + a_lo = a; + phi_lo = phi; + } + } + + return 0; + } + + for (var iteration = 0; iteration < 10; ++iteration) { + weightedSum(next.x, 1.0, current.x, a, pk); + phi = next.fx = f(next.x, next.fxprime); + phiPrime = dot(next.fxprime, pk); + if ((phi > (phi0 + c1 * a * phiPrime0)) || + (iteration && (phi >= phi_old))) { + return zoom(a0, a, phi_old); + } + + if (Math.abs(phiPrime) <= -c2 * phiPrime0) { + return a; + } + + if (phiPrime >= 0 ) { + return zoom(a, a0, phi); + } + + phi_old = phi; + a0 = a; + a *= 2; + } + + return 0; + }; })(venn); (function(venn) { @@ -1337,5 +1608,5 @@ var venn = venn || {}; window.venn = lib; } else { module.exports = lib; - } + } })(venn); diff --git a/venn.min.js b/venn.min.js index e41785a..a0156b2 100644 --- a/venn.min.js +++ b/venn.min.js @@ -1 +1 @@ -var venn=venn||{};!function(a){"use strict";function b(b,c,d){var e,f,g=c[0].radius-a.distance(c[0],b);for(e=1;e=f&&(g=f);for(e=0;e=f&&(g=f);return g}function c(c,d){var e,f=[];for(e=0;e=i&&(h=f[e],i=j)}var k=a.fmin(function(a){return-1*b({x:a[0],y:a[1]},c,d)},[h.x,h.y],{maxIterations:500,minErrorDelta:1e-10}).solution,l={x:k[0],y:k[1]},m=!0;for(e=0;ec[e].radius){m=!1;break}for(e=0;e0&&console.log("WARNING: area "+f+" not represented on screen")}return d}a.VennDiagram=function(){function b(b){b.each(function(b){var n=m(b);j&&(n=a.normalizeSolution(n,i));var o=a.scaleSolution(n,e,f,g),p=d(o,b),q=d3.select(this).selectAll("svg").data([o]);q.enter().append("svg"),q.attr("width",e).attr("height",f);var r={},s=!1;q.selectAll("g").each(function(b){var c=d3.select(this).select("path").attr("d");1==b.sets.length&&c&&(s=!0,r[b.sets[0]]=a.circleFromPath(c))});var t=function(b){return function(c){var d=b.sets.map(function(a){var b=r[a],d=o[a];return b||(b={x:e/2,y:f/2,radius:1}),d||(d={x:e/2,y:f/2,radius:1}),{x:b.x*(1-c)+d.x*c,y:b.y*(1-c)+d.y*c,radius:b.radius*(1-c)+d.radius*c}});return a.intersectionAreaPath(d)}},u=q.selectAll("g").data(b,function(a){return a.sets}),v=u.enter().append("g").attr("class",function(a){return"venn-area venn-"+(1==a.sets.length?"circle":"intersection")+(" venn-sets-"+a.sets.join("_"))});v.append("path").style("fill-opacity","0").filter(function(a){return 1==a.sets.length}).style("fill",function(a){return l(c(a))}).style("fill-opacity",".25");var w=v.append("text").style("fill",function(a){return 1==a.sets.length?l(c(a)):"#444"}).text(function(a){return c(a)}).attr("text-anchor","middle").attr("dy",".35em").attr("x",e/2).attr("y",f/2),x=u.transition("venn").duration(s?h:0);x.select("path").attrTween("d",t);var y=x.select("text").text(function(a){return c(a)}).each("end",a.wrapText(o,c)).attr("x",function(a){return Math.floor(p[a.sets].x)}).attr("y",function(a){return Math.floor(p[a.sets].y)});null!==k&&(w.style("font-size","0px"),y.style("font-size",k));var z=u.exit().transition("venn").duration(h).remove();z.select("path").attrTween("d",t),z.select("text").text(function(a){return c(a)}).attr("x",e/2).attr("y",f/2).style("font-size","0px")})}function c(a){return a.label?a.label:1==a.sets.length?""+a.sets[0]:void 0}var e=600,f=350,g=15,h=1e3,i=Math.PI/2,j=!0,k=null,l=d3.scale.category10(),m=a.venn;return b.width=function(a){return arguments.length?(e=a,b):e},b.height=function(a){return arguments.length?(f=a,b):f},b.padding=function(a){return arguments.length?(g=a,b):g},b.colours=function(a){return arguments.length?(l=a,b):l},b.fontSize=function(a){return arguments.length?(k=a,b):k},b.duration=function(a){return arguments.length?(h=a,b):h},b.layoutFunction=function(a){return arguments.length?(m=a,b):m},b.normalize=function(a){return arguments.length?(j=a,b):j},b.orientation=function(a){return arguments.length?(i=a,b):i},b},a.wrapText=function(a,b){return function(){for(var c,d=d3.select(this),e=d.datum(),f=a[e.sets[0]].radius||50,g=b(e)||"",h=g.split(/\s+/).reverse(),i=3,j=(g.length+h.length)/i,k=h.pop(),l=[k],m=0,n=1.1,o=d.text(null).append("tspan").text(k);;){if(k=h.pop(),!k)break;l.push(k),c=l.join(" "),o.text(c),c.length>j&&o.node().getComputedTextLength()>f&&(l.pop(),o.text(l.join(" ")),l=[k],o=d.append("tspan").text(k),m++)}var p=.35-m*n/2,q=d.attr("x"),r=d.attr("y");d.selectAll("tspan").attr("x",q).attr("y",r).attr("dy",function(a,b){return p+b*n+"em"})}},a.computeTextCentre=c,a.computeTextCentres=d,a.sortAreas=function(a,b){a.selectAll("g").sort(function(a,c){return a.sets.length!=c.sets.length?a.sets.length-c.sets.length:a==b||c==b?a==b?1:-1:c.size-a.size})},a.circlePath=function(a,b,c){var d=[];return d.push("\nM",a,b),d.push("\nm",-c,0),d.push("\na",c,c,0,1,0,2*c,0),d.push("\na",c,c,0,1,0,2*-c,0),d.join(" ")},a.circleFromPath=function(a){var b=a.split(" ");return{x:parseFloat(b[1]),y:parseFloat(b[2]),radius:-parseFloat(b[4])}},a.intersectionAreaPath=function(b){var c={};a.intersectionArea(b,c);var d=c.arcs;if(0===d.length)return"M 0 0";if(1==d.length){var e=d[0].circle;return a.circlePath(e.x,e.y,e.radius)}for(var f=["\nM",d[0].p2.x,d[0].p2.y],g=0;gi;f.push("\nA",i,i,0,j?1:0,1,h.p1.x,h.p1.y)}return f.join(" ")}}(venn),function(a){"use strict";function b(a,b){a.sort(function(a,b){return b.radius-a.radius});var c;if(a.length>0){var d=a[0].x,e=a[0].y;for(c=0;c1){var f,g,h=Math.atan2(a[1].x,a[1].y)-b,i=Math.cos(h),j=Math.sin(h);for(c=0;c2){for(var k=Math.atan2(a[2].x,a[2].y)-b;0>k;)k+=2*Math.PI;for(;k>2*Math.PI;)k-=2*Math.PI;if(k>Math.PI){var l=a[1].y/(1e-10+a[1].x);for(c=0;c=Math.min(h[n].size,h[o].size)&&(m=0),i[n].push({set:o,size:l.size,weight:m}),i[o].push({set:n,size:l.size,weight:m})}var p=[];for(g in i)if(i.hasOwnProperty(g)){var q=0;for(j=0;jF&&(D=F,E=u[v])}f(E,s)}return h},a.classicMDSLayout=function(b){for(var c=[],d={},e=0;ef&&(d+=f)),c?e=m.yRange.max-g.yRange.min+n:(e=m.yRange.max-g.yRange.max-n,f=(g.yRange.max-g.yRange.min)/2-(m.yRange.max-m.yRange.min)/2,0>f&&(e+=f));for(var h=0;h0)throw"Initial bisect points must have opposite signs";if(0===g)return b;if(0===h)return c;for(var j=0;e>j;++j){i/=2;var k=b+i,l=a(k);if(l*g>=0&&(b=k),Math.abs(i)q;++q){var r=c.slice();r[q]=r[q]?r[q]*g:h,p[q+1]=r,p[q+1].fx=a(r)}for(var s=function(a,b){return a.fx-b.fx},t=c.slice(),u=c.slice(),v=c.slice(),w=c.slice(),x=0;f>x&&(p.sort(s),n&&n(p),!(Math.abs(p[0].fx-p[o].fx)q;++q){t[q]=0;for(var y=0;o>y;++y)t[q]+=p[y][q];t[q]/=o}var z=p[o];if(b(u,1+j,t,-j,z),u.fx=a(u),u.fx<=p[0].fx)b(w,1+k,t,-k,z),w.fx=a(w),w.fx=p[o-1].fx){var A=!1;if(u.fx<=z.fx?(b(v,1+l,t,-l,z),v.fx=a(v),v.fx1){var l=a.getCenter(h);for(f=0;f-1){var s=d[o.parentIndex[r]],t=Math.atan2(o.x-s.x,o.y-s.y),u=Math.atan2(n.x-s.x,n.y-s.y),v=u-t;0>v&&(v+=2*Math.PI);var w=u-v/2,x=a.distance(p,{x:s.x+s.radius*Math.sin(w),y:s.y+s.radius*Math.cos(w)});(null===q||q.width>x)&&(q={circle:s,width:x,p1:o,p2:n})}k.push(q),i+=a.circleArea(q.circle.radius,q.width),n=o}}else{var y=d[0];for(f=1;fMath.abs(y.radius-d[f].radius)){z=!0;break}z?i=j=0:(i=y.radius*y.radius*Math.PI,k.push({circle:y,p1:{x:y.x,y:y.y+y.radius},p2:{x:y.x-c,y:y.y+y.radius},width:2*y.radius}))}return j/=2,e&&(e.area=i+j,e.arcArea=i,e.polygonArea=j,e.arcs=k,e.innerPoints=h,e.intersectionPoints=g),i+j},a.containedInCircles=function(b,d){for(var e=0;ed[e].radius+c)return!1;return!0},a.circleIntegral=function(a,b){var c=Math.sqrt(a*a-b*b);return b*c+a*a*Math.atan2(b,c)},a.circleArea=function(b,c){return a.circleIntegral(b,c-b)-a.circleIntegral(b,-b)},a.distance=function(a,b){return Math.sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y))},a.circleOverlap=function(b,c,d){if(d>=b+c)return 0;if(d<=Math.abs(b-c))return Math.PI*Math.min(b,c)*Math.min(b,c);var e=b-(d*d-c*c+b*b)/(2*d),f=c-(d*d-b*b+c*c)/(2*d);return a.circleArea(b,e)+a.circleArea(c,f)},a.circleCircleIntersection=function(b,c){var d=a.distance(b,c),e=b.radius,f=c.radius;if(d>=e+f||d<=Math.abs(e-f))return[];var g=(e*e-f*f+d*d)/(2*d),h=Math.sqrt(e*e-g*g),i=b.x+g*(c.x-b.x)/d,j=b.y+g*(c.y-b.y)/d,k=-(c.y-b.y)*(h/d),l=-(c.x-b.x)*(h/d);return[{x:i+k,y:j-l},{x:i-k,y:j+l}]},a.getCenter=function(a){for(var b={x:0,y:0},c=0;c=f&&(g=f);for(e=0;e=f&&(g=f);return g}function c(c,d){var e,f=[];for(e=0;e=i&&(h=f[e],i=j)}var k=a.fmin(function(a){return-1*b({x:a[0],y:a[1]},c,d)},[h.x,h.y],{maxIterations:500,minErrorDelta:1e-10}).solution,l={x:k[0],y:k[1]},m=!0;for(e=0;ec[e].radius){m=!1;break}for(e=0;e0&&console.log("WARNING: area "+f+" not represented on screen")}return d}a.VennDiagram=function(){function b(b){b.each(function(b){var n=m(b);j&&(n=a.normalizeSolution(n,i));var o=a.scaleSolution(n,e,f,g),p=d(o,b),q=d3.select(this).selectAll("svg").data([o]);q.enter().append("svg"),q.attr("width",e).attr("height",f);var r={},s=!1;q.selectAll("g").each(function(b){var c=d3.select(this).select("path").attr("d");1==b.sets.length&&c&&(s=!0,r[b.sets[0]]=a.circleFromPath(c))});var t=function(b){return function(c){var d=b.sets.map(function(a){var b=r[a],d=o[a];return b||(b={x:e/2,y:f/2,radius:1}),d||(d={x:e/2,y:f/2,radius:1}),{x:b.x*(1-c)+d.x*c,y:b.y*(1-c)+d.y*c,radius:b.radius*(1-c)+d.radius*c}});return a.intersectionAreaPath(d)}},u=q.selectAll("g").data(b,function(a){return a.sets}),v=u.enter().append("g").attr("class",function(a){return"venn-area venn-"+(1==a.sets.length?"circle":"intersection")+(" venn-sets-"+a.sets.join("_"))});v.append("path").style("fill-opacity","0").filter(function(a){return 1==a.sets.length}).style("fill",function(a){return l(c(a))}).style("fill-opacity",".25");var w=v.append("text").style("fill",function(a){return 1==a.sets.length?l(c(a)):"#444"}).text(function(a){return c(a)}).attr("text-anchor","middle").attr("dy",".35em").attr("x",e/2).attr("y",f/2),x=u.transition("venn").duration(s?h:0);x.select("path").attrTween("d",t);var y=x.select("text").text(function(a){return c(a)}).each("end",a.wrapText(o,c)).attr("x",function(a){return Math.floor(p[a.sets].x)}).attr("y",function(a){return Math.floor(p[a.sets].y)});null!==k&&(w.style("font-size","0px"),y.style("font-size",k));var z=u.exit().transition("venn").duration(h).remove();z.select("path").attrTween("d",t),z.select("text").text(function(a){return c(a)}).attr("x",e/2).attr("y",f/2).style("font-size","0px")})}function c(a){return a.label?a.label:1==a.sets.length?""+a.sets[0]:void 0}var e=600,f=350,g=15,h=1e3,i=Math.PI/2,j=!0,k=null,l=d3.scale.category10(),m=a.venn;return b.width=function(a){return arguments.length?(e=a,b):e},b.height=function(a){return arguments.length?(f=a,b):f},b.padding=function(a){return arguments.length?(g=a,b):g},b.colours=function(a){return arguments.length?(l=a,b):l},b.fontSize=function(a){return arguments.length?(k=a,b):k},b.duration=function(a){return arguments.length?(h=a,b):h},b.layoutFunction=function(a){return arguments.length?(m=a,b):m},b.normalize=function(a){return arguments.length?(j=a,b):j},b.orientation=function(a){return arguments.length?(i=a,b):i},b},a.wrapText=function(a,b){return function(){for(var c,d=d3.select(this),e=d.datum(),f=a[e.sets[0]].radius||50,g=b(e)||"",h=g.split(/\s+/).reverse(),i=3,j=(g.length+h.length)/i,k=h.pop(),l=[k],m=0,n=1.1,o=d.text(null).append("tspan").text(k);;){if(k=h.pop(),!k)break;l.push(k),c=l.join(" "),o.text(c),c.length>j&&o.node().getComputedTextLength()>f&&(l.pop(),o.text(l.join(" ")),l=[k],o=d.append("tspan").text(k),m++)}var p=.35-m*n/2,q=d.attr("x"),r=d.attr("y");d.selectAll("tspan").attr("x",q).attr("y",r).attr("dy",function(a,b){return p+b*n+"em"})}},a.computeTextCentre=c,a.computeTextCentres=d,a.sortAreas=function(a,b){a.selectAll("g").sort(function(a,c){return a.sets.length!=c.sets.length?a.sets.length-c.sets.length:a==b||c==b?a==b?1:-1:c.size-a.size})},a.circlePath=function(a,b,c){var d=[];return d.push("\nM",a,b),d.push("\nm",-c,0),d.push("\na",c,c,0,1,0,2*c,0),d.push("\na",c,c,0,1,0,2*-c,0),d.join(" ")},a.circleFromPath=function(a){var b=a.split(" ");return{x:parseFloat(b[1]),y:parseFloat(b[2]),radius:-parseFloat(b[4])}},a.intersectionAreaPath=function(b){var c={};a.intersectionArea(b,c);var d=c.arcs;if(0===d.length)return"M 0 0";if(1==d.length){var e=d[0].circle;return a.circlePath(e.x,e.y,e.radius)}for(var f=["\nM",d[0].p2.x,d[0].p2.y],g=0;gi;f.push("\nA",i,i,0,j?1:0,1,h.p1.x,h.p1.y)}return f.join(" ")}}(venn),function(a){"use strict";function b(a,b,c,d){var e,f=0;for(e=0;e0&&l>=o||0>m&&o>=l||(f+=2*p*p,b[2*e]+=4*p*(g-j),b[2*e+1]+=4*p*(h-k),b[2*i]+=4*p*(j-g),b[2*i+1]+=4*p*(k-h))}return f}function c(a,b){a.sort(function(a,b){return b.radius-a.radius});var c;if(a.length>0){var d=a[0].x,e=a[0].y;for(c=0;c1){var f,g,h=Math.atan2(a[1].x,a[1].y)-b,i=Math.cos(h),j=Math.sin(h);for(c=0;c2){for(var k=Math.atan2(a[2].x,a[2].y)-b;0>k;)k+=2*Math.PI;for(;k>2*Math.PI;)k-=2*Math.PI;if(k>Math.PI){var l=a[1].y/(1e-10+a[1].x);for(c=0;c=Math.min(c[g].size,c[h].size)?l=1:b.size<=1e-10&&(l=-1),f[g][h]=f[h][g]=l}),{distances:e,constraints:f}},a.bestInitialLayout=function(b,c){var d=a.greedyLayout(b,c);if(b.length>=8){var e=a.constrainedMDSLayout(b,c),f=a.lossFunction(e,b),g=a.lossFunction(d,b);g>f+1e-8&&(d=e)}return d},a.constrainedMDSLayout=function(c,d){d=d||{};var e,f=d.restarts||10,g=[],h={};for(e=0;ee;++e){var q=a.zeros(2*k.length).map(Math.random);o=a.minimizeConjugateGradient(p,q,d),(!n||o.fx=Math.min(h[n].size,h[o].size)&&(m=0),i[n].push({set:o,size:l.size,weight:m}),i[o].push({set:n,size:l.size,weight:m})}var p=[];for(g in i)if(i.hasOwnProperty(g)){var q=0;for(j=0;jF&&(D=F,E=u[v])}f(E,s)}return h},a.classicMDSLayout=function(b){for(var c=[],d={},e=0;ef&&(d+=f)),c?e=m.yRange.max-g.yRange.min+n:(e=m.yRange.max-g.yRange.max-n,f=(g.yRange.max-g.yRange.min)/2-(m.yRange.max-m.yRange.min)/2,0>f&&(e+=f));for(var h=0;hc;++c)b[c]=0;return b}function c(a,c){return b(a).map(function(){return b(c)})}function d(a,b){for(var c=0,d=0;d0)throw"Initial bisect points must have opposite signs";if(0===g)return b;if(0===h)return c;for(var j=0;e>j;++j){i/=2;var k=b+i,l=a(k);if(l*g>=0&&(b=k),Math.abs(i)q;++q){var r=b.slice();r[q]=r[q]?r[q]*f:h,p[q+1]=r,p[q+1].fx=a(r)}for(var s=function(a,b){return a.fx-b.fx},t=b.slice(),u=b.slice(),v=b.slice(),w=b.slice(),x=0;e>x&&(p.sort(s),n&&n(p),!(Math.abs(p[0].fx-p[o].fx)q;++q){t[q]=0;for(var y=0;o>y;++y)t[q]+=p[y][q];t[q]/=o}var z=p[o];if(g(u,1+j,t,-j,z),u.fx=a(u),u.fx<=p[0].fx)g(w,1+k,t,-k,z),w.fx=a(w),w.fx=p[o-1].fx){var A=!1;if(u.fx<=z.fx?(g(v,1+l,t,-l,z),v.fx=a(v),v.fxp;++p){if(h.history&&h.history.push({x:l.x.slice(),fx:l.fx,fxprime:l.fxprime.slice()}),o=a.wolfeLineSearch(b,i,l,m,o)){g(n,1,m.fxprime,-1,l.fxprime);var q=d(l.fxprime,l.fxprime),r=Math.max(0,d(n,m.fxprime)/q);g(i,r,i,-1,m.fxprime),j=l,l=m,m=j}else for(var s=0;sq;++q)if(f=(j+n)/2,g(e.x,1,c.x,f,b),m=e.fx=a(e.x,e.fxprime),o=d(e.fxprime,b),m>k+h*f*l||m>=p)n=f;else{if(Math.abs(o)<=-i*l)return f;o*(n-j)>=0&&(n=j),j=f,p=m}return 0}var k=c.fx,l=d(c.fxprime,b),m=k,n=k,o=l,p=0;f=f||1;for(var q=0;10>q;++q){if(g(e.x,1,c.x,f,b),m=e.fx=a(e.x,e.fxprime),o=d(e.fxprime,b),m>k+h*f*l||q&&m>=n)return j(p,f,n);if(Math.abs(o)<=-i*l)return f;if(o>=0)return j(f,p,m);n=m,p=f,f*=2}return 0}}(venn),function(a){"use strict";function b(b){for(var c=[],d=0;d1){var l=a.getCenter(h);for(f=0;f-1){var s=d[o.parentIndex[r]],t=Math.atan2(o.x-s.x,o.y-s.y),u=Math.atan2(n.x-s.x,n.y-s.y),v=u-t;0>v&&(v+=2*Math.PI);var w=u-v/2,x=a.distance(p,{x:s.x+s.radius*Math.sin(w),y:s.y+s.radius*Math.cos(w)});(null===q||q.width>x)&&(q={circle:s,width:x,p1:o,p2:n})}k.push(q),i+=a.circleArea(q.circle.radius,q.width),n=o}}else{var y=d[0];for(f=1;fMath.abs(y.radius-d[f].radius)){z=!0;break}z?i=j=0:(i=y.radius*y.radius*Math.PI,k.push({circle:y,p1:{x:y.x,y:y.y+y.radius},p2:{x:y.x-c,y:y.y+y.radius},width:2*y.radius}))}return j/=2,e&&(e.area=i+j,e.arcArea=i,e.polygonArea=j,e.arcs=k,e.innerPoints=h,e.intersectionPoints=g),i+j},a.containedInCircles=function(b,d){for(var e=0;ed[e].radius+c)return!1;return!0},a.circleIntegral=function(a,b){var c=Math.sqrt(a*a-b*b);return b*c+a*a*Math.atan2(b,c)},a.circleArea=function(b,c){return a.circleIntegral(b,c-b)-a.circleIntegral(b,-b)},a.distance=function(a,b){return Math.sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y))},a.circleOverlap=function(b,c,d){if(d>=b+c)return 0;if(d<=Math.abs(b-c))return Math.PI*Math.min(b,c)*Math.min(b,c);var e=b-(d*d-c*c+b*b)/(2*d),f=c-(d*d-b*b+c*c)/(2*d);return a.circleArea(b,e)+a.circleArea(c,f)},a.circleCircleIntersection=function(b,c){var d=a.distance(b,c),e=b.radius,f=c.radius;if(d>=e+f||d<=Math.abs(e-f))return[];var g=(e*e-f*f+d*d)/(2*d),h=Math.sqrt(e*e-g*g),i=b.x+g*(c.x-b.x)/d,j=b.y+g*(c.y-b.y)/d,k=-(c.y-b.y)*(h/d),l=-(c.x-b.x)*(h/d);return[{x:i+k,y:j-l},{x:i-k,y:j+l}]},a.getCenter=function(a){for(var b={x:0,y:0},c=0;c