
Estoy intentando generar esta imagen fractal particular de una flor, pero ni siquiera sé dónde ni cómo empezar. ¿Se puede utilizar TikZ para generar un "Espiral filotáctica"?
Lo vi aquí:https://www.reddit.com/r/FractalPorn/comments/xr17t1/fractal_rose/
y la imagen se ve como se muestra a continuación:
Parecen muchos puntos, así que comencé a intentarlo con un diagrama de dispersión pgfplots
, pero fracasé por completo. No hay ningún código que valga la pena mostrar aquí.
EDITAR: ¿Cómo pongo una marca verde en más de una respuesta? ¡Los resultados que ustedes han dado son asombrosos!
Respuesta1
Estoy usandoLa fórmula de Sandy G.aquí, básicamente la .707^<level>
parte.
Dos enfoques:
- PGF y LuaLaTeX que utilizaEl gran guión de Poisson Lua de JLDiaz.
- TikZ y PGFmath que solo usa la
rnd
función.
La macro \pgfpointspiralifdefined
garantiza que no sea necesario volver a calcular las coordenadas que ya se han calculado.
En lugar de las coordenadas a
, b
y , c
también d
puedes utilizar los vertex
anclajes delforma de cometaque utiliza la respuesta de Sandy G (por supuesto, debe nombrar los nodos, por ejemplo spiral-\l-\n
).
En ambas soluciones estoy elevando al cubo uno de los valores aleatorios para que los puntos queden agrupados a un lado de las cometas.
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 + PGFmatemáticas
También podría \pgfpointspiralifdefined
haberse implementado mediante un sistema de coordenadas TikZ personalizado, pero ¿para qué molestarse?
\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}
Producción
Respuesta2
Aquí está la rosa, que utiliza la kite
forma de nodo de la biblioteca tikz shapes.geometric
. Dejo que otros llenen los nodos con puntos.
\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 obtener una rosa de 8 vértices, los ángulos de los vértices de la cometa deben diferir en 45 (120 y 75 en el código anterior). Puedes cambiar .703
a (sin((\aaa-45)/2)/sin(\aaa/2))
, donde \aaa
está el ángulo mayor para obtener variaciones en la forma. El 1.38
factor también necesita ajustes.
Respuesta3
Intenté hacer la construcción usando una pic
curva en forma de hélice. Todos los cálculos están ocultos en la definición de petalPiece
(el pic
elemento) que crea un cuadrilátero; cada pétalo estará formado por \nbQuad
piezas.
Hay dos variables globales: el número de pétalos y el número de piezas de cada pétalo. Por ejemplo, con 9 pétalos, obtenemos el dibujo de abajo.
El 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}