Skip to content

Latest commit

 

History

History
127 lines (96 loc) · 8.63 KB

File metadata and controls

127 lines (96 loc) · 8.63 KB

CLAUDE.md — thinr

Working rules for Claude Code (and any human collaborator) when editing this package. The figureextract meta-repo's ARCHITECTURE.md and DECISIONS.md describe the wider ecosystem; this file is the per-package complement.

Package responsibility

thinr provides binary image thinning (skeletonization) algorithms — Zhang-Suen, Guo-Hall, Lee (2-D), K3M, the parallel form commonly attributed to Hilditch, OPTA / SPTA, and Holt — behind a single dispatching API. Also provides the medial axis transform (Blum 1967) and a fast distance transform (Felzenszwalb-Huttenlocher 2012; classic two-pass sweep). EBImage provides binary morphology but no thinning operator, so thinr complements it rather than replacing any of its functions. Per ADR-007 this is the one public CRAN package in the figureextract ecosystem; LGPL-3 is chosen for EBImage compatibility.

Current state

  • Slice: 0 — Infrastructure
  • Version: 0.2.0
  • Status: CRAN-prep release. Seven thinning algorithms fully implemented in Rcpp, all verified against original papers (or the Lam-Lee-Suen 1992 survey for Hilditch's parallel form). Medial axis and distance transform shipped as standalone exported utilities. PR #1 (release-prep) and PR #2 (coverage-bump) both merged to main. Tests pass; lintr clean; R CMD check --as-cran clean (0/0/2 NOTEs, both expected). GitHub Actions: R-CMD-check (matrix), pkgdown, test-coverage, lint, pr-commands.
  • Recent shipments:
    • R-side coverage to its practical maximum (2026-05-21, PR #2, 1870e25) — added tests covering the remaining branches in the thin() dispatcher and the storage-restoration helpers.
    • release-prep merged (2026-05-20, PR #1, 98f4a80) — the CRAN-prep branch (with all reviewer-feedback fixes, the K3M / OPTA / Holt verifications, the Stentiford / Pavlidis drop, and pkgdown reference-index fix) landed on main.
    • Dropped stentiford (folk misattribution; the 1983 paper is preprocessing not thinning) and pavlidis (the implementation didn't match the contour-following algorithm of the 1980 paper). The dropped algorithms are not implemented in any major image-processing library (scikit-image, OpenCV, MATLAB, ImageJ, mahotas); per the package's "widely used elsewhere" inclusion criterion, removing them keeps the package focused. (2026-05-20)
    • Algorithm verification pass against papers in references/: K3M lookup tables corrected against Saeed et al. 2010; OPTA rewritten per survey's safe-point expression; Holt rewritten per the original CACM paper (correcting a survey transcription error in the middle clause). (2026-05-20)
    • Tier-1 + Tier-2 algorithm expansion: Hilditch, OPTA, Holt; plus medial_axis() and distance_transform(). (2026-05-16)
    • CRAN reviewer feedback addressed (function-name quotes + DOIs). (2026-05-16)
    • v0.2.0 stub-replacement: Lee 2-D and K3M fully implemented. (2026-05-16)
    • v0.1.0 skeleton with Rcpp setup, 2 algorithms, vignette, README, NEWS, GitHub Actions CI, pkgdown. (2026-05-16)

Coding rules

  • Style: tidyverse style guide. styler::style_pkg() clean. lintr::lint_package() clean per .lintr (line length 100, snake_case + CamelCase, no commented-code linter).
  • C++: ISO C++17 baseline (Rcpp default for current R). Two-space indent. No using namespace std. Avoid Rcpp sugar in tight loops where it costs measurable performance.
  • R version: ≥ 4.2.
  • Pipe: native |> preferred.
  • Imports: Rcpp only. Don't add dependencies without a strong reason — this is a small, focused, CRAN-friendly package.

Testing conventions

  • Framework: testthat 3rd edition with the describe/it BDD style (legible test reports for a public package).
  • Coverage: every algorithm in methods <- c(...) (currently nine) is exercised against the same property suite (solid square thins, line collapse, idempotence, empty input, isolated-pixel preservation, ring topology). New methods are added to the vector and inherit all tests automatically.
  • distance_transform and medial_axis each have their own test files (tests/testthat/test-distance-transform.R, test-medial-axis.R).
  • Acceptance: R CMD check --as-cran clean (0 errors, 0 warnings, NOTEs acceptable for "new submission" and the Ubuntu system compilation-flags note).

Module boundaries

C++ sources in src/:

  • thinr_common.h — shared inline helpers (crossing_number, neighbour_count, is_border_4).
  • zhang_suen.cpp — Zhang & Suen (1984).
  • guo_hall.cpp — Guo & Hall (1989).
  • lee.cpp — Lee, Kashyap & Chu (1994), 2-D adaptation.
  • k3m.cpp — Saeed et al. (2010); paper lookup tables reproduced verbatim.
  • hilditch.cpp — parallel form commonly attributed to Hilditch (1969); the actual implementation follows the Rutovitz-style R1–R4 conditions as documented in Lam, Lee & Suen (1992).
  • opta.cpp — Naccache & Shinghal (1984), Safe Point Thinning Algorithm; boolean safe-point expression follows the survey.
  • holt.cpp — Holt, Stewart, Clint & Perrott (1987); condition H follows the original CACM paper (a survey transcription error was caught and corrected against the original).
  • distance_transform.h + distance_transform.cpp — Felzenszwalb-Huttenlocher 2012 squared Euclidean + Rosenfeld-Pfaltz two-pass sweep for L1 and L∞.
  • medial_axis.cpp — ridge detection on the squared Euclidean DT.
  • RcppExports.cpp — auto-generated; do not edit (regenerated by Rcpp::compileAttributes()).

R sources in R/:

  • thin.Rthin() dispatching function and the as_binary_matrix() / restore_storage() coercion helpers.
  • distance_transform.R — exported wrapper for .distance_transform_cpp.
  • medial_axis.R — exported wrapper for .medial_axis_cpp.
  • thinr-package.R — package-level Roxygen doc.
  • RcppExports.R — auto-generated; do not edit.

Public API surface

  • Exported: thin(), medial_axis(), distance_transform().
  • Internal: as_binary_matrix(), restore_storage() (helpers; not exported).

Extension points

To add a new thinning algorithm:

  1. Add src/<algorithm>.cpp exporting .<algorithm>_cpp(IntegerMatrix, int). Use the helpers in thinr_common.h.
  2. Run Rcpp::compileAttributes(".") so R/RcppExports.R is regenerated.
  3. Add the method name to the match.arg list and the switch() in R/thin.R.
  4. Add the method to the methods vector at the top of tests/testthat/test-thin.R — all property tests apply automatically.
  5. Update NEWS.md, the algorithms table in README.md, the algorithms section in R/thinr-package.R, and the algorithms table in vignettes/choosing-a-method.Rmd.
  6. Add the published reference to DESCRIPTION Description field if it has a DOI.

Documentation requirements

CRAN package documentation conventions:

  • Every exported function has Roxygen @param, @return, @examples.
  • Examples are runnable (R CMD check runs them with --run-donttest).
  • The vignette is non-trivial; it shows a real comparison of algorithms.
  • The README has install instructions and a usage snippet.
  • NEWS.md follows the standard "version - bullet list" format.
  • cran-comments.md is updated on every CRAN submission.

Workflow rules

Safe to auto-approve

  • R CMD check, devtools::check(), devtools::test(), devtools::document().
  • Rcpp::compileAttributes(), roxygen2::roxygenize().
  • lintr::lint_package(), styler::style_pkg(), covr::package_coverage().
  • pkgdown::build_site(), usethis::use_*() helpers that only edit local files.
  • Reading any file; ls, git status, git log, git diff.

Requires explicit confirmation

  • Adding / removing dependencies (this package wants to stay small).
  • Renaming / removing exported functions (breaking change).
  • Bumping the major version.
  • Modifying CI configuration.
  • Any git commit, tag, branch, or push.
  • Submitting to CRAN (devtools::submit_cran(), devtools::release()).
  • Modifying the LGPL-3 license declaration.

Never

  • Force-push.
  • Commit secrets.
  • Modify git config.
  • Skip git hooks.
  • Destructive resets without per-instance approval.

Process rules

  • Multi-step work: propose a plan, wait for explicit approval.
  • Surface suggestions; don't implement without approval.
  • Convert relative dates to absolute when committing or writing docs.

License

LGPL-3, per ADR-007 and ADR-017. Public CRAN release.

  • The LGPL-3 license is the same as EBImage's, so EBImage can depend on thinr without relicensing concerns.
  • Source files do not carry per-file copyright headers (CRAN convention); the LGPL-3 text is included by R's standard license machinery via License: LGPL-3 in DESCRIPTION.
  • Contributors retain copyright in their contributions, licensed under LGPL-3.