Cyclic permutation of arguments / list of arguments
With a bit of fooling around it is possible to write the parser using \pgfkeys
:
\documentclass[tikz,border=5]{standalone}%
\makeatletter
\def\atchar{@}
\pgfkeys{/Centroid/.code args={(#1)#2}{\pgfkeys{/Centroid ..={(#1,#1)(#2,@)}}},
Centroid ../.code args={(#1,#2,#3)(#4,#5)}{%
\pgfcoordinate{#4}{%
\pgfpointscale{0.5}{\pgfpointadd{\pgfpointanchor{#1}{center}}%
{\pgfpointanchor{#2}{center}}}}%
\def\tmp{#5}\ifx\tmp\atchar\else%
\pgfkeys{/Centroid ..={(#2,#3)(#5)}}%
\fi%
}}
\def\Centroid(#1)#2{\pgfkeys{/Centroid={(#1)#2}}}
\begin{document}
\begin{tikzpicture}
\draw [gray, thick] (0, 0) coordinate (A) -- (5, 0) coordinate (B) --
(1, 3) coordinate (C) -- cycle;
\Centroid(A,B,C){I,J,K}
\foreach \point in {A,B,C,I,J,K}
\fill [fill=red] (\point) circle [radius=2pt] node [above] {\point};
\draw [gray, thick, shift=(270:5)]
(1, 0) coordinate (A) -- (5, 1) coordinate (B) --
(3, 4) coordinate (C) -- (0, 3) coordinate (D) -- cycle;
\Centroid(A,B,C,D){I,J,K,L}
\foreach \point in {A,B,C,D,I,J,K,L}
\fill [fill=blue] (\point) circle [radius=2pt] node [above] {\point};
\end{tikzpicture}
\end{document}
It is also possible to create the parser without pgfkeys
:
\makeatletter
\def\@stop{\@stop}
\def\Centroid(#1)#2{\@Centroid(#1,#1)(#2,\@stop)}
\def\@Centroid(#1,#2,#3)(#4,#5){%
\pgfcoordinate{#4}{%
\pgfpointscale{0.5}{\pgfpointadd{\pgfpointanchor{#1}{center}}%
{\pgfpointanchor{#2}{center}}}}%
\def\@tmp{#5}%
\ifx\@tmp\@stop%
\else%
\@Centroid(#2,#3)(#5)%
\fi}
\makeatother
I am not sure if that answers.
(Turns out I had misunderstood OP's query and that mid points names are not to be generated automatically; update at bottom adds pure TeX approach to handle this, with names of mid-points already given. Not knowing TikZ I only provide tool to generate the \path
as in OP.)
I wanted to use more of TikZ own toos but for example discovered that \foreach \point in {\foo}
did not give naively expected result if \foo
expands to comma separated names, but some error message from the TikZ parser, hence I again used an \xintFor
loop rather.
\documentclass{article}
\usepackage{tikz}
\usepackage{xinttools}
\makeatletter
\def\GetMidPoints@a #1{,midpoint#1}
\def\GetMidPoints@b #1{to coordinate(midpoint#1) (#1)}
\def\GetMidPoints(#1,#2){%
% #1=first point, #2=next points, ending again with first point
% define labels for MidPoints
\fdef\MyPoints {\xintCSVtoList{#2}}%
\fdef\MidPoints{\xintApplyUnbraced\GetMidPoints@a\MyPoints}%
\fdef\MidPoints{\expandafter\@gobble\MidPoints}%
% apparently this lets TikZ computes mid point coordinates
\path (#1) \xintApplyUnbraced\GetMidPoints@b\MyPoints;
}
\makeatother
\begin{document}
\begin{tikzpicture}
\path coordinate (A) at (0,0)
coordinate (B) at (5,0)
coordinate (C) at (2,3)
coordinate (D) at (1,4)
coordinate (E) at (0,1);
\draw (A) -- (B) -- (C) -- (D) -- (E) -- cycle ;
\GetMidPoints(A,B,C,D,E,A)%
\foreach \point in {A,B,C,D,E}{%
\fill [black,opacity=.5] (\point) circle (2pt);}%
\xintFor #1 in \MidPoints \do {%
\fill [red,opacity=.5] (#1) circle (2pt);}%
\end{tikzpicture}
\end{document}
Here is pure TeX approach.
\documentclass{article}
\usepackage{tikz}
\makeatletter
\def\Centroid(#1)#2{\Centroid@a #1;#2,\relax,;}%
\def\Centroid@a #1#2,#3;{\path (#1#2)\Centroid@b #3,#1#2,\relax,;}%
\def\Centroid@b #1#2,#3;#4#5,{\if\relax#1\expandafter\Centroid@end\fi
to coordinate(#4#5) (#1#2) \Centroid@b #3;}
\def\Centroid@end #1;{}
\makeatother
\begin{document}
\begin{tikzpicture}
\path coordinate (A) at (0,0)
coordinate (B) at (5,0)
coordinate (C) at (2,3)
coordinate (D) at (1,7)
coordinate (E) at (0,1);
\draw (A) -- (B) -- (C) -- (D) -- (E) -- cycle ;
\Centroid(A,B,C,D,E){I,J,K,L,M}%
\foreach \point in {A,B,C,D,E}
\fill [black,opacity=.5] (\point) circle [radius=2pt] node [below left] {\point};
\foreach \point in {I,J,K,L,M}
\fill [red,opacity=.5] (\point) circle [radius=2pt] node [above right] {\point};
\end{tikzpicture}
\end{document}
Just for fun another solution using \foreach
loops.
(The test part of the code is shamelessly borrowed from @MarkWibrow's answer.)
\documentclass[tikz,border=5]{standalone}
\usetikzlibrary{calc}
% ----------------------
\def\Centroid(#1)#2{
\edef\pts{#1,#1}
\edef\midpts{#2}
\foreach[count=\i] ~ in\midpts{
\foreach[count=\j] \A in\pts{
\ifnum \j = \i \relax
\xdef\FirstPoint{\A}
\fi
\ifnum \j = \numexpr \i + 1 \relax
\xdef\SecondPoint{\A}
\breakforeach
\fi
}
\coordinate (~) at ($(\FirstPoint)!.5!(\SecondPoint)$);
}
}
% ----------------------
\begin{document}
\begin{tikzpicture}
\draw [gray, thick] (0, 0) coordinate (A) -- (5, 0) coordinate (B) --
(1, 3) coordinate (C) -- cycle;
\Centroid(A,B,C){I,J,K}
\foreach \point in {A,B,C,I,J,K}
\fill [fill=red] (\point) circle [radius=2pt] node [above] {\point};
\draw [gray, thick, shift=(270:5)]
(1, 0) coordinate (A) -- (5, 1) coordinate (B) --
(3, 4) coordinate (C) -- (0, 3) coordinate (D) -- cycle;
\Centroid(A,B,C,D){I,J,K,L}
\foreach \point in {A,B,C,D,I,J,K,L}
\fill [fill=blue] (\point) circle [radius=2pt] node [above] {\point};
\end{tikzpicture}
\end{document}