TurksHead   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 91
Duplicated Lines 0 %

Importance

Changes 9
Bugs 0 Features 0
Metric Value
dl 0
loc 91
rs 10
c 9
b 0
f 0
wmc 10

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __init__() 0 16 1
A line_width() 0 6 1
A outer_radius() 0 6 1
A p_prime() 0 6 1
A q_prime() 0 6 1
A q() 0 6 1
A d() 0 6 1
A inner_radius() 0 6 1
A p() 0 6 1
A draw() 0 6 1
1
# coding: utf8
2
3
# Copyright 2013-2015 Vincent Jacques <[email protected]>
4
5
"""
6
.. class:: Colorer
7
8
    Objects passed as the ``colorer`` argument of :class:`.TurksHead` must implement this interface.
9
    More precisely, they must implement **one** of the following methods:
10
11
    .. py:method:: compute_color_hsv(knot, k, theta, altitude):
12
13
        Return a tuple ``(h, s, v)`` of the color to be applied to the ``k``-th string of the ``knot``,
14
        at angle ``theta``, at the given ``altitude``.
15
16
        ``h`` must be between 0 and 360
17
        ``s`` and ``v`` must be between 0 and 1.
18
19
        :param knot: the :class:`.TurksHead` instance.
20
        :param k: the index of the current string. Between 0 and ``knot.d``.
21
        :param theta: the angle on the current string. Between 0 and ``2 * knot.q_prime * math.pi``.
22
        :param altitude: the altitude of the string at this point. Between -1 and 1.
23
24
    .. py:method:: compute_color_rgb(knot, k, theta, altitude):
25
26
        Return a tuple ``(r, g, b)`` of the color to be applied to the ``k``-th string of the ``knot``,
27
        at angle ``theta``, at the given ``altitude``.
28
29
        ``r``, ``g`` and ``b`` must be between 0 and 1.
30
31
        :param knot: the :class:`.TurksHead` instance.
32
        :param k: the index of the current string. Between 0 and ``knot.d``.
33
        :param theta: the angle on the current string. Between 0 and ``2 * knot.q_prime * math.pi``.
34
        :param altitude: the altitude of the string at this point. Between -1 and 1.
35
"""
36
37
import collections
38
import math
39
import unittest
40
41
import cairo
42
43
from .color import hsv_to_rgb
44
from .knot import Knot
45
from .knot.knot import String, Segment, End, Bridge, Tunnel
46
from ._turkshead import Drawer
47
48
49
class DefaultColorer(object):
50
    """
51
    The :class:`Colorer` used when you don't provide one explicitly to :class:`.TurksHead`.
52
53
    It uses one color per string (spread on the spectrum) and makes it darker when the string goes down.
54
    """
55
    def compute_color_hsv(self, knot, k, theta, altitude):
56
        # @todo Could we (automatically) add this code to the generated doc?
57
        h = k * 360. / knot.d
58
        s = 0.5
59
        v = 0.5 + altitude / 2
60
        return h, s, v
61
62
63
class TurksHead(object):
64
    """
65
    Turk's head knot objects.
66
67
    :param bights: the number of times the string touches the outised of the knot.
68
    :param leads: the number of times the string turns around the center.
69
    :param inner: the radius of the empty area inside the knot.
70
    :param outer: the radius of the knot.
71
    :param line: the width of the string.
72
    :param colorer: a :class:`.Colorer` instance. If ``None`` or not provided, a :class:`.DefaultColorer` will be used.
73
    """
74
    def __init__(self, bights, leads, inner, outer, line, colorer=None):
75
        knot = Knot(bights, leads)
76
77
        self.__p = knot.p
78
        self.__q = knot.q
79
        self.__d = knot.d
80
        self.__p_prime = knot.p_prime
81
        self.__q_prime = knot.q_prime
82
        self.__inner_radius = inner
83
        self.__outer_radius = outer
84
        self.__line_width = line
85
86
        self.__drawer = Drawer(
87
            knot=self,
88
            colorer=colorer or DefaultColorer(),
89
            strings=knot.strings,
90
        )
91
92
    @property
93
    def p(self):
94
        """
95
        The number of bights.
96
        """
97
        return self.__p
98
99
    @property
100
    def q(self):
101
        """
102
        The number of leads.
103
        """
104
        return self.__q
105
106
    @property
107
    def d(self):
108
        """
109
        The greatest common divisor of :attr:`~.TurksHead.p` and :attr:`~.TurksHead.q`.
110
        """
111
        return self.__d
112
113
    @property
114
    def p_prime(self):
115
        """
116
        :attr:`~.TurksHead.p` divided by :attr:`~.TurksHead.d`.
117
        """
118
        return self.__p_prime
119
120
    @property
121
    def q_prime(self):
122
        """
123
        :attr:`~.TurksHead.q` divided by :attr:`~.TurksHead.d`.
124
        """
125
        return self.__q_prime
126
127
    @property
128
    def inner_radius(self):
129
        """
130
        The radius of the empty area inside the knot.
131
        """
132
        return self.__inner_radius
133
134
    @property
135
    def outer_radius(self):
136
        """
137
        The radius of the knot.
138
        """
139
        return self.__outer_radius
140
141
    @property
142
    def line_width(self):
143
        """
144
        The width of the string.
145
        """
146
        return self.__line_width
147
148
    def draw(self, ctx):
149
        """
150
        Draw the knot on a :class:`cairo.Context`.
151
        See `documentation of PyCairo <http://www.cairographics.org/documentation/pycairo/2/reference/context.html>`__.
152
        """
153
        self.__drawer.draw(ctx)
154