Add commented reference helpers to kisscut_gui.py
This commit is contained in:
183
kisscut_gui.py
183
kisscut_gui.py
@@ -244,6 +244,187 @@ def export_mask_as_bezier_svg(mask, path, rdp_epsilon_mm=0.2, spline_smooth=8.0,
|
||||
f.write(svg)
|
||||
return smooth_poly
|
||||
|
||||
# --- Commented reference helpers from old code/ for future experiments ---
|
||||
# These stay commented so the current workflow remains unchanged, but the
|
||||
# snippets can be copied back in without keeping the old files around.
|
||||
|
||||
# def fit_spline_polyline(points, num_out=200, smooth=5.0):
|
||||
# """SciPy spline fit used by an earlier GUI version (periodic curve)."""
|
||||
# x, y = points[:, 0], points[:, 1]
|
||||
# tck, _ = splprep([x, y], s=smooth, per=True)
|
||||
# unew = np.linspace(0, 1.0, num_out)
|
||||
# out = splev(unew, tck)
|
||||
# return np.vstack([out[0], out[1]]).T
|
||||
|
||||
# def catmull_rom_to_beziers(points, closed=True, max_handle_frac=0.5):
|
||||
# """Catmull–Rom to cubic Bézier conversion with handle clamping."""
|
||||
# points = np.asarray(points)
|
||||
# n = len(points)
|
||||
# beziers = []
|
||||
# if closed:
|
||||
# pts = np.vstack([points[-1], points, points[:2]])
|
||||
# rng = range(1, n + 1)
|
||||
# else:
|
||||
# pts = np.vstack([points[0], points, points[-1]])
|
||||
# rng = range(1, n)
|
||||
# for i in rng:
|
||||
# p0, p1, p2, p3 = pts[i - 1], pts[i], pts[i + 1], pts[i + 2]
|
||||
# bp0 = p1
|
||||
# v1 = (p2 - p0) / 6.0
|
||||
# v2 = (p3 - p1) / 6.0
|
||||
# seg1 = np.linalg.norm(p2 - p1)
|
||||
# seg0 = np.linalg.norm(p1 - p0)
|
||||
# seg2 = np.linalg.norm(p3 - p2)
|
||||
# max_len1 = max_handle_frac * min(seg1, seg0)
|
||||
# max_len2 = max_handle_frac * min(seg2, seg1)
|
||||
# v1_len = np.linalg.norm(v1)
|
||||
# v2_len = np.linalg.norm(v2)
|
||||
# if v1_len > max_len1 and v1_len > 0:
|
||||
# v1 = v1 * (max_len1 / v1_len)
|
||||
# if v2_len > max_len2 and v2_len > 0:
|
||||
# v2 = v2 * (max_len2 / v2_len)
|
||||
# bp1 = p1 + v1
|
||||
# bp2 = p2 - v2
|
||||
# bp3 = p2
|
||||
# beziers.append([bp0, bp1, bp2, bp3])
|
||||
# return beziers
|
||||
|
||||
# def export_polyline_svg(points, path, width, height):
|
||||
# """Quick SVG export of a polyline outline for debugging."""
|
||||
# d = "M " + " L ".join(f"{x:.2f},{y:.2f}" for x, y in points) + " Z"
|
||||
# svg = f'<svg width="{width}" height="{height}" xmlns="http://www.w3.org/2000/svg">\\n'
|
||||
# svg += f'<path d="{d}" fill="none" stroke="red" stroke-width="1"/>\\n</svg>'
|
||||
# with open(path, "w") as f:
|
||||
# f.write(svg)
|
||||
|
||||
# def sample_polyline(points, N=1000):
|
||||
# """Evenly sample points along a polyline."""
|
||||
# points = np.asarray(points)
|
||||
# dists = np.sqrt(np.sum(np.diff(points, axis=0)**2, axis=1))
|
||||
# cumlen = np.concatenate([[0], np.cumsum(dists)])
|
||||
# total_len = cumlen[-1]
|
||||
# interp_locs = np.linspace(0, total_len, N)
|
||||
# interp_points = []
|
||||
# for loc in interp_locs:
|
||||
# idx = np.searchsorted(cumlen, loc) - 1
|
||||
# idx = min(idx, len(points) - 2)
|
||||
# seglen = cumlen[idx+1] - cumlen[idx]
|
||||
# t = (loc - cumlen[idx]) / seglen if seglen > 0 else 0
|
||||
# interp = (1 - t) * points[idx] + t * points[idx+1]
|
||||
# interp_points.append(interp)
|
||||
# return np.array(interp_points)
|
||||
|
||||
# def _legacy_bezier_q(ctrl_poly, t):
|
||||
# """Cubic Bézier evaluation reused by sampling helpers."""
|
||||
# mt = 1 - t
|
||||
# return (
|
||||
# mt**3 * ctrl_poly[0][0] + 3 * mt**2 * t * ctrl_poly[1][0] + 3 * mt * t**2 * ctrl_poly[2][0] + t**3 * ctrl_poly[3][0],
|
||||
# mt**3 * ctrl_poly[0][1] + 3 * mt**2 * t * ctrl_poly[1][1] + 3 * mt * t**2 * ctrl_poly[2][1] + t**3 * ctrl_poly[3][1]
|
||||
# )
|
||||
|
||||
# def sample_bezier_path(beziers, N=1000):
|
||||
# """Sample a list of cubic Béziers into N evenly spaced points."""
|
||||
# samples = []
|
||||
# segs = len(beziers)
|
||||
# pts_per_seg = max(2, N // segs)
|
||||
# for bez in beziers:
|
||||
# for i in range(pts_per_seg):
|
||||
# t = i / (pts_per_seg - 1)
|
||||
# p = _legacy_bezier_q(bez, t)
|
||||
# samples.append(np.array(p))
|
||||
# return np.array(samples[:N])
|
||||
|
||||
# def find_deviations(poly_points, bezier_points, threshold=5.0):
|
||||
# """Locate indexes where Bézier samples deviate from the polyline."""
|
||||
# dists = np.linalg.norm(poly_points - bezier_points, axis=1)
|
||||
# deviations = np.where(dists > threshold)[0]
|
||||
# return deviations, dists
|
||||
|
||||
# def blend_bezier_with_polyline(beziers, poly_points, bezier_points, deviations, alpha=0.7):
|
||||
# """Pull Bézier handles toward polyline points where error is large."""
|
||||
# N = len(bezier_points)
|
||||
# segs = len(beziers)
|
||||
# pts_per_seg = max(2, N // segs)
|
||||
# for idx in deviations:
|
||||
# seg_idx = idx // pts_per_seg
|
||||
# if seg_idx >= len(beziers):
|
||||
# continue
|
||||
# p_poly = poly_points[idx]
|
||||
# for c_idx in (1, 2):
|
||||
# c = np.array(beziers[seg_idx][c_idx])
|
||||
# beziers[seg_idx][c_idx] = tuple(alpha * c + (1 - alpha) * p_poly)
|
||||
# return beziers
|
||||
|
||||
# Potrace + Skia offset pipeline (old kisscut_wrap.py). Requires potrace CLI,
|
||||
# lxml, svg.path, and skia-python; kept for reference if a true stroke offset
|
||||
# is preferred over the contour-based approach here.
|
||||
# import subprocess, tempfile
|
||||
# from lxml import etree
|
||||
# from svg.path import parse_path, CubicBezier, Line, QuadraticBezier, Arc
|
||||
# import skia
|
||||
#
|
||||
# def png_to_pnm(input_png, pnm_path):
|
||||
# img = Image.open(input_png).convert("L")
|
||||
# img.save(pnm_path, format="PPM")
|
||||
#
|
||||
# def pnm_to_base_svg(pnm_path, svg_path):
|
||||
# subprocess.run([
|
||||
# "potrace", "-s", "-o", svg_path, "-b", "svg",
|
||||
# "--alphamax", "0.1", "--turdsize", "1", pnm_path
|
||||
# ], check=True)
|
||||
#
|
||||
# def offset_svg_paths(input_svg, output_svg, offset_pt=9.0):
|
||||
# parser = etree.XMLParser(remove_blank_text=True)
|
||||
# tree = etree.parse(input_svg, parser)
|
||||
# root = tree.getroot()
|
||||
# ns = {"svg": "http://www.w3.org/2000/svg"}
|
||||
# svg_ns = "http://www.w3.org/2000/svg"
|
||||
# new_root = etree.Element("{%s}svg" % svg_ns,
|
||||
# nsmap={None: svg_ns},
|
||||
# width=root.get("width"),
|
||||
# height=root.get("height"),
|
||||
# viewBox=root.get("viewBox") or f"0 0 {root.get('width')} {root.get('height')}")
|
||||
# for path_el in root.xpath("//svg:path", namespaces=ns):
|
||||
# d = path_el.get("d")
|
||||
# path = parse_path(d)
|
||||
# sk_path = skia.Path()
|
||||
# start = path[0].start
|
||||
# sk_path.moveTo(start.real, -start.imag)
|
||||
# for seg in path:
|
||||
# if isinstance(seg, CubicBezier):
|
||||
# sk_path.cubicTo(
|
||||
# seg.control1.real, -seg.control1.imag,
|
||||
# seg.control2.real, -seg.control2.imag,
|
||||
# seg.end.real, -seg.end.imag
|
||||
# )
|
||||
# elif isinstance(seg, Line):
|
||||
# sk_path.lineTo(seg.end.real, -seg.end.imag)
|
||||
# elif isinstance(seg, QuadraticBezier):
|
||||
# c1 = seg.start + 2/3*(seg.control - seg.start)
|
||||
# c2 = seg.end + 2/3*(seg.control - seg.end)
|
||||
# sk_path.cubicTo(
|
||||
# c1.real, -c1.imag,
|
||||
# c2.real, -c2.imag,
|
||||
# seg.end.real, -seg.end.imag
|
||||
# )
|
||||
# elif isinstance(seg, Arc):
|
||||
# sk_path.lineTo(seg.end.real, -seg.end.imag)
|
||||
# stroke = skia.StrokeRec()
|
||||
# stroke.setStrokeStyle(offset_pt)
|
||||
# sk_offset = sk_path.strokeAndConvertToPath(stroke)
|
||||
# d2 = sk_offset.toSVGString()
|
||||
# etree.SubElement(new_root, "path",
|
||||
# d=d2,
|
||||
# fill="none",
|
||||
# stroke="red",
|
||||
# **{"stroke-width": "1"})
|
||||
# etree.ElementTree(new_root).write(
|
||||
# output_svg,
|
||||
# pretty_print=True,
|
||||
# xml_declaration=True,
|
||||
# encoding="utf-8"
|
||||
# )
|
||||
|
||||
# --- Preview Widget (just display, auto-margin alignment) ---
|
||||
class PreviewWidget(QLabel):
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -514,4 +695,4 @@ if __name__ == '__main__':
|
||||
app = QApplication(sys.argv)
|
||||
window = MainWindow()
|
||||
window.show()
|
||||
sys.exit(app.exec())
|
||||
sys.exit(app.exec())
|
||||
|
||||
Reference in New Issue
Block a user