This file is indexed.

/usr/share/pyshared/pyx/metapost/path.py is in python-pyx 0.12.1-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
# -*- coding: ISO-8859-1 -*-
#
# Copyright (C) 2011 Michael Schindler <m-schindler@users.sourceforge.net>
#
# This file is part of PyX (http://pyx.sourceforge.net/).
#
# PyX is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# PyX is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with PyX; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA

from math import atan2, radians
from pyx import unit, attr, normpath
from pyx import path as pathmodule

from mp_path import mp_endpoint, mp_explicit, mp_given, mp_curl, mp_open, mp_end_cycle, mp_make_choices

# global epsilon (default precision length of metapost, in pt)
_epsilon = 1e-5

def set(epsilon=None):
    global _epsilon
    if epsilon is not None:
        _epsilon = epsilon

################################################################################
# Path knots
################################################################################

class _knot:

    """Internal knot as used in MetaPost (mp.c)"""

    def __init__(self, x_pt, y_pt, ltype, lx_pt, ly_pt, rtype, rx_pt, ry_pt):
        self.x_pt = x_pt
        self.y_pt = y_pt
        self.ltype = ltype
        self.lx_pt = lx_pt
        self.ly_pt = ly_pt
        self.rtype = rtype
        self.rx_pt = rx_pt
        self.ry_pt = ry_pt
        # this is a linked list:
        self.next = self

    def set_left_tension(self, tens):
        self.ly_pt = tens
    def set_right_tension(self, tens):
        self.ry_pt = tens
    def set_left_curl(self, curl):
        self.lx_pt = curl
    def set_right_curl(self, curl):
        self.rx_pt = curl
    set_left_given = set_left_curl
    set_right_given = set_right_curl

    def left_tension(self):
        return self.ly_pt
    def right_tension(self):
        return self.ry_pt
    def left_curl(self):
        return self.lx_pt
    def right_curl(self):
        return self.rx_pt
    left_given = left_curl
    right_given = right_curl

    def linked_len(self):
        """returns the length of a circularly linked list of knots"""
        n = 1
        p = self.next
        while not p is self:
            n += 1
            p = p.next
        return n

    def __repr__(self):
        result = ""
        # left
        if self.ltype == mp_endpoint:
            pass
        elif self.ltype == mp_explicit:
            result += "{explicit %s %s}" % (self.lx_pt, self.ly_pt)
        elif self.ltype == mp_given:
            result += "{given %g tens %g}" % (self.lx_pt, self.ly_pt)
        elif self.ltype == mp_curl:
            result += "{curl %g tens %g}" % (self.lx_pt, self.ly_pt)
        elif self.ltype == mp_open:
            result += "{open tens %g}" % (self.ly_pt)
        elif self.ltype == mp_end_cycle:
            result += "{cycle tens %g}" % (self.ly_pt)
        result += "(%g %g)" % (self.x_pt, self.y_pt)
        # right
        if self.rtype == mp_endpoint:
            pass
        elif self.rtype == mp_explicit:
            result += "{explicit %g %g}" % (self.rx_pt, self.ry_pt)
        elif self.rtype == mp_given:
            result += "{given %g tens %g}" % (self.rx_pt, self.ry_pt)
        elif self.rtype == mp_curl:
            result += "{curl %g tens %g}" % (self.rx_pt, self.ry_pt)
        elif self.rtype == mp_open:
            result += "{open tens %g}" % (self.ry_pt)
        elif self.rtype == mp_end_cycle:
            result += "{cycle tens %g}" % (self.ry_pt)
        return result

class beginknot_pt(_knot):

    """A knot which interrupts a path, or which allows to continue it with a straight line"""

    def __init__(self, x_pt, y_pt, curl=1, angle=None):
        if angle is None:
            type, value = mp_curl, curl
        else:
            type, value = mp_given, angle
        # tensions are modified by the adjacent curve, but default is 1
        _knot.__init__(self, x_pt, y_pt, mp_endpoint, None, None, type, value, 1)

class beginknot(beginknot_pt):

    def __init__(self, x, y, curl=1, angle=None):
        if not (angle is None):
            angle = radians(angle)
        beginknot_pt.__init__(self, unit.topt(x), unit.topt(y), curl, angle)

startknot = beginknot

class endknot_pt(_knot):

    """A knot which interrupts a path, or which allows to continue it with a straight line"""

    def __init__(self, x_pt, y_pt, curl=1, angle=None):
        if angle is None:
            type, value = mp_curl, curl
        else:
            type, value = mp_given, angle
        # tensions are modified by the adjacent curve, but default is 1
        _knot.__init__(self, x_pt, y_pt, type, value, 1, mp_endpoint, None, None)

class endknot(endknot_pt):

    def __init__(self, x, y, curl=1, angle=None):
        if not (angle is None):
            angle = radians(angle)
        endknot_pt.__init__(self, unit.topt(x), unit.topt(y), curl, angle)

class smoothknot_pt(_knot):

    """A knot with continous tangent and "mock" curvature."""

    def __init__(self, x_pt, y_pt):
        # tensions are modified by the adjacent curve, but default is 1
        _knot.__init__(self, x_pt, y_pt, mp_open, None, 1, mp_open, None, 1)

class smoothknot(smoothknot_pt):

    def __init__(self, x, y):
        smoothknot_pt.__init__(self, unit.topt(x), unit.topt(y))

knot = smoothknot

class roughknot_pt(_knot):

    """A knot with noncontinous tangent."""

    def __init__(self, x_pt, y_pt, lcurl=1, rcurl=None, langle=None, rangle=None):
        """Specify either the relative curvatures, or tangent angles left (l)
        or right (r) of the point."""
        if langle is None:
            ltype, lvalue = mp_curl, lcurl
        else:
            ltype, lvalue = mp_given, langle
        if rcurl is not None:
            rtype, rvalue = mp_curl, rcurl
        elif rangle is not None:
            rtype, rvalue = mp_given, rangle
        else:
            rtype, rvalue = ltype, lvalue
        # tensions are modified by the adjacent curve, but default is 1
        _knot.__init__(self, x_pt, y_pt, ltype, lvalue, 1, rtype, rvalue, 1)

class roughknot(roughknot_pt):

    def __init__(self, x, y, lcurl=1, rcurl=None, langle=None, rangle=None):
        if langle is not None:
            langle = radians(langle)
        if rangle is not None:
            rangle = radians(rangle)
        roughknot_pt.__init__(self, unit.topt(x), unit.topt(y), lcurl, rcurl, langle, rangle)

################################################################################
# Path links
################################################################################

class _link:
    def set_knots(self, left_knot, right_knot):
        """Sets the internal properties of the metapost knots"""
        pass

class line(_link):

    """A straight line"""

    def __init__(self, keepangles=False):
        """The option keepangles will guarantee a continuous tangent. The
        curvature may become discontinuous, however"""
        self.keepangles = keepangles

    def set_knots(self, left_knot, right_knot):
        left_knot.rtype = mp_endpoint
        right_knot.ltype = mp_endpoint
        left_knot.rx_pt, left_knot.ry_pt = None, None
        right_knot.lx_pt, right_knot.ly_pt = None, None
        if self.keepangles:
            angle = atan2(right_knot.y_pt-left_knot.y_pt, right_knot.x_pt-left_knot.x_pt)
            left_knot.ltype = mp_given
            left_knot.set_left_given(angle)
            right_knot.rtype = mp_given
            right_knot.set_right_given(angle)


class controlcurve_pt(_link):

    """A cubic Bezier curve which has its control points explicity set"""

    def __init__(self, lcontrol_pt, rcontrol_pt):
        """The control points at the beginning (l) and the end (r) must be
        coordinate pairs"""
        self.lcontrol_pt = lcontrol_pt
        self.rcontrol_pt = rcontrol_pt

    def set_knots(self, left_knot, right_knot):
        left_knot.rtype = mp_explicit
        right_knot.ltype = mp_explicit
        left_knot.rx_pt, left_knot.ry_pt = self.lcontrol_pt
        right_knot.lx_pt, right_knot.ly_pt = self.rcontrol_pt

class controlcurve(controlcurve_pt):

    def __init__(self, lcontrol, rcontrol):
        controlcurve_pt.__init__(self, (unit.topt(lcontrol[0]), unit.topt(lcontrol[1])),
                                       (unit.topt(rcontrol[0]), unit.topt(rcontrol[1])))


class tensioncurve(_link):

    """A yet unspecified cubic Bezier curve"""

    def __init__(self, ltension=1, latleast=False, rtension=None, ratleast=None):
        """The tension parameters indicate the tensions at the beginning (l)
        and the end (r) of the curve. Set the parameters (l/r)atleast to True
        if you want to avoid inflection points."""
        if rtension is None:
            rtension = ltension
        if ratleast is None:
            ratleast = latleast
        # make sure that tension >= 0.75 (p. 9 mpman.pdf)
        self.ltension = max(0.75, abs(ltension))
        self.rtension = max(0.75, abs(rtension))
        if latleast:
            self.ltension = -self.ltension
        if ratleast:
            self.rtension = -self.rtension

    def set_knots(self, left_knot, right_knot):
        if left_knot.rtype <= mp_explicit or right_knot.ltype <= mp_explicit:
            raise Exception("metapost curve with given tension cannot have explicit knots")
        left_knot.set_right_tension(self.ltension)
        right_knot.set_left_tension(self.rtension)

curve = tensioncurve


################################################################################
# Path creation class
################################################################################

class path(pathmodule.path):

    """A MetaPost-like path, which finds an optimal way through given points.

    At points, you can either specify a given tangent direction (angle in
    degrees) or a certain "curlyness" (relative to the curvature at the other
    end of a curve), or nothing. In the latter case, both the tangent and the
    "mock" curvature (an approximation to the real curvature, introduced by
    J.D. Hobby in MetaPost) will be continuous.

    The shape of the cubic Bezier curves between two points is controlled by
    its "tension", unless you choose to set the control points manually."""

    def __init__(self, elems, epsilon=None):
        """elems should contain metapost knots or links"""
        if epsilon is None:
            epsilon = _epsilon
        knots = []
        is_closed = True
        for i, elem in enumerate(elems):
            if isinstance(elem, _link):
                elem.set_knots(elems[i-1], elems[(i+1)%len(elems)])
            elif isinstance(elem, _knot):
                knots.append(elem)
                if elem.ltype == mp_endpoint or elem.rtype == mp_endpoint:
                    is_closed = False

        # link the knots among each other
        for i in range(len(knots)):
            knots[i-1].next = knots[i]

        # determine the control points
        mp_make_choices(knots[0], epsilon)

        pathmodule.path.__init__(self)
        # build up the path
        do_moveto = True
        do_lineto = False
        do_curveto = False
        prev = None
        for i, elem in enumerate(elems):
            if isinstance(elem, _link):
                do_moveto = False
                if isinstance(elem, line):
                    do_lineto, do_curveto = True, False
                else:
                    do_lineto, do_curveto = False, True
            elif isinstance(elem, _knot):
                if do_moveto:
                    self.append(pathmodule.moveto_pt(elem.x_pt, elem.y_pt))
                if do_lineto:
                    self.append(pathmodule.lineto_pt(elem.x_pt, elem.y_pt))
                elif do_curveto:
                    self.append(pathmodule.curveto_pt(prev.rx_pt, prev.ry_pt, elem.lx_pt, elem.ly_pt, elem.x_pt, elem.y_pt))
                do_moveto = True
                do_lineto = False
                do_curveto = False
                prev = elem

        # close the path if necessary
        if knots[0].ltype == mp_explicit:
            elem = knots[0]
            if do_lineto and is_closed:
                self.append(pathmodule.closepath())
            elif do_curveto:
                self.append(pathmodule.curveto_pt(prev.rx_pt, prev.ry_pt, elem.lx_pt, elem.ly_pt, elem.x_pt, elem.y_pt))
                if is_closed:
                    self.append(pathmodule.closepath())