Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

What I want to do

I want to create a command \planfigur{<edges>}{<angles>} which draws a triangle using TikZ. \planfigur should have 2 mandatory arguments, which let me specify edges and/or angles (where a = alpha, b = beta and c = gamma) of the triangle, which are drawn in red instead of black color.

E. g. \planfigur{ab}{bc} draws a black triangle, where the edges a and b and the angles beta and gamma are red.

planfigur

I use expl3 and xparse. I already have read (Is it reasonable to expect an expl3-compatible release of TikZ/PGF in the future?), that there are problems in using expl3 and tikz together (which makes sense).

So I played around and tried to outsmart TikZ. I had the following idea, which unfortunately doesn't work (1:0 for TikZ :-)). The approach is to move all expl3 code into a new command, where I can use \tl_if_in:nnT to check the arguments.

Code

\documentclass{article}

\usepackage{expl3, xparse}

\usepackage{tikz}
\usetikzlibrary{calc}

\ExplSyntaxOn

\tl_new:N \__edu_planfigur_temp

\DeclareDocumentCommand \planfigurLines { m } {

  \tl_clear:N \__edu_planfigur_temp

  \tl_if_in:nnT {#1} {a} {
    \tl_put_right:Nn \__edu_planfigur_temp {\draw (b) -- (c);}
  }

  \tl_if_in:nnT {#1} {b} {
    \tl_put_right:Nn \__edu_planfigur_temp {\draw (a) -- (c);}
  }

  \tl_if_in:nnT {#1} {c} {
    \tl_put_right:Nn \__edu_planfigur_temp {\draw (a) -- (b);}
  }

  \tl_use:N \__edu_planfigur_temp
}

\DeclareExpandableDocumentCommand \planfigurAngles { m } {
  \tl_if_in:nnT {#1} {a} {
    \tl_put_right:Nn \__edu_planfigur_temp {\draw ($(a) + (0:1)$) arc (0:40:1) ($(a) + (20:0.7)$) node {$\alpha$};}
  }
  \tl_if_in:nnT {#1} {b} {
    \tl_put_right:Nn \__edu_planfigur_temp {\draw ($(b) + (120:1)$) arc (120:180:1) ($(b) + (150:0.7)$) node {$\beta$};}
  }
  \tl_if_in:nnT {#1} {c} {
    \tl_put_right:Nn \__edu_planfigur_temp {\draw ($(c) + (220:1)$) arc (220:300:1) ($(c) + (260:0.65)$) node {$\gamma$};}
  }

  \tl_use:N \__edu_planfigur_temp
}

\ExplSyntaxOff

\DeclareExpandableDocumentCommand \planfigur { m m } {
  \begin{tikzpicture}[scale=0.65, line join=round, thick]

    \coordinate (a) at (0,0);
    \coordinate (b) at (5,0);
    \coordinate (c) at (3.37, 2.83);

    \draw (a) -- node[below] {$c$} (b) -- node[above right] {$a$} (c) -- node[above left] {$b$} (a) -- cycle;

    \draw (a) node[left] {$A$};
    \draw (b) node[right] {$B$};
    \draw (c) node[above] {$C$};

    \begin{scope}[color=red, fill=red!25, very thick]
      \planfigurLines{#1}
      \planfigurAngles{#2}
    \end{scope}

\end{tikzpicture}
}

\begin{document}

\planfigur{ac}{a}

\end{document}

Error

! Package pgf Error: No shape named 0:1 is known.

See the pgf package documentation for explanation. Type H for immediate help. ...
l.70 \planfigur{ac}{a}

share|improve this question
2  
I strongly suspect that the problem is due to the fact that in expl3 then : has the catcode of a letter but TikZ expects it to be other. One way around this is to define a token list containing a colon with catcode "other" and use that in place of the bare : in your code. –  Loop Space Aug 19 at 20:18
    
@LoopSpace: Yeah, that makes sense. I forgot the problem with :. This would also explain, why the lines (which don't contain a :) work without any problem. Your approach sounds promising, but I don't know how to do this. :-( –  dawu Aug 19 at 20:23
2  
You can do \tl_const:Nx \c_edu_colon_tl { \token_to_str:N : } and then use \c_edu_colon_tl instead of : in coordinates. \c_edu_colon_tl then contains a : with catcode 12 (other) instead of 11 (letter). –  cgnieder Aug 19 at 20:24
    
@cgnieder: Yes, this did it! You are my hero of the day. :-) What to do with the answer? Do you want to answes the question or should I answer it with the full working code? –  dawu Aug 19 at 20:26
    
@dawu Your \planfigur... commands are not expandable, so they should be declared with \NewDocumentCommand. –  egreg Aug 19 at 20:49

2 Answers 2

up vote 10 down vote accepted

One of the things \ExplSyntaxOn does is giving the colon category code 11 (letter) so it can be used as part of macro names. In coordinates TikZ however expects a colon with category code 12 (other). One solution that works is defining a token list that contains only a : with category code 12

\tl_const:Nx \c_edu_colon_tl { \token_to_str:N : } 

and then use said token list \c_edu_colon_tl instead of : in TikZ' coordinates.

BTW: your token list \__edu_planfigur_temp misses the recommended ending for a token list: _tl. It also misses the recommended start \l or \g which denotes if it is local or global. I'd rename it into \l__edu_planfigur_temp_tl.

In expl3 variables generally should start either with \l (local), \g (global) or \c (constant) and end with the type of variable (_tl for a token list, _int for an integer and so on).

share|improve this answer
    
Thanks for the explanation. I know about the naming conventions of expl3, but this example was very quick and dirty. But you are right, of course! –  dawu Aug 19 at 20:38
    
@dawu well, the answer is for you but also for others with a similar problem and they might not be aware of the naming convention. So it's better to repeat it. :) I'd also say it's better to follow the convention in MWEs, too: otherwise one might be tempted to get sloppy also in “real” code... :) –  cgnieder Aug 19 at 20:45
    
You are right. Should I correct it in my MWE? As you said, it would be better. –  dawu Aug 19 at 20:48
    
@dawu I don't think it's necessary: since I explained the convention in my answer we should be fine, I think. –  cgnieder Aug 19 at 20:50

Two more possibilities

\newcommand*\tikzangle[2]{#1:#2}
…
\ExplSyntaxOn
\draw (0,0) -- (\tikzangle{20}{2cm});
\ExplSyntaxOff

and a more practical one

\begingroup
\lccode`\X=`\:
\lowercase{\endgroup
  \gdef\tikzangle(#1X#2){#1:#2}}
\ExplSyntaxOn
\draw (0,0) -- \tikzangle(20:2cm);
\ExplSyntaxOff

To add the more general one, “easier to see” than cgnieder's

\def\othercolon{:}
\ExplSyntaxOn
\draw (0,0) -- (20\othercolon2cm);
\ExplSyntaxOff
share|improve this answer
    
Also very nice, thank you! It's always interesting to find new ways how to play a trick on the syntax. :o) But I think the first one is a bit "cleaner". –  dawu Aug 21 at 22:06
    
Nice. This must be adapted for arc (220:300:1) as well but that should not be a problem :) –  cgnieder Aug 21 at 22:49
    
@dawu The cool thing about the second one is that you just need to add \tikzangle (or whatever name you choose) before the angle you would write in TikZ (20:2cm). –  Manuel Aug 22 at 2:24
    
@cgnieder May be defining something like \tikzarc similar to this one. –  Manuel Aug 22 at 2:25
1  
The expl3 version also will always have a : with catcode 12 while \def\othercolon{:} saves : with whatever catcode it has (possibly 13 with \usepackage[french]{babel} for example). The equivalent would rather be \newcommand\othercolon{}\edef\othercolon{\string:} –  cgnieder Aug 23 at 18:52

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.