PerfectVector
Di Irene Kim

Tratteggio SVG: crea veri tracciati per pen plotter

Genera tracciati di tratteggio aperti da un'area SVG chiusa. Riproduci i controlli di fori, spaziatura, angolo e file salvati con un esempio originale Paper.js.

12 min di lettura
In questa pagina

Per riempire un SVG con tratteggio per un pen plotter, genera linee aperte dentro l'area chiusa prevista, dividile ai suoi confini ed esporta i segmenti rimanenti come geometria. Controlla nel file salvato i percorsi attraverso i fori e fuori dalla forma prima di preparare il lavoro macchina.

Un riempimento colorato o un'anteprima a strisce non forniscono da soli quei percorsi di disegno. Questo tutorial costruisce un emblema originale a cinque lati con un foro rettangolare, usa Paper.js per intersecare linee aperte con quell'area e riapre gli SVG salvati per l'ispezione. I controlli stabiliscono geometria digitale delle linee centrali, non un tracciamento fisico riuscito.

1. Scegli un'area da riempire, non una linea da recuperare

Ti serve una regione chiusa i cui fori facciano parte della geometria. Un rettangolo bianco sopra una forma piena può sembrare un foro ma lasciare intatta la regione sottostante. La documentazione sul tratteggio di GRBL-Plotter illustra questa distinzione tra oggetti sovrapposti e un'apertura dentro un tracciato. Qui non abbiamo eseguito GRBL-Plotter.

Se vuoi recuperare un tratto al centro di una linea raster spessa, usa la guida agli SVG a linea singola. Il tratteggio crea più tratti attraverso un'area; non recupera la linea centrale originale della penna.

Conserva una copia della grafica piena. L'esempio produce deliberatamente percorsi di tratteggio senza aggiungere un passaggio sul contorno. Se vuoi disegnare anche il confine esterno o quello del foro, preparali come percorsi separati e intenzionali.

2. Distingui aspetto ritagliato e tracciati tagliati

Un pattern SVG dipinge una tessera ripetuta. Un tracciato di ritaglio limita la regione renderizzata senza cambiare la geometria sottostante. Entrambi possono creare un'immagine utile a schermo, ma un'applicazione richiede ancora un metodo per trasformare quell'aspetto in percorsi di penna.

Il nostro controllo con solo ritaglio memorizza dieci linee orizzontali, ciascuna lunga 200 unità utente. Il ritaglio ne nasconde le parti esterne e l'apertura rettangolare. Le lunghezze delle linee memorizzate sommano ancora 2000 unità.

L'esportazione a spaziatura ampia con segmenti tagliati contiene 14 tracciati aperti separati per un totale di 1320 unità. Non ha tracciati di ritaglio, pattern, maschere, immagini incorporate o simboli riutilizzati. Quattro righe di tratteggio si dividono in due tracciati intorno al foro. La differenza è ispezionabile nell'SVG salvato, anche quando le anteprime ritagliata e tagliata si assomigliano.

SVG effettivamente riaperti confrontano un'anteprima di tratteggio con solo ritaglio e tracciati di tratteggio aperti espliciti a due spaziature e con angolo di 30 gradi
Campione digitale originale ed esportazioni effettive di Paper.js. Il foro rimane aperto in tutti e tre i file di percorsi. I controlli riguardano le linee centrali; non è stato eseguito alcun test con plotter o penna fisica.

La guida alle unità dei pattern SVG tratta il colore ripetuto quando è l'uscita prevista. Qui l'uscita richiesta è geometria aperta esplicita.

3. Esegui l'esempio completo Paper.js

Usa un browser, un editor di testo e la build completa Paper.js 0.12.18 dal rilascio ufficiale. Inserisci paper-full.min.js in una cartella library. Salva questo HTML come generate.html e il JavaScript seguente come hatch.js accanto a quella cartella. L'emblema originale è incluso nel codice.

<!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.';

Apri generate.html nel browser. Lo abbiamo eseguito con Paper.js 0.12.18 in Chromium 155. Ogni risultato mostra un'anteprima e il suo markup SVG esatto. Copia le tre stringhe SVG complete in hatch-coarse.svg, hatch-dense.svg e hatch-angled.svg, poi apri quei file salvati indipendentemente.

La chiamata fondamentale è line.intersect(area, { trace: false, insert: false }). Paper.js documenta trace: false come divisione del primo tracciato alle intersezioni e conservazione delle sue curve dentro l'area del secondo tracciato. Questo mantiene i segmenti aperti di tratteggio. La modalità predefinita di tracciamento delle aree risponde a una domanda booleana diversa; la guida alle forme piene Paper.js tratta quel flusso.

La funzione imposta fillColor su null e assegna un tratto a ogni percorso. Controlla anche che i risultati siano aperti a due punti prima dell'esportazione. L'area chiusa rimane un aiuto di costruzione e non è inclusa nel gruppo di consegna.

4. Controlla insieme spaziatura, angolo e scala fisica

Tutte e tre le esportazioni dichiarano width="100mm", height="70mm" e viewBox="0 0 200 140". Questo mappa un'unità utente su 0.5 mm nell'SVG. Una spaziatura di tratteggio da 10 unità rappresenta quindi 5 mm; 5 unità rappresentano 2.5 mm.

Queste spaziature volutamente ampie rendono facili da esaminare i singoli percorsi. Non sono raccomandazioni per una copertura piena d'inchiostro. Il tratto a schermo è largo un'unità utente, ma il suo aspetto non misura il segno di una penna reale su un materiale.

Il ciclo degli scostamenti fissa la fase del tratteggio a metà spaziatura. Cambiare quella fase può cambiare quali caratteristiche del confine incontra una linea. A 30° positivi, la direzione scende verso destra in questo sistema di coordinate SVG. La spaziatura è misurata perpendicolarmente alle linee parallele, non come separazione verticale a schermo.

File salvatoAngoloSpaziaturaPercorsi apertiLunghezza delle linee centrali disegnate
hatch-coarse.svg0°10 unità / 5 mm141320 unità / 660 mm
hatch-dense.svg0°5 unità / 2.5 mm282640 unità / 1320 mm
hatch-angled.svg30°10 unità / 5 mm20Circa 1318.564 unità / 659.282 mm

Abbiamo calcolato indipendentemente le intersezioni previste tra linee e poligono, poi confrontato le coordinate salvate con una tolleranza di 0.000002 unità utente. Ogni percorso esportato corrispondeva alle estremità previste. Ogni percorso era aperto e nessun punto campionato della linea centrale attraversava il foro o l'esterno oltre quella tolleranza. Tutti e tre gli SVG salvati conservavano la mappatura dichiarata delle dimensioni fisiche.

Per un'altra forma, controlla i percorsi effettivamente esportati invece di presumere che valgano i conteggi di questo campione. Curve, spazi molto piccoli, autointersezioni, gruppi trasformati e documenti SVG importati arbitrari sono fuori dall'ambito del test di questo esempio.

5. Separa gli spazi tra percorsi da un piano di movimento ottimizzato

Il file a spaziatura ampia ha 14 percorsi aperti e 13 spazi tra percorsi consecutivi nell'ordine serializzato. Collegare quegli spazi con la penna abbassata aggiungerebbe segni indesiderati. Il flusso di disegno deve gestire le transizioni come previsto prima di disegnare.

Lo script mantiene un semplice ordine a senso unico: visita gli scostamenti del tratteggio in sequenza e segue ogni segmento nella stessa direzione. Sommare le distanze rettilinee dalla fine di ogni percorso all'inizio del successivo dà circa 1562.997 unità utente per il file a spaziatura ampia. Il file più denso ha 27 spazi e una somma dei collegamenti di circa 3281.578 unità.

Quelle somme escludono l'avvicinamento iniziale e il ritorno finale. Sono conseguenze geometriche di questo ordine, non movimento macchina misurato, una stima del tempo o un piano ottimizzato. Un'applicazione di disegno può invertire o riordinare i percorsi. Dimezzare la spaziatura ha raddoppiato lunghezza disegnata e numero di percorsi di questo campione; non ha stabilito un raddoppio universale del tempo di lavoro.

Riapri il file nell'applicazione che controllerà il plotter, verificane le dimensioni ed esamina anteprima dei percorsi e comportamento di sollevamento della penna. Prova penna, materiale, spaziatura, distanza dai bordi e impostazioni di movimento sulla tua configurazione. Non abbiamo eseguito un lavoro con plotter, generato codice macchina o provato Cricut Draw/Attach.

Correggi gli errori geometrici più comuni

SintomoChe cosa esaminare e cambiare
Il tratteggio attraversa il foro previstoEsamina l'area piena. Sostituisci una sovrapposizione bianca con un'apertura reale nella geometria composta prima dell'intersezione.
L'anteprima è corretta ma restano linee completeCerca una dipendenza da ritaglio o pattern. Esamina le coordinate dei percorsi salvati invece di affidarti alla sagoma renderizzata.
Le linee diventano forme chiuseConferma che il primo operando sia una linea aperta e che sia presente trace: false. L'esempio rifiuta risultati chiusi o con più segmenti.
L'inchiostro si estende oltre un confineDistingui la linea centrale dall'ingombro del tratto. Questo esempio non rientra l'area del raggio del pennino; prepara una distanza adatta e prova lo strumento effettivo.
Il riempimento è rado o la superficie diventa troppo bagnataRegola usando un campione controllato di penna/materiale. La sola spaziatura digitale non stabilisce copertura o comportamento di asciugatura.
Il file compie salti inattesiEsamina ordine e transizioni a penna sollevata nel software di destinazione. Conserva i percorsi originali prima di applicare un ottimizzatore, poi ricontrolla fori e confini.

Se la sorgente è soltanto una sagoma raster piatta, il flusso da clipart a SVG di PerfectVector può aiutare a recuperare prima grafica chiusa. Esamina contorno e ogni apertura, poi genera i percorsi di tratteggio dalla geometria accettata. Grafica vettoriale pulita esistente può passare direttamente alla preparazione del tratteggio.

Vettorizzare la sagoma e generare i percorsi di tratteggio sono passaggi separati. L'emblema originale di questo articolo è stato scritto come geometria vettoriale; non è un campione di conversione PerfectVector.

Domande frequenti

Un riempimento SVG diventa automaticamente tratteggio per penna? No. Un riempimento descrive l'aspetto dipinto. Un flusso con plotter richiede percorsi di tratteggio o un altro modo supportato per creare tratti di disegno da quell'area.

Perché l'anteprima del tratteggio contiene ancora linee attraverso il foro? Un ritaglio può nascondere parti di linee complete senza tagliarne la geometria memorizzata. Controlla le coordinate salvate e rendi il foro parte dell'area effettiva prima di produrre percorsi espliciti.

Quale spaziatura di tratteggio dovrei usare? Sceglila con una prova di penna e materiale alla scala prevista. Questo esempio digitale usa spaziature di 5 mm e 2.5 mm per rendere visibili i percorsi; non stabilisce copertura piena o un'impostazione universale della penna.

È un unico tracciato continuo? No. Il risultato a spaziatura ampia contiene 14 percorsi aperti separati. Il suo foro divide quattro righe e il flusso di disegno deve gestire gli spazi tra percorsi senza aggiungere segni indesiderati.

Fonti

  1. Intersezione PathItem di Paper.js — Documenta il comportamento di divisione dei tracciati aperti di trace false.
  2. Pattern SVG — Definisce il colore ripetuto separatamente dalla geometria esplicita dei percorsi.
  3. Mascheratura CSS e tracciati di ritaglio — Spiega perché il ritaglio cambia il rendering senza tagliare la forma sottostante.
  4. Riempimento a tratteggio GRBL-Plotter — Mostra la distinzione tra oggetti sovrapposti e un foro dentro un tracciato.
  5. Rilascio Paper.js 0.12.18 — Identifica la versione della libreria usata per l'esempio eseguibile.

Se una sagoma disponibile solo come raster richiede confini modificabili, prepara un SVG candidato della clipart, esaminane i fori e genera e verifica separatamente i percorsi di tratteggio prima di provare il lavoro fisico.

Altro dal blog

PerfectVector

Prepara tracciati SVG puliti per
taglio e produzione

Nessuna carta di credito