예제 #1
0
    def test_scale(self):
        p = Point(4, 5)
        m = AffineTransformation.scaling(2)
        p.transform(m)
        self.assertEqual(p.x, 8)
        self.assertEqual(p.y, 10)

        p = Point(4, 5)
        m = AffineTransformation.scaling(1.5, -2)
        p.transform(m)
        self.assertEqual(p.x, 6)
        self.assertEqual(p.y, -10)
예제 #2
0
    def test_translate(self):
        p = Point(30, 70)
        p.rotate(Point(0, 0), math.pi / 4)
        self.assertEqual(p.x, -28.284271247461906)
        self.assertEqual(p.y, 70.71067811865476)

        p = Point(30, 70)
        m = AffineTransformation.rotation(math.pi / 4)
        p.transform(m)
        self.assertAlmostEqual(p.x, -28.284271247461906)
        self.assertAlmostEqual(p.y, 70.71067811865476)

        p = Point(0, 10)
        m = AffineTransformation.translation(Point(5, -2))
        p.transform(m)
        self.assertEqual(p.x, 5)
        self.assertEqual(p.y, 8)
예제 #3
0
def findshifts(segs, splitline):
    """ Yields lines which are possible positions of splitline. This includes
        all maxima and minima on the segments list and also every 20 units. """
    trans = splitline.alignmentTransformation()
    bounds = []
    maxy = -1e6
    miny = 1e6
    for _s in segs:
        # rotate segment so dealing purely in y, the splitline is in effect horizontal
        s = _s.transformed(trans)
        # add segment ends or any maxima to the list of possible positions
        if len(s) == 2:
            bounds = _addBound(bounds,
                               Bound(s[0].x, s[0].y, s[0].y > s[1].y, s.slope))
            bounds = _addBound(
                bounds, Bound(s[1].x, s[1].y, s[1].y >= s[0].y, s.slope))
            # collect overall segment list extrema in y
            maxy = max(maxy, s[0].y, s[1].y)
            miny = min(miny, s[0].y, s[1].y)
        elif len(s) == 3:
            d2 = s[0].y - 2 * s[1].y + s[2].y
            if not isclose(d2, 0.):
                rt = (s[0].y - s[1].y) / d2
                if 0 <= rt <= 1.:
                    p = s.pointAtTime(rt)
                    bounds.append(Bound(p.x, p.y, d2 < 0., 0.))
                    maxy = max(maxy, s[0].y, s[2].y, p.y)
                    miny = min(miny, s[0].y, s[2].y, p.y)
                    continue
            bounds = _addBound(
                bounds,
                Bound(s[0].x, s[0].y, s[0].y > s[2].y,
                      s.derivative()[0].slope))
            bounds = _addBound(
                bounds,
                Bound(s[2].x, s[2].y, s[2].y >= s[0].y,
                      s.derivative()[1].slope))
            maxy = max(maxy, s[0].y, s[2].y)
            miny = min(miny, s[0].y, s[2].y)
    # create transform back from horizontal to original direction
    backt = AffineTransformation()
    backt.apply_backwards(trans)
    backt.invert()
    last = None
    # yield each of the calculated bounds as a splitline
    for b in sorted(bounds, key=lambda b: (b[1], b)):
        if last is not None and isclose(last, b[1]):
            continue
        res = splitline.transformed(trans)
        res[0].y += b.y
        res[1].y += b.y
        #        yield res.transformed(backt)
        last = b[1]
    # Now yield every 20 em units as a splitline
    for y in range(int(miny), int(maxy), max(20, int((maxy - miny) * .05))):
        res = splitline.transformed(trans)
        res[0].y += y
        res[1].y += y
        yield res.transformed(backt)
예제 #4
0
 def test_multiple_application(self):
     p = Point(10, 10)
     m = AffineTransformation()
     m.translate(Point(6, 5))
     m.scale(1.5, 2)
     p.transform(m)
     self.assertEqual(p.x, 24)
     self.assertEqual(p.y, 30)
예제 #5
0
 def alignmentTransformation(self):
   m = AffineTransformation.translation(self.start * -1)
   m.rotate((self.end.transformed(m)).angle * -1)
   return m
예제 #6
0
def splitWith(segs, splitline, args=None):
    """ Splits a list of segments given a straight splitting line. Returns
        2 lists of segments such that the resulting segments are closed paths. """
    trans = splitline.alignmentTransformation()
    lefts = []
    rights = []
    splits = []
    for _s in segs:
        # transform so splitline is horizontal and is y=0
        s = _s.transformed(trans)
        roots = s._findRoots("y")
        # does y=0 cut this segment?
        if len(roots) == 2:
            # chop a quadratic cuver and put parts in left and right collection
            l, r = s.splitAtTime(roots[0])
            (rights if s.start.y < 0 else lefts).append(l)
            l, r = r.splitAtTime(roots[1])
            (rights if s.end.y < 0 else lefts).append(r)
            # keep split points so we can add joinup lines later
            splits.append(
                (l.start.x, (l.start.x < s.start.x) ^ (s.start.y < 0)))
            splits.append((l.end.x, (l.end.x > s.end.x) ^ (s.start.y < 0)))
        elif len(roots) == 1:
            # chop a straight line
            l, r = s.splitAtTime(roots[0])
            if s.start.y < 0:
                rights.append(l)
                lefts.append(r)
                splits.append((r.start.x, True))
            else:
                lefts.append(l)
                rights.append(r)
                splits.append((r.start.x, False))
        # otherwise no cut and simply allocate the segment
        elif s.start.y < 0 or s.end.y < 0:
            rights.append(s)
        else:
            lefts.append(s)
    # to convert from y=0 back to original co-ordinates
    backt = AffineTransformation()
    backt.apply_backwards(trans)
    backt.invert()
    if args is not None and args.detail & 8:
        print("      ", [(Point(s[0], 0).transformed(backt), s[1])
                         for s in sorted(splits)])
    curr = False
    lastP = None
    # find adjacent pairs of bounding points on the splitline and join them up on either side
    # thus making closed paths, even if the segments aren't end to start all the way round.
    for x, d in sorted(splits):
        newP = Point(x, 0)
        if d != curr:
            curr = d
        if lastP is None:
            lastP = newP
            continue
        l = Line(lastP, newP)
        r = Line(newP, lastP)
        if not d:
            rights.append(l)
            lefts.append(r)
        lastP = newP
    rights = [s.transformed(backt) for s in rights]
    lefts = [s.transformed(backt) for s in lefts]
    return (rights, lefts)
예제 #7
0
 def alignmentTransformation(self):
     m = AffineTransformation.translation(self.start * -1)
     m.rotate((self.end.transformed(m)).angle * -1)
     return m