# Bubble smartdiagram with weighted bubbles / bubble sizes

I really like the bubble smartdiagram:

http://texample.net/tikz/examples/smart-bubbles/

But I would like to assign custom node sizes.

More specifically I would like to recreate this graphic:

Can this be done? Is the smartdiagram the wrong tool for this? Is there a similar tool or what should I use?

Just for fun, I wrote some asymptote code to mostly recreate your example. The diagram is laid out automatically. The only inputs are the labels and numbers.

Note that the spacing between circles is the same regardless of circle size. Also, the program logic decides if a label will fit in its circle and adjusts the label position and color accordingly.

The areas of all the circles are proportionally correct based on the numbers. Note however that the numbers don't add up to 2597, so the sum of the areas of the blue and red circles doesn't equal the area of the gray circle.

\documentclass{standalone}
\usepackage{asypictureB}
\begin{document}
\begin{asypicture}{name=smartDiagram}

unitsize(1inch); // Because I'm from USA

int allNumber = 2597;
real allRadius = 1.25; // Changing this size will effect the relative font size
real allCircumference = 2.0 * pi * allRadius;

real labelSpacing = 0.18;

struct Cause // This is a structure representing a cause
{
string[] name;
int number;
real angularPosition;
pen color;

void operator init(string name, int number, pen color = blue)
{
this.name = split(name, " ");
this.number = number;
this.color = color;
}
}

Cause[] causes;
causes.push(Cause("Heart disease", 611));
causes.push(Cause("Cancer",        585));
causes.push(Cause("Medical error", 251, red));
causes.push(Cause("COPD",          149));
causes.push(Cause("Suicide",        41));
causes.push(Cause("Firearms",       34));
causes.push(Cause("Motor vehicles", 34));

// set angular positions to achieve equal spacing
real spaceBetween = (allCircumference - 2*sumRadii) / causes.length;
causes[0].angularPosition = 180.0;
for (int i = 1; i < causes.length; ++i)
{
causes[i].angularPosition = causes[i-1].angularPosition -
allCircumference;
}

// Function to draw a label on a picture
void drawLabel(picture p, Cause c, pair loc = (0,0), pen color = black)
{
real yOffset = labelSpacing * c.name.length / 2.0;
for (int i = 0; i < c.name.length; ++i)
{
label(p, baseline(c.name[i]), loc+(0,yOffset), color);
yOffset -= labelSpacing;
}
label(p, baseline(string(c.number)), loc+(0,yOffset), color);
}

// draw gray circle and label
label(baseline("All causes"), (0,labelSpacing/2));
label(baseline(string(allNumber)), (0,-labelSpacing/2));

// draw other circles and labels
for (int i = 0; i < causes.length; ++i)
{

// determine size of a label to see if it will fit in circle
picture p;
unitsize(p, 1inch);
drawLabel(p, causes[i]);
pair labelSize = size(p, true);

{
// draw label outside of circle if it won't fit
}
else
{
// otherwise draw label inside of circle
drawLabel(currentpicture, causes[i], center, white);
}
}

\end{asypicture}
\end{document}


A different plot can be created by making changes to only the lines shown below.

int allNumber = 2597;
real allRadius = 1.25; // Changing this size will effect the relative font size

causes.push(Cause("Heart disease", 611));
causes.push(Cause("Cancer",        585));
causes.push(Cause("Medical error", 251, red));
causes.push(Cause("COPD",          149));
causes.push(Cause("Suicide",        41));
causes.push(Cause("Firearms",       34));
causes.push(Cause("Motor vehicles", 34));

• Looks nice :) Cool work! – Spenhouet Jul 12 '18 at 15:11