├── .gitignore ├── LICENSE ├── MANIFEST.in ├── README.rst ├── Tree ├── __init__.py ├── cli.py ├── core.py ├── draw.py └── utils.py ├── docs ├── Makefile ├── cli.rst ├── conf.py ├── examples.rst ├── index.rst ├── installation.rst └── reference │ ├── core.rst │ ├── draw.rst │ └── index.rst ├── images └── example.png ├── requirements.txt └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | docs/_build/ 3 | dist 4 | build 5 | test.py 6 | FractalTree.egg-info 7 | Tree.egg-info 8 | launch.json 9 | *.png 10 | *.sh 11 | Pipfile 12 | Pipfile.lock 13 | .vscode/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Pixelwar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.rst -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | PyTree 2 | ====== 3 | .. image:: https://img.shields.io/pypi/v/tree.svg?style=flat-square 4 | :target: https://pypi.python.org/pypi/Tree 5 | 6 | .. image:: https://img.shields.io/pypi/l/Tree.svg?style=flat-square 7 | :target: https://github.com/PixelwarStudio/PyTree/blob/master/LICENSE 8 | 9 | Python package, which you can use to generate and drawing trees, realistic or fractal ones. 10 | 11 | Usage 12 | ----- 13 | .. code-block:: bash 14 | 15 | $ pip install Tree 16 | 17 | .. code-block:: python 18 | 19 | from math import pi, radians as rad 20 | from Tree.core import Tree 21 | from PIL import Image 22 | 23 | branches = ( 24 | (.5, rad(-30)), 25 | (.6, rad(30)), 26 | (.4, rad(60)) 27 | ) 28 | 29 | def main(): 30 | tree = Tree( 31 | pos=(0, 0, 0, -500), 32 | branches=branches 33 | ) 34 | 35 | # Let the tree grow 36 | tree.grow(10) 37 | 38 | # Move the tree in the right position, so that the tree is completly in the image 39 | tree.move_in_rectangle() 40 | 41 | im = Image.new("RGB", tree.get_size(), (239, 239, 239)) 42 | tree.draw_on(im, (85, 25, 0, 128, 53, 21), (0, 62, 21), 10) 43 | im.show() 44 | 45 | if __name__ == '__main__': 46 | main() 47 | 48 | .. image:: https://raw.githubusercontent.com/PixelwarStudio/PyTree/master/images/example.png 49 | 50 | Documentation 51 | ------------- 52 | The documentation is hosted on Readthedocs_. 53 | 54 | .. _Readthedocs: http://pytree.readthedocs.io/en/latest/ -------------------------------------------------------------------------------- /Tree/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Package for creating and drawing trees. 3 | """ 4 | __version__ = "v0.2.4" 5 | __author__ = "Pixelwar" 6 | -------------------------------------------------------------------------------- /Tree/cli.py: -------------------------------------------------------------------------------- 1 | from math import radians 2 | 3 | import click 4 | 5 | from PIL import Image 6 | import svgwrite 7 | 8 | from Tree.core import Tree 9 | 10 | def get_format(path): 11 | pos = path.find(".") 12 | 13 | if pos == -1: 14 | return False 15 | return path[pos+1:] 16 | 17 | @click.command() 18 | @click.option("--length", "-l", help="The start length of tree.", type=float, default=300) 19 | @click.option("--branches", "-b", help="Add a branch with a scale and a angle.", multiple=True, type=(float, int), default=[[.5, 45], [.5, -45]]) 20 | @click.option("--sigma", "-s", help="Add randomness to scale and angle.", nargs=2, type=float, default=(0, 0)) 21 | @click.option("--age", "-a", help="Indicates how many time the tree should be iterated.",type=int, default=5) 22 | @click.option("--path", "-p", help="The path for saving the tree. Multiple formats supported e.g. svg.", default=None) 23 | @click.option("--show", help="Shows a image of the tree.", is_flag=True) 24 | @click.option("--stem_color1", "-sc1", help="The stem start color given as r g b", nargs=3, type=int, default=(255, 0, 255)) 25 | @click.option("--stem_color2", "-sc2", help="The stem end color given as r g b", nargs=3, type=int, default=(255, 0, 255)) 26 | @click.option("--leaf_color", "-lc", help="The leaf color given as r g b", nargs=3, type=int, default=(255, 255, 255)) 27 | @click.option("--thickness", "-t", help="The start width of the first branch.", type=int, default=5) 28 | 29 | def create_tree(length, branches, sigma, age, path, show, stem_color1, stem_color2, leaf_color, thickness): 30 | stem_color = stem_color1+stem_color2 31 | options = [ 32 | stem_color, 33 | leaf_color, 34 | thickness 35 | ] 36 | 37 | #Convert angles to radians 38 | branches = [[branch[0], radians(branch[1])] for branch in branches] 39 | 40 | tree = Tree((0, 0, 0, -length), branches, sigma) 41 | tree.grow(times=age) 42 | tree.move_in_rectangle() 43 | 44 | form = get_format(path) if path is not None else None 45 | 46 | if show or form not in ("svg", None): 47 | im = Image.new("RGB", tree.get_size()) 48 | tree.draw_on(im, *options) 49 | 50 | if form == "svg": 51 | svg = svgwrite.Drawing(path) 52 | tree.draw_on(svg, *options) 53 | svg.save() 54 | 55 | if form not in ("svg", None): 56 | im.save(path) 57 | 58 | if show: 59 | im.show() 60 | 61 | if __name__ == "__main__": 62 | create_tree() 63 | -------------------------------------------------------------------------------- /Tree/core.py: -------------------------------------------------------------------------------- 1 | """ 2 | Module for creating trees 3 | """ 4 | from math import pi, log, sqrt 5 | from random import gauss 6 | from Tree.utils import Node 7 | from Tree.draw import SUPPORTED_CANVAS 8 | 9 | class Tree: 10 | """The standard tree.""" 11 | def __init__(self, pos=(0, 0, 0, -100), branches=None, sigma=(0, 0)): 12 | """The contructor. 13 | 14 | Args: 15 | pos (tupel): A tupel, holding the start and end point of the tree. (x1, y1, x2, y2) 16 | branches (tupel/array): Holding array/s with scale and angle for every branch. 17 | sigma (tuple): Holding the branch and angle sigma. e.g.(0.1, 0.2) 18 | """ 19 | self.pos = pos 20 | self.length = sqrt((pos[2]-pos[0])**2+(pos[3]-pos[1])**2) 21 | self.branches = branches 22 | self.sigma = sigma 23 | 24 | self.comp = len(self.branches) 25 | self.age = 0 26 | 27 | self.nodes = [ 28 | [Node(pos[2:])] 29 | ] 30 | 31 | def get_rectangle(self): 32 | """Gets the coordinates of the rectangle, in which the tree can be put. 33 | 34 | Returns: 35 | tupel: (x1, y1, x2, y2) 36 | """ 37 | rec = [self.pos[0], self.pos[1]]*2 38 | for age in self.nodes: 39 | for node in age: 40 | # Check max/min for x/y coords 41 | for i in range(2): 42 | if rec[0+i] > node.pos[i]: 43 | rec[0+i] = node.pos[i] 44 | elif rec[2+i] < node.pos[i]: 45 | rec[2+i] = node.pos[i] 46 | return tuple(rec) 47 | 48 | def get_size(self): 49 | """Get the size of the tree. 50 | 51 | Returns: 52 | tupel: (width, height) 53 | """ 54 | rec = self.get_rectangle() 55 | return (int(rec[2]-rec[0]), int(rec[3]-rec[1])) 56 | 57 | def get_branch_length(self, age=None, pos=0): 58 | """Get the length of a branch. 59 | 60 | This method calculates the length of a branch in specific age. 61 | The used formula: length * scale^age. 62 | 63 | Args: 64 | age (int): The age, for which you want to know the branch length. 65 | Returns: 66 | float: The length of the branch 67 | """ 68 | if age is None: 69 | age = self.age 70 | 71 | return self.length * pow(self.branches[pos][0], age) 72 | 73 | def get_steps_branch_len(self, length): 74 | """Get, how much steps will needed for a given branch length. 75 | 76 | Returns: 77 | float: The age the tree must achieve to reach the given branch length. 78 | """ 79 | return log(length/self.length, min(self.branches[0][0])) 80 | 81 | def get_node_sum(self, age=None): 82 | """Get sum of all branches in the tree. 83 | 84 | Returns: 85 | int: The sum of all nodes grown until the age. 86 | """ 87 | if age is None: 88 | age = self.age 89 | 90 | return age if self.comp == 1 else int((pow(self.comp, age+1) - 1) / (self.comp - 1)) 91 | 92 | def get_node_age_sum(self, age=None): 93 | """Get the sum of branches grown in an specific age. 94 | 95 | Returns: 96 | int: The sum of all nodes grown in an age. 97 | """ 98 | if age is None: 99 | age = self.age 100 | 101 | return pow(self.comp, age) 102 | 103 | def get_nodes(self): 104 | """Get the tree nodes as list. 105 | 106 | Returns: 107 | list: A 2d-list holding the grown nodes coordinates as tupel for every age. 108 | Example: 109 | [ 110 | [(10, 40)], 111 | [(20, 80), (100, 30)], 112 | [(100, 90), (120, 40), ...], 113 | ... 114 | ] 115 | """ 116 | nodes = [] 117 | for age, level in enumerate(self.nodes): 118 | nodes.append([]) 119 | for node in level: 120 | nodes[age].append(node.get_tuple()) 121 | return nodes 122 | 123 | def get_branches(self): 124 | """Get the tree branches as list. 125 | 126 | Returns: 127 | list: A 2d-list holding the grown branches coordinates as tupel for every age. 128 | Example: 129 | [ 130 | [(10, 40, 90, 30)], 131 | [(90, 30, 100, 40), (90, 30, 300, 60)], 132 | [(100, 40, 120, 70), (100, 40, 150, 90), ...], 133 | ... 134 | ] 135 | """ 136 | branches = [] 137 | for age, level in enumerate(self.nodes): 138 | branches.append([]) 139 | for n, node in enumerate(level): 140 | if age == 0: 141 | p_node = Node(self.pos[:2]) 142 | else: 143 | p_node = self._get_node_parent(age-1, n) 144 | branches[age].append(p_node.get_tuple() + node.get_tuple()) 145 | 146 | return branches 147 | 148 | def move(self, delta): 149 | """Move the tree. 150 | 151 | Args: 152 | delta (tupel): The adjustment of the position. 153 | """ 154 | pos = self.pos 155 | self.pos = (pos[0]+delta[0], pos[1]+delta[1], pos[2]+delta[0], pos[3]+delta[1]) 156 | 157 | # Move all nodes 158 | for age in self.nodes: 159 | for node in age: 160 | node.move(delta) 161 | 162 | def move_in_rectangle(self): 163 | """Move the tree so that the tree fits in the rectangle.""" 164 | rec = self.get_rectangle() 165 | self.move((-rec[0], -rec[1])) 166 | 167 | def grow(self, times=1): 168 | """Let the tree grow. 169 | 170 | Args: 171 | times (integer): Indicate how many times the tree will grow. 172 | """ 173 | self.nodes.append([]) 174 | 175 | for n, node in enumerate(self.nodes[self.age]): 176 | if self.age == 0: 177 | p_node = Node(self.pos[:2]) 178 | else: 179 | p_node = self._get_node_parent(self.age-1, n) 180 | angle = node.get_node_angle(p_node) 181 | for i in range(self.comp): 182 | tot_angle = self.__get_total_angle(angle, i) 183 | length = self.__get_total_length(self.age+1, i) 184 | self.nodes[self.age+1].append(node.make_new_node(length, tot_angle)) 185 | 186 | self.age += 1 187 | 188 | if times > 1: 189 | self.grow(times-1) 190 | 191 | def draw_on(self, canvas, stem_color, leaf_color, thickness, ages=None): 192 | """Draw the tree on a canvas. 193 | 194 | Args: 195 | canvas (object): The canvas, you want to draw the tree on. Supported canvases: svgwrite.Drawing and PIL.Image (You can also add your custom libraries.) 196 | stem_color (tupel): Color or gradient for the stem of the tree. 197 | leaf_color (tupel): Color for the leaf (= the color for last iteration). 198 | thickness (int): The start thickness of the tree. 199 | """ 200 | if canvas.__module__ in SUPPORTED_CANVAS: 201 | drawer = SUPPORTED_CANVAS[canvas.__module__] 202 | drawer(self, canvas, stem_color, leaf_color, thickness, ages).draw() 203 | 204 | def __get_total_angle(self, angle, pos): 205 | """Get the total angle.""" 206 | tot_angle = angle - self.branches[pos][1] 207 | if self.sigma[1] != 0: 208 | tot_angle += gauss(0, self.sigma[1]) * pi 209 | return tot_angle 210 | 211 | def __get_total_length(self, age, pos): 212 | length = self.get_branch_length(age, pos) 213 | if self.sigma[0] != 0: 214 | length *= (1+gauss(0, self.sigma[0])) 215 | return length 216 | 217 | def _get_node_parent(self, age, pos): 218 | """Get the parent node of node, whch is located in tree's node list. 219 | 220 | Returns: 221 | object: The parent node. 222 | """ 223 | return self.nodes[age][int(pos / self.comp)] 224 | 225 | def generate_branches(scales=None, angles=None, shift_angle=0): 226 | """Generates branches with alternative system. 227 | 228 | Args: 229 | scales (tuple/array): Indicating how the branch/es length/es develop/s from age to age. 230 | angles (tuple/array): Holding the branch and shift angle in radians. 231 | shift_angle (float): Holding the rotation angle for all branches. 232 | 233 | Returns: 234 | branches (2d-array): A array consists of arrays holding scale and angle for every branch. 235 | """ 236 | branches = [] 237 | for pos, scale in enumerate(scales): 238 | angle = -sum(angles)/2 + sum(angles[:pos]) + shift_angle 239 | branches.append([scale, angle]) 240 | return branches 241 | -------------------------------------------------------------------------------- /Tree/draw.py: -------------------------------------------------------------------------------- 1 | """ 2 | Module for drawing trees. 3 | """ 4 | from PIL import ImageDraw 5 | import svgwrite 6 | from Tree.utils import convert_color 7 | 8 | class Drawer(object): 9 | """A generic class for drawing tree on acanvas.""" 10 | def __init__(self, tree, canvas, stem_color=(255, 255, 255), leaf_color=(230, 120, 34), thickness=1, ages=None): 11 | """Constructor of drawer. 12 | 13 | Args: 14 | tree (object): The tree, which should drawn on canvas. 15 | canvas (object): The canvas for drawing the tree. 16 | stem_color (tupel): Color or gradient for the steam of the tree. 17 | leaf_color (tupel): Color for the leaf (= the color for last iteration). 18 | thickness (int): The start thickness of the tree. 19 | ages (array): Contains the ages you want to draw. 20 | 21 | Returns: 22 | int: The thickness of the branch/es 23 | """ 24 | self.canvas = canvas 25 | self.tree = tree 26 | self.stem_color = stem_color 27 | self.leaf_color = leaf_color 28 | self.thickness = thickness 29 | self.ages = range(tree.age+1) if ages is None else ages 30 | 31 | def _get_thickness(self, age): 32 | """Get the thickness depending on age. 33 | 34 | Args: 35 | age (int): The age of the branch/es 36 | 37 | Returns: 38 | int: The thickness of the branch/es 39 | """ 40 | return int((self.thickness*5)/(age+5)) 41 | 42 | def _get_color(self, age): 43 | """Get the fill color depending on age. 44 | 45 | Args: 46 | age (int): The age of the branch/es 47 | 48 | Returns: 49 | tuple: (r, g, b) 50 | """ 51 | if age == self.tree.age: 52 | return self.leaf_color 53 | color = self.stem_color 54 | tree = self.tree 55 | 56 | if len(color) == 3: 57 | return color 58 | 59 | diff = [color[i+3]-color[i] for i in range(3)] 60 | per_age = [diff[i]/(tree.age-1) for i in range(3)] 61 | 62 | return tuple([int(color[i]+per_age[i]*age) for i in range(3)]) 63 | 64 | def _draw_branch(self, branch, color, thickness, age): 65 | """Placeholder for specific draw methods for a branch. 66 | 67 | Args: 68 | branch (tupel): The coordinates of the branch. 69 | color (tupel): The color of the branch. 70 | thickness (int): The thickness of the branch. 71 | age (int): The age of the tree the branch is drawn. 72 | """ 73 | pass 74 | 75 | def draw(self): 76 | """Draws the tree. 77 | 78 | Args: 79 | ages (array): Contains the ages you want to draw. 80 | """ 81 | for age, level in enumerate(self.tree.get_branches()): 82 | if age in self.ages: 83 | thickness = self._get_thickness(age) 84 | color = self._get_color(age) 85 | for branch in level: 86 | self._draw_branch(branch, color, thickness, age) 87 | 88 | class PilDrawer(Drawer): 89 | """A drawer class for drawing on PIL/Pillow images.""" 90 | def _draw_branch(self, branch, color, thickness, age): 91 | ImageDraw.Draw(self.canvas).line(branch, color, thickness) 92 | 93 | class SvgDrawer(Drawer): 94 | """A drawer class for drawing on svg documents. 95 | 96 | Attributes: 97 | group (list): Saves the groups created for every age. 98 | """ 99 | def __init__(self, tree, canvas, color=(255, 255, 255), thickness=1): 100 | super(SvgDrawer, self).__init__(tree, canvas, color, thickness) 101 | self.group = [] 102 | 103 | def _draw_branch(self, branch, color, thickness, age): 104 | color = convert_color(color) 105 | self.group[age].add( 106 | self.canvas.line( 107 | start=branch[:2], 108 | end=branch[2:], 109 | stroke=color, 110 | stroke_width=thickness 111 | ) 112 | ) 113 | 114 | def draw(self): 115 | self.group = [] 116 | for _ in self.ages: 117 | self.group.append(self.canvas.add(svgwrite.container.Group())) 118 | Drawer.draw(self) 119 | 120 | SUPPORTED_CANVAS = { 121 | "PIL.Image": PilDrawer, 122 | "svgwrite.drawing": SvgDrawer 123 | } 124 | -------------------------------------------------------------------------------- /Tree/utils.py: -------------------------------------------------------------------------------- 1 | """ 2 | Helper module. 3 | """ 4 | from math import atan2, cos, sin, pi, sqrt 5 | 6 | def convert_color(color): 7 | """Convert color tupel(r, g, b) to string("rgb({r}, {g}, {b}"). 8 | 9 | Args: 10 | color (tupel): RGB color. e.g. (134, 8, 45) 11 | 12 | Returns: 13 | string: "rgb({r}, {g}, {b}" 14 | """ 15 | return "rgb({}, {}, {})".format(color[0], color[1], color[2]) 16 | 17 | class Node(object): 18 | """A node. 19 | 20 | Attributes: 21 | pos (tupel): The position of the node. (x, y) 22 | """ 23 | def __init__(self, pos): 24 | self.pos = pos 25 | 26 | def make_new_node(self, distance, angle): 27 | """Make a new node from an existing one. 28 | 29 | This method creates a new node with a distance and angle given. 30 | The position of the new node is calculated with: 31 | x2 = cos(-angle)*distance+x1 32 | y2 = sin(-angle)*distance+y1 33 | 34 | Args: 35 | distance (float): The distance of the original node to the new node. 36 | angle (rad): The angle between the old and new node, relative to the horizont. 37 | 38 | Returns: 39 | object: The node with calculated poistion. 40 | """ 41 | return Node((cos(-angle)*distance+self.pos[0], 42 | sin(-angle)*distance+self.pos[1])) 43 | 44 | def get_node_angle(self, node): 45 | """Get the angle beetween 2 nodes relative to the horizont. 46 | 47 | Args: 48 | node (object): The other node. 49 | 50 | Returns: 51 | rad: The angle 52 | """ 53 | return atan2(self.pos[0]-node.pos[0], self.pos[1]-node.pos[1]) - pi / 2 54 | 55 | def get_distance(self, node): 56 | """Get the distance beetween 2 nodes 57 | 58 | Args: 59 | node (object): The other node. 60 | """ 61 | delta = (node.pos[0]-self.pos[0], node.pos[1]-self.pos[1]) 62 | return sqrt(delta[0]**2+delta[1]**2) 63 | 64 | def get_tuple(self): 65 | """Get the position of the node as tuple. 66 | 67 | Returns: 68 | tupel: (x, y) 69 | """ 70 | return self.pos 71 | 72 | def move(self, delta): 73 | """Move the node. 74 | 75 | Args: 76 | delta (tupel): A tupel, holding the adjustment of the position. 77 | """ 78 | self.pos = (self.pos[0]+delta[0], self.pos[1]+delta[1]) 79 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SPHINXPROJ = FractalTree 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -------------------------------------------------------------------------------- /docs/cli.rst: -------------------------------------------------------------------------------- 1 | Commandline 2 | =========== 3 | Usage 4 | ----- 5 | .. code-block:: bash 6 | 7 | tree-cli [OPTIONS] 8 | 9 | 10 | **Options:** 11 | 12 | -l, --length The start length of tree. 13 | -b, --branches Add a branch with a scale and a angle. 14 | -s, --sigma Add randomness to scale and angle. 15 | -a, --age Indicates how many time the tree should be iterated. 16 | -p, --path The path for saving the tree. 17 | -c1, --color1 The starting color given as r g b. 18 | -c2, --color2 The end color given as r g b. 19 | -t, --thickness The start width of the first branch. 20 | --help Show this message and exit. 21 | --show Shows a image of the tree. 22 | 23 | 24 | Examples 25 | -------- -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # FractalTree documentation build configuration file, created by 5 | # sphinx-quickstart on Mon Apr 17 18:59:17 2017. 6 | # 7 | # This file is execfile()d with the current directory set to its 8 | # containing dir. 9 | # 10 | # Note that not all possible configuration values are present in this 11 | # autogenerated file. 12 | # 13 | # All configuration values have a default; values that are commented out 14 | # serve to show the default. 15 | 16 | # If extensions (or modules to document with autodoc) are in another directory, 17 | # add these directories to sys.path here. If the directory is relative to the 18 | # documentation root, use os.path.abspath to make it absolute, like shown here. 19 | # 20 | # import os 21 | # import sys 22 | # sys.path.insert(0, os.path.abspath('.')) 23 | import sphinx_rtd_theme 24 | import Tree 25 | 26 | # -- General configuration ------------------------------------------------ 27 | 28 | # If your documentation needs a minimal Sphinx version, state it here. 29 | # 30 | # needs_sphinx = '1.0' 31 | 32 | # Add any Sphinx extension module names here, as strings. They can be 33 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 34 | # ones. 35 | extensions = ['sphinx.ext.autodoc', 36 | 'sphinx.ext.doctest', 37 | 'sphinx.ext.napoleon', 38 | 'sphinx.ext.todo'] 39 | 40 | # Add any paths that contain templates here, relative to this directory. 41 | templates_path = ['_templates'] 42 | 43 | # The suffix(es) of source filenames. 44 | # You can specify multiple suffix as a list of string: 45 | # 46 | # source_suffix = ['.rst', '.md'] 47 | source_suffix = '.rst' 48 | 49 | # The master toctree document. 50 | master_doc = 'index' 51 | 52 | # General information about the project. 53 | project = Tree.__name__ 54 | copyright = "2017, " + Tree.__author__ 55 | author = Tree.__author__ 56 | 57 | # The version info for the project you're documenting, acts as replacement for 58 | # |version| and |release|, also used in various other places throughout the 59 | # built documents. 60 | # 61 | # The short X.Y version. 62 | version = Tree.__version__ 63 | # The full version, including alpha/beta/rc tags. 64 | release = Tree.__version__ 65 | 66 | # The language for content autogenerated by Sphinx. Refer to documentation 67 | # for a list of supported languages. 68 | # 69 | # This is also used if you do content translation via gettext catalogs. 70 | # Usually you set "language" from the command line for these cases. 71 | language = None 72 | 73 | # List of patterns, relative to source directory, that match files and 74 | # directories to ignore when looking for source files. 75 | # This patterns also effect to html_static_path and html_extra_path 76 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 77 | 78 | # The name of the Pygments (syntax highlighting) style to use. 79 | pygments_style = 'sphinx' 80 | 81 | # If true, `todo` and `todoList` produce output, else they produce nothing. 82 | todo_include_todos = True 83 | 84 | 85 | # -- Options for HTML output ---------------------------------------------- 86 | 87 | # The theme to use for HTML and HTML Help pages. See the documentation for 88 | # a list of builtin themes. 89 | # 90 | html_theme = 'sphinx_rtd_theme' 91 | 92 | # Theme options are theme-specific and customize the look and feel of a theme 93 | # further. For a list of options available for each theme, see the 94 | # documentation. 95 | # 96 | # html_theme_options = {} 97 | html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] 98 | 99 | # Add any paths that contain custom static files (such as style sheets) here, 100 | # relative to this directory. They are copied after the builtin static files, 101 | # so a file named "default.css" will overwrite the builtin "default.css". 102 | html_static_path = ['_static'] 103 | 104 | 105 | # -- Options for HTMLHelp output ------------------------------------------ 106 | 107 | # Output file base name for HTML help builder. 108 | htmlhelp_basename = 'FractalTreedoc' 109 | 110 | 111 | # -- Options for LaTeX output --------------------------------------------- 112 | 113 | latex_elements = { 114 | # The paper size ('letterpaper' or 'a4paper'). 115 | # 116 | # 'papersize': 'letterpaper', 117 | 118 | # The font size ('10pt', '11pt' or '12pt'). 119 | # 120 | # 'pointsize': '10pt', 121 | 122 | # Additional stuff for the LaTeX preamble. 123 | # 124 | # 'preamble': '', 125 | 126 | # Latex figure (float) alignment 127 | # 128 | # 'figure_align': 'htbp', 129 | } 130 | 131 | # Grouping the document tree into LaTeX files. List of tuples 132 | # (source start file, target name, title, 133 | # author, documentclass [howto, manual, or own class]). 134 | latex_documents = [ 135 | (master_doc, 'FractalTree.tex', 'FractalTree Documentation', 136 | 'Pixelwar', 'manual'), 137 | ] 138 | 139 | 140 | # -- Options for manual page output --------------------------------------- 141 | 142 | # One entry per manual page. List of tuples 143 | # (source start file, name, description, authors, manual section). 144 | man_pages = [ 145 | (master_doc, 'fractaltree', 'FractalTree Documentation', 146 | [author], 1) 147 | ] 148 | 149 | 150 | # -- Options for Texinfo output ------------------------------------------- 151 | 152 | # Grouping the document tree into Texinfo files. List of tuples 153 | # (source start file, target name, title, author, 154 | # dir menu entry, description, category) 155 | texinfo_documents = [ 156 | (master_doc, 'FractalTree', 'FractalTree Documentation', 157 | author, 'FractalTree', 'One line description of project.', 158 | 'Miscellaneous'), 159 | ] 160 | -------------------------------------------------------------------------------- /docs/examples.rst: -------------------------------------------------------------------------------- 1 | Examples 2 | ======== -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | Welcome to FractalTree's documentation! 2 | ======================================= 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: Table of Contents 7 | 8 | installation.rst 9 | examples.rst 10 | cli.rst 11 | reference/index.rst 12 | -------------------------------------------------------------------------------- /docs/installation.rst: -------------------------------------------------------------------------------- 1 | Installation 2 | ============ 3 | .. code-block:: bash 4 | 5 | pip3 install Tree 6 | 7 | 8 | Development Version 9 | ------------------- 10 | .. code-block:: bash 11 | 12 | git clone https://github.com/PixelwarStudio/PyTree.git 13 | cd PyTree 14 | pip3 install . 15 | -------------------------------------------------------------------------------- /docs/reference/core.rst: -------------------------------------------------------------------------------- 1 | core 2 | ==== 3 | .. autoclass:: Tree.core.Tree 4 | :special-members: 5 | :members: -------------------------------------------------------------------------------- /docs/reference/draw.rst: -------------------------------------------------------------------------------- 1 | draw 2 | **** 3 | .. autoclass:: Tree.draw.Drawer 4 | :special-members: 5 | :members: 6 | .. autoclass:: Tree.draw.PilDrawer 7 | :members: 8 | .. autoclass:: Tree.draw.SvgDrawer 9 | :members: -------------------------------------------------------------------------------- /docs/reference/index.rst: -------------------------------------------------------------------------------- 1 | Reference 2 | ========= 3 | .. toctree:: 4 | :maxdepth: 2 5 | 6 | core 7 | draw -------------------------------------------------------------------------------- /images/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PixelwarStudio/PyTree/314f84c12dd982bd1317994e62549fed806623d3/images/example.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | click==6.7 2 | sphinx_rtd_theme==0.2.4 3 | setuptools==65.5.1 4 | svgwrite==1.1.10 5 | Pillow==4.2.1 6 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | import Tree 3 | 4 | def readme(): 5 | with open("README.rst") as f: 6 | return f.read() 7 | 8 | NAME = Tree.__name__ 9 | VERSION = Tree.__version__ 10 | AUTHOR = Tree.__author__ 11 | DESCRIPTION = "A package for creating and drawing trees" 12 | LONG_DESCRIPTION = readme() 13 | URL = "https://github.com/PixelwarStudio/PyTree" 14 | REQUIRED = [ 15 | "Pillow", 16 | "svgwrite", 17 | "setuptools", 18 | "click" 19 | ] 20 | 21 | setup( 22 | name=NAME, 23 | version=VERSION, 24 | description=DESCRIPTION, 25 | long_description=LONG_DESCRIPTION, 26 | url=URL, 27 | author=AUTHOR, 28 | classifiers=[ 29 | "Development Status :: 4 - Beta", 30 | "Intended Audience :: Developers", 31 | "License :: OSI Approved :: MIT License", 32 | "Programming Language :: Python :: 3.5", 33 | "Topic :: Scientific/Engineering :: Mathematics", 34 | ], 35 | install_requires=REQUIRED, 36 | license="MIT", 37 | packages=["Tree"], 38 | entry_points = { 39 | "console_scripts": ["tree-cli=Tree.cli:create_tree"], 40 | }, 41 | zip_safe=False, 42 | include_package_data=True 43 | ) 44 | --------------------------------------------------------------------------------