This file is indexed.

/usr/share/pyshared/pyx/connector.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
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
# -*- encoding: utf-8 -*-
#
#
# Copyright (C) 2003-2006 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


import math
from math import degrees, radians, pi, sin, cos, atan2, tan, hypot, acos, sqrt
import path, unit, mathutils, normpath


#########################
##   helpers
#########################

class connector_pt(normpath.normpath):

    def omitends(self, box1, box2):
        """intersects a path with the boxes' paths"""

        # cut off the start of self
        # XXX how can decoration of this box1.path() be handled?
        sp = self.intersect(box1.path())[0]
        if sp:
            self.normsubpaths = self.split(sp[-1:])[1].normsubpaths

        # cut off the end of self
        sp = self.intersect(box2.path())[0]
        if sp:
            self.normsubpaths = self.split(sp[:1])[0].normsubpaths

    def shortenpath(self, dists):
        """shortens a path by the given distances"""

        # XXX later, this should be done by extended boxes instead of intersecting with circles
        # cut off the start of self
        center = self.atbegin_pt()
        cutpath = path.circle_pt(center[0], center[1], dists[0])
        try:
            cutpath = cutpath.normpath()
        except normpath.NormpathException:
            pass
        else:
            sp = self.intersect(cutpath)[0]
            self.normsubpaths = self.split(sp[-1:])[1].normsubpaths

        # cut off the end of self
        center = self.atend_pt()
        cutpath = path.circle_pt(center[0], center[1], dists[1])
        try:
            cutpath = cutpath.normpath()
        except normpath.NormpathException:
            pass
        else:
            sp = self.intersect(cutpath)[0]
            if sp:
                self.normsubpaths = self.split(sp[:1])[0].normsubpaths


################
## classes
################


class line_pt(connector_pt):

    def __init__(self, box1, box2, boxdists=[0,0]):

        self.box1 = box1
        self.box2 = box2

        connector_pt.__init__(self,
            [path.normsubpath([path.normline_pt(self.box1.center[0], self.box1.center[1],
                                                self.box2.center[0], self.box2.center[1])], closed=0)])

        self.omitends(box1, box2)
        self.shortenpath(boxdists)


class arc_pt(connector_pt):

    def __init__(self, box1, box2, relangle=45,
                 absbulge=None, relbulge=None, boxdists=[0,0]):

        # the deviation of arc from the straight line can be specified:
        # 1. By an angle between a straight line and the arc
        #    This angle is measured at the centers of the box.
        # 2. By the largest normal distance between line and arc: absbulge
        #    or, equivalently, by the bulge relative to the length of the
        #    straight line from center to center.
        # Only one can be used.

        self.box1 = box1
        self.box2 = box2

        tangent = (self.box2.center[0] - self.box1.center[0],
                   self.box2.center[1] - self.box1.center[1])
        distance = hypot(*tangent)
        tangent = tangent[0] / distance, tangent[1] / distance

        if relbulge is not None or absbulge is not None:
            # usage of bulge overrides the relangle parameter
            bulge = 0
            if absbulge is not None:
                bulge += absbulge
            if relbulge is not None:
                bulge += relbulge*distance
        else:
            # otherwise use relangle, which should be present
            bulge = 0.5 * distance * math.tan(0.5*radians(relangle))

        if abs(bulge) < normpath._epsilon:
            # fallback solution for too straight arcs
            connector_pt.__init__(self,
                [path.normsubpath([path.normline_pt(*(self.box1.center+self.box2.center))], closed=0)])
        else:
            radius = abs(0.5 * (bulge + 0.25 * distance**2 / bulge))
            centerdist = mathutils.sign(bulge) * (radius - abs(bulge))
            center = (0.5 * (self.box1.center[0] + self.box2.center[0]) + tangent[1]*centerdist,
                      0.5 * (self.box1.center[1] + self.box2.center[1]) - tangent[0]*centerdist)
            angle1 = atan2(self.box1.center[1] - center[1], self.box1.center[0] - center[0])
            angle2 = atan2(self.box2.center[1] - center[1], self.box2.center[0] - center[0])

            if bulge > 0:
                connectorpath = path.path(path.moveto_pt(*self.box1.center),
                                          path.arcn_pt(center[0], center[1], radius, degrees(angle1), degrees(angle2)))
                connector_pt.__init__(self, connectorpath.normpath().normsubpaths)
            else:
                connectorpath = path.path(path.moveto_pt(*self.box1.center),
                                          path.arc_pt(center[0], center[1], radius, degrees(angle1), degrees(angle2)))
                connector_pt.__init__(self, connectorpath.normpath().normsubpaths)

        self.omitends(box1, box2)
        self.shortenpath(boxdists)


class curve_pt(connector_pt):

    def __init__(self, box1, box2,
                 relangle1=45, relangle2=45,
                 absangle1=None, absangle2=None,
                 absbulge=0, relbulge=0.39, boxdists=[0,0]):

        # The deviation of the curve from a straight line can be specified:
        # A. By an angle at each center
        #    These angles are either absolute angles with origin at the positive x-axis
        #    or the relative angle with origin at the straight connection line
        # B. By the (expected) largest normal distance between line and arc: absbulge
        #    and/or by the (expected) bulge relative to the length of the
        #    straight line from center to center.
        # Here, we need both informations.
        #
        # a curve with relbulge=0.39 and relangle1,2=45 leads
        # approximately to the arc with angle=45

        self.box1 = box1
        self.box2 = box2

        rel = (self.box2.center[0] - self.box1.center[0],
               self.box2.center[1] - self.box1.center[1])
        distance = hypot(*rel)
        # absolute angle of the straight connection
        dangle = atan2(rel[1], rel[0])

        # calculate the armlength and absolute angles for the control points:
        # absolute and relative bulges are added
        bulge = abs(distance*relbulge + absbulge)

        if absangle1 is not None:
            angle1 = radians(absangle1)
        else:
            angle1 = dangle + radians(relangle1)
        if absangle2 is not None:
            angle2 = radians(absangle2)
        else:
            angle2 = dangle + radians(relangle2)

        # get the control points
        control1 = (cos(angle1), sin(angle1))
        control2 = (cos(angle2), sin(angle2))
        control1 = (self.box1.center[0] + control1[0] * bulge, self.box1.center[1] + control1[1] * bulge)
        control2 = (self.box2.center[0] - control2[0] * bulge, self.box2.center[1] - control2[1] * bulge)

        connector_pt.__init__(self,
               [path.normsubpath([path.normcurve_pt(*(self.box1.center +
                                                   control1 +
                                                   control2 + self.box2.center))], 0)])

        self.omitends(box1, box2)
        self.shortenpath(boxdists)


class twolines_pt(connector_pt):

    def __init__(self, box1, box2,
                 absangle1=None, absangle2=None,
                 relangle1=None, relangle2=None, relangleM=None,
                 length1=None, length2=None,
                 bezierradius=None, beziersoftness=1,
                 arcradius=None,
                 boxdists=[0,0]):

        # The connection with two lines can be done in the following ways:
        # 1. an angle at each box-center
        # 2. two armlengths (if they are long enough)
        # 3. angle and armlength at the same box
        # 4. angle and armlength at different boxes
        # 5. one armlength and the angle between the arms
        #
        # Angles at the box-centers can be relative or absolute
        # The angle in the middle is always relative
        # lengths are always absolute

        self.box1 = box1
        self.box2 = box2

        begin = self.box1.center
        end = self.box2.center
        rel = (self.box2.center[0] - self.box1.center[0],
               self.box2.center[1] - self.box1.center[1])
        distance = hypot(*rel)
        dangle = atan2(rel[1], rel[0])

        # find out what arguments are given:
        if relangle1 is not None: relangle1 = radians(relangle1)
        if relangle2 is not None: relangle2 = radians(relangle2)
        if relangleM is not None: relangleM = radians(relangleM)
        # absangle has priority over relangle:
        if absangle1 is not None: relangle1 = dangle - radians(absangle1)
        if absangle2 is not None: relangle2 = math.pi - dangle + radians(absangle2)

        # check integrity of arguments
        no_angles, no_lengths=0,0
        for anangle in (relangle1, relangle2, relangleM):
            if anangle is not None: no_angles += 1
        for alength in (length1, length2):
            if alength is not None: no_lengths += 1

        if no_angles + no_lengths != 2:
            raise NotImplementedError, "Please specify exactly two angles or lengths"

        # calculate necessary angles and armlengths
        # always length1 and relangle1

        # the case with two given angles
        # use the "sine-theorem" for calculating length1
        if no_angles == 2:
            if relangle1 is None: relangle1 = math.pi - relangle2 - relangleM
            elif relangle2 is None: relangle2 = math.pi - relangle1 - relangleM
            elif relangleM is None: relangleM = math.pi - relangle1 - relangle2
            length1 = distance * abs(sin(relangle2)/sin(relangleM))
            middle = self._middle_a(begin, dangle, length1, relangle1)
        # the case with two given lengths
        # uses the "cosine-theorem" for calculating length1
        elif no_lengths == 2:
            relangle1 = acos((distance**2 + length1**2 - length2**2) / (2.0*distance*length1))
            middle = self._middle_a(begin, dangle, length1, relangle1)
        # the case with one length and one angle
        else:
            if relangle1 is not None:
                if length1 is not None:
                    middle = self._middle_a(begin, dangle, length1, relangle1)
                elif length2 is not None:
                    length1 = self._missinglength(length2, distance, relangle1)
                    middle = self._middle_a(begin, dangle, length1, relangle1)
            elif relangle2 is not None:
                if length1 is not None:
                    length2 = self._missinglength(length1, distance, relangle2)
                    middle = self._middle_b(end, dangle, length2, relangle2)
                elif length2 is not None:
                    middle = self._middle_b(end, dangle, length2, relangle2)
            elif relangleM is not None:
                if length1 is not None:
                    length2 = self._missinglength(distance, length1, relangleM)
                    relangle1 = acos((distance**2 + length1**2 - length2**2) / (2.0*distance*length1))
                    middle = self._middle_a(begin, dangle, length1, relangle1)
                elif length2 is not None:
                    length1 = self._missinglength(distance, length2, relangleM)
                    relangle1 = acos((distance**2 + length1**2 - length2**2) / (2.0*distance*length1))
                    middle = self._middle_a(begin, dangle, length1, relangle1)
            else:
                raise NotImplementedError, "I found a strange combination of arguments"

        connectorpath = path.path(path.moveto_pt(*self.box1.center),
                                  path.lineto_pt(*middle),
                                  path.lineto_pt(*self.box2.center))
        connector_pt.__init__(self, connectorpath.normpath().normsubpaths)

        self.omitends(box1, box2)
        self.shortenpath(boxdists)

    def _middle_a(self, begin, dangle, length1, angle1):
        a = dangle - angle1
        dir = cos(a), sin(a)
        return begin[0] + length1*dir[0], begin[1] + length1*dir[1]

    def _middle_b(self, end, dangle, length2, angle2):
        # a = -math.pi + dangle + angle2
        return self._middle_a(end, -math.pi+dangle, length2, -angle2)

    def _missinglength(self, lenA, lenB, angleA):
        # calculate lenC, where side A and angleA are opposite
        tmp1 = lenB * cos(angleA)
        tmp2 = sqrt(tmp1**2 - lenB**2 + lenA**2)
        if tmp1 > tmp2: return tmp1 - tmp2
        return tmp1 + tmp2



class line(line_pt):

    """a line is the straight connector between the centers of two boxes"""

    def __init__(self, box1, box2, boxdists=(0,0)):
        line_pt.__init__(self, box1, box2, boxdists=map(unit.topt, boxdists))


class curve(curve_pt):

    """a curve is the curved connector between the centers of two boxes.
    The constructor needs both angle and bulge"""


    def __init__(self, box1, box2,
                 relangle1=45, relangle2=45,
                 absangle1=None, absangle2=None,
                 absbulge=0, relbulge=0.39,
                 boxdists=[0,0]):
        curve_pt.__init__(self, box1, box2,
                          relangle1=relangle1, relangle2=relangle2,
                          absangle1=absangle1, absangle2=absangle2,
                          absbulge=unit.topt(absbulge), relbulge=relbulge,
                          boxdists=map(unit.topt, boxdists))

class arc(arc_pt):

    """an arc is a round connector between the centers of two boxes.
    The constructor gets
         either an angle in (-pi,pi)
         or a bulge parameter in (-distance, distance)
           (relbulge and absbulge are added)"""

    def __init__(self, box1, box2, relangle=45,
                 absbulge=None, relbulge=None, boxdists=[0,0]):
        if absbulge is not None:
            absbulge = unit.topt(absbulge)
        arc_pt.__init__(self, box1, box2,
                        relangle=relangle,
                        absbulge=absbulge, relbulge=relbulge,
                        boxdists=map(unit.topt, boxdists))


class twolines(twolines_pt):

    """a twolines is a connector consisting of two straight lines.
    The construcor takes a combination of angles and lengths:
      either two angles (relative or absolute)
      or two lenghts
      or one length and one angle"""

    def __init__(self, box1, box2,
                 absangle1=None, absangle2=None,
                 relangle1=None, relangle2=None, relangleM=None,
                 length1=None, length2=None,
                 bezierradius=None, beziersoftness=1,
                 arcradius=None,
                 boxdists=[0,0]):
        if length1 is not None:
            length1 = unit.topt(length1)
        if length2 is not None:
            length2 = unit.topt(length2)
        if bezierradius is not None:
            bezierradius = unit.topt(bezierradius)
        if arcradius is not None:
            arcradius = unit.topt(arcradius)
        twolines_pt.__init__(self, box1, box2,
                             absangle1=absangle1, absangle2=absangle2,
                             relangle1=relangle1, relangle2=relangle2,
                             relangleM=relangleM,
                             length1=length1, length2=length2,
                             bezierradius=bezierradius, beziersoftness=1,
                             arcradius=arcradius,
                             boxdists=map(unit.topt, boxdists))