
Estou tentando gerar esta imagem fractal específica de uma flor, mas nem sei por onde ou como começar. O TikZ pode ser usado para gerar um "Espiral filotática"?
Eu vi aqui:https://www.reddit.com/r/FractalPorn/comments/xr17t1/fractal_rose/
e a imagem fica conforme abaixo:
Parecem muitos pontos, então comecei a tentar com um gráfico de dispersão pgfplots
, mas falhei completamente. Nenhum código que valha a pena mostrar aqui.
EDITAR: Como coloco uma marca verde em mais de uma resposta? Os resultados que vocês deram são surpreendentes!
Responder1
estou a usarFórmula de Sandy Gaqui, basicamente a .707^<level>
parte.
Duas abordagens:
- PGF e LuaLaTeX que usamO ótimo roteiro de poisson lua de JLDiaz.
- TikZ e PGFmath que apenas usam a
rnd
função.
A macro \pgfpointspiralifdefined
garante que as coordenadas que já foram calculadas não precisem ser recalculadas.
Em vez das coordenadas a
, b
, c
e d
, você também pode usar as vertex
âncoras doformato de pipaque a resposta de Sandy G usa (você precisa nomear os nós, é claro, por exemplo spiral-\l-\n
).
Em ambas as soluções, estou cubando um dos valores aleatórios para que os pontos fiquem agrupados em um lado das pipas.
PGF + LuaLaTeX
\documentclass{standalone}
\usepackage{pgf,pgffor}
\usepackage{jldiaz-poisson}% https://tex.stackexchange.com/a/185423/16595
\usepackage{xcolor} % colorwheel
\definecolor{cw0}{HTML}{9AFF00}\definecolor{cw1}{HTML}{FFA500}
\definecolor{cw2}{HTML}{FF001A}\definecolor{cw3}{HTML}{FF00D9}
\definecolor{cw4}{HTML}{6500FF}\definecolor{cw5}{HTML}{005AFF}
\definecolor{cw6}{HTML}{00FFE5}\definecolor{cw7}{HTML}{00FF25}
\pgfset{
declare function={
spiralAngle(\level,\spiral) = \directlua{tex.print(
180/(\pgfkeysvalueof{/pgf/spiral\space N})*\level
+360/(\pgfkeysvalueof{/pgf/spiral\space N})*\spiral)};
spiralRadius(\level) = \directlua{tex.print(
.707^\level*(\pgfkeysvalueof{/pgf/spiral\space radius}))};
xSpread(\n)=\n^3*.8+.1; ySpread(\n)=\n*.8+.1;},
spiral radius/.initial=5, spiral N/.initial=8}
\newcommand*\pgfpointspiral[2]{% #1 = level, #2 = spiral
\pgfpointpolarxy{spiralAngle(#1,#2)}{spiralRadius(#1)}}
\makeatletter
\newcommand*\pgfpointspiralifdefined[3]{%
% if spiral-#2-#3 doesn't exist, define it
% if it does do nothing
\pgfutil@ifundefined{pgf@sh@ns@spiral-#2-#3}{%
\pgfcoordinate{spiral-#2-#3}{\pgfpointspiral{#2}{#3}}%
}{}% and make it an alias for #1
\pgfnodealias{#1}{spiral-#2-#3}}
\makeatother
\begin{document}
\begin{pgfpicture}
\pgfsetxvec{\pgfqpoint{5mm}{0mm}}
\pgfsetyvec{\pgfqpoint{0mm}{5mm}}
\foreach \l in {0,...,6}{
\foreach \n in {0,...,7}{
\pgfpointspiralifdefined{a}{\l} {\n}
\pgfpointspiralifdefined{b}{\inteval{\l+1}}{\n}
\pgfpointspiralifdefined{c}{\l} {\inteval{\n+1}}
\pgfpointspiralifdefined{d}{\inteval{\l-1}}{\inteval{\n+1}}
\pgfsetfillcolor{cw\n}
\foreach[expand list, evaluate={\xSpread=xSpread(\x);}]
\x/\y in {\poissonpointslist{1}{1}{.02+.0\l}{10}} {
\pgfpathcircle{
\pgfpointlineattime{ySpread(\y)}
{\pgfpointlineattime{\xSpread}
{\pgfpointanchor{a}{center}}{\pgfpointanchor{b}{center}}}
{\pgfpointlineattime{\xSpread}
{\pgfpointanchor{d}{center}}{\pgfpointanchor{c}{center}}}
}{+.25pt}
\pgfusepath{fill}
}
}
}
\end{pgfpicture}
\end{document}
TikZ + PGFmath
O \pgfpointspiralifdefined
também poderia ter sido implementado por um sistema de coordenadas TikZ personalizado, mas por que se preocupar…
\documentclass[tikz]{standalone}
\usetikzlibrary{calc}
\pgfset{
declare function={
xSpread(\n)=\n^3*.8+.1; ySpread(\n)=\n*.8+.1;},
spiral radius/.initial=5,
spiral N/.initial=8}
\newcommand*\pgfpointspiral[2]{% #1 = level, #2 = spiral
\pgfpointpolarxy{180/(\pgfkeysvalueof{/pgf/spiral N})*(#1)
+360/(\pgfkeysvalueof{/pgf/spiral N})*(#2)}
{.707^(#1)*(\pgfkeysvalueof{/pgf/spiral radius})}}
\makeatletter
\newcommand*\pgfpointspiralifdefined[3]{%
\pgfutil@ifundefined{pgf@sh@ns@spiral-#2-#3}{%
\pgfcoordinate{spiral-#2-#3}{\pgfpointspiral{#2}{#3}}%
}{}%
\pgfnodealias{#1}{spiral-#2-#3}}
\makeatother
\begin{document}
\begin{tikzpicture}[x=+5mm, y=+5mm]
\foreach \l[evaluate={\Dots=250*.7^\l}] in {0,...,6} {
\foreach \n in {0,...,7} {
\pgfpointspiralifdefined{a}{\l} {\n}
\pgfpointspiralifdefined{b}{\inteval{\l+1}}{\n}
\pgfpointspiralifdefined{c}{\l} {\inteval{\n+1}}
\pgfpointspiralifdefined{d}{\inteval{\l-1}}{\inteval{\n+1}}
\fill[radius=+.4pt] foreach[
evaluate={\xSpread=xSpread rnd; \ySpread=ySpread rnd;}]
\dot in {0,...,\Dots} {
($($(a)!\ySpread!(d)$)!\xSpread!($(b)!\ySpread!(c)$)$)
circle[radius=+.4pt]};
}
}
\end{tikzpicture}
\end{document}
Saída
Responder2
Aqui está a rosa, que usa o kite
formato de nó da biblioteca tikz shapes.geometric
. Deixo para outros preencherem os nós com pontos.
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric}
\tikzset{mykite/.style={inner sep=.1pt, kite, fill=red!30, kite vertex angles=120 and 75}}
\begin{document}
\begin{tikzpicture}
\foreach \l in {1,...,12}{
\foreach \n[evaluate=\n as \t using \l*22.5+\n*45, % \t is the angle for node placement
evaluate=\n as \s using .703^(\l-1), % \s is the scaling factor for the distance from 0 for each level
evaluate=\n as \c using \s-.01] in {1,...,8} % \c is used to shrink each node just a bit.
{\node[mykite, rotate=\t, minimum size=\c cm] at (\t-90:{\s*1.38}){};}
}
\end{tikzpicture}
\end{document}
Para obter uma rosa de 8 vértices, os ângulos dos vértices da pipa devem diferir em 45 (120 e 75 no código acima). Você pode mudar .703
para (sin((\aaa-45)/2)/sin(\aaa/2))
, onde \aaa
é o ângulo maior para obter variações na forma. O 1.38
fator também precisa de ajuste.
Responder3
Tentei fazer a construção usando uma pic
curva em forma de hélice. Todos os cálculos estão ocultos na definição do petalPiece
( pic
elemento) que cria um quadrilátero; cada pétala será composta por \nbQuad
pedaços.
Existem duas variáveis globais: o número de pétalas e o número de peças de cada pétala. Por exemplo, com 9 pétalas, obtemos o desenho abaixo.
O código
\documentclass[11pt, margin=1cm]{standalone}
\usepackage{tikz}
\usetikzlibrary{math, calc}
\begin{document}
\tikzmath{
integer \nbPetals, \nbQuad;
\nbPetals = 8;
\nbQuad = 7;
real \a, \base, \r;
\a = 360/\nbPetals; % petal's angle
\base = 2; % base of the exponential definig the helix
\r = .35; % scaling constant
function tmpR(\i) {% integer giving a point along the helix
return {\r*pow(\base, 3.145*\i/\nbQuad)};
};
}
\tikzset{%
pics/petalPiece/.style 2 args={% branch number, base point number
code={%
\tikzmath{integer \b, \p; \b = #1; \p = #2;}
\path
(\p/\nbQuad*180 +\b*\a: {tmpR(\p)}) coordinate (NW)
({(\p +1)/\nbQuad*180 +\b*\a}: {tmpR(\p +1)}) coordinate (NE)
({(\p +2)/\nbQuad*180 +(\b -1)*\a}: {tmpR(\p +2)}) coordinate (SE)
({(\p +1)/\nbQuad*180 +(\b -1)*\a}: {tmpR(\p +1)}) coordinate (SW);
\foreach \i in {0, .05, ..., .9}{%
\draw[white, thick, fill=magenta!90, opacity=.05]
($(NW)!\i!(SW)$) -- ($(NE)!\i/2!(SE)$) -- (SE) -- (SW) -- cycle;
}
}
}
}
\begin{tikzpicture}
\foreach \l in {1, 2, ..., \nbPetals}{
\foreach \i in {-1, 0, 1, 2, ..., \nbQuad}{%
\path (0, 0) pic {petalPiece={\l}{\i}};
}
}
\end{tikzpicture}