Skip to main content

Circle packing algorithm for Python

Project description

PyPi version Python compatibility Build Status Coverage Codacy

circlify

Pure Python implementation of circle packing layout algorithm.

Circles are first arranged via a version of A1.0 by Huang et al (see https://home.mis.u-picardie.fr/~cli/Publis/circle.pdf for details) and then enclosed in a circle created around them using Matoušek-Sharir-Welzl algorithm used in d3js (see https://beta.observablehq.com/@mbostock/miniball, http://www.inf.ethz.ch/personal/emo/PublFiles/SubexLinProg_ALG16_96.pdf, and https://github.com/d3/d3-hierarchy/blob/master/src/pack/enclose.js)

Installation

Using pip:

pip install circlify

or using the source:

git clone git://github.com/elmotec/circlify.git
cd circlify
python setup.py install

The last step may require sudo if you don’t have root access.

Usage

The main function circlify is supported by a small data class circlify.Circle and takes 3 parameters:

  • A list of positive values sorted from largest to smallest.

  • (optional) A target enclosure where the packed circles should fit. It defaults to the unit circle (0, 0, 1).

  • (optional) A boolean indicating if the target enclosure should be appended to the output.

The function returns a list of circlify.Circle objects, each one corresponding to the coordinates and radius of cirlces proportional to the corresponding input value.

Example

>>> from pprint import pprint as pp
>>> import circlify as circ
>>> circles = circ.circlify([19, 17, 13, 11, 7, 5, 3, 2, 1], show_enclosure=True)
>>> pp(circles)
[Circle(x=0.0, y=0.0, r=1.0, level=0, ex=None),
 Circle(x=0.09222041925800777, y=0.8617116738294696, r=0.09068624109026069, level=1, ex={'datum': 1}),
 Circle(x=-0.40283175658099674, y=0.7512387781681531, r=0.12824971207048294, level=1, ex={'datum': 2}),
 Circle(x=0.3252787490004198, y=0.7776370388468007, r=0.15707317711577193, level=1, ex={'datum': 3}),
 Circle(x=0.48296614887228806, y=0.4541723195782383, r=0.20278059970175755, level=1, ex={'datum': 5}),
 Circle(x=-0.6132109517981927, y=0.4490810687795324, r=0.23993324126007678, level=1, ex={'datum': 7}),
 Circle(x=-0.045884607890591435, y=-0.6977206243364218, r=0.3007722353441051, level=1, ex={'datum': 11}),
 Circle(x=-0.04661299415374866, y=0.4678014425767657, r=0.32697389223002427, level=1, ex={'datum': 13}),
 Circle(x=-0.411432317820337, y=-0.13064957525245907, r=0.3739089508053733, level=1, ex={'datum': 17}),
 Circle(x=0.35776879346704843, y=-0.13064957525245907, r=0.39529216048201216, level=1, ex={'datum': 19})]

A simple matplotlib representation. See circlify.bubbles helper function (requires matplotlib):

visualization of circlify circle packing of first 9 prime numbers.

Starting with version 0.10, circlify also handle hierarchical input so that:

>>> from pprint import pprint as pp
>>> import circlify as circ
>>> data = [
        0.05, {'id': 'a2', 'datum': 0.05},
        {'id': 'a0', 'datum': 0.8, 'children': [0.3, 0.2, 0.2, 0.1], },
        {'id': 'a1', 'datum': 0.1, 'children': [
            {'id': 'a1_1', 'datum': 0.05}, {'datum': 0.04}, 0.01],
        },
    ]
>>> circles = circ.circlify(data, show_enclosure=True)
>>> pp(circles)
[Circle(x=0.0, y=0.0, r=1.0, level=0, ex=None),
 Circle(x=-0.565803075997749, y=0.41097786651145324, r=0.18469903125906464, level=1, ex={'datum': 0.05}),
 Circle(x=-0.3385727489559141, y=0.7022188441650276, r=0.18469903125906464, level=1, ex={'id': 'a2', 'datum': 0.05}),
 Circle(x=-0.7387961250362587, y=0.0, r=0.2612038749637415, level=1, ex={'id': 'a1', 'datum': 0.1, 'children': [{'id': 'a1_1', 'datum': 0.05}, {'datum': 0.04}, 0.01]}),
 Circle(x=0.2612038749637414, y=0.0, r=0.7387961250362586, level=1, ex={'id': 'a0', 'datum': 0.8, 'children': [0.3, 0.2, 0.2, 0.1]}),
 Circle(x=-0.7567888163564136, y=0.14087823651338607, r=0.0616618704777984, level=2, ex={'datum': 0.01}),
 Circle(x=-0.8766762590444033, y=0.0, r=0.1233237409555968, level=2, ex={'datum': 0.04}),
 Circle(x=-0.6154723840806618, y=0.0, r=0.13788013400814464, level=2, ex={'id': 'a1_1', 'datum': 0.05}),
 Circle(x=0.6664952237042423, y=0.3369290873460549, r=0.2117455702848763, level=2, ex={'datum': 0.1}),
 Circle(x=-0.11288314691830154, y=-0.230392881357073, r=0.2994534572692975, level=2, ex={'datum': 0.2}),
 Circle(x=0.15631936804871832, y=0.30460197676548245, r=0.2994534572692975, level=2, ex={'datum': 0.2}),
 Circle(x=0.5533243963620484, y=-0.230392881357073, r=0.36675408601105247, level=2, ex={'datum': 0.3})]

A simple matplotlib representation. See circlify.bubbles helper function (requires matplotlib):

visualization of circlify nested circle packing for a hierarchical input.

Note that the area of the circles are proportional to the values passed in input only if the circles are at the same hierarchical level. For instance: circles a1_1 and a2 both have a value of 0.05, yet a1_1 is smaller than a2 because a1_1 is fitted within its parent circle a1 one level below the level of a2. In other words, the level 1 circles a1 and a2 are both proportional to their respective values but a1_1 is proportional to the values on level 2 witin a1.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

circlify-0.12.1.tar.gz (9.6 kB view details)

Uploaded Source

Built Distribution

circlify-0.12.1-py2.py3-none-any.whl (10.0 kB view details)

Uploaded Python 2 Python 3

File details

Details for the file circlify-0.12.1.tar.gz.

File metadata

  • Download URL: circlify-0.12.1.tar.gz
  • Upload date:
  • Size: 9.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.24.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.46.1 CPython/3.8.5

File hashes

Hashes for circlify-0.12.1.tar.gz
Algorithm Hash digest
SHA256 ad6f74be76c7102fcfe567dc9ad6231aca7cd99d0c9b2cf7ea0bccd3da174bc5
MD5 c7ec068e44485cb52563100735798cba
BLAKE2b-256 fe0f472d559f1bd8e57ddcb31f1952d1518952adeec322e61b2a397ba3aa6d8c

See more details on using hashes here.

File details

Details for the file circlify-0.12.1-py2.py3-none-any.whl.

File metadata

  • Download URL: circlify-0.12.1-py2.py3-none-any.whl
  • Upload date:
  • Size: 10.0 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.24.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.46.1 CPython/3.8.5

File hashes

Hashes for circlify-0.12.1-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 b95f2a896f9dcfede72db394b34635a68ac0fc91fca6f26b00b437ec6b04dc20
MD5 1cb2a2ab47506414ced7c0a289bdae08
BLAKE2b-256 c747a44c6940516d90ef81265352481f79ead9cc42f7416a55d5be6e5fd4c267

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page