Штриховка SVG: реальные контуры для перьевого плоттера
Создайте открытые контуры штриховки из замкнутой области SVG. Повторите проверки отверстия, интервала, угла и сохранённых файлов на собственном примере Paper.js.
На этой странице
- 1. Выберите область для заливки, а не линию для восстановления
- 2. Различайте обрезанный вид и укороченные контуры
- 3. Запустите полный пример Paper.js
- 4. Проверяйте интервал, угол и физический масштаб вместе
- 5. Отделяйте разрывы маршрутов от оптимального плана перемещений
- Исправьте типичные ошибки геометрии
- Частые вопросы
- Источники
Для штриховки SVG перьевым плоттером создайте открытые линии внутри нужной замкнутой области, разделите их на границах и экспортируйте оставшиеся отрезки как геометрию. До подготовки машинного задания проверьте сохранённый файл на маршруты через отверстия и за пределами фигуры.
Цветная заливка или полосатый предпросмотр сами по себе не задают эти маршруты рисования. В руководстве мы создаём собственную пятиугольную эмблему с прямоугольным отверстием, пересекаем открытые линии с этой областью в Paper.js и заново открываем сохранённые SVG для проверки. Проверки устанавливают цифровую осевую геометрию, а не успешное физическое рисование.
1. Выберите область для заливки, а не линию для восстановления
Нужна замкнутая область, отверстия которой входят в геометрию. Белый прямоугольник над сплошной фигурой может выглядеть отверстием, сохраняя область под ним целой. Документация GRBL-Plotter по штриховке показывает различие между наложенными объектами и отверстием внутри одного контура. Мы не запускали здесь GRBL-Plotter.
Если нужно восстановить одну линию посередине толстого растрового штриха, используйте руководство по однолинейному SVG. Штриховка создаёт множество линий поперёк области, а не восстанавливает исходную осевую линию пера.
Сохраните копию залитого рисунка. Пример намеренно создаёт маршруты штриховки без прохода по внешнему очертанию. Если нужно рисовать также внешнюю границу или границу отверстия, подготовьте их отдельными осознанными маршрутами.
2. Различайте обрезанный вид и укороченные контуры
Узор SVG рисует повторяющуюся плитку. Обтравочный контур ограничивает отрисованную область, не меняя исходную геометрию. Оба способа полезны для экранного изображения, но программе ещё нужен метод превращения вида в маршруты пера.
Наш контрольный вариант только с обтравкой хранит десять горизонтальных линий по 200 пользовательских единиц. Обтравка скрывает внешние части и прямоугольное отверстие. Сохранённая суммарная длина линий по-прежнему 2 000 единиц.
Укороченный редкий экспорт содержит 14 отдельных открытых контуров общей длиной 1 320 единиц. В нём нет обтравочного контура, узора, маски, встроенного изображения или повторно используемого символа. Четыре строки штриховки делятся вокруг отверстия на два контура. Эту разницу видно в сохранённом SVG, даже если предпросмотры с обтравкой и укороченными линиями похожи.

Руководство по единицам узоров SVG рассматривает повторяющуюся окраску, если нужна именно она. Здесь требуются явные открытые геометрические линии.
3. Запустите полный пример Paper.js
Используйте браузер, текстовый редактор и полную сборку Paper.js 0.12.18 из официального выпуска. Поместите paper-full.min.js в папку library. Сохраните HTML как generate.html, а следующий JavaScript как hatch.js рядом с этой папкой. Собственная эмблема включена в код.
<!doctype html>
<html lang="en">
<meta charset="utf-8">
<title>Generate original hatch routes</title>
<canvas id="work" width="200" height="140" hidden></canvas>
<p id="status">Running</p>
<pre id="export-receipt"></pre>
<h2>0 degrees, 10-unit spacing</h2>
<img id="preview-coarse" width="400" alt="Coarse hatch">
<pre id="svg-coarse"></pre>
<h2>0 degrees, 5-unit spacing</h2>
<img id="preview-dense" width="400" alt="Dense hatch">
<pre id="svg-dense"></pre>
<h2>30 degrees, 10-unit spacing</h2>
<img id="preview-angled" width="400" alt="Angled hatch">
<pre id="svg-angled"></pre>
<script src="library/paper-full.min.js"></script>
<script src="hatch.js"></script>
</html>paper.setup(document.getElementById('work'));
// Original area: a five-sided boundary with a rectangular hole.
const areaData = 'M20 20 L140 20 L180 60 L180 120 L20 120 Z ' +
'M60 50 L60 90 L110 90 L110 50 Z';
const configurations = [
{ id: 'coarse', angle: 0, spacing: 10 },
{ id: 'dense', angle: 0, spacing: 5 },
{ id: 'angled', angle: 30, spacing: 10 }
];
function makeHatch(angle, spacing) {
const area = new paper.CompoundPath({
pathData: areaData,
fillRule: 'nonzero',
insert: false
});
const radians = angle * Math.PI / 180;
const direction = new paper.Point(Math.cos(radians), Math.sin(radians));
const normal = new paper.Point(-direction.y, direction.x);
const center = new paper.Point(100, 70);
const delivery = new paper.Group({ insert: false });
for (let offset = -200 + spacing / 2; offset < 200; offset += spacing) {
const origin = center.add(normal.multiply(offset));
const line = new paper.Path.Line({
from: origin.subtract(direction.multiply(300)),
to: origin.add(direction.multiply(300)),
insert: false
});
const kept = line.intersect(area, { trace: false, insert: false });
const parts = kept instanceof paper.CompoundPath ? [...kept.children] : [kept];
const routes = parts.filter(path => path.length > 1e-7);
for (const path of routes) {
if (path.closed || path.segments.length !== 2) {
throw new Error('Expected one open straight segment');
}
if (path.firstSegment.point.dot(direction) > path.lastSegment.point.dot(direction)) {
path.reverse();
}
}
routes.sort((a, b) => a.firstSegment.point.dot(direction) - b.firstSegment.point.dot(direction));
for (const path of routes) {
path.fillColor = null;
path.strokeColor = '#2f6977';
path.strokeWidth = 1;
path.strokeCap = 'butt';
delivery.addChild(path);
}
if (kept instanceof paper.CompoundPath || routes.length === 0) {
kept.remove();
}
line.remove();
}
area.remove();
const geometry = delivery.exportSVG({ asString: true, precision: 6 });
const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="100mm" height="70mm" ' +
'viewBox="0 0 200 140">' + geometry + '</svg>';
const routeCount = delivery.children.length;
const drawnLength = delivery.children.reduce((sum, path) => sum + path.length, 0);
let transitionLength = 0;
for (let index = 1; index < routeCount; index += 1) {
transitionLength += delivery.children[index - 1].lastSegment.point
.getDistance(delivery.children[index].firstSegment.point);
}
delivery.remove();
return { svg, routeCount, drawnLength, transitionLength };
}
const receipt = { paper: paper.version, units: 'viewBox user units; 0.5 mm per unit', rows: [] };
for (const configuration of configurations) {
const result = makeHatch(configuration.angle, configuration.spacing);
document.getElementById('svg-' + configuration.id).textContent = result.svg;
const preview = document.getElementById('preview-' + configuration.id);
preview.src = URL.createObjectURL(new Blob([result.svg], { type: 'image/svg+xml' }));
receipt.rows.push({ ...configuration, route_count: result.routeCount,
drawn_length: result.drawnLength, transition_length: result.transitionLength });
}
document.getElementById('export-receipt').textContent = JSON.stringify(receipt, null, 2);
document.getElementById('status').textContent = 'Generated. Save each exact SVG shown below, then reopen those saved files for independent checks.';Откройте generate.html в браузере. Мы запускали его с Paper.js 0.12.18 в Chromium 155. Каждый результат показывает предпросмотр и точную разметку SVG. Скопируйте три полные строки SVG в hatch-coarse.svg, hatch-dense.svg и hatch-angled.svg, затем независимо откройте сохранённые файлы.
Ключевой вызов — line.intersect(area, { trace: false, insert: false }). Paper.js описывает trace: false как разделение первого контура на пересечениях с сохранением его кривых внутри области второго контура. Так сохраняются открытые отрезки штриховки. Стандартный режим обведения областей решает другую булеву задачу; этот процесс рассматривает руководство по залитым фигурам Paper.js.
Функция устанавливает fillColor в null и задаёт каждому маршруту обводку. Перед экспортом она также проверяет открытые результаты с двумя точками. Замкнутая область остаётся вспомогательной конструкцией и не входит в передаваемую группу.
4. Проверяйте интервал, угол и физический масштаб вместе
Все три экспорта объявляют width="100mm", height="70mm" и viewBox="0 0 200 140". Это даёт 0,5 мм на пользовательскую единицу SVG. Поэтому интервал штриховки 10 единиц означает 5 мм, а 5 единиц — 2,5 мм.
Эти намеренно широкие интервалы упрощают проверку отдельных маршрутов. Они не рекомендуются для сплошного покрытия чернилами. Экранная обводка имеет ширину одну пользовательскую единицу, но её вид не измеряет след настоящего пера на материале.
Цикл смещений фиксирует фазу штриховки на половине интервала. Изменение фазы может изменить элементы границы, с которыми пересекается линия. При положительных 30° направление идёт вниз вправо в этой системе координат SVG. Интервал измеряется перпендикулярно параллельным линиям, а не как вертикальное расстояние на экране.
| Сохранённый файл | Угол | Интервал | Открытые маршруты | Длина нарисованных осевых линий |
|---|---|---|---|---|
hatch-coarse.svg | 0° | 10 единиц / 5 мм | 14 | 1 320 единиц / 660 мм |
hatch-dense.svg | 0° | 5 единиц / 2,5 мм | 28 | 2 640 единиц / 1 320 мм |
hatch-angled.svg | 30° | 10 единиц / 5 мм | 20 | Около 1 318,564 единиц / 659,282 мм |
Мы независимо рассчитали ожидаемые пересечения линий и многоугольника, затем сравнили сохранённые координаты с допуском 0,000002 пользовательской единицы. Концы каждого экспортированного маршрута совпали с ожидаемыми. Все маршруты были открыты, и ни одна проверенная точка осевой линии не попадала в отверстие или наружу сверх допуска. Все три сохранённых SVG сохранили заявленное соответствие физическим размерам.
Для другой фигуры проверяйте реальные экспортированные маршруты, не ожидая тех же чисел. Кривые, очень узкие промежутки, самопересечения, преобразованные группы и произвольные импортированные документы SVG находятся вне области тестирования этого примера.
5. Отделяйте разрывы маршрутов от оптимального плана перемещений
Редкий файл содержит 14 открытых маршрутов и 13 промежутков между соседними маршрутами в порядке записи. Соединение этих промежутков с опущенным пером добавит ненужные следы. До рисования ваш процесс должен правильно обрабатывать переходы.
Скрипт сохраняет простой однонаправленный порядок: последовательно обходит смещения и проходит каждый отрезок в одном направлении. Сумма прямых расстояний от конца маршрута до начала следующего составляет около 1 562,997 пользовательских единиц для редкого файла. В плотном файле 27 промежутков с суммой соединителей около 3 281,578 единиц.
Эти суммы не включают начальный подход и конечный возврат. Это геометрические последствия данного порядка, а не измеренный ход машины, оценка времени или оптимальный план. Программа плоттера может разворачивать или переставлять маршруты. Уменьшение интервала вдвое удвоило длину рисунка и число маршрутов этого образца, но не установило универсального удвоения времени задания.
Заново откройте файл в программе управления плоттером, проверьте размер, предпросмотр маршрутов и подъём пера. Испытайте перо, материал, интервал, отступ от границ и настройки движения на своей установке. Мы не запускали задание плоттера, не создавали машинный код и не тестировали Cricut Draw/Attach.
Исправьте типичные ошибки геометрии
| Симптом | Что проверить и изменить |
|---|---|
| Штриховка пересекает нужное отверстие | Проверьте залитую область. До пересечения замените белое наложение настоящим отверстием в составной геометрии. |
| Предпросмотр верен, но полные линии остались | Ищите зависимость от обтравки или узора. Проверяйте сохранённые координаты маршрутов, а не только отрисованный силуэт. |
| Линии стали замкнутыми фигурами | Подтвердите, что первый операнд — открытая линия и есть trace: false. Пример отвергает замкнутые и многосегментные результаты. |
| Чернила выходят за границу | Различайте осевую линию и отпечаток обводки. Пример не сужает область на радиус пера; подготовьте подходящий отступ и испытайте настоящий инструмент. |
| Заливка редкая или поверхность слишком мокрая | Настраивайте на контролируемом образце пера и материала. Один цифровой интервал не определяет покрытие и высыхание. |
| Файл совершает неожиданные скачки | Проверьте порядок и переходы с поднятым пером в целевой программе. Сохраните исходные маршруты перед оптимизацией, затем перепроверьте отверстия и границы. |
Если источник — только плоский растровый силуэт, процесс клипарта в SVG PerfectVector поможет сначала восстановить замкнутый рисунок. Осмотрите очертание и каждое отверстие, затем создайте штриховку из принятой геометрии. Существующий чистый вектор можно сразу готовить к штриховке.
Векторизация силуэта и создание маршрутов штриховки — отдельные этапы. Собственная эмблема этой статьи создана векторной геометрией и не является образцом конвертации PerfectVector.
Частые вопросы
Превращается ли заливка SVG в штриховку пера автоматически? Нет. Заливка описывает закрашенный вид. Процесс плоттера требует маршрутов штриховки или другого поддерживаемого способа создания рисуемых штрихов из области.
Почему в предпросмотре штриховки остались линии через отверстие? Обтравка может скрывать части полных линий без изменения сохранённой геометрии. Проверьте координаты и включите отверстие в настоящую область до создания явных маршрутов.
Какой интервал штриховки использовать? Выбирайте его испытанием пера и материала в нужном масштабе. Этот цифровой пример использует 5 и 2,5 мм для наглядности; он не устанавливает сплошное покрытие или универсальную настройку пера.
Это один непрерывный контур? Нет. Редкий результат содержит 14 отдельных открытых маршрутов. Отверстие разделяет четыре строки, и процесс рисования должен обрабатывать разрывы без лишних следов.
Источники
- Пересечение PathItem Paper.js — Описывает разделение открытых контуров при trace false.
- Узоры SVG — Определяет повторяющуюся окраску отдельно от явной геометрии маршрутов.
- Маски и обтравочные контуры CSS — Объясняет, почему обтравка меняет отрисовку, не укорачивая исходную фигуру.
- Штриховка GRBL-Plotter — Показывает различие наложенных объектов и отверстия в одном контуре.
- Выпуск Paper.js 0.12.18 — Определяет версию библиотеки рабочего примера.
Если растровому силуэту нужны редактируемые границы, подготовьте кандидат SVG из клипарта, проверьте отверстия и отдельно создайте и проверьте штриховку до испытания физического задания.
Ещё из блога

Линии биговки и реза SVG: читайте геометрию
Прочитайте геометрию сгиба SVG до назначения Score или Cut. Сравните открытые контуры, залитые полосы и пунктир, затем проверьте документированный процесс Cricut.

Трафареты для травления стекла: что удалять
Выберите защищённые и открытые области маски для стекла. Проверьте эмблему, островки просветов и взаимодополняющие схемы с учётом ограничений поставщика.
