
Ich versuche, Text in Formen zu zeichnen (mithilfe von Skalierung und Pfad). Ich möchte, dass der Text folgendermaßen angezeigt wird:
Ich habe viele verschiedene Methoden ausprobiert, aber es gelingt mir nicht. Ich komme dem Problem mit etwas wie diesem hier näher:
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations.text}
\begin{document}
\pagenumbering{gobble}
\begin{tikzpicture}
\node (One) at (-15,0) {.};
\node (Two) at (15,0) {.};
\draw [decorate,decoration={text effects along path,
text={TTTTTTTTTTTTTTTT},
text align=center,
text effects/.cd,
path from text,
character count=\i, character total=\n,
characters= {text along path, scale=(2 + abs(\i - (\n / 2) - 0.5) * 1 )}}] (One) to (Two);
\end{tikzpicture}
\end{document}
Was dazu führt :
Ich möchte, dass die Oberseite des Textes nach oben gebogen ist, wie im gezeigten Beispiel.
Antwort1
\outline
Ich habe das Makro (erfordert pdflatex) nur aus Spaß eingefügt .
Das \outline
Zeug steht in der Präambel, während der Einschnürungscode im Hauptdokument steht. Ich habe den Code, aus dem es besteht, ursprünglich \outline
von Malipivo geklaut beiTikZ: Heiligenschein um Text?
Ich erstelle eine Box ( \mytext
) mit dem Text (ein wenig aufgefüllt, damit später nichts abgeschnitten wird) und wende dann nacheinander eine an, \clipbox
die die Textbox vertikal \cuts
mal aufschneidet. Bei jedem Schnitt wende ich eine an, \scalebox
um den Text als Funktion der Schnittnummer und zu verkleinern \dip
, was den maximalen Einschnürungsanteil darstellt. Die Funktion, die ich hier wähle, ist parabolisch, obwohl auch andere entwickelt werden können.
\documentclass{article}
\usepackage{ifthen,trimclip,calc,fp,graphicx,xcolor}
%%%%% FOR TEXT OUTLINING
\input pdf-trans
\newbox\qbox
\def\usecolor#1{\csname\string\color@#1\endcsname\space}
\newcommand\bordercolor[1]{\colsplit{1}{#1}}
\newcommand\fillcolor[1]{\colsplit{0}{#1}}
\newcommand\outline[1]{\leavevmode%
\def\maltext{#1}%
\setbox\qbox=\hbox{\maltext}%
\boxgs{Q q 2 Tr \thickness\space w \fillcol\space \bordercol\space}{}%
\copy\qbox%
}
\newcommand\colsplit[2]{\colorlet{tmpcolor}{#2}\edef\tmp{\usecolor{tmpcolor}}%
\def\tmpB{}\expandafter\colsplithelp\tmp\relax%
\ifnum0=#1\relax\edef\fillcol{\tmpB}\else\edef\bordercol{\tmpC}\fi}
\def\colsplithelp#1#2 #3\relax{%
\edef\tmpB{\tmpB#1#2 }%
\ifnum `#1>`9\relax\def\tmpC{#3}\else\colsplithelp#3\relax\fi
}
\bordercolor{blue}
\fillcolor{yellow}
\def\thickness{.5}
%%%%%
\begin{document}
\Huge
\edef\dip{.5}% percent to depress the amplitude
\def\cuts{200}% Number of cuts
\newsavebox\mytext
\savebox{\mytext}{\kern.3pt\textbf{\textsf{\outline{Valley Text}}}\kern.3pt}% TEXT
\newlength\clipsize
\FPeval{\myprod}{1/cuts}
\clipsize=\myprod\wd\mytext\relax
\newcounter{mycount}
\whiledo{\value{mycount}<\cuts}{%
\stepcounter{mycount}%
\edef\NA{\themycount}%
\edef\NB{\the\numexpr\cuts-\themycount\relax}%
\FPeval{\myprod}{1 - \dip*\NA*\NB*4/\cuts/\cuts}%
\clipbox{%
\value{mycount}\clipsize\relax{} %
-1pt %
\wd\mytext-\value{mycount}\clipsize-\clipsize\relax{} %
-1pt%
}{\scalebox{1}[\myprod]{\usebox{\mytext}}}%
}
\end{document}
Ohne den \outline
Code ist der Code übersichtlicher. (BEARBEITET) Hier konvertiere ich ihn in ein Makro \parabtext[<mode>]{<lift>}{<neck>}{<cuts>}{<content>}
mit mehreren Ergänzungen von oben:
<mode>
ist 0 für schmale Mitte und 1 für schmale Enden;
<lift>
ist der fraktionale Maximallift der Basislinie während der Transformation
<neck>
ist die geringfügige Verringerung der Gesamthöhe am Hals;
<cuts>
sind die Anzahl der vertikalen Scheiben, die auf die Box angewendet werden sollen (zu klein, und es sieht treppenförmig aus)
<content>
ist das Zeug, das man in eine Kiste packt und umwandelt.
\documentclass{article}
\usepackage{ifthen,trimclip,calc,fp,graphicx,xcolor}
\newsavebox\mytext
\newcounter{mycount}
\newlength\clipsize
\newcommand\parabtext[5][0]{%
\edef\neck{#3}% percent to depress the amplitude
\def\cuts{#4}% Number of cuts
\savebox{\mytext}{\kern.2pt#5\kern.2pt}% TEXT
\FPeval{\myprod}{1/cuts}%
\clipsize=\myprod\wd\mytext\relax%
\setcounter{mycount}{0}%
\whiledo{\value{mycount}<\cuts}{%
\stepcounter{mycount}%
\edef\NA{\themycount}%
\edef\NB{\the\numexpr\cuts-\themycount\relax}%
\FPeval{\myprod}{\NA*\NB*4/\cuts/\cuts}%
\ifnum0#1=0\relax%
\FPeval{\myprod}{1 - \neck*(\myprod)}%
\else%
\FPeval{\myprod}{1 - \neck*(1-\myprod)}%
\fi%
\clipbox{%
\value{mycount}\clipsize\relax{} %
-1pt %
\wd\mytext-\value{mycount}\clipsize-\clipsize\relax{} %
-1pt%
}{\raisebox{#2\dimexpr\ht\mytext-\myprod\ht\mytext}{%
\scalebox{1}[\myprod]{\usebox{\mytext}}}}%
}%
}
\begin{document}
\Huge\centering\def\X{\textbf{XXX}}%
\parabtext{0}{.7}{200}{\textbf{\textcolor{brown}{Valley Text}}}\par
\X\parabtext{0}{.7}{200}{\X}\parabtext[1]{0}{.7}{200}{\X}\X\par
\X\parabtext{1}{.7}{200}{\X}\parabtext[1]{1}{.7}{200}{\X}\X\par
\X\parabtext{.425}{.7}{200}{\X}\parabtext[1]{.425}{.7}{200}{\X}\X
\end{document}
Die zuletzt bearbeitete Option, <mode>
, ändert die Formfunktion der Transformation. In beiden Modi wird eine Funktion ausgewertet
\FPeval{\myprod}{\NA*\NB*4/\cuts/\cuts}%
Das ist eine Parabel, die an beiden Enden der Box den Wert 1 und in der Mitte den Wert 0 hat. Wenn der Modus 0 ist, lautet die Transformation
\FPeval{\myprod}{1 - \neck*(\myprod)}%
Wenn der Wert ungleich Null ist, ist die Transformation
\FPeval{\myprod}{1 - \neck*(1-\myprod)}%
Durch diesen einfachen Unterschied ergeben sich jeweils die Versionen mit Hals und die tonnenförmige Version.
VORGESCHLAGENE METHODIK
Die Methode ist zwar etwas rechenintensiv, soll aber für den Wow!-Effekt sparsam eingesetzt werden.
Zunächst zeige ich einen leicht veränderten Code, der tatsächlich von einer Vorwärtsdifferenz zu einer Zentraldifferenz führt, auch wenn der Rechenaufwand etwas höher sein kann.
Ich denke aber, dass es am besten funktioniert, die Anzahl der Slices in einer benutzerdefinierten Variable auf eine niedrige Zahl zu setzen \def\slices{5}
und Ihr Dokument auf dieser Grundlage zu entwickeln. Bei der endgültigen Kompilierung, wenn alles im endgültigen Layout festgelegt ist, setzen Sie \def\slices
die Zahl auf die gewünschte Zahl zurück {200}
und kompilieren Sie ein letztes Mal neu.
\documentclass{article}
\usepackage{ifthen,trimclip,calc,fp,graphicx,xcolor}
\newsavebox\mytext
\newcounter{mycount}
\newlength\clipsize
\newcommand\parabtext[5][0]{%
\edef\neck{#3}% percent to depress the amplitude
\def\cuts{#4}% Number of cuts
\savebox{\mytext}{\kern.2pt#5\kern.2pt}% TEXT
\FPeval{\myprod}{1/cuts}%
\clipsize=\myprod\wd\mytext\relax%
\setcounter{mycount}{0}%
\whiledo{\value{mycount}<\cuts}{%
\stepcounter{mycount}%
\edef\NA{\themycount}%
\edef\NB{\the\numexpr\cuts-\themycount\relax}%
\FPeval{\myprod}{(\NA-.5)*(\NB+.5)*4/\cuts/\cuts}%
\ifnum0#1=0\relax%
\FPeval{\myprod}{1 - \neck*(\myprod)}%
\else%
\FPeval{\myprod}{1 - \neck*(1-\myprod)}%
\fi%
\clipbox{%
\value{mycount}\clipsize-\clipsize\relax{} %
-1pt %
\wd\mytext-\value{mycount}\clipsize\relax{} %
-1pt%
}{\raisebox{#2\dimexpr\ht\mytext-\myprod\ht\mytext}{%
\scalebox{1}[\myprod]{\usebox{\mytext}}}}%
}%
}
\begin{document}
\def\slices{200}
\Huge\centering\def\X{\textbf{XXX}}%
\parabtext{0}{.7}{\slices}{\textbf{\textcolor{brown}{Valley Text}}}\par
\X\parabtext{0}{.7}{\slices}{\X}\parabtext[1]{0}{.7}{\slices}{\X}\X\par
\X\parabtext{1}{.7}{\slices}{\X}\parabtext[1]{1}{.7}{\slices}{\X}\X\par
\X\parabtext{.425}{.7}{\slices}{\X}\parabtext[1]{.425}{.7}{\slices}{\X}\X
\end{document}
Hier ist beispielsweise die Ausgabe mit \slices
der Einstellung 5
für die Lo-Res-Kompilierung:
HINWEIS FÜR XeLaTeX-BENUTZER
Der OP merkte an, dass dieser Ansatz in XeLaTeX nicht funktionierte. Nach einiger Untersuchung reduzierte ich das Problem auf einen Fehler im trimclip
Paket (\clipbox einer \scalebox funktioniert in xelatex nicht richtig). Joseph Wright war so freundlich, das Problem zu diagnostizieren und einen Patch für den trimclip
Code bereitzustellen, der in XeLaTeX ausgeführt wird.
\makeatletter
\ifdefined\XeTeXversion
\def\@cliptoboxdim#1{%
\setbox #1=\hbox{%
\Gin@defaultbp\WIDTH{\wd #1}%
\Gin@defaultbp \DEPTH {\dp #1}%
\@tempdima \ht #1%
\advance\@tempdima\dp#1%
\Gin@defaultbp \TOTALHEIGHT {\@tempdima }%
\special{pdf:literal q}%
\special{pdf:literal 0 -\DEPTH \space \WIDTH \space \TOTALHEIGHT \space re W n }%
\rlap{\copy #1}%
\special {pdf:literal Q}%
\hskip\wd#1%
}%
}
\fi
\makeatother
Antwort2
Aktualisieren
Durch die Verwendung eines Dreiecksnetzes können wir jede kontinuierliche Transformation approximieren.
\documentclass[border=9,tikz]{standalone}
\begin{document}
\pgfmathdeclarefunction{fx}{2}{\pgfmathparse{#1*(3+cos(#2*20))/3}}
\pgfmathdeclarefunction{fy}{2}{\pgfmathparse{#2*(3-cos(#1*20))/3}}
\pgfmathdeclarefunction{fxx}{2}{\pgfmathparse{fx(#1+1,#2)-fx(#1,#2)}}
\pgfmathdeclarefunction{fxy}{2}{\pgfmathparse{fy(#1+1,#2)-fy(#1,#2)}}
\pgfmathdeclarefunction{fyx}{2}{\pgfmathparse{fx(#1,#2+1)-fx(#1,#2)}}
\pgfmathdeclarefunction{fyy}{2}{\pgfmathparse{fy(#1,#2+1)-fy(#1,#2)}}
\tikz{
\path(-15,-15)(15,15);
\foreach\i in{-10,...,9}{
\foreach\j in{-10,...,9}{
\pgfmathsetmacro\aa{fxx(\i,\j)}
\pgfmathsetmacro\ab{fxy(\i,\j)}
\pgfmathsetmacro\ba{fyx(\i,\j)}
\pgfmathsetmacro\bb{fyy(\i,\j)}
\pgfmathsetmacro\xx{fx (\i,\j)}
\pgfmathsetmacro\yy{fy (\i,\j)}
\pgflowlevelobj{
\pgfsettransformentries{\aa}{\ab}{\ba}{\bb}{\xx cm}{\yy cm}
}{
\fill[black!10](1,0)--(0,0)--(0,1);
\clip(1,0)--(0,0)--(0,1)--cycle;
\tikzset{shift={(-\i,-\j)}}
\path(0,0)node{\includegraphics[width=20cm]{lena.png}};
}
\pgfmathsetmacro\aa{fxx(\i ,\j+1)}
\pgfmathsetmacro\ab{fxy(\i ,\j+1)}
\pgfmathsetmacro\ba{fyx(\i+1,\j )}
\pgfmathsetmacro\bb{fyy(\i+1,\j )}
\pgfmathsetmacro\xx{fx (\i+1,\j+1)}
\pgfmathsetmacro\yy{fy (\i+1,\j+1)}
\pgflowlevelobj{
\pgfsettransformentries{\aa}{\ab}{\ba}{\bb}{\xx cm}{\yy cm}
}{
\clip(0,0)--(-1,0)--(0,-1)--cycle;
\tikzset{shift={(-\i-1,-\j-1)}}
\path(0,0)node{\includegraphics[width=20cm]{lena.png}};
}
}
}
}
\end{document}
Alte Antwort
Ich kopiere einfach die Idee von @Steven B. Segletes, nur dass das Raster 2D ist und in PGF/Ti erstellt wirdkZ.
% !TEX program = XeLaTeX
% !TEX encoding = UTF-8 Unicode
\documentclass[border=9,tikz]{standalone}
\usepackage{fontspec}\setmainfont{Arial Unicode MS}
\begin{document}
\pgfmathdeclarefunction{fxx}{1}{\pgfmathparse{#1}}
\pgfmathdeclarefunction{fxy}{1}{\pgfmathparse{sin(222+30*#1)}}
\pgfmathdeclarefunction{fyx}{1}{\pgfmathparse{sin(20*#1)}}
\pgfmathdeclarefunction{fyy}{1}{\pgfmathparse{#1}}
\pgfmathdeclarefunction{gxx}{1}{\pgfmathparse{fxx(#1+1)-fxx(#1)}}
\pgfmathdeclarefunction{gxy}{1}{\pgfmathparse{fxy(#1+1)-fxy(#1)}}
\pgfmathdeclarefunction{gyx}{1}{\pgfmathparse{fyx(#1+1)-fyx(#1)}}
\pgfmathdeclarefunction{gyy}{1}{\pgfmathparse{fyy(#1+1)-fyy(#1)}}
\tikz{
\path(-2,-2)(103,23);
\foreach\i in{0,...,100}{
\foreach\j in{0,...,20}{
{
\pgfmathsetmacro\aa{gxx(\i)}
\pgfmathsetmacro\ab{gxy(\i)}
\pgfmathsetmacro\ba{gyx(\j)}
\pgfmathsetmacro\bb{gyy(\j)}
\pgfmathsetmacro\xx{fxx(\i)+fyx(\j)}
\pgfmathsetmacro\yy{fxy(\i)+fyy(\j)}
\pgflowlevelobj{
\pgfsettransformentries{\aa}{\ab}{\ba}{\bb}{\xx cm}{\yy cm}
}{
\clip(0,0)--(1,0)--(1,1)--(0,1)--cycle;
\draw[gray](1,0)--(0,0)--(0,1);
\path(-\i,-\j)+(50,10)node{\fontsize{500pt}{0}\selectfont Valley Text};
}
}
}
}
}
\end{document}
Etwas Mathematik
In meinem Code wird eine Transformation definiert durch
(x,y) |--> ( fxx(x)+fyx(y) , fxy(x)+fyy(y) )
wobei fxx, fyx, fxy, fyy sindGutFunktionen. Eine solche Transformation wandelt ein Quadrat in ein Parallelogramm um. Zufällig unterstützt PDF affine Transformationen, die ebenfalls ein Quadrat in ein Parallelogramm umwandeln. Daher kann ich eine stückweise affine Transformation verwenden, um die ursprüngliche Transformation anzunähern. Das Ergebnis ist, dass jede Kurve erhalten bleibtin Verbindung gebracht, obwohl nicht differenzierbar.