File: mathFunctions.py

package info (click to toggle)
fontmath 0.9.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 308 kB
  • sloc: python: 3,736; makefile: 4
file content (134 lines) | stat: -rw-r--r-- 3,168 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
from __future__ import division
import math
import sys

__all__ = [
    "add",
    "addPt",
    "sub",
    "subPt",
    "mul",
    "mulPt",
    "div",
    "divPt",
    "factorAngle",
    "_roundNumber",
]

def add(v1, v2):
    return v1 + v2

def addPt(pt1, pt2):
    return pt1[0] + pt2[0], pt1[1] + pt2[1]

def sub(v1, v2):
    return v1 - v2

def subPt(pt1, pt2):
    return pt1[0] - pt2[0], pt1[1] - pt2[1]

def mul(v, f):
    return v * f

def mulPt(pt1, f):
    (f1, f2) = f
    return pt1[0] * f1, pt1[1] * f2

def div(v, f):
    return v / f

def divPt(pt, f):
    (f1, f2) = f
    return pt[0] / f1, pt[1] / f2

def factorAngle(angle, f, func):
    (f1, f2) = f
    # If both factors are equal, assume a scalar factor and scale the angle as such.
    if f1 == f2:
        return func(angle, f1)
    # Otherwise, scale x and y components separately.
    rangle = math.radians(angle)
    x = math.cos(rangle)
    y = math.sin(rangle)
    return math.degrees(
        math.atan2(
            func(y, f2), func(x, f1)
        )
    )


def round2(number, ndigits=None):
    """
    Implementation of Python 2 built-in round() function.
    Rounds a number to a given precision in decimal digits (default
    0 digits). The result is a floating point number. Values are rounded
    to the closest multiple of 10 to the power minus ndigits; if two
    multiples are equally close, rounding is done away from 0.
    ndigits may be negative.
    See Python 2 documentation:
    https://docs.python.org/2/library/functions.html?highlight=round#round

    This is taken from the to-be-deprecated py23 fuction of fonttools
    """
    import decimal as _decimal

    if ndigits is None:
        ndigits = 0

    if ndigits < 0:
        exponent = 10 ** (-ndigits)
        quotient, remainder = divmod(number, exponent)
        if remainder >= exponent // 2 and number >= 0:
            quotient += 1
        return float(quotient * exponent)
    else:
        exponent = _decimal.Decimal("10") ** (-ndigits)

        d = _decimal.Decimal.from_float(number).quantize(
            exponent, rounding=_decimal.ROUND_HALF_UP
        )

        return float(d)


def setRoundIntegerFunction(func):
    """ Globally set function for rounding floats to integers.

    The function signature must be:

        def func(value: float) -> int
    """
    global _ROUND_INTEGER_FUNC
    _ROUND_INTEGER_FUNC = func


def setRoundFloatFunction(func):
    """ Globally set function for rounding floats within given precision.

    The function signature must be:

        def func(value: float, ndigits: int) -> float
    """
    global _ROUND_FLOAT_FUNC
    _ROUND_FLOAT_FUNC = func


_ROUND_INTEGER_FUNC = round
_ROUND_FLOAT_FUNC = round


def _roundNumber(value, ndigits=None):
    """Round number using the Python 3 built-in round function.

    You can change the default rounding functions using setRoundIntegerFunction
    and/or setRoundFloatFunction.
    """
    if ndigits is not None:
        return _ROUND_FLOAT_FUNC(value, ndigits)
    return _ROUND_INTEGER_FUNC(value)


if __name__ == "__main__":
    import sys
    import doctest
    sys.exit(doctest.testmod().failed)