OK, there is a lot going on here, but hopefully the comments go someway to making it clear how I've achieved this. I use a lot of nested style
definitions, which possibly may make things tricky to follow but hopefully the style
names give some indication of what they do. I also use a lot of nested \foreach
loops for no other reason than I found it easier than using a matrix.
Some apologies in advance for mangling the German words in the style
definitions.
\documentclass[border=5pt]{standalone}
\usepackage{tikz}
% pifont for tick and cross.
\usepackage{pifont}
% Only need the matrix library for delimiters.
\usetikzlibrary{matrix,fit}
\usetikzlibrary{shapes.geometric}
% Define some colors.
\colorlet{Klasse A}{red}
\colorlet{Klasse B}{blue}
\colorlet{probe color}{Klasse A}
\colorlet{correct color}{Klasse A}
\colorlet{incorrect color}{Klasse A}
\colorlet{testproben}{gray!20}
\def\vmark{}
\tikzset{
tight fit/.style={inner sep=0pt, outer sep=0pt},
probe color/.code={\colorlet{probe color}{#1}},
correct color/.code={\colorlet{correct color}{#1}},
incorrect color/.code={\colorlet{incorrect color}{#1}},
probe/.style args={#1-#2}{%
outer sep=0pt,
shape=rectangle,
probe #1-#2/.try,
execute at begin node={%
% Hide the testproben spike in a style rather than
% clutter up the main code.
\begin{tikzpicture}[x=2.75pt,y=1.5pt, scale=0.625]
\path [draw=probe color] plot [smooth] coordinates {(0,0)
(1,2) (2,10) (3,1) (4,3) (5,1) (6,4) (7,0)};
\end{tikzpicture}}
},
vorhesage/.style args={#1-#2}{
shape=circle,
draw=correct color,
text=white,
font=\bf\small,
vorhesage #1-#2/.try,
incorrect vorhesage #1-#2/.try,
minimum size=0.625cm
},
surrogat/.style={
shape=regular polygon,
regular polygon sides=3,
minimum height=1cm,
draw
}
}
\tikzset{
% The styles applied to specified testproben and (correct) vorhesage
testproben/.style args={#1-#2}{
probe #1-#2/.style={
fill=testproben
},
vorhesage #1-#2/.style={
fill=correct color,
execute at begin node=\def\vmark{\ding{51}}% A tick
}
},
% The styles applied to specified testproben and (incorrect) vorhesage
testproben */.style args={#1-#2}{
probe #1-#2/.style={
fill=testproben
},
incorrect vorhesage #1-#2/.style={
fill=incorrect color,
draw=correct color,
very thick,
execute at begin node=\def\vmark{\ding{55}}% A cross
}
},
Daten A/.style={
A/.try,
probe color=Klasse A,
},
Daten B/.style={
B/.try,
probe color=Klasse B,
shift={(5,0)}
},
Vorhesage A/.style={
A/.try,
correct color=Klasse A,
incorrect color=Klasse B,
},
Vorhesage B/.style={
B/.try,
correct color=Klasse B,
incorrect color=Klasse A,
shift={(5,0)}
},
iteration 1/.style={
% Define the testproben (and vorhesagen) for iteration 1
A/.style={
testproben={1-4}, % testproben row 1, column 4
testproben={2-3}, testproben={2-5},
testproben *={3-1}, testproben={3-2},
},
B/.style={
testproben={1-2}, testproben={1-3},
testproben *={2-1},
testproben={3-4}
},
},
iteration 2/.style={
A/.style={
testproben={1-1}, testproben={1-4},testproben={1-5},
testproben={2-2},
testproben={3-5}
},
B/.style={
testproben={1-2}, testproben={2-1},
testproben={3-1}, testproben={3-3}
}
},
iteration 3/.style={
A/.style={
testproben={1-5}, testproben={1-4},
testproben={2-2}, testproben={2-2},
testproben *={3-1}
},
B/.style={
testproben={1-2},
testproben={2-1},
testproben={3-3}, testproben={3-4}
},
}
}
\begin{document}
\begin{tikzpicture}[x=0.75cm, y=0.75cm, >=stealth]
\foreach \itr in {1,2,3}{
% Install the A and B styles for this iteration.
% The A and B styles define the testproben for Klasse A
% and Kasse B.
\tikzset{iteration \itr/.try}
\foreach \g in {1,2,3}{
\ifcase\g
\or
% Draw the probes
\foreach \K/\I/\J in {A/3/5, B/3/4}{%
% Install the Daten \K style.
% For Daten Klasse A this sets the probe color to blue
% For Daten Klasse B this sets the probe color to red
% and shifts everything along.
% In both cases the relevant style (A or B) is `executed'
% defining which probes are testproben.
\tikzset{Daten \K/.try}
\foreach \i in {1, ..., \I}{%
\foreach \j in {1, ..., \J}{%
\node (probe \itr-\K-\i-\j) at (\j, -\itr*3.5-\i)
[probe=\i-\j] {};
}
}
% Define a node that fits around all the nodes for this
% particular Daten Klasse.
\node [tight fit,fit=(probe \itr-\K-1-1)
(probe \itr-\K-\I-\J)]
(iteration \itr\space daten \K){};
}
\or
% Now draw the Surrogats (Surrogaten?)
\foreach \I in {1,2,3}{
\tikzset{shift=(probe \itr-B-1-4.east)}
\node (surrogat \itr-\I) at (1.125,1-\I) [surrogat] {};
\draw [ultra thick, ->]
(surrogat \itr-\I.west) ++(-0.625,0) -- ++(0.5,0);
\draw [ultra thick, ->]
(surrogat \itr-\I.east) ++(0.125,0) -- ++(0.5,0);
}
\or
% Finally the Forcasts
%
% Shift things along a but from the surrogats.
\tikzset{shift={(surrogat \itr-1)}, shift=(0:0.5)}
\foreach \K/\I/\J in {A/3/5, B/3/4}{
% This is the same as for the Daten Klasse,
% execept tis time the vorhesage proben are drawn.
\tikzset{Vorhesage \K/.try}
\foreach \i in {1, ..., \I}{
\foreach \j in {1, ..., \J}{
\node (vorhesage \itr-\K-\i-\j) at (\j, -\i+1)
[vorhesage=\i-\j] {\vmark};
}
},
% Draw a node around each set of vorhesage nodes.
\node [tight fit,
fit=(vorhesage \itr-\K-1-1) (vorhesage \itr-\K-\I-\J)]
(iteration \itr\space vorhesage \K){};
}
\fi%
}
}
% Now add the labels and delimiters.
\foreach \itr in {1,2,3}{
\node [tight fit, fit={(iteration \itr\space daten A)}, left
delimiter=\{, label={[xshift=-0.5cm]left:\itr.
Iteration}] {};
}
\foreach \K in {A, B}{
\node [tight fit, fit={(iteration 1 daten \K)}, above
delimiter=\{,label={[yshift=0.5cm]90:Daten Klassen \K}] {};
\node [tight fit, fit={(iteration 1 vorhesage \K)}, above
delimiter=\{,label={[yshift=0.5cm, align=center]90:{Vorhesage
\\Proben \K}}] {};
}
\node [fill=testproben, rounded corners=1ex, below=0.25cm, anchor=north west]
(testprobe)
at (probe 3-A-3-1.south east){Testprobe};
\draw [very thick, ->, rounded corners=1ex]
(testprobe.west) -| (probe 3-A-3-1.south);
\node [below=0.25cm, anchor=north west]
(trainingsprobe)
at (probe 3-A-3-4.south east){Trainingsprobe};
\draw [very thick, ->, rounded corners=1ex]
(trainingsprobe.west) -| (probe 3-A-3-4.south);
\node [below=1cm, anchor=north east]
(surrogatsmodelle)
at (surrogat 3-3.south west){$i=3\times k=3$ Surrogatsmodelle};
\draw [very thick, ->, rounded corners=1ex]
(surrogatsmodelle.east) -| (surrogat 3-3.south);
\node [below=0.5cm, align=left, anchor=north west] (eingeordnet)
at (vorhesage 3-A-3-1.south east){Testprobe aus Klasse \textcolor{Klasse
A}{A} wird \\als Klasse \textcolor{Klasse B}{B} eingeordnet};
\draw [very thick, ->, rounded corners=1ex]
(eingeordnet.west) -| (vorhesage 3-A-3-1.south);
\end{tikzpicture}
\end{document}
You can use the same \foreach
loop for the labeling:
\foreach \cSolution in {1,2}
\foreach \cRadius in {1,...,2}
\node[green,dot={right:$\ifnum\cSolution=2\expandafter\tilde\fi F^*_\cRadius$}]
(n-\cRadius-\cSolution)
at (intersection cs: first node={1:\cRadius},
second node={2:\cRadius},
solution=\cSolution) {};
The math behind the intersection cs
seems to be a little bit un-precise, so I repeated the task with the intersections
library.
(I also have cleaned up a little bit.)
Code (intersection cs
)
\documentclass[tikz,convert=false]{standalone}
\usetikzlibrary{through,calc}
\makeatletter
\tikzset{circle through extra radius/.code={% unorthodox addon for the through library
% needs to be used after 'circle through'!
% this can be avoided by slightly changing the source
\tikz@addoption{%
\pgfmathsetlengthmacro\pgf@tempa{\pgfkeysvalueof{/pgf/minimum width}+2*(#1)}%
\pgfset{/pgf/minimum width/.expanded=\pgf@tempa}%
}%
}}
\makeatother
\begin{document}
\begin{tikzpicture}[
every label/.append style={font=\small},
dot/.style={fill,outer sep=+0pt,inner sep=+0pt,shape=circle,draw=none,label={#1}},
dot/.default=,
small dot/.style={minimum size=2pt,dot={#1}},
small dot/.default=,
big dot/.style={minimum size=3pt,dot={#1}},
big dot/.default=
]
\begin{scope}[rotate around ={-20.5560452:(1, -.75)}]
\node[small dot = {right: \(P_1\)}] (P1) at (3cm, 0) {};
\node[small dot = {\(P_2\)}] (P2) at (-1, 0) {};
\node[small dot = {below: \(F\)}] (F) at (1cm, -.75cm) {};
\path[blue] (F) edge (P1) edge (P2) (P1) edge (P2);
\path ($(P1)!.75!(P2)$) coordinate (Fm) node[dot={right:$F_m^*$}] {};
\foreach \cPoint in {1, 2}
\foreach \sStyleR/\dDeltaRadius[count = \cRadius from 0] in {.0cm, .5cm, 1cm, 1.5cm}
\node[draw] at (P\cPoint.center) (\cPoint:\cRadius) [circle through=(Fm), circle through extra radius = \dDeltaRadius] {};
\foreach \cSolution in {1,2}
\foreach \cRadius in {1,2}
\node[green,big dot={right:$\ifnum\cSolution=2\expandafter\tilde\fi F^*_\cRadius$}]
(n-\cRadius-\cSolution) at (intersection cs: first node={1:\cRadius},
second node={2:\cRadius},
solution=\cSolution) {};
\clip(-4, -5) rectangle (8, 5);
\draw [samples = 50, domain = -0.99:0.99, xshift = 1cm, red,
thick] plot ({(-1 - (\x)^2) / (1 - (\x)^2)},
{1.73 * (-2) * (\x) / (1 - (\x)^2)});
\end{scope}
\end{tikzpicture}
\end{document}
Output (intersection cs
)
Code (intersections
library)
\documentclass[tikz,convert=false]{standalone}
\usetikzlibrary{through,calc,intersections}
\makeatletter
\tikzset{circle through extra radius/.code={% unorthodox addon for the through library
% needs to be used after 'circle through'!
% this can be avoided by slightly changing the source
\tikz@addoption{%
\pgfmathsetlengthmacro\pgf@tempa{\pgfkeysvalueof{/pgf/minimum width}+2*(#1)}%
\pgfset{/pgf/minimum width/.expanded=\pgf@tempa}%
}%
}}
\makeatother
\begin{document}
\begin{tikzpicture}[
every label/.append style={font=\small},
dot/.style={fill,outer sep=+0pt,inner sep=+0pt,shape=circle,draw=none,label={#1}},
dot/.default=,
small dot/.style={minimum size=2pt,dot={#1}},
small dot/.default=,
big dot/.style={minimum size=3pt,dot={#1}},
big dot/.default=
]
\begin{scope}[rotate around ={-20.5560452:(1, -.75)}]
\node[small dot = {right: \(P_1\)}] (P1) at (3cm, 0) {};
\node[small dot = {\(P_2\)}] (P2) at (-1, 0) {};
\node[small dot = {below: \(F\)}] (F) at (1cm, -.75cm) {};
\path[blue] (F) edge (P1) edge (P2) (P1) edge (P2);
\path ($(P1)!.75!(P2)$) coordinate (Fm) node[dot={right:$F_m^*$}] {};
\foreach \cPoint in {1, 2}
\foreach \dDeltaRadius[count = \cRadius from 0] in {.0cm, .5cm, 1cm, 1.5cm}
\node[draw, name path global/.expanded=\cPoint:\cRadius] at (P\cPoint.center) (\cPoint:\cRadius) [circle through=(Fm), circle through extra radius = \dDeltaRadius] {};
\foreach \cRadius in {1,2} {
\tikzset{name intersections={of/.expanded={1:\cRadius} and 2:\cRadius,name/.expanded=n'-\cRadius}}
\foreach \cSolution in {1,2}
\node[green,big dot={right:$\ifnum\cSolution=2\expandafter\tilde\fi F^*_\cRadius$}] (n-\cRadius-\cSolution) at (n'-\cRadius-\cSolution){};
}
\clip (-4, -5) rectangle (8, 5);
\draw [samples = 50, domain = -0.99:0.99, xshift = 1cm, red,
thick] plot ({(-1 - (\x)^2) / (1 - (\x)^2)},
{1.73 * (-2) * (\x) / (1 - (\x)^2)});
\end{scope}
\end{tikzpicture}
\end{document}
Output (intersections
library)
Best Answer
I hope this helps you with the first two parts of your question.
The
calc
library provides the($(p1)!<magic>!(p2)$)
syntax that evaluates to various coordinates.If
<magic>
is a ratio (say,.1
,.5
or even-.1
) the resulting coordinate lies between(p1)
(ratio =0
) and(p2)
(ratio =1
). If<magic>
is a coordinate (like(F)
), this coordinate is projected orthogonal onto the line between(p1)
and(p2)
(in the example below, the resulting circles a gray).The very small library
through
provides only one option:circle through
. This option accepts one coordinate through which the circle (this is a node of the shapecircle
) goes.The option
circle through extra radius
which is to be used aftercircle through
adds its argument to the circle’s radius.The coordinate which will produce equal-radius circles will be saved under the name
(half-center)
, the coordinate where(F)
is projected onto the line will be stored unter the name(F-center)
(please use better names in your project;)
). One could also use calc’s($<stuff>$)
syntax forcircle through
but this way, we can reference these coordinates later without the need to let TikZ re-calculate the coordinate over and over again (and it is easier to maintain).The—apparently un-documented—
intersection cs
can be used to find the intersection of line/line, lines/circle and circle/circle. This works only if the circle is a node!There is also the
intersections
library which can find any intersection between arbitrary paths (refer to Gonzalo Medina’s example, and also TeX.se which has some interesting (and abusing) examples).Now, I don’t know nothing about this “arc”. If it is a true arc (part of a circle = constant radius) you can take three coordinates (preferable the most outer ones and the center one) and calculate the needed center and start and end angle), but if not, you can add more hidden circles as I did in the example below with
{draw=none}/3cm
.If you want a correct smooth hyperbole, I’mma gonna need some math.
Code
Output
Code (with
plot
/smooth
)Output,
.gif