예제 #1
0
def test_sectRect():
    intersects, rect = sectRect((0, 10, 20, 30), (0, 40, 20, 50))
    assert not intersects

    intersects, rect = sectRect((0, 10, 20, 30), (5, 20, 35, 50))
    assert intersects
    assert rect == (5, 20, 20, 30)
예제 #2
0
def test_sectRect():
    intersects, rect = sectRect((0, 10, 20, 30), (0, 40, 20, 50))
    assert not intersects

    intersects, rect = sectRect((0, 10, 20, 30), (5, 20, 35, 50))
    assert intersects
    assert rect == (5, 20, 20, 30)
예제 #3
0
파일: touche.py 프로젝트: andreirobu/Touche
    def checkPair(self, g1, g2):
        """New checking method contributed by Frederik

        Returns a Boolean if overlapping.
        """

        kern = self.getKerning(g1, g2)
        
        # Check sidebearings first (PvB's idea)
        if self.rsb[g1] + self.lsb[g2] + kern > 0:
            return False

        # get the bounds and check them
        bounds1 = g1.box
        if bounds1 is None:
            return False
        bounds2 = g2.box
        if bounds2 is None:
            return False    

        # shift bounds2
        bounds2 = offsetRect(bounds2, g1.width+kern, 0)
        # check for intersection bounds
        intersectingBounds, _ = sectRect(bounds1, bounds2)
        if not intersectingBounds:
            return False
        # move bounds1 back, moving bounds is faster then moving all coordinates in a glyph
        bounds1 = offsetRect(bounds1, -g2.width-kern, 0)

        # create a pen for g1 with a shifted rect, draw the glyph into the pen
        pen1 = findPossibleOverlappingSegmentsPen.FindPossibleOverlappingSegmentsPen(g1.getParent(), bounds2)
        g1.draw(pen1)

        # create a pen for g2 with a shifted rect and move each found segment with the width and kerning
        pen2 = findPossibleOverlappingSegmentsPen.FindPossibleOverlappingSegmentsPen(g2.getParent(), bounds1, (g1.width+kern, 0))
        # draw the glyph into the pen
        g2.draw(pen2)

        for segment1 in pen1.segments:
            for segment2 in pen2.segments:
                if len(segment1) == 4 and len(segment2) == 4:
                    a1, a2, a3, a4 = segment1
                    b1, b2, b3, b4 = segment2
                    result = intersectCubicCubic(a1, a2, a3, a4, b1, b2, b3, b4)
                elif len(segment1) == 4:
                    p1, p2, p3, p4 = segment1
                    a1, a2 = segment2
                    result = intersectCubicLine(p1, p2, p3, p4, a1, a2)
                elif len(segment2) == 4:
                    p1, p2, p3, p4 = segment2
                    a1, a2 = segment1
                    result = intersectCubicLine(p1, p2, p3, p4, a1, a2)
                else:
                    a1, a2 = segment1
                    b1, b2 = segment2
                    result = intersectLineLine(a1, a2, b1, b2)
                if result.status == "Intersection":
                    return True

        return False
 def mouseUp(self, info):
     # get the glyph
     glyph = info["glyph"]
     # get the current tool
     tool = info["tool"]
     # only work when the curren tools is the editingTool
     if not isinstance(tool, EditingTool):
         return
     # go on when the option is down and there is no point selection in the glyph
     if tool.optionDown and not glyph.selection:
         # get the marque rect from the tool
         (x, y), (w, h) = tool.getMarqueRect()
         # normalize the rect to a minx, miny, maxx, maxy rectangle
         marqueRect = normRect((x, y, x + w, y + h))
         # loop over all components
         for component in glyph.components:
             # get the component bounding box
             comonentBounds = component.box
             # empty components are possible
             if comonentBounds:
                 # check if there an intersection between the marque rect and the component bounding box
                 interesect, intersectionRect = sectRect(marqueRect, component.box)
                 # if so...
                 if interesect:
                     # check if shift is down
                     if tool.shiftDown:
                         # on shift down, just toggle the current selection
                         component.selected = not component.selected
                     else:
                         # othewise set the component as selected
                         component.selected = True
             else:
                 # empty component
                 # check if the off set point of the component is inside the marque rect
                 if pointInRect(component.offset, marqueRect):
                     # check if shift is down
                     if tool.shiftDown:
                         # on shift down, just toggle the current selection
                         component.selected = not component.selected
                     else:
                         # othewise set the component as selected
                         component.selected = True
         # update the glyph
         glyph.update()
예제 #5
0
 def contourInside(self, other, segmentLength=10):
     """
     Returns a boolean indicating if **other** is in the
     "black" area of the contour. This uses a flattened
     version of other's curves to calculate the location
     of the curves within this contour. **segmentLength**
     defines the desired length for the flattening process.
     A lower value will yeild higher accuracy but will require
     more computation time.
     """
     if segmentLength < 1:
         segmentLength = 1
     # test bounding boxes for intersection
     rect1 = self.bounds
     rect2 = other.bounds
     if not arrayTools.sectRect(rect1, rect2)[0]:
         return False
     # test existing on curves
     testedPoints = set()
     for point in other:
         if point.segmentType is None:
             continue
         pt = (point.x, point.y)
         if pt in testedPoints:
             continue
         if not self.pointInside(pt):
             return False
         testedPoints.add(pt)
     # flatten into line and test new points
     flat2 = other.getRepresentation("defcon.contour.flattened",
                                     approximateSegmentLength=segmentLength,
                                     segmentLines=True)
     for point in flat2:
         pt = (point.x, point.y)
         if pt in testedPoints:
             continue
         if not self.pointInside(pt):
             return False
         testedPoints.add(pt)
     return True
예제 #6
0
 def contourInside(self, other, segmentLength=10):
     """
     Returns a boolean indicating if **other** is in the
     "black" area of the contour. This uses a flattened
     version of other's curves to calculate the location
     of the curves within this contour. **segmentLength**
     defines the desired length for the flattening process.
     A lower value will yeild higher accuracy but will require
     more computation time.
     """
     if segmentLength < 1:
         segmentLength = 1
     # test bounding boxes for intersection
     rect1 = self.bounds
     rect2 = other.bounds
     if not arrayTools.sectRect(rect1, rect2)[0]:
         return False
     # test existing on curves
     testedPoints = set()
     for point in other:
         if point.segmentType is None:
             continue
         pt = (point.x, point.y)
         if pt in testedPoints:
             continue
         if not self.pointInside(pt):
             return False
         testedPoints.add(pt)
     # flatten into line and test new points
     flat2 = other.getRepresentation("defcon.contour.flattened", approximateSegmentLength=segmentLength, segmentLines=True)
     for point in flat2:
         pt = (point.x, point.y)
         if pt in testedPoints:
             continue
         if not self.pointInside(pt):
             return False
         testedPoints.add(pt)
     return True
예제 #7
0
    def checkPair(self, g1, g2):
        """New checking method contributed by Frederik

        Returns a Boolean if overlapping.
        """
        kern = g1._layer.rightKerningForLayer_(g2._layer)
        if kern > 10000:
            kern = 0
        # Check sidebearings first (PvB's idea)
        if self.rsb[g1] + self.lsb[g2] + kern > 0:
            return False

        # get the bounds and check them
        bounds1 = g1.box
        if bounds1 is None:
            return False
        bounds2 = g2.box
        if bounds2 is None:
            return False

        bounds2 = offsetRect(bounds2, g1.width + kern, 0)
        # check for intersection bounds
        intersectingBounds, _ = sectRect(bounds1, bounds2)
        if not intersectingBounds:
            return False

        # create a pen for g1 with a shifted rect, draw the glyph into the pen
        pen1 = self.penCache.get(g1.name, None)
        if not pen1:
            pen1 = SegmentsPen.SegmentsPen(self.font)
            g1.draw(pen1)
            self.penCache[g1.name] = pen1

        # create a pen for g2 with a shifted rect and move each found segment with the width and kerning

        pen2 = self.penCache.get(g2.name, None)
        if not pen2:
            pen2 = SegmentsPen.SegmentsPen(self.font)
            g2.draw(pen2)
            self.penCache[g2.name] = pen2

        offset = g1.width + kern

        for segment1 in pen1.segments:
            if not segmentInBound(segment1, bounds2):
                continue

            for segment2 in pen2.segments:
                segment2 = [(p[0] + offset, p[1]) for p in segment2]
                if not segmentInBound(segment2, bounds1):
                    continue
                if len(segment1) == 4 and len(segment2) == 4:
                    a1, a2, a3, a4 = segment1
                    b1, b2, b3, b4 = segment2
                    result = GSIntersectBezier3Bezier3(a1, a2, a3, a4, b1, b2,
                                                       b3, b4)
                elif len(segment1) == 4:
                    p1, p2, p3, p4 = segment1
                    a1, a2 = segment2
                    result = GSIntersectBezier3Line(p1, p2, p3, p4, a1, a2)
                elif len(segment2) == 4:
                    p1, p2, p3, p4 = segment2
                    a1, a2 = segment1
                    result = GSIntersectBezier3Line(p1, p2, p3, p4, a1, a2)
                else:
                    a1, a2 = segment1
                    b1, b2 = segment2
                    result = GSIntersectLineLine(a1, a2, b1, b2)
                    result = result.x < 100000
                if result:
                    return True
        return False
예제 #8
0
    def checkPair(self, g1, g2):
        """New checking method contributed by Frederik

        Returns a Boolean if overlapping.
        """
        kern = g1._layer.rightKerningForLayer_(g2._layer)
        if kern > 10000:
            kern = 0
        # Check sidebearings first (PvB's idea)
        if self.rsb[g1] + self.lsb[g2] + kern > 0:
            return False

        # get the bounds and check them
        bounds1 = g1.box
        if bounds1 is None:
            return False
        bounds2 = g2.box
        if bounds2 is None:
            return False

        bounds2 = offsetRect(bounds2, g1.width+kern, 0)
        # check for intersection bounds
        intersectingBounds, _ = sectRect(bounds1, bounds2)
        if not intersectingBounds:
            return False

        # create a pen for g1 with a shifted rect, draw the glyph into the pen
        pen1 = self.penCache.get(g1.name, None)
        if not pen1:
            pen1 = SegmentsPen.SegmentsPen(self.font)
            g1.draw(pen1)
            self.penCache[g1.name] = pen1
        
        # create a pen for g2 with a shifted rect and move each found segment with the width and kerning
        
        pen2 = self.penCache.get(g2.name, None)
        if not pen2:
            pen2 = SegmentsPen.SegmentsPen(self.font)
            g2.draw(pen2)
            self.penCache[g2.name] = pen2
        
        offset = g1.width+kern
        
        for segment1 in pen1.segments:
            if not segmentInBound(segment1, bounds2):
                continue
            
            for segment2 in pen2.segments:
                segment2 = [(p[0] + offset, p[1]) for p in segment2]
                if not segmentInBound(segment2, bounds1):
                    continue
                if len(segment1) == 4 and len(segment2) == 4:
                    a1, a2, a3, a4 = segment1
                    b1, b2, b3, b4 = segment2
                    result = GSIntersectBezier3Bezier3(a1, a2, a3, a4, b1, b2, b3, b4)
                elif len(segment1) == 4:
                    p1, p2, p3, p4 = segment1
                    a1, a2 = segment2
                    result = GSIntersectBezier3Line(p1, p2, p3, p4, a1, a2)
                elif len(segment2) == 4:
                    p1, p2, p3, p4 = segment2
                    a1, a2 = segment1
                    result = GSIntersectBezier3Line(p1, p2, p3, p4, a1, a2)
                else:
                    a1, a2 = segment1
                    b1, b2 = segment2
                    result = GSIntersectLineLine(a1, a2, b1, b2)
                    result = result.x < 100000
                if result:
                    return True
        return False
예제 #9
0
def _curve_curve_intersections_t(curve1,
                                 curve2,
                                 precision=1e-3,
                                 range1=None,
                                 range2=None):
    bounds1 = _curve_bounds(curve1)
    bounds2 = _curve_bounds(curve2)

    if not range1:
        range1 = (0.0, 1.0)
    if not range2:
        range2 = (0.0, 1.0)

    # If bounds don't intersect, go home
    intersects, _ = sectRect(bounds1, bounds2)
    if not intersects:
        return []

    def midpoint(r):
        return 0.5 * (r[0] + r[1])

    # If they do overlap but they're tiny, approximate
    if rectArea(bounds1) < precision and rectArea(bounds2) < precision:
        return [(midpoint(range1), midpoint(range2))]

    c11, c12 = _split_segment_at_t(curve1, 0.5)
    c11_range = (range1[0], midpoint(range1))
    c12_range = (midpoint(range1), range1[1])

    c21, c22 = _split_segment_at_t(curve2, 0.5)
    c21_range = (range2[0], midpoint(range2))
    c22_range = (midpoint(range2), range2[1])

    found = []
    found.extend(
        _curve_curve_intersections_t(c11,
                                     c21,
                                     precision,
                                     range1=c11_range,
                                     range2=c21_range))
    found.extend(
        _curve_curve_intersections_t(c12,
                                     c21,
                                     precision,
                                     range1=c12_range,
                                     range2=c21_range))
    found.extend(
        _curve_curve_intersections_t(c11,
                                     c22,
                                     precision,
                                     range1=c11_range,
                                     range2=c22_range))
    found.extend(
        _curve_curve_intersections_t(c12,
                                     c22,
                                     precision,
                                     range1=c12_range,
                                     range2=c22_range))

    unique_key = lambda ts: (int(ts[0] / precision), int(ts[1] / precision))
    seen = set()
    unique_values = []

    for ts in found:
        key = unique_key(ts)
        if key in seen:
            continue
        seen.add(key)
        unique_values.append(ts)

    return unique_values
예제 #10
0
    def checkPair(self, g1, g2):
        """New checking method contributed by Frederik

        Returns a Boolean if overlapping.
        """

        kern = self.getKerning(g1, g2)

        # Check sidebearings first (PvB's idea)
        if self.rsb[g1] + self.lsb[g2] + kern > 0:
            return False

        # get the bounds and check them
        bounds1 = g1.box
        if bounds1 is None:
            return False
        bounds2 = g2.box
        if bounds2 is None:
            return False

        # shift bounds2
        bounds2 = offsetRect(bounds2, g1.width + kern, 0)
        # check for intersection bounds
        intersectingBounds, _ = sectRect(bounds1, bounds2)
        if not intersectingBounds:
            return False
        # move bounds1 back, moving bounds is faster then moving all coordinates in a glyph
        bounds1 = offsetRect(bounds1, -g2.width - kern, 0)

        # create a pen for g1 with a shifted rect, draw the glyph into the pen
        pen1 = findPossibleOverlappingSegmentsPen.FindPossibleOverlappingSegmentsPen(
            g1.getParent(), bounds2)
        g1.draw(pen1)

        # create a pen for g2 with a shifted rect and move each found segment with the width and kerning
        pen2 = findPossibleOverlappingSegmentsPen.FindPossibleOverlappingSegmentsPen(
            g2.getParent(), bounds1, (g1.width + kern, 0))
        # draw the glyph into the pen
        g2.draw(pen2)

        for segment1 in pen1.segments:
            for segment2 in pen2.segments:
                if len(segment1) == 4 and len(segment2) == 4:
                    a1, a2, a3, a4 = segment1
                    b1, b2, b3, b4 = segment2
                    result = intersectCubicCubic(a1, a2, a3, a4, b1, b2, b3,
                                                 b4)
                elif len(segment1) == 4:
                    p1, p2, p3, p4 = segment1
                    a1, a2 = segment2
                    result = intersectCubicLine(p1, p2, p3, p4, a1, a2)
                elif len(segment2) == 4:
                    p1, p2, p3, p4 = segment2
                    a1, a2 = segment1
                    result = intersectCubicLine(p1, p2, p3, p4, a1, a2)
                else:
                    a1, a2 = segment1
                    b1, b2 = segment2
                    result = intersectLineLine(a1, a2, b1, b2)
                if result.status == "Intersection":
                    return True

        return False
예제 #11
0
def checkIfPairOverlaps(g1, g2):
    assert g1.getParent() is g2.getParent(), 'the two glyphs do not belong to the same font'

    """Checking method from Touche!
    Returns a Boolean if overlapping.
    """

    kern = g1.getParent().naked().flatKerning.get((g1.name, g2.name), 0)

    # Check sidebearings first (PvB's idea)
    if g1.rightMargin + g2.leftMargin + kern > 0:
        return False

    # get the bounds and check them
    if version[0] == '2':
        bounds1 = g1.bounds
    else:
        bounds1 = g1.box
    if bounds1 is None:
        return False
    if version[0] == '2':
        bounds2 = g2.bounds
    else:
        bounds2 = g2.box
    if bounds2 is None:
        return False

    # shift bounds2
    bounds2 = offsetRect(bounds2, g1.width+kern, 0)
    # check for intersection bounds
    intersectingBounds, _ = sectRect(bounds1, bounds2)
    if not intersectingBounds:
        return False
    # move bounds1 back, moving bounds is faster then moving all coordinates in a glyph
    bounds1 = offsetRect(bounds1, -g2.width-kern, 0)

    # create a pen for g1 with a shifted rect, draw the glyph into the pen
    pen1 = FindPossibleOverlappingSegmentsPen(g1.getParent(), bounds2)
    g1.draw(pen1)

    # create a pen for g2 with a shifted rect and move each found segment with the width and kerning
    pen2 = FindPossibleOverlappingSegmentsPen(g2.getParent(), bounds1, (g1.width+kern, 0))
    # draw the glyph into the pen
    g2.draw(pen2)

    for segment1 in pen1.segments:
        for segment2 in pen2.segments:
            if len(segment1) == 4 and len(segment2) == 4:
                a1, a2, a3, a4 = segment1
                b1, b2, b3, b4 = segment2
                result = intersectCubicCubic(a1, a2, a3, a4, b1, b2, b3, b4)
            elif len(segment1) == 4:
                p1, p2, p3, p4 = segment1
                a1, a2 = segment2
                result = intersectCubicLine(p1, p2, p3, p4, a1, a2)
            elif len(segment2) == 4:
                p1, p2, p3, p4 = segment2
                a1, a2 = segment1
                result = intersectCubicLine(p1, p2, p3, p4, a1, a2)
            else:
                a1, a2 = segment1
                b1, b2 = segment2
                result = intersectLineLine(a1, a2, b1, b2)
            if result.status == "Intersection":
                return True

    return False