Joint tissage - dessiner un noeud Sierpiński


33

Pour un nombre entier N> = 2, créez une image représentant un nœud de Sierpiński de degré N.

Par exemple, voici les nœuds de degré 2, 3, 4 et 5:

Degré 2 Degré 3 Degré 4 Degré 5

Cliquez sur les images pour les afficher en taille réelle (plus le degré est élevé, plus l'image est grande).

spécification

  1. Un nœud de Sierpiński de degré N est dessiné en utilisant les sommets d’un triangle de Sierpiński de degré N comme points de repère. Un triangle de Sierpiński de degré N est constitué de trois triangles de Sierpiński de degré N-1 disposés en un triangle plus grand. Un triangle de Sierpiński de degré 0 est un triangle équilatéral.
  2. Les triangles les plus petits ont une longueur de côté 64, ce qui donne au triangle de Sierpiński sur lequel le nœud est basé une longueur totale de côté de 64 * 2 ^ N
  3. Le centre du triangle extérieur est positionné au centre de l'image. Cela ne donne pas un espace blanc égal en haut et en bas.
  4. La sortie est une image carrée de côté plafond (64 * 2 ^ N * 2 / ROOT3)plafond (x)est ceiling(x), le plus petit entier supérieur ou égal à x. C'est juste assez grand pour que le sommet du triangle de Sierpiński sous-jacent soit contenu dans l'image lorsque le centre du triangle est au centre de l'image.
  5. La courbe unique doit passer par-dessus et sous elle-même en alternant strictement. Les solutions peuvent choisir entre dessous puis dessus et dessous.
  6. Les exemples d'images montrent un avant-plan noir et un arrière-plan blanc. Vous pouvez choisir deux couleurs faciles à distinguer. L'anti-aliasing est autorisé mais pas nécessaire.
  7. Il ne doit pas y avoir de lacunes où deux arcs se rencontrent ou où la courbe passe par dessus ou par dessous.
  8. La sortie peut être vers n'importe quel fichier image au format raster ou vers n'importe quel fichier image au format vectoriel comportant une taille d'affichage par défaut correcte. Si vous affichez directement à l’écran, le formulaire doit permettre au défilement de voir la totalité de l’image lorsque celle-ci est plus grande que l’écran.

Détermination du centre, du rayon et de l'épaisseur de l'arc

  1. Le nœud est construit comme une série d’arcs circulaires qui se rejoignent à des points où leurs tangentes sont parallèles pour donner une jointure homogène. Ces arcs sont affichés sous forme de secteurs annulaires (arcs d'épaisseur).
  2. Les centres de ces arcs sont les sommets des plus petits triangles à l'envers. Chacun de ces sommets est le centre d'exactement un arc.
  3. Chaque arc a un rayon de 64 * ROOT3 / 2
  4. La seule exception est que les arcs des trois triangles les plus extérieurs (aux coins du grand triangle) ont un centre qui est le centre des deux sommets internes adjacents et ont donc un rayon de 64 * (ROOT3 / 2-1 / 2)
  5. Chaque arc est représenté par une épaisseur totale (différence entre le rayon intérieur et le rayon extérieur) de 64 * (ROOT3 / 2) / 4et les bordures noires de cet arc ont chacune une épaisseur de. 64 * (ROOT3 / 2) / 16La courbe doit avoir ces bordures et non pas simplement une bande pleine.

Unités de mesure

  1. Toutes les distances sont en pixels (1 est la distance horizontale ou verticale entre 2 pixels adjacents).
  2. La racine carrée de 3 doit être précise à 7 chiffres significatifs. C'est-à-dire que vos calculs doivent être équivalents à l'utilisation d'un ROOT3 tel que1.7320505 <= ROOT3 < 1.7320515

Notation

Le code le plus court en octets gagne.


Pour ceux qui s’interrogent, N = 0 et N = 1 ne sont pas inclus car ils correspondent à un cercle et à un trèfle, qui ne correspondent pas tout à fait au modèle qui s’applique pour N> = 2. Je m'attendrais à ce que la plupart des approches de ce défi aient besoin d'ajouter un code de cas spécial pour 0 et 1, alors j'ai décidé de les omettre.


1
Est-ce que cela aiderait d'avoir un diagramme pour montrer à quoi tous les nombres se rapportent?
Trichoplax

Avant de jouer au golf, il faut 7 chiffres significatifs pour les petits détails tels que l’épaisseur de la ligne, etc. Une précision du type "7 chiffres significatifs ou 1 pixel, selon la valeur la plus grande") semble plus appropriée.
Level River St

@LevelRiverSt étant donné que la taille de l'image est proportionnelle à l'entrée, 7 chiffres significatifs sont insuffisants pour une précision de 1 pixel pour un grand N. J'ai choisi 7 chiffres significatifs après une discussion en discussion, de sorte que toutes les réponses restent identiques. la norme.
Trichoplax

Oui, il est nécessaire pour la mise à l'échelle de l'image pour un plus grand N. 7 chiffres significatifs sur une image de 1000000 x 1000000 correspondent à 0,1 pixel, mais avec des calculs intermédiaires, cela pourrait être pire que cela. Je pense juste que stroke-width:3.464102pareil est un peu excessif si l’idée était d’obtenir une précision de 1 pixel. Je vais aller de l'avant et l'inclure comme ça, cependant, si c'est la décision.
Level River St

Réponses:


27

Ruby, 1168 932

Correction d'une erreur de la nuit dernière, plus de golf à faire après avoir clarifié.

C'est (actuellement) un programme complet qui accepte un numéro de stdin et génère un svgfichier sur stdout. J'ai choisi svg parce que je savais qu'il était possible de répondre à toutes les exigences de la question, mais cela posait quelques problèmes. SVG, en particulier, ne prend en charge que les arcs de cercle en tant que partie de l’ pathobjet et ne les définit pas en termes de centre mais plutôt de deux extrémités.

Code

n=gets.to_i
r=64*w=0.75**0.5
m=1<<n-2
z=128*m/w
a=(s="<path style='fill:none;stroke:black;stroke-width:3.464102' transform='translate(%f %f)'
")%[0,r-r*m*8/3]+"d='M18.11943,-2A#{b=r-6*w-32} #{b} 0 0,0 #{-b} 0#{k='A%f %f 0 0 '%([58*w]*2)}0 0,38.71692
M28.58980,1.968882#{l='A%f %f 0 0 '%([70*w]*2)}0 #{c=r+6*w-32} 0A#{c} #{c} 0 0,0 #{-c} 0#{l}0 -9 44.65423'/>"
p=2
m.times{|i|(i*2+1).times{|j|(p>>j)%8%3==2&&a<<s%[128*(j-i),r*3+r*i*4-r*m*8/3]+
"d='M-55,44.65423#{k}0 11.5,25.11473#{l}1 35.41020,1.968882
M-64,51.48786#{l}0 20.5,30.31089#{k}1 36.82830,13.17993
M-82.17170,-2.408529#{l}1 -11.5,25.11473#{k}0 0,38.71692
M-81.52984 8.35435#{k}1 -20.5,30.31089#{l}0 -9,44.65423
M9,44.65423#{k}0 81.52984,8.35435
M0,51.48786#{l}0 91.17169,13.17993'/>"}
p^=p*4}
puts "<svg xmlns='http://www.w3.org/2000/svg' viewBox='#{-z} #{-z} #{e=2*z+1} #{e}' width='#{e}px' height='#{e}px'>"+
"<g transform='rotate(%d)'>#{a}</g>"*3%[0,120,240]+"</svg>"

Sortie N = 4

remise à l'échelle par échange de pile. Semble beaucoup mieux que l'original.

entrez la description de l'image ici Explication

Au début, j'ai envisagé quelque chose comme http://euler.nmt.edu/~jstarret/sierpinski.html, où le triangle est divisé en trois volets de couleurs différentes, chacun formant un chemin d'un coin à l'autre. Les cercles incomplets y sont représentés par des hexagones incomplets. l'inscription des cercles à l'intérieur des hexagones montre que le rayon du cercle doit être sqrt(3)/2multiplié par le sens de la longueur. Les brins peuvent être construits de manière récursive comme indiqué, mais il existe une complication supplémentaire car les angles doivent être arrondis et il est difficile de savoir dans quelle direction se courber. Je n'ai donc pas utilisé cette approche.

Ce que j'ai fait était le suivant.

Dans l'image ci-dessous, vous pouvez voir des torsions horizontales appartenant aux unités N = 2 (en vert) disposées dans un triangle de Sierpinski et des torsions de pontage supplémentaires (en bleu).

Il est de notoriété publique que les nombres impairs du triangle de Pascal forment un triangle de sierpinski. Un triangle sierpinski de chiffres binaires peut être obtenu de manière analogue en partant du nombre p=1et en le mémorisant de manière itérative p<<1.

J'ai modifié cette approche, en commençant par p=2xoring itératif p*4. Cela donne un triangle sierpinski alternant avec des colonnes de zéros.

Maintenant nous pouvons changer de droits p et inspecter les trois derniers bits en utilisant %8. Si c'est le cas, 010nous devons dessiner une torsion verte appartenant à une unité N = 2. si tel est le cas, 101nous devons tracer un pont bleu. Pour tester ensemble ces deux nombres, nous trouvons le modulo %3et, si ce nombre est égal à 2, nous devons tirer le tournant.

Enfin, en plus des torsions horizontales, nous faisons deux copies pivotées de 120 et 240 degrés pour dessiner les torsions en diagonale et compléter le tableau. Il ne reste plus qu'à ajouter les coins.

Code commenté

n=gets.to_i

#r=vertical distance between rows 
r=64*w=0.75**0.5

#m=number of rows of horizontal twists
m=1<<n-2

#z=half the size of the viewport
z=128*m/w

#s=SVG common to all paths
s="<path style='fill:none;stroke:black;stroke-width:3.464102' transform='translate(%f %f)'
"

#initialize a with SVG to draw top corner loop. Set k and l to the SVG common to all arcs of 58*w and 70*w radius 
a=s%[0,r-r*m*8/3]+
"d='M18.11943,-2A#{b=r-6*w-32} #{b} 0 0,0 #{-b} 0#{k='A%f %f 0 0 '%([58*w]*2)}0 0,38.71692
M28.58980,1.968882#{l='A%f %f 0 0 '%([70*w]*2)}0 #{c=r+6*w-32} 0A#{c} #{c} 0 0,0 #{-c} 0#{l}0 -9 44.65423'/>"

#p is the pattern variable, top row of twists has one twist so set to binary 00000010
p=2

#loop vertically and horizontally
m.times{|i|
 (i*2+1).times{|j|

   #leftshift p. if 3 digits inspected are 010 or 101 
   (p>>j)%8%3==2&&

   #append to a, the common parts of a path...
   a<<s%[128*(j-i),r*3+r*i*4-r*m*8/3]+

   #...and the SVG for the front strand and left and right parts of the back strand (each strand has 2 borders)
"d='M-55,44.65423#{k}0 11.5,25.11473#{l}1 35.41020,1.968882
M-64,51.48786#{l}0 20.5,30.31089#{k}1 36.82830,13.17993
M-82.17170,-2.408529#{l}1 -11.5,25.11473#{k}0 0,38.71692
M-81.52984 8.35435#{k}1 -20.5,30.31089#{l}0 -9,44.65423
M9,44.65423#{k}0 81.52984,8.35435
M0,51.48786#{l}0 91.17169,13.17993'/>"}

#modify the pattern by xoring with 4 times itself for the next row
p^=p*4}

#output complete SVG of correct size with three copies of the finished pattern rotated through 0,120,240 degrees.
puts "<svg xmlns='http://www.w3.org/2000/svg' viewBox='#{-z} #{-z} #{e=2*z+1} #{e}' width='#{e}px' height='#{e}px'>"+
"<g transform='rotate(%d)'>#{a}</g>"*3%[0,120,240]+"</svg>"

entrez la description de l'image ici


Lorsque vous dites "semble beaucoup mieux que l'original", il serait peut-être utile d'ajouter quelque chose comme "(cliquez sur l'image pour voir en taille réelle)" pour ceux qui ne s'en rendent pas compte.
Trichoplax

@trichoplax, il ne m’était pas venu de cliquer sur l’image. Quoi qu'il en soit, il s'agit d'un fichier PNG, car l'échange de pile n'accepte pas les images svg, de sorte que les contours sont délibérément flous. Mon fichier SVG local a des bords beaucoup plus nets et une apparence bien meilleure.
Level River St

@trichoplax quick fix sur la taille de l'image effectuée. Will golf plus un autre jour.
Level River St

1
+1 excellent travail. J'aime particulièrement l'explication détaillée avec le schéma codé par couleur.
Trichoplax

1
Le lien hypertexte est mort.
mbomb007
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.