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))
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
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