Example #1
0
def process_tilt(filename, args):
    msg("Load tilt")
    tilt = Tilt(filename)
    msg("Load strokes")
    # TODO: this seems to do nothing; is there a function that's supposed to be called here?
    tilt.sketch.strokes  # pylint: disable=pointless-statement
    msg("")

    if args.debug:
        msg("Clone strokes")
        before_strokes = [s.clone() for s in tilt.sketch.strokes]

    # Do this before color quantization, because it removes strokes (and their colors)
    if args.convert_brushes:
        convert_brushes(tilt, BRUSH_REPLACEMENTS)

    if args.remove_stray_strokes is not None:
        remove_stray_strokes(tilt, args.remove_stray_strokes,
                             BrushLookup.get().get_unique_guid("Wire"))

    if args.pos_error_tolerance > 0:
        reduce_control_points(tilt, args.pos_error_tolerance)

    if args.simplify_colors is not None:
        simplify_colors(tilt,
                        num_colors=args.simplify_colors,
                        preserve_colors=args.preserve_colors)

    if args.debug:
        final_strokes = []
        # interleave them so it renders semi-nicely...
        for before, after in itertools.zip_longest(before_strokes,
                                                   tilt.sketch.strokes):
            if before is not None:
                for cp in before.controlpoints:
                    cp.position[1] += 10
                final_strokes.append(before)
            if after is not None:
                final_strokes.append(after)
        tilt.sketch.strokes[:] = final_strokes

    tilt.write_sketch()
    msgln("Wrote %s" % os.path.basename(tilt.filename))
Example #2
0
def get_replacements_by_guid(replacements_by_name):
    """Returns a lookup table that is by-guid rather than by-name."""
    brush_lookup = BrushLookup.get()

    def guid_or_name_to_guid(guid_or_name):
        if guid_or_name in brush_lookup.guid_to_name:
            return guid_or_name
        if guid_or_name in brush_lookup.name_to_guids:
            return brush_lookup.get_unique_guid(guid_or_name)
        raise LookupError("Not a known brush or brush guid: %r" % guid_or_name)

    dct = {}
    for before, after in replacements_by_name:
        before_guid = guid_or_name_to_guid(before)
        if after is True:
            after_guid = before_guid
        elif after is None:
            after_guid = None
        else:
            after_guid = guid_or_name_to_guid(after)
        dct[before_guid] = after_guid
    return dct
Example #3
0
def convert_brushes(tilt, replacements_by_name, show_removed=False):
    """Convert brushes to 3d-printable versions, or remove their strokes from the tilt."""
    replacements = get_replacements_by_guid(replacements_by_name)
    brush_lookup = BrushLookup.get()

    with tilt.mutable_metadata() as dct:
        index_to_guid = dct['BrushIndex']

        # First, show us what brushes the tilt file uses
        used_guids = Counter()
        for stroke in tilt.sketch.strokes:
            guid = index_to_guid[stroke.brush_idx]
            used_guids[guid] += 1
        print("Brushes used:")
        for guid, n in sorted(list(used_guids.items()), key=lambda p: -p[1]):
            print("  %5d %s" % (n, brush_lookup.guid_to_name.get(guid)))
        sys.stdout.flush()
        del used_guids

        index_to_new_index = {}

        for i, guid in enumerate(index_to_guid):
            name = brush_lookup.guid_to_name.get(guid, guid)
            try:
                new_guid = replacements[guid]
            except KeyError:
                print("%d: Don't know what to do with brush %s" % (i, name))
                index_to_new_index[i] = i
            else:
                new_name = brush_lookup.guid_to_name.get(new_guid, new_guid)
                if new_guid is None:
                    print("%d: Remove %s" % (i, name))
                    index_to_new_index[i] = None
                else:
                    if guid == new_guid:
                        print("%d: Keep %s" % (i, name))
                    elif name == new_name:
                        print("%d: Replace %s/%s -> %s/%s" %
                              (i, name, guid, new_name, new_guid))
                    else:
                        print("%d: Replace %s -> %s" % (i, name, new_name))
                    try:
                        new_idx = index_to_guid.index(new_guid)
                    except ValueError:
                        new_idx = len(index_to_guid)
                        index_to_guid.append(new_guid)
                    index_to_new_index[i] = new_idx

    brush_indices_to_remove = set(
        i for (i, new_i) in list(index_to_new_index.items()) if new_i is None)

    if brush_indices_to_remove:
        old_len = len(tilt.sketch.strokes)
        if show_removed:
            # Render in magenta instead of removing
            for stroke in tilt.sketch.strokes:
                if stroke.brush_idx in brush_indices_to_remove:
                    stroke.brush_color = (1, 0, 1, 1)
                else:
                    stroke.brush_color = stroke.brush_color
        else:
            tilt.sketch.strokes[:] = [
                s for s in tilt.sketch.strokes
                if s.brush_idx not in brush_indices_to_remove
            ]
        new_len = len(tilt.sketch.strokes)
        print("Strokes %d -> %d" % (old_len, new_len))

    for stroke in tilt.sketch.strokes:
        new_idx = index_to_new_index[stroke.brush_idx]
        # Might be none if it's a removed brush
        if new_idx is not None:
            stroke.brush_idx = new_idx