Skip to content
← All projects

JewelWeight

A Rhino 8 plugin that calculates the metal weight of jewelry models, built for my own work at a jewelry workshop and now used by my colleagues there.

Role
Solo. Spec, product decisions and testing by me; code written with Claude Code
Stack
Python 3.9, RhinoCommon, Eto.Forms, unittest
Platform
Rhino 8, Windows
Status
v1.0.0, in daily use at the workshop
Select the objects, press an alloy, get grams. The feed keeps every result, so alloys can be compared on the same selection.

Problem

In jewelry, weight is cost. Clients set budgets in grams, and the price of an order follows the metal.

Before JewelWeight, the weight of a model was found in one of two ways:

  • run Rhino's Volume command and multiply by the alloy density on a calculator, again for every alloy;
  • or not estimate it at all and find out after casting, when the model can no longer be changed.

Solution

One window inside Rhino: Select objects → press an alloy → weight in grams.

  • 8 standard alloys (585 and 750 red / yellow / white, 999, silver 925) plus custom alloys; every density is editable.
  • Validation before every calculation: open or non-manifold geometry is blocked, the broken objects are highlighted in the viewport, and the message says how to fix them.
  • Exported STL meshes that are printable but technically non-manifold are cleaned in memory and still calculated; the model itself is never changed.
  • Any document units are converted to mm³; weight is rounded half-up to 0.01 g.
  • The selection stays valid while the model changes: deleted objects and a switched document are detected on every click.

Proof: the 9-gram pair

estimated
8.99 g
limit
9.00 g
alloy
585 yellow
  • Order: a pair of rings in 585 yellow gold, no more than 9 g for both.
  • JewelWeight: 2 objects, 666.71 mm³ → 8.99 g in 585 yellow.
  • After casting: the weight matched the estimate. Finishing and polishing remove a little metal, so the finished pair came in slightly lighter, safely under 9 g.
  • Why per-alloy buttons matter: the same pair in 585 white is 9.17 g, over the limit. The alloy alone changes the answer by 0.18 g.
Two rings selected in Rhino. JewelWeight shows 2 objects and 666.71 mm³, a warning that intersecting bodies are counted twice, and 585 white: 9.17 g.
Same two rings checked in 585 white: 9.17 g, over the 9 g limit. The warning reminds you that intersecting bodies are counted twice.
JewelWeight window in Rhino showing 585 red, 750 yellow and silver 925 weights for one selected ring.

Engineering highlights

  1. Printable STL rejected as non-manifold. Duplicate and collapsed triangles break IsManifold but add no volume. Closed meshes are re-tested on a cleaned in-memory copy (weld vertices, cull degenerate and duplicate faces); if it passes, that volume is used and a note is shown.
  2. Correct grams in any units. The unit scale is cubed to mm³; documents without reliable units are rejected; rounding uses Decimal half-up, so 4.365 always becomes 4.37. Covered by unit tests.
  3. A selection that survives edits. Object IDs and the document serial are stored; every alloy click re-inspects the objects, drops deleted ones with a notice and highlights failing ones.
  4. A custom dark UI from Python inside Rhino. Eto.Forms via pythonnet: custom-drawn buttons with hover and pressed states (native WPF buttons broke the theme), deferred clicks so viewport picking works, one window per Rhino session.
  5. Settings that survive updates and broken files. UTF-8 JSON in %APPDATA% with schema versions and migrations, atomic writes, and a timestamped backup of damaged files. Only user overrides are stored, so improved defaults still reach unchanged alloys.

Rhino-free logic (calculation, storage, theme) lives in pure modules tested outside Rhino.

Numbers

lines of Python, 21 files
2,543
unit tests
65
built-in alloys + unlimited custom
8
third-party dependencies
0
first commit to release v1.0.0 in one evening
5 commits

How I built it with AI

I wrote the spec and the prompts and split the work into three phases: core calculation, settings and UI, installer. I made the product calls: weight only, no price, because the gold price changes daily and is quoted to the client later; Rhino 8 only; Russian UI, because the users are the workshop. I tested every phase in Rhino on real models, including the STL that failed validation, which led to the mesh-cleanup fix. Claude Code wrote the code and the unit tests from the spec.

What's next

  • A .yak package for food4Rhino
  • SubD support via conversion to Brep
  • Automatic toolbar setup (.rui)

Links

github.com/Khanapin-T/rhino-jewelweight

Learnt. Built. Shipped.