2012-11-16 17 views
14

Ich habe eine Reihe von Koordinaten, die ich in einen SVG-Pfad (mit kubischen Beziers, um es glatt zu machen) verwandeln. Wenn ich eine bestimmte Strichbreite anwenden, erhalte ich das folgende Ergebnis (die blauen Punkte meine Koordinaten) cubic svg path with stroke widthsvg: generate 'outline path'

Was mich interessiert ist, einen Weg zu bekommen, die sich um die graue Form läuft (wie: jeder Punkt holen auf der grau/weißen Umrandung und rund um die Form, bis du wieder am Startpunkt bist).

Wie würde ich einen solchen Pfad berechnen?

als Referenz, das ist mein svg Info:

<g> 
    <title>number 3</title> 
    <path d="m238,50c5.67569,-1.01351 11.8327,-3.8229 20.92029,-2.14724c8.68106,0.69732 14.21173,4.90255 18.07971,7.14724c6.23697,3.61945 13.47556,9.5931 15,18c1.07056,5.90372 1.17343,10.97649 -4,16c-6.76816,6.57204 -19.45392,9.57738 -25.69687,10.59046c-3.94836,0.64074 4.73492,3.29883 10.69687,5.40954c8.05417,2.85142 15,8 21,14c6,6 5.26578,10.94739 5.26578,17.03015c-2.4541,7.30975 -4.23343,11.08675 -11.26578,12.96985c-3.98279,1.0665 -11.92578,3.49756 -17,4c-8.95618,0.88684 -15.80411,2.97838 -26,0l-9.19197,-3.44464" id="svg_1" opacity="0.5" stroke-width="10" stroke-linejoin="round" stroke="#000000" fill="none"/> 
</g> 
+0

Das ist eine schwierige Frage. Müssen Sie es programmgesteuert machen oder können Sie Illustrator oder Inkscape verwenden? – Duopixel

+0

Ich muss dies programmatisch tun, aber wenn Sie sagen können, wie man in einem Programm tut, würde das auch nützlich sein ... danke! – Hoff

+1

In Illustrator wählen Sie den Pfad und das Menü Objekt> Darstellung erweitern. Ich habe nur eine vage Vorstellung von der Mathematik dahinter, aber es wäre keine einfache Aufgabe. – Duopixel

Antwort

1

I geschaffen, um die Funktion, die für svgContour Szenarien ähnlich wie gedacht ist,
die sich ergebende Kontur nicht auf den Wert stroke-width bezogenen Offset und muss als Parameter für die Funktion eingestellt werden.

Im Moment wird es immer eine Seite nach der anderen finden, aber wenn Sie es einmal pro Seite ausführen, können Sie dieses Problem lösen.

TLDR
Eigentlich durch svgContour Sie die Kontur aller svg Formen, zur Zeit ist es nicht Fill-Modi unterstützen, aber eines der nächsten Ziele ist, dass zu implementieren. es auf getPathData beruht(), um die PathData jeder SVGGeometryElement zu bekommen, dann geht diese Daten durch drei Phasen:

  • redrawSteepCurve
    Premise: eine Beizer-Kurve parallel zu einer anderen Zeichnung nicht erreicht Versatz der Punkte/Kontrollpunkte der Kurve nur , es sei denn, die Kurve ist ausreichend flach (in diesem Fall ist die visuelle Wiedergabe in Ordnung); Diese Methode benötigt SVGPathData und falls sie eine steile Kurve findet, teilt sie sie auf, bis sie flach genug ist (gibt ein visuell äquivalentes SVGPathData zurück).

  • contourPathData
    In diesem Stadium ist die PathData in Punkten dissambled wird, werden Punkte in den Segmenten verbunden sind, wobei jedes Segment offsetted ist, wird ein Schnittpunkt dann für jedes zusammenhängende Segment gefunden (was wir wieder eine Liste von versetzte Punkte).

  • drawLine
    Diese Phase stellt die Punkte aus Schritt 2 in der PathData aus Schritt 1, und zieht schließlich die Kontur.

Ein Beispiel:

const path = document.querySelector('path') 
 

 
svgContour(path, 5)
svg { 
 
    width: 100vw; 
 
    height: 100vh 
 
}
<script src="https://cdn.rawgit.com/fracalo/svg-contour/master/dist/svg-contour.js"></script> 
 

 
<svg viewBox='300 0 100 200'> 
 
    <g> 
 
    <title>number 3</title> 
 
    <path d="m238,50c5.67569,-1.01351 11.8327,-3.8229 20.92029,-2.14724c8.68106,0.69732 14.21173,4.90255 18.07971,7.14724c6.23697,3.61945 13.47556,9.5931 15,18c1.07056,5.90372 1.17343,10.97649 -4,16c-6.76816,6.57204 -19.45392,9.57738 -25.69687,10.59046c-3.94836,0.64074 4.73492,3.29883 10.69687,5.40954c8.05417,2.85142 15,8 21,14c6,6 5.26578,10.94739 5.26578,17.03015c-2.4541,7.30975 -4.23343,11.08675 -11.26578,12.96985c-3.98279,1.0665 -11.92578,3.49756 -17,4c-8.95618,0.88684 -15.80411,2.97838 -26,0l-9.19197,-3.44464" 
 
    id="svg_1" opacity="0.5" stroke-width="10" stroke-linejoin="round" stroke="#000000" fill="none" /> 
 
    </g> 
 
</svg>

die Kontur verfolgt wird!

+0

das ist großartig, danke! – Hoff

1

Ich bin nicht sicher, ob dies Ihr Problem löst. Es hängt davon ab, was Sie mit dem Outline-Pfad machen möchten.

PostScript verfügt über Funktionen zum Berechnen eines Umrisses für markierte Pfade, die beim Ausfüllen dieselbe visuelle Ausgabe erzeugen wie der ursprüngliche Pfad. Die resultierenden Pfaddaten sind jedoch möglicherweise weniger elegant als erwartet.

Das folgende Postscript-Programm (nennen wir es path2outlines.ps verwandelt einen Postscript-Pfad in einen „befüllbar“ SVG Pfad:.

%! 
% First, we're converting to outlines. 
strokepath 

% This is just a string buffer 
/S 99 string def 

% This defines a procedure for printing coordinates to stdout 
/printCoordinates {  % coord* number command 
    print     % coord* number 
    array astore   % array 
    {      % coord 
    ()print   % coord 
    //S cvs    % string 
    print    % 
    }forall 
    (\n)print 
} bind def 

% This iterates over the path segments and prints the SVG path data. 
{2(M) printCoordinates} 
{2(L) printCoordinates} 
{6(C) printCoordinates} 
{(Z\n)print} 
pathforall 

quit 

Sie haben es Datendateien wie diese zu füttern (% startet einen Kommentar) Lassen Sie uns Anruf diese data.ps:

%! 
% First, set up the graphics state parameters 
% Equivalent to stroke-width="10" 
10 setlinewidth 

% Equivalent to stroke-linejoin="round" (0 = miter, 1 = round, 2 = bevel) 
1 setlinejoin 

% Now, we're defining the path. 
% Use postfix notation, i.e. first coordinates, then command. 
% m/M = moveto 
% l = rlineto 
% L = lineto 
% c = rcurveto 
% C = curveto 

238 50 moveto 
5.67569 -1.01351 11.8327 -3.8229 20.92029 -2.14724 rcurveto 
8.68106 0.69732 14.21173 4.90255 18.07971 7.14724 rcurveto 
6.23697 3.61945 13.47556 9.5931 15 18 rcurveto 
1.07056 5.90372 1.17343 10.97649 -4 16 rcurveto 
-6.76816 6.57204 -19.45392 9.57738 -25.69687 10.59046 rcurveto 
-3.94836 0.64074 4.73492 3.29883 10.69687 5.40954 rcurveto 
8.05417 2.85142 15 8 21 14 rcurveto 
6 6 5.26578 10.94739 5.26578 17.03015 rcurveto 
-2.4541 7.30975 -4.23343 11.08675 -11.26578 12.96985 rcurveto 
-3.98279 1.0665 -11.92578 3.49756 -17 4 rcurveto 
-8.95618 0.88684 -15.80411 2.97838 -26 0 rcurveto 
-9.19197 -3.44464 rlineto 

auf der Plattform Je Sie verwenden, können Sie Ghostscript verwenden Sie es etwas ähnlich aufrufen zu:

gs -q data.ps path2outlines.ps > outlinePath.txt 

Probieren Sie es aus, aber ich bin mir nicht sicher, ob Sie zufrieden sein werden. Die Komplexität der Ausgabe könnte einen Hinweis auf die tatsächliche Komplexität des Problems geben. Besonders sich selbst überschneidende Pfade sind ein Problem.

Bearbeiten (von Problemen sprechen): Ich glaube, dass es im Allgemeinen mathematisch nicht möglich ist, eine Bézier-Kurve zu erstellen, die perfekt "parallel" zu einer gegebenen Bézier-Kurve ist.

0

Dies ist sehr anspruchsvoll. Ehrlich gesagt bezweifle ich, dass du in der Lage bist, einen Zaubercode zu schreiben, der das macht, ohne eine Lib, die es für dich tun wird.

Diese Technik wird manchmal "Puffer" genannt. So erstellen Sie einen Puffer um ein Objekt herum.

Wenn Sie Programmiersprache C verwenden können, sollten Sie sich die LEDA-Bibliothek anschauen. In Java weiß ich nichts, vielleicht die GeoTools lib.