라텍스의 예

라텍스의 예

tikz의 경로를 따라 텍스트 정렬에 문제가 있습니다. 나는 사용자 정의 모양을 만들고 다음과 같은 방법으로 그 안에 경로를 따라 텍스트를 썼습니다.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations.text}
\begin{document}
\begin{tikzpicture}

% shape
\draw (70:3) arc (70:110:3)
   -- (110:5)  arc (110:70:5)
   -- cycle;

\path[
  postaction={
    decorate,
    decoration={
      text along path,
      text align = center,
      text={Gershon Daly Bonifacy Yaw}
    }
  }
]
(105:4.5) arc (105:75:4.5)
(105:4.0) arc (105:75:4.0)
(105:3.5) arc (105:75:3.5);

\end{tikzpicture}
\end{document}

결과는 꽤 괜찮으나 작은 문제가 있습니다. 이것은 출력이다없이중앙 정렬:

정렬하지 않고

그리고 이건~와 함께중앙 정렬:

정렬로

내 문제는 경로가 아닌 모양의 중심선을 기준으로 올바른 줄 바꿈(단어 중간에 줄을 끊지 않음)과 정렬을 원한다는 것입니다.

나는 경로를 따라 텍스트를 렌더링할 때 모든 문자가 서로 다르게 래핑되고 \hbox개별적으로 올바른 정도로 바뀌는 것을 알고 있습니다.

어떤 제안이 있으십니까?

업데이트:

~ 안에이것응답 경로는 텍스트가 경로에 맞는 경우에만 장식됩니다. 적합한 텍스트로만 경로를 장식하고 나머지 텍스트는 다른 경로에 남겨 두는 유사한 접근 방식이 있을 수 있습니까?

업데이트 2:

텍스트가 설명된 대로 왼쪽 들여쓰기 상태를 재정의하는 경로에 맞지 않으면 텍스트를 숨길 수 있습니다.위에서 언급한 답변:

\makeatletter
  \pgfkeys{
    /pgf/decoration/omit long text/.code={%
      \expandafter\def\csname pgf@decorate@@text along path@left indent@options\expandafter\expandafter\expandafter\endcsname\expandafter\expandafter\expandafter{\csname pgf@decorate@@text along path@left indent@options\endcsname,switch if less than=\pgf@lib@dec@text@width to final}%
    },
  }
\makeatother

내 생각은 텍스트 조판을 건너뛰는 것(최종 상태로 전환)뿐만 아니라 텍스트가 조판되지 않았음을 의미하는 플래그도 설정하여 텍스트 길이를 줄이고 데코레이션을 다시 호출할 수 있도록 하는 것입니다.

답변1

내 아이디어(OP 질문에 대한 설명)에 따라 LuaTeX로 몇 가지 실험을 수행했습니다. 이는 예비 결과입니다.

라텍스의 예

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations.text}
\directlua{dofile("testing.lua")}
\begin{document}
\sffamily

% Before entering tikzpicture
\directlua{PrepareText({{105,75,4.5}, {105,75,4}, {105,75,3.5}}, 
           "Gershon Daly Bonifacy Yaw")}
\begin{tikzpicture}
\draw (70:3) arc (70:110:3)
   -- (110:5)  arc (110:70:5)
   -- cycle;
\directlua{TypeInArcs()}
\end{tikzpicture}
%
% A second example
\directlua{PrepareText({{105,75,4.5}, {105,75,4}, {105,75,3.5}}, 
"This is another longer test, which does not Fit")}
\begin{tikzpicture}
\draw (70:3) arc (70:110:3)
   -- (110:5)  arc (110:70:5)
   -- cycle;
\directlua{TypeInArcs()}
\end{tikzpicture}
%
% Third example
\directlua{PrepareText({{105,75,4.5}, {105,75,4}, {105,75,3.5}, {105,75,3}}, 
"This is another longer test, which now does Fit")}
\begin{tikzpicture}
\draw (70:2.5) arc (70:110:2.5)
   -- (110:5)  arc (110:70:5)
   -- cycle;
\directlua{TypeInArcs()}
\end{tikzpicture}

\end{document}

결과

다음으로 컴파일한 후lualatex

결과

루아 코드

파일에 저장하십시오 testing.lua.

function GetLinesFromBox()
        local lines,i,j,l,d,list,words
        lines = {}; j = 1;
        d=node.types();
        list = tex.box[0].head
        node.unprotect_glyphs(list)
        for l in node.traverse(list) do
            if (d[l.id]=="hlist") then
                words = {}; i = 1
                for l in node.traverse(l.head) do
                    if (d[l.id]=="glyph") then
                        words[i] = string.char(l.char)
                        i=i+1
                    end
                    if (d[l.id]=="glue") then
                        words[i] = " "
                        i=i+1
                    end
                end
                lines[j] = table.concat(words,"")
                j=j+1
            end
        end
        return lines
end

function ComputeLengthArc(start_, end_, radius)
    return (radius*(math.abs(start_-end_)*2*math.pi/360))
end

global_arcs = {}
global_text = ""

function PrepareText(arcs, text)
    local j,l
    global_arcs = arcs
    global_text = text
    tex.print("\\setbox0=\\vbox{\\centering\\parshape ", #arcs)
    for j=1,#arcs do
        l = ComputeLengthArc(arcs[j][1], arcs[j][2], arcs[j][3] )
        tex.print("0cm "..l.."cm ")
    end
    tex.print("\\noindent ".. text .. "}")
end

function TypeInArcs()
    local lines,j
    lines = GetLinesFromBox()
    for j=1,#global_arcs do
        if lines[j]~=nil then
            tex.sprint("\\path[ postaction = { decorate, decoration = {")
            tex.sprint("  text along path,")
            tex.sprint("  text align = center,")
            tex.sprint("  text={"..lines[j].."}")
            tex.sprint("} } ]")
            tex.sprint("("..global_arcs[j][1]..":"..global_arcs[j][3]..
                  ") arc ("..global_arcs[j][1]..":"..global_arcs[j][2]..":"..global_arcs[j][3]..");")
        end
    end
end

설명 및 주의사항

이것은 단지 개념 증명일 뿐입니다. 알고리즘은 매우 순진합니다. 나는 TeX의 상자 0에 텍스트를 조판했지만 parshape각 줄에 적절한 길이를 사용했습니다. 그런 다음 Lua의 결과 노드를 검사합니다. 각 노드는 hbox선이고, glyph해당 상자 안의 각 노드는 문자이고, 각 노드 glue는 공백이라고 가정합니다. 이렇게 하면 나중에 tikz 그림을 그릴 때 각 줄에 사용할 문자열을 "재구성"합니다.

내가 해결하지 못한 몇 가지 문제가 있습니다(방법을 모르겠습니다).

  1. 텍스트의 합자는 ASCII에 해당하지 않는 문자 모양을 생성하므로 알고리즘을 손상시킵니다. 이것이 제가 "fi" 합자를 피하기 위해 "fit" 대신 "Fit"을 쓴 이유입니다.
  2. 같은 이유로 악센트 부호가 있는 문자는 허용되지 않습니다(테스트되지 않음).
  3. 분명히 tikz는 TeX 권투 메커니즘을 방해합니다. 왜냐하면 tikz 환경 내부에 상자를 만들려고 하면 상자가 생성되지 않기 때문입니다. 이것이 내가 tikz에 들어가기 전에 상자를 "준비"해야 하는 이유입니다.
  4. 아마도 아직 발견되지 않은 더 많은 문제가 있을 것입니다(많이 테스트되지 않음)

관련 정보