I defined a new shape that draws a flower with predefined filling and coloring:
\makeatletter
\pgfdeclareshape{flower}{
\savedanchor{\center}{%
\pgfpointorigin}
\anchor{center}{\center}
\backgroundpath{%
\begingroup
\tikz@mode
\iftikz@mode@draw
\foreach \a in {60,120,...,360} {
\pgftransformrotate{\a}
\pgfpathellipse{\pgfpointxy{0}{0.7}}{\pgfpointxy{0.25}{0}}{\pgfpointxy{0}{0.5}}
}
\pgfpathcircle{\pgfpoint{0}{0}}{0.4cm}
\let\my@color\tikz@strokecolor!60!\tikz@fillcolor
\foreach \a in {30,60,...,360} {%
\pgftransformrotate{\a+7}%
\pgfpathmoveto{\pgfpointxy{0}{0.1}}
\def\y{0.6+0.05*rand}
\pgfpathlineto{\pgfpointxy{0}{\y}}
\pgfpathcircle{\pgfpointxy{0}{\y}}{0.05cm}
}
\fi
\iftikz@mode@fill
\begin{scope}
\foreach \a in {60,120,...,360} {
\pgftransformrotate{\a}
\pgfpathellipse{\pgfpointxy{0}{0.7}}{\pgfpointxy{0.25}{0}}{\pgfpointxy{0}{0.5}}
}
\pgfusepath{clip}
\pgfpathcircle{\pgfpointxy{0}{0}}{1.2cm}
\pgfutil@colorlet{tikz@radial@outer}{\tikz@fillcolor!70}
\pgfutil@colorlet{tikz@radial@inner}{\tikz@fillcolor!60!\tikz@strokecolor}
\pgfshadepath{radial}{0}
\pgfusepath{}
\end{scope}
% \tikz@mode@clipfalse
\let\my@strokecolor\tikz@strokecolor
\let\my@fillcolor\tikz@fillcolor
\pgfsetfillcolor{\my@strokecolor}
\pgfpathcircle{\pgfpointxy{0}{0}}{0.4cm}
\pgfusepath{fill}
\foreach \a in {30,60,...,360} {%
\pgftransformrotate{\a+7}%
\pgfpathmoveto{\pgfpointxy{0}{0.1}}
\def\y{0.5+0.05*rand}
\pgfpathlineto{\pgfpointxy{0}{\y}}
\pgfpathcircle{\pgfpointxy{0}{\y}}{0.05cm}
}
\let\my@color\my@fillcolor
\pgfutil@colorlet{\my@color}{\my@strokecolor!60!\my@fillcolor}
\pgfsetstrokecolor{\my@color}
\pgfsetfillcolor{\my@color}
\pgfusepath{stroke,fill}
\fi
\endgroup
}
}
\makeatother
which results in a nicely filled and colored flower when used as:
\node[flower, fill=pink, draw=purple] {};
Still, I have several problems and questions, for which I am not able to find an answer myself.
1) if I do not use \begin{scope} and \end{scope}, I do not know how to stop clipping which I do in the filling section. Is there a way to avoid using scopes? Or it is completely fine to have them there?
2) In the drawing of stamens, their height can be slightly changed using random function
\def\y{0.6+0.05*rand}
\pgfpathlineto{\pgfpointxy{0}{\y}}
\pgfpathcircle{\pgfpointxy{0}{\y}}{0.05cm}
but each time the value of \y is recalculated and I do not know how to fix it here.
3) If I do not specify the colors of stroke and fill
fill=pink, draw=purple
I get compiling errors. I even get errors if I use
\node[flower, fill, color=red] {};
In that case, how can I use the default colors?
4) I would like to define a new decoration that would decorate a path with flowers of random size, moreover I expect these flowers to be exactly the same as on the picture above. Here is the code of my decoration:
\pgfdeclaredecoration{flowers}{initial}{
\state{initial}[width=1cm]
{
\pgfmathparse{round(rnd*90)}
\pgftransformrotate{\pgfmathresult}
\pgfmathparse{0.2+rand*0.1}
\pgftransformscale{\pgfmathresult}
\pgfsetlinewidth{\pgfmathresult*\pgflinewidth}
\pgfsetcolor{pink}
\pgfsetfillcolor{pink}
\pgfsetstrokecolor{purple}
\pgfnode{flower}{center}{}{}{\pgfusepath{stroke,fill}}
}
\state{final}
{
\pgfpathmoveto{\pgfpointdecoratedpathlast}
}
}
My first problem is that I get "plain" flowers by calling
\draw[decorate, decoration={flowers}] (-4,-3) -- (4,-3);
instead of a nice filling/coloring. What should I modify in the definition of flower?
Then, I would prefer to use random step between the flowers, how it can be done?
Best Answer
This is probably still a little way off because there are a few places where I'm not sure what you're after.
You have to limit the
clip
somehow and scopes are the right way to do this. You can use the lower-level\pgfscope
and\endpgfscope
to be consistent with your use of the\pgf...
commands.I see several uses of this code and I'm guessing that you want them all to be mutually consistent. There are two problems: one with the code above and one with the global reuse. With the code above then
\y
gets computed twice and each time it uses a different random number. So instead of\def\y{...}
you want to make\y
the result of that computation. For this, use\pgfmathsetmacro\y{...}
. The second problem is addressed by resetting the random seed for\pgfmath
at appropriate places. This is done using\pgfmathsetseed
.TikZ only sets
\tikz@strokecolor
and\tikz@fillcolor
if thedraw
orfill
options were given explicit colours. A general colour is saved astikz@color
(note that this is a colour name not a macro) so you need to use that. I recommend putting a "get the right colours" bit at the top of your code and then using your own names. As I said in my comment, I'm not completely clear as to which colours correspond to which actions (fill, stroke, fade) on the parts of the flower so my code (below) will probably get this wrong.The plain flowers comes from the fact that you are defining the colours in the decoration using low-level commands (
\pgfsetstrokecolor
) but extracting the colours from the TikZ level commands (\tikz@strokecolor
). There isn't, as far as I can see, a way to extract the current stroke colour so we have to set them using the TikZ method. The same goes for thestroke
andfill
actions. As you're using\tikz@mode@...
in your code you have to use the TikZ method of specifyingdraw
andfill
.The
width
is evaluated afresh each time so you can set it to a newdimen
and then adjust this dimension on each run.Here's my adaptation of your code implementing all the above. As I've said, I don't think I get quite what you're looking for in a few places but hopefully it is close enough that you can see where to go next.
Update I've gone through the code a little and removed some of the repetition and tidied up a few things. Comments in code.