JewelWeight
Плагин для Rhino 8, который считает вес металла в ювелирных моделях. Сделал для своей работы в ювелирной мастерской, теперь им пользуются и коллеги.
- Роль
- Один. ТЗ, продуктовые решения и тестирование мои; код написан с Claude Code
- Стек
- Python 3.9, RhinoCommon, Eto.Forms, unittest
- Платформа
- Rhino 8, Windows
- Статус
- v1.0.0, ежедневно используется в мастерской
- Ссылки
- GitHub Релиз v1.0.0
Проблема
В ювелирке вес — это цена. Клиенты задают бюджет в граммах, и стоимость заказа идёт от металла.
До JewelWeight вес модели узнавали одним из двух способов:
- команда
Volumeв Rhino и умножение на плотность сплава на калькуляторе, заново для каждого сплава; - или вообще без расчёта: вес становился известен после отливки, когда модель уже не исправить.
Решение
Одно окно внутри Rhino: выдели объекты → нажми сплав → вес в граммах.
- 8 стандартных сплавов (585 и 750 красное / жёлтое / белое, 999, серебро 925) и свои сплавы; любую плотность можно изменить.
- Проверка перед каждым расчётом: открытая или non-manifold геометрия блокируется, проблемные объекты подсвечиваются во viewport, а сообщение говорит, как исправить.
- STL, которые печатаются, но формально non-manifold, очищаются в памяти и всё равно считаются; сама модель не меняется.
- Любые единицы документа переводятся в мм³; вес округляется half-up до 0.01 г.
- Выделение остаётся рабочим, пока модель меняется: удалённые объекты и смена документа определяются при каждом клике.
Доказательство: пара на 9 грамм
- расчёт
- 8.99 г
- лимит
- 9.00 г
- сплав
- 585 жёлтое
- Заказ: пара колец из 585 жёлтого золота, не больше 9 г за обе.
- JewelWeight: 2 объекта, 666.71 мм³ → 8.99 г в 585 жёлтом.
- После отливки: вес совпал с расчётом. Обработка и полировка снимают немного металла, поэтому готовая пара вышла чуть легче и спокойно уложилась в 9 г.
- Почему отдельная кнопка на каждый сплав: та же пара в 585 белом весит 9.17 г, это больше лимита. Один только сплав меняет ответ на 0.18 г.


Инженерные задачи
- Печатный STL отклонялся как non-manifold. Дублированные и вырожденные треугольники ломают
IsManifold, но не добавляют объёма. Закрытые меши перепроверяются на очищенной копии в памяти (сварка вершин, удаление вырожденных и дублированных граней); если копия проходит, берётся её объём и показывается заметка. - Правильные граммы в любых единицах. Масштаб единиц возводится в куб до мм³; документы без надёжных единиц отклоняются; округление через
Decimalhalf-up, поэтому 4.365 всегда становится 4.37. Покрыто unit-тестами. - Выделение, которое переживает правки. Хранятся ID объектов и serial документа; каждый клик по сплаву заново проверяет объекты, исключает удалённые с уведомлением и подсвечивает проблемные.
- Своя тёмная тема из Python внутри Rhino. Eto.Forms через pythonnet: кнопки отрисованы вручную с hover и pressed (нативные WPF-кнопки ломали тему), отложенный клик, чтобы работал выбор во viewport, одно окно на сессию Rhino.
- Настройки переживают обновления и битые файлы. UTF-8 JSON в
%APPDATA%с версией схемы и миграциями, атомарная запись, бэкап повреждённого файла с меткой времени. Хранятся только изменения пользователя, поэтому улучшенные значения по умолчанию доходят до неизменённых сплавов.
Логика без Rhino (расчёт, хранение, тема) вынесена в чистые модули с тестами вне Rhino.
Цифры
- строки Python, 21 файл
- 2 543
- unit-тестов
- 65
- встроенных сплавов + сколько угодно своих
- 8
- сторонних зависимостей
- 0
- от первого коммита до релиза v1.0.0 за один вечер
- 5 коммитов
Как я сделал это с ИИ
Я написал ТЗ и промпты и разбил работу на три фазы: ядро расчёта, настройки и UI, установщик. Продуктовые решения мои: только вес, без цены, потому что цена золота меняется каждый день и называется клиенту позже; только Rhino 8; интерфейс на русском, потому что пользователи — мастерская. Каждую фазу я проверял в Rhino на реальных моделях, включая STL, который не проходил проверку; из-за него появилась очистка мешей. Код и unit-тесты по ТЗ написал Claude Code.
Что дальше
- Пакет
.yakдля food4Rhino - Поддержка SubD через конвертацию в Brep
- Автоматическая установка toolbar (
.rui)
Ссылки
github.com/Khanapin-T/rhino-jewelweight
Learnt. Built. Shipped.