示例#1
0
def checkPolygons(map):
    clean = True
    for edge in map.edgeIter():
        l, pa = edge.length(), edge.partialArea()
        p = Polygon(edge)
        p.invalidateProperties()
        if abs(l - p.length()) > 1e-6:
            print "edge %d: length wrong (was %s, is %s)" % (
                edge.label(), l, p.length())
            clean = False
        if abs(pa - p.partialArea()) > 1e-6:
            print "edge %d: partial area wrong (was %s, is %s)" % (
                edge.label(), pa, p.partialArea())
            clean = False
    return clean
示例#2
0
def checkPolygons(map):
    clean = True
    for edge in map.edgeIter():
        l, pa = edge.length(), edge.partialArea()
        p = Polygon(edge)
        p.invalidateProperties()
        if abs(l - p.length()) > 1e-6:
            print "edge %d: length wrong (was %s, is %s)" % (edge.label(), l,
                                                             p.length())
            clean = False
        if abs(pa - p.partialArea()) > 1e-6:
            print "edge %d: partial area wrong (was %s, is %s)" % (
                edge.label(), pa, p.partialArea())
            clean = False
    return clean
示例#3
0
def clipPoly(polygon, clipRect, closeAtBorder = None):
    """clipPoly(polygon, clipRect)

    Clips away those parts of polygon which are not in clipRect.
    Returns a list of polygons (since the polygon may leave clipRect,
    enter again, leave, ...).  Polygon segments crossing clipRect's
    borders are cut, such that the resulting polyons get new endpoints
    exactly on the border."""
    
    result = []

#     print "clipPoly(%s..%s)" % (clipRect.begin(), clipRect.end())
#     print list(polygon)

    if closeAtBorder is None:
        closeAtBorder = (polygon[0] == polygon[-1])

    x1, y1 = clipRect.begin()
    x2, y2 = clipRect.end()

    part = None
    startBorder = None
    parts = []

    relPos = None
    for i, p in enumerate(polygon):
        prevRP = relPos
        relPos = 0
        if p[0] < x1:
            relPos |= LEFT
        elif p[0] > x2:
            relPos |= RIGHT
        if p[1] < y1:
            relPos |= TOP
        elif p[1] > y2:
            relPos |= BOTTOM

        if relPos: # outside
            if not i: # incomplete first segment
                continue

            if prevRP & relPos:
                # complete segment outside
                continue

            # calculate leaving intersection
            diff = polygon[i-1] - p
            l = -1.0
            if relPos & LEFT:
                l = max(l, (x1 - p[0]) / diff[0])
                endBorder = LEFT
            if relPos & RIGHT:
                l = max(l, (x2 - p[0]) / diff[0])
                endBorder = RIGHT
            if relPos & TOP:
                nl = (y1 - p[1]) / diff[1]
                if nl > l:
                    l = nl
                    endBorder = TOP
            if relPos & BOTTOM:
                nl = (y2 - p[1]) / diff[1]
                if nl > l:
                    l = nl
                    endBorder = BOTTOM
            ip = p + l * diff

            if prevRP:
                # segment may cross cliprect, calc. start intersection
                pl = 2.0
                if prevRP & LEFT:
                    pl = min(pl, (x1 - p[0]) / diff[0])
                    startBorder = LEFT
                if prevRP & RIGHT:
                    pl = min(pl, (x2 - p[0]) / diff[0])
                    startBorder = RIGHT
                if prevRP & TOP:
                    npl = (y1 - p[1]) / diff[1]
                    if npl < pl:
                        pl = npl
                        startBorder = TOP
                if prevRP & BOTTOM:
                    npl = (y2 - p[1]) / diff[1]
                    if npl < pl:
                        pl = npl
                        startBorder = BOTTOM

                if pl <= l:
                    # we never crossed the clipRect
                    continue

                pip = p + pl * diff
                part = Polygon([pip, ip])
            else:
                part.append(ip)

            if part.length():
                parts.append((startBorder, part, endBorder))
            part = None
            continue

        if not part:
            part = Polygon()
            if i:
                # calculate entering intersection:
                diff = polygon[i-1] - p
                l = 2.0
                if prevRP & LEFT:
                    l = min(l, (x1 - p[0]) / diff[0])
                    startBorder = LEFT
                if prevRP & RIGHT:
                    l = min(l, (x2 - p[0]) / diff[0])
                    startBorder = RIGHT
                if prevRP & TOP:
                    nl = (y1 - p[1]) / diff[1]
                    if nl < l:
                        l = nl
                        startBorder = TOP
                if prevRP & BOTTOM:
                    nl = (y2 - p[1]) / diff[1]
                    if nl < l:
                        l = nl
                        startBorder = BOTTOM
                ip = p + l * diff
                part.append(ip)

        part.append(p)

    if part and part.length():
        parts.append((startBorder, part, None))

    if not parts:
        return []

    if not polygon.closed():
        return [p[1] for p in parts]

    # if polygon[0] (== polygon[-1]) is inside clipRect, we may
    # need to join the first and last part here:
    if parts[0][1][0] == parts[-1][1][-1]:
        assert parts[0][0] is None and parts[-1][-1] is None
        # polygon is entirely within clipRect:
        if len(parts) == 1:
            return [parts[0][1]]
        parts[-1][1].extend(parts[0][1])
        parts[0] = (parts[-1][0], parts[-1][1], parts[0][2])
        del parts[-1]

    if not closeAtBorder:
        return [p[1] for p in parts]

    # compose counterclockwise list of intersection points at clip border:
    sides = (
        ([(-p[1][-1][0], p[1], True ) for p in parts if p[2] == TOP] +
         [(-p[1][ 0][0], p[1], False) for p in parts if p[0] == TOP]),
        ([( p[1][-1][1], p[1], True ) for p in parts if p[2] == LEFT] +
         [( p[1][ 0][1], p[1], False) for p in parts if p[0] == LEFT]),
        ([( p[1][-1][0], p[1], True ) for p in parts if p[2] == BOTTOM] +
         [( p[1][ 0][0], p[1], False) for p in parts if p[0] == BOTTOM]),
        ([(-p[1][-1][1], p[1], True ) for p in parts if p[2] == RIGHT] +
         [(-p[1][ 0][1], p[1], False) for p in parts if p[0] == RIGHT]))

    # counterclockwise list of corner positions:
    corners = (clipRect.begin(),
               clipRect.begin()+(0, clipRect.size()[1]),
               clipRect.end(),
               clipRect.begin()+(clipRect.size()[0], 0))

    isCCW = polygon.partialArea() > 0

    # bookkeeping about mergings (always use the most current polygon)
    merged = {}
    def mergeRoot(poly):
        while True:
            result = merged.get(poly, poly)
            if result is poly:
                break
            poly = result
        return result
    
    lastPoly = None
    prevPoly = None
    prevOutside = None

    for side, end in zip(sides, corners):
        for _, poly, outside in sorted(side):
#            assert outside != prevOutside; prevOutside = outside
            if outside == isCCW:
                prevPoly = poly
            else:
                if prevPoly == None:
                    lastPoly = poly
                    continue
                prevPoly = mergeRoot(prevPoly)
                if prevPoly == poly:
                    poly.append(poly[0])
                    result.append(poly)
                else:
                    prevPoly.extend(poly)
                    merged[poly] = prevPoly
                prevPoly = None

        if prevPoly:
            mergeRoot(prevPoly).append(end)

    if lastPoly:
        lastPoly.append(lastPoly[0])
        if lastPoly.length():
            result.append(lastPoly)

    return result
示例#4
0
def clipPoly(polygon, clipRect, closeAtBorder=None):
    """clipPoly(polygon, clipRect)

    Clips away those parts of polygon which are not in clipRect.
    Returns a list of polygons (since the polygon may leave clipRect,
    enter again, leave, ...).  Polygon segments crossing clipRect's
    borders are cut, such that the resulting polyons get new endpoints
    exactly on the border."""

    result = []

    #     print "clipPoly(%s..%s)" % (clipRect.begin(), clipRect.end())
    #     print list(polygon)

    if closeAtBorder is None:
        closeAtBorder = (polygon[0] == polygon[-1])

    x1, y1 = clipRect.begin()
    x2, y2 = clipRect.end()

    part = None
    startBorder = None
    parts = []

    relPos = None
    for i, p in enumerate(polygon):
        prevRP = relPos
        relPos = 0
        if p[0] < x1:
            relPos |= LEFT
        elif p[0] > x2:
            relPos |= RIGHT
        if p[1] < y1:
            relPos |= TOP
        elif p[1] > y2:
            relPos |= BOTTOM

        if relPos:  # outside
            if not i:  # incomplete first segment
                continue

            if prevRP & relPos:
                # complete segment outside
                continue

            # calculate leaving intersection
            diff = polygon[i - 1] - p
            l = -1.0
            if relPos & LEFT:
                l = max(l, (x1 - p[0]) / diff[0])
                endBorder = LEFT
            if relPos & RIGHT:
                l = max(l, (x2 - p[0]) / diff[0])
                endBorder = RIGHT
            if relPos & TOP:
                nl = (y1 - p[1]) / diff[1]
                if nl > l:
                    l = nl
                    endBorder = TOP
            if relPos & BOTTOM:
                nl = (y2 - p[1]) / diff[1]
                if nl > l:
                    l = nl
                    endBorder = BOTTOM
            ip = p + l * diff

            if prevRP:
                # segment may cross cliprect, calc. start intersection
                pl = 2.0
                if prevRP & LEFT:
                    pl = min(pl, (x1 - p[0]) / diff[0])
                    startBorder = LEFT
                if prevRP & RIGHT:
                    pl = min(pl, (x2 - p[0]) / diff[0])
                    startBorder = RIGHT
                if prevRP & TOP:
                    npl = (y1 - p[1]) / diff[1]
                    if npl < pl:
                        pl = npl
                        startBorder = TOP
                if prevRP & BOTTOM:
                    npl = (y2 - p[1]) / diff[1]
                    if npl < pl:
                        pl = npl
                        startBorder = BOTTOM

                if pl <= l:
                    # we never crossed the clipRect
                    continue

                pip = p + pl * diff
                part = Polygon([pip, ip])
            else:
                part.append(ip)

            if part.length():
                parts.append((startBorder, part, endBorder))
            part = None
            continue

        if not part:
            part = Polygon()
            if i:
                # calculate entering intersection:
                diff = polygon[i - 1] - p
                l = 2.0
                if prevRP & LEFT:
                    l = min(l, (x1 - p[0]) / diff[0])
                    startBorder = LEFT
                if prevRP & RIGHT:
                    l = min(l, (x2 - p[0]) / diff[0])
                    startBorder = RIGHT
                if prevRP & TOP:
                    nl = (y1 - p[1]) / diff[1]
                    if nl < l:
                        l = nl
                        startBorder = TOP
                if prevRP & BOTTOM:
                    nl = (y2 - p[1]) / diff[1]
                    if nl < l:
                        l = nl
                        startBorder = BOTTOM
                ip = p + l * diff
                part.append(ip)

        part.append(p)

    if part and part.length():
        parts.append((startBorder, part, None))

    if not parts:
        return []

    if not polygon.closed():
        return [p[1] for p in parts]

    # if polygon[0] (== polygon[-1]) is inside clipRect, we may
    # need to join the first and last part here:
    if parts[0][1][0] == parts[-1][1][-1]:
        assert parts[0][0] is None and parts[-1][-1] is None
        # polygon is entirely within clipRect:
        if len(parts) == 1:
            return [parts[0][1]]
        parts[-1][1].extend(parts[0][1])
        parts[0] = (parts[-1][0], parts[-1][1], parts[0][2])
        del parts[-1]

    if not closeAtBorder:
        return [p[1] for p in parts]

    # compose counterclockwise list of intersection points at clip border:
    sides = (([(-p[1][-1][0], p[1], True) for p in parts if p[2] == TOP] +
              [(-p[1][0][0], p[1], False) for p in parts if p[0] == TOP]),
             ([(p[1][-1][1], p[1], True) for p in parts if p[2] == LEFT] +
              [(p[1][0][1], p[1], False) for p in parts if p[0] == LEFT]),
             ([(p[1][-1][0], p[1], True) for p in parts if p[2] == BOTTOM] +
              [(p[1][0][0], p[1], False) for p in parts if p[0] == BOTTOM]),
             ([(-p[1][-1][1], p[1], True) for p in parts if p[2] == RIGHT] +
              [(-p[1][0][1], p[1], False) for p in parts if p[0] == RIGHT]))

    # counterclockwise list of corner positions:
    corners = (clipRect.begin(), clipRect.begin() + (0, clipRect.size()[1]),
               clipRect.end(), clipRect.begin() + (clipRect.size()[0], 0))

    isCCW = polygon.partialArea() > 0

    # bookkeeping about mergings (always use the most current polygon)
    merged = {}

    def mergeRoot(poly):
        while True:
            result = merged.get(poly, poly)
            if result is poly:
                break
            poly = result
        return result

    lastPoly = None
    prevPoly = None
    prevOutside = None

    for side, end in zip(sides, corners):
        for _, poly, outside in sorted(side):
            #            assert outside != prevOutside; prevOutside = outside
            if outside == isCCW:
                prevPoly = poly
            else:
                if prevPoly == None:
                    lastPoly = poly
                    continue
                prevPoly = mergeRoot(prevPoly)
                if prevPoly == poly:
                    poly.append(poly[0])
                    result.append(poly)
                else:
                    prevPoly.extend(poly)
                    merged[poly] = prevPoly
                prevPoly = None

        if prevPoly:
            mergeRoot(prevPoly).append(end)

    if lastPoly:
        lastPoly.append(lastPoly[0])
        if lastPoly.length():
            result.append(lastPoly)

    return result