Aktualisieren

Aktualisieren

Ich versuche, Text in Formen zu zeichnen (mithilfe von Skalierung und Pfad). Ich möchte, dass der Text folgendermaßen angezeigt wird:

Valley Text

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 :

Ergebnis

Ich möchte, dass die Oberseite des Textes nach oben gebogen ist, wie im gezeigten Beispiel.

Antwort1

\outlineIch habe das Makro (erfordert pdflatex) nur aus Spaß eingefügt .

Das \outlineZeug steht in der Präambel, während der Einschnürungscode im Hauptdokument steht. Ich habe den Code, aus dem es besteht, ursprünglich \outlinevon 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, \clipboxdie die Textbox vertikal \cutsmal aufschneidet. Bei jedem Schnitt wende ich eine an, \scaleboxum 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}

Bildbeschreibung hier eingeben

Ohne den \outlineCode 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}

Bildbeschreibung hier eingeben

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\slicesdie 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 \slicesder Einstellung 5für die Lo-Res-Kompilierung:

Bildbeschreibung hier eingeben

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 trimclipPaket (\clipbox einer \scalebox funktioniert in xelatex nicht richtig). Joseph Wright war so freundlich, das Problem zu diagnostizieren und einen Patch für den trimclipCode 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.

verwandte Informationen